Escher: TabViewController is working!

Change-Id: I4aa730abbf1d7034d2fcbc40416dcb84076a347b
This commit is contained in:
Romain Goyet
2016-05-26 11:33:42 +02:00
parent b79b7b5133
commit 095901a7ca
12 changed files with 278 additions and 72 deletions

View File

@@ -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;
*/
}

View File

@@ -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\

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View 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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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() {