mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Escher: TabViewController is working!
Change-Id: I4aa730abbf1d7034d2fcbc40416dcb84076a347b
This commit is contained in:
@@ -5,6 +5,55 @@ extern "C" {
|
||||
#include <ion.h>
|
||||
}
|
||||
|
||||
/*
|
||||
class App {
|
||||
public:
|
||||
void run();
|
||||
protected:
|
||||
ViewController * rootViewController() = 0;
|
||||
private:
|
||||
View m_window;
|
||||
};
|
||||
|
||||
void App::run() {
|
||||
self.window = rootViewController()->view();
|
||||
self.responder = rootViewController()->responder();
|
||||
}
|
||||
|
||||
class GraphApp : public App {
|
||||
public:
|
||||
GraphApp();
|
||||
void run() override;
|
||||
protected:
|
||||
ViewController * rootViewController() override;
|
||||
private:
|
||||
FunctionController m_functionController;
|
||||
GraphController m_graphController;
|
||||
TabViewController m_tabController;
|
||||
};
|
||||
|
||||
class FunctionStore {
|
||||
};
|
||||
|
||||
class FunctionController : public ViewController {
|
||||
|
||||
};
|
||||
|
||||
class GraphController : public ViewController {
|
||||
};
|
||||
|
||||
GraphApp::GraphApp() {
|
||||
m_functionController = FunctionController();
|
||||
m_graphController = GraphController();
|
||||
ViewController * tabs[] = {
|
||||
&m_functionController,
|
||||
&m_graphController
|
||||
};
|
||||
m_tabController = TabViewController(tabs);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
class MyTextView : public View {
|
||||
using View::View;
|
||||
public:
|
||||
@@ -15,8 +64,64 @@ void MyTextView::drawRect(KDRect frame) {
|
||||
KDPoint zero = {0, 0};
|
||||
KDDrawString("Hello, world!", zero, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
class DemoViewController : public ViewController {
|
||||
public:
|
||||
DemoViewController(KDColor c);
|
||||
View * view() override;
|
||||
char * title() override;
|
||||
private:
|
||||
SolidColorView m_view;
|
||||
};
|
||||
|
||||
DemoViewController::DemoViewController(KDColor c) :
|
||||
m_view(SolidColorView(c))
|
||||
{
|
||||
}
|
||||
|
||||
View * DemoViewController::view() {
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
char * DemoViewController::title() {
|
||||
return "HELLO";
|
||||
}
|
||||
|
||||
void ion_app() {
|
||||
|
||||
//KDDrawString("Hello", {0,0}, 0);
|
||||
|
||||
//KDFillRect({0,0,100,100}, 0x55);
|
||||
//KDFillRect({100,100,100,100}, 0x99);
|
||||
|
||||
Window window;
|
||||
DemoViewController v1 = DemoViewController(0x55);
|
||||
DemoViewController v2 = DemoViewController(0x99);
|
||||
ViewController * tabs[]= { &v1, &v2};
|
||||
TabViewController tabVC = TabViewController(tabs, 2);
|
||||
|
||||
window.setFrame({{0,0}, {200, 200}});
|
||||
window.setSubview(tabVC.view(), 0);
|
||||
tabVC.view()->setFrame(window.bounds());
|
||||
|
||||
|
||||
int i = 0;
|
||||
|
||||
while(true) {
|
||||
tabVC.setActiveTab(i);
|
||||
ion_event_t event = ion_get_event();
|
||||
tabVC.handleKeyEvent(event);
|
||||
i = (i+1)%2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
static GraphApp app = GraphApp();
|
||||
app.run();
|
||||
*/
|
||||
/*
|
||||
KDRect wholeScreen = {0, 0, 100, 100};
|
||||
KDColor a = 0x55;
|
||||
View * window = new SolidColorView(wholeScreen, a);
|
||||
@@ -24,7 +129,7 @@ void ion_app() {
|
||||
MyTextView * textView = new MyTextView(textRect);
|
||||
window->addSubview(textView);
|
||||
|
||||
window->draw();
|
||||
//window->draw();
|
||||
|
||||
while (1) {
|
||||
ion_sleep();
|
||||
@@ -34,4 +139,5 @@ void ion_app() {
|
||||
|
||||
delete textView;
|
||||
delete window;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ objs += $(addprefix escher/src/,\
|
||||
childless_view.o\
|
||||
solid_color_view.o\
|
||||
tab_view.o\
|
||||
tab_view_cell.o\
|
||||
tab_view_controller.o\
|
||||
text_view.o\
|
||||
view.o\
|
||||
|
||||
@@ -8,23 +8,21 @@ class TabViewController;
|
||||
|
||||
class TabView : public View {
|
||||
public:
|
||||
// We'll ask the TabViewController for its controllers
|
||||
// and each controller know its name!
|
||||
// and also the active index !
|
||||
TabView(TabViewController * tabViewController);
|
||||
//void drawRect(KDRect rect) override;
|
||||
TabView();
|
||||
int numberOfSubviews() override;
|
||||
View * subview(int index) override;
|
||||
void layoutSubviews() override;
|
||||
|
||||
void addTabNamed(const char * name);
|
||||
//TODO: void removeLastTab();
|
||||
void setActiveIndex(int index);
|
||||
protected:
|
||||
void storeSubviewAtIndex(View * view, int index) override;
|
||||
private:
|
||||
TabViewController * m_tabViewController;
|
||||
/*
|
||||
static constexpr uint8_t k_maxNumberOfTabs = 4;
|
||||
uint8_t m_numberOfTabs;
|
||||
TabViewCell m_cells[k_maxNumberOfTabs];
|
||||
*/
|
||||
uint8_t m_numberOfTabs;
|
||||
uint8_t m_activeTabIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
#include <escher/view.h>
|
||||
#include <escher/text_view.h>
|
||||
|
||||
class TabViewCell : public View {
|
||||
class TabViewCell : public ChildlessView {
|
||||
public:
|
||||
TabViewCell();
|
||||
int numberOfSubviews() override;
|
||||
View * subview(int index) override;
|
||||
|
||||
void drawRect(KDRect rect) override;
|
||||
void setName(const char * name);
|
||||
void setActive(bool active);
|
||||
private:
|
||||
TextView m_textView;
|
||||
bool m_active;
|
||||
const char * m_name;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,17 +6,18 @@
|
||||
|
||||
class TabViewController : public ViewController {
|
||||
public:
|
||||
TabViewController(ViewController ** children);
|
||||
TabViewController(ViewController ** children, uint8_t numberOfChildren);
|
||||
View * view() override;
|
||||
void handleKeyEvent(int key) override;
|
||||
|
||||
void setActiveTab(uint8_t index);
|
||||
uint8_t numberOfTabs();
|
||||
|
||||
const char * tabName(uint8_t index);
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(TabViewController * vc);
|
||||
ContentView();
|
||||
|
||||
int numberOfSubviews() override;
|
||||
View * subview(int index) override;
|
||||
@@ -24,14 +25,15 @@ private:
|
||||
void layoutSubviews() override;
|
||||
|
||||
void setActiveView(View * view);
|
||||
private:
|
||||
TabView m_tabView;
|
||||
private:
|
||||
View * m_activeView;
|
||||
};
|
||||
|
||||
ContentView m_view;
|
||||
|
||||
ViewController ** m_children;
|
||||
uint8_t m_numberOfChildren;
|
||||
uint8_t m_activeChildIndex;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,10 +5,19 @@
|
||||
|
||||
class TextView : public ChildlessView {
|
||||
public:
|
||||
TextView(const char * text);
|
||||
TextView();//;: TextView(nullptr, 0.0f, 0.0f);
|
||||
// alignment = 0 -> align left or top
|
||||
// alignment = 0.5 -> align center
|
||||
// alignment = 1.0 -> align right or bottom
|
||||
TextView(const char * text,
|
||||
float horizontalAlignment,
|
||||
float verticalAlignment);
|
||||
void drawRect(KDRect rect) override;
|
||||
void setText(const char * text);
|
||||
private:
|
||||
const char * m_text;
|
||||
float m_horizontalAlignment;
|
||||
float m_verticalAlignment;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,8 @@ public:
|
||||
void redraw();
|
||||
|
||||
void setSubview(View * v, int index);
|
||||
protected:
|
||||
KDRect bounds();
|
||||
protected:
|
||||
virtual bool isOnScreen();
|
||||
virtual int numberOfSubviews() = 0;
|
||||
virtual View * subview(int index) = 0;
|
||||
|
||||
@@ -1,31 +1,58 @@
|
||||
#include <escher/tab_view.h>
|
||||
#include <escher/tab_view_controller.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
TabView::TabView(TabViewController * tabViewController) :
|
||||
TabView::TabView() :
|
||||
View(),
|
||||
m_tabViewController(tabViewController)
|
||||
m_numberOfTabs(0),
|
||||
m_activeTabIndex(0)
|
||||
{
|
||||
/*
|
||||
m_numberOfTabs = tabViewController->numberOfTabs();
|
||||
for (uint8_t i=0; i<m_numberOfTabs; i++) {
|
||||
//m_cells[i] = TabViewCell(name);
|
||||
//FIXME: use setName
|
||||
}
|
||||
|
||||
void TabView::addTabNamed(const char * name) {
|
||||
assert(m_numberOfTabs < k_maxNumberOfTabs);
|
||||
uint8_t tabIndex = m_numberOfTabs;
|
||||
m_cells[tabIndex].setName(name);
|
||||
m_numberOfTabs++;
|
||||
setSubview(&m_cells[tabIndex], tabIndex);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void TabView::setActiveIndex(int index) {
|
||||
assert(index < m_numberOfTabs);
|
||||
if (m_activeTabIndex == index) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
m_cells[m_activeTabIndex].setActive(false);
|
||||
m_activeTabIndex = index;
|
||||
m_cells[m_activeTabIndex].setActive(true);
|
||||
}
|
||||
|
||||
int TabView::numberOfSubviews() {
|
||||
return 0; //FIXME
|
||||
return m_numberOfTabs;
|
||||
}
|
||||
|
||||
View * TabView::subview(int index) {
|
||||
return nullptr;
|
||||
assert(index < m_numberOfTabs);
|
||||
return &m_cells[index];
|
||||
}
|
||||
|
||||
void TabView::layoutSubviews() {
|
||||
// TODO
|
||||
// Simple layout: all tabs have the same length
|
||||
KDCoordinate tabLength = bounds().width/m_numberOfTabs;
|
||||
for (int i=0; i<m_numberOfTabs; i++) {
|
||||
m_cells[i].setFrame({
|
||||
(KDCoordinate)(i*tabLength),
|
||||
0,
|
||||
tabLength,
|
||||
bounds().height
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TabView::storeSubviewAtIndex(View * view, int index) {
|
||||
// TODO
|
||||
// We're not doing anything here, because we already store all the subviews we ever wanna have
|
||||
assert(&m_cells[index] == view);
|
||||
}
|
||||
|
||||
25
escher/src/tab_view_cell.cpp
Normal file
25
escher/src/tab_view_cell.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <escher/tab_view_cell.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
TabViewCell::TabViewCell() :
|
||||
ChildlessView(),
|
||||
m_active(false),
|
||||
m_name(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void TabViewCell::setName(const char * name) {
|
||||
m_name = name;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void TabViewCell::setActive(bool active) {
|
||||
m_active = active;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void TabViewCell::drawRect(KDRect rect) {
|
||||
KDDrawString(m_name, {0,0}, m_active);
|
||||
}
|
||||
@@ -3,20 +3,33 @@ extern "C" {
|
||||
}
|
||||
#include <escher/tab_view_controller.h>
|
||||
|
||||
TabViewController::ContentView::ContentView(TabViewController * vc) :
|
||||
TabViewController::ContentView::ContentView() :
|
||||
View(),
|
||||
m_tabView(TabView(vc)),
|
||||
m_activeView(nullptr)
|
||||
{
|
||||
setSubview(&m_tabView, 0);
|
||||
};
|
||||
|
||||
void TabViewController::ContentView::setActiveView(View * view) {
|
||||
setSubview(view, 1);
|
||||
layoutSubviews();
|
||||
}
|
||||
|
||||
void TabViewController::ContentView::layoutSubviews() {
|
||||
KDCoordinate tabHeight = 20;
|
||||
m_tabView.setFrame({
|
||||
0,
|
||||
0,
|
||||
this->bounds().width,
|
||||
tabHeight
|
||||
});
|
||||
if (m_activeView) {
|
||||
m_activeView->setFrame(this->bounds());
|
||||
m_activeView->setFrame({
|
||||
0,
|
||||
tabHeight,
|
||||
this->bounds().width,
|
||||
(KDCoordinate)(this->bounds().height - tabHeight)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,17 +46,20 @@ View * TabViewController::ContentView::subview(int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void TabViewController::ContentView::ContentView::storeSubviewAtIndex(View * view, int index) {
|
||||
assert(index == 1);
|
||||
m_activeView = view;
|
||||
void TabViewController::ContentView::storeSubviewAtIndex(View * view, int index) {
|
||||
if (index == 1) {
|
||||
m_activeView = view;
|
||||
}
|
||||
}
|
||||
|
||||
TabViewController::TabViewController(ViewController ** children) :
|
||||
TabViewController::TabViewController(ViewController ** children, uint8_t numberOfChildren) :
|
||||
m_children(children),
|
||||
m_activeChildIndex(0),
|
||||
m_view(ContentView(this))
|
||||
m_numberOfChildren(numberOfChildren),
|
||||
m_activeChildIndex(-1)
|
||||
{
|
||||
setActiveTab(0);
|
||||
for (int i=0; i<numberOfChildren; i++) {
|
||||
m_view.m_tabView.addTabNamed(children[i]->title());
|
||||
}
|
||||
}
|
||||
|
||||
void TabViewController::setActiveTab(uint8_t i) {
|
||||
@@ -53,15 +69,27 @@ void TabViewController::setActiveTab(uint8_t i) {
|
||||
//TODO assert(i <= m_numberOfchildren);
|
||||
ViewController * activeVC = m_children[i];
|
||||
m_view.setActiveView(activeVC->view());
|
||||
m_view.m_tabView.setActiveIndex(i);
|
||||
m_activeChildIndex = i;
|
||||
m_view.redraw();
|
||||
//m_tabView.redraw();
|
||||
}
|
||||
|
||||
View * TabViewController::view() {
|
||||
// We're asked for a view!
|
||||
// Let's populate our tabview
|
||||
setActiveTab(0);
|
||||
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
void TabViewController::handleKeyEvent(int key) {
|
||||
// Switch tabs!
|
||||
}
|
||||
|
||||
uint8_t TabViewController::numberOfTabs() {
|
||||
return m_numberOfChildren;
|
||||
}
|
||||
|
||||
const char * TabViewController::tabName(uint8_t index) {
|
||||
return m_children[index]->title();
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
#include <escher/text_view.h>
|
||||
|
||||
/*
|
||||
KDRect ViewFrame(const char * text) {
|
||||
KDRect r;
|
||||
r.origin = origin;
|
||||
r.size = KDStringSize(text);
|
||||
return r;
|
||||
TextView::TextView() : TextView(nullptr, 0.0f, 0.0f)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
TextView::TextView(const char * text) :
|
||||
ChildlessView() {
|
||||
TextView::TextView(const char * text, float horizontalAlignment, float verticalAlignment) :
|
||||
ChildlessView(),
|
||||
m_text(text),
|
||||
m_horizontalAlignment(horizontalAlignment),
|
||||
m_verticalAlignment(verticalAlignment)
|
||||
{
|
||||
}
|
||||
|
||||
void TextView::setText(const char * text) {
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
//TODO: implement "setFrame"
|
||||
|
||||
void TextView::drawRect(KDRect rect) {
|
||||
KDPoint zero = {0, 0};
|
||||
KDDrawString(m_text, zero, 0);
|
||||
KDSize textSize = KDStringSize(m_text);
|
||||
KDPoint origin = {
|
||||
(KDCoordinate)(m_horizontalAlignment*(bounds().width - textSize.width)),
|
||||
(KDCoordinate)(m_verticalAlignment*(bounds().height - textSize.height))
|
||||
};
|
||||
KDDrawString(m_text, origin, 0);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ void View::redraw(KDRect rect) {
|
||||
if (!isOnScreen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fisrt, let's draw our own content by calling drawRect
|
||||
KDSetDrawingArea(absoluteDrawingArea());
|
||||
this->drawRect(rect);
|
||||
@@ -54,14 +55,10 @@ void View::redraw(KDRect rect) {
|
||||
}
|
||||
}
|
||||
|
||||
void setSubview(View * v, int index);
|
||||
|
||||
|
||||
void View::setSubview(View * view, int index) {
|
||||
view->m_superview = this;
|
||||
storeSubviewAtIndex(view, index);
|
||||
assert(subview(index) == view);
|
||||
layoutSubviews();
|
||||
redraw();
|
||||
}
|
||||
|
||||
@@ -80,28 +77,37 @@ void View::addSubview(View * subview) {
|
||||
// That subview needs to be drawn
|
||||
subview->redraw();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void View::removeFromSuperview() {
|
||||
assert(m_superview != nullptr);
|
||||
// First, remove the view from its parent hierarchy
|
||||
assert(false); // FIXME: Unimplemented
|
||||
for (int i=0; i<m_superview->numberOfSubviews(); i++) {
|
||||
if (m_superview->subview(i) == this) {
|
||||
m_superview->storeSubviewAtIndex(nullptr, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Then, redraw the parent
|
||||
m_superview->redraw(m_frame);
|
||||
// Eventually clear the superview ivar
|
||||
m_superview = nullptr;
|
||||
}
|
||||
*/
|
||||
|
||||
void View::setFrame(KDRect frame) {
|
||||
// TODO: Return if frame is equal to m_frame
|
||||
KDRect previousFrame = m_frame;
|
||||
m_frame = frame;
|
||||
if (m_superview != nullptr) {
|
||||
/* We have moved this view. This left a blank spot in its superview were it
|
||||
* previously was. So let's redraw that part of the superview. */
|
||||
m_superview->redraw(previousFrame);
|
||||
}
|
||||
layoutSubviews();
|
||||
// The view now needs to redraw itself entirely
|
||||
redraw();
|
||||
// TODO: Return if frame is equal to m_frame
|
||||
KDRect previousFrame = m_frame;
|
||||
m_frame = frame;
|
||||
if (m_superview != nullptr) {
|
||||
/* We have moved this view. This left a blank spot in its superview were it
|
||||
* previously was. So let's redraw that part of the superview. */
|
||||
m_superview->redraw(previousFrame);
|
||||
}
|
||||
layoutSubviews();
|
||||
// The view now needs to redraw itself entirely
|
||||
redraw();
|
||||
}
|
||||
|
||||
KDRect View::bounds() {
|
||||
|
||||
Reference in New Issue
Block a user