From 095901a7ca2032f7fe2c7da111134873163ad8ec Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 26 May 2016 11:33:42 +0200 Subject: [PATCH] Escher: TabViewController is working! Change-Id: I4aa730abbf1d7034d2fcbc40416dcb84076a347b --- app/escher_demo.cpp | 108 +++++++++++++++++++- escher/Makefile | 1 + escher/include/escher/tab_view.h | 16 ++- escher/include/escher/tab_view_cell.h | 10 +- escher/include/escher/tab_view_controller.h | 8 +- escher/include/escher/text_view.h | 11 +- escher/include/escher/view.h | 2 +- escher/src/tab_view.cpp | 51 ++++++--- escher/src/tab_view_cell.cpp | 25 +++++ escher/src/tab_view_controller.cpp | 50 +++++++-- escher/src/text_view.cpp | 30 +++--- escher/src/view.cpp | 38 ++++--- 12 files changed, 278 insertions(+), 72 deletions(-) create mode 100644 escher/src/tab_view_cell.cpp diff --git a/app/escher_demo.cpp b/app/escher_demo.cpp index a751ceec9..acb80b8eb 100644 --- a/app/escher_demo.cpp +++ b/app/escher_demo.cpp @@ -5,6 +5,55 @@ extern "C" { #include } +/* +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; + */ } diff --git a/escher/Makefile b/escher/Makefile index 2612e54a7..a0aef571b 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -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\ diff --git a/escher/include/escher/tab_view.h b/escher/include/escher/tab_view.h index 4ca991ee2..ce37a7e89 100644 --- a/escher/include/escher/tab_view.h +++ b/escher/include/escher/tab_view.h @@ -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 diff --git a/escher/include/escher/tab_view_cell.h b/escher/include/escher/tab_view_cell.h index 3ec4f276d..0eb2195ad 100644 --- a/escher/include/escher/tab_view_cell.h +++ b/escher/include/escher/tab_view_cell.h @@ -4,15 +4,15 @@ #include #include -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 diff --git a/escher/include/escher/tab_view_controller.h b/escher/include/escher/tab_view_controller.h index b386fb5a7..b5d137e48 100644 --- a/escher/include/escher/tab_view_controller.h +++ b/escher/include/escher/tab_view_controller.h @@ -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; }; diff --git a/escher/include/escher/text_view.h b/escher/include/escher/text_view.h index c3ab092de..319739711 100644 --- a/escher/include/escher/text_view.h +++ b/escher/include/escher/text_view.h @@ -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 diff --git a/escher/include/escher/view.h b/escher/include/escher/view.h index fa05f0b85..0ce25ba2a 100644 --- a/escher/include/escher/view.h +++ b/escher/include/escher/view.h @@ -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; diff --git a/escher/src/tab_view.cpp b/escher/src/tab_view.cpp index 50232bc2a..880c808e5 100644 --- a/escher/src/tab_view.cpp +++ b/escher/src/tab_view.cpp @@ -1,31 +1,58 @@ #include #include +extern "C" { +#include +} -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 +extern "C" { +#include +} + +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); +} diff --git a/escher/src/tab_view_controller.cpp b/escher/src/tab_view_controller.cpp index 2a9ae3d68..7fc12c391 100644 --- a/escher/src/tab_view_controller.cpp +++ b/escher/src/tab_view_controller.cpp @@ -3,20 +3,33 @@ extern "C" { } #include -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; ititle()); + } } 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(); +} diff --git a/escher/src/text_view.cpp b/escher/src/text_view.cpp index 2f53ae9df..ccc17b710 100644 --- a/escher/src/text_view.cpp +++ b/escher/src/text_view.cpp @@ -1,22 +1,26 @@ #include -/* -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); } diff --git a/escher/src/view.cpp b/escher/src/view.cpp index a39de593b..076f22b58 100644 --- a/escher/src/view.cpp +++ b/escher/src/view.cpp @@ -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; inumberOfSubviews(); 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() {