diff --git a/Makefile b/Makefile index 4e8011a04..72fcadf17 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ include ion/Makefile include kandinsky/Makefile include poincare/Makefile include escher/Makefile -include app/Makefile +include apps/Makefile include quiz/Makefile # Quiz should be included at the end %.elf: $(objs) diff --git a/app/escher_demo.cpp b/app/escher_demo.cpp deleted file mode 100644 index 5c1faae50..000000000 --- a/app/escher_demo.cpp +++ /dev/null @@ -1,376 +0,0 @@ -extern "C" { -#include -#include -#include -} -#include - -class MyFunCell : public ChildlessView, public Responder { -public: - MyFunCell(); - void setMessage(const char * message); - void setEven(bool even); - - void drawRect(KDRect rect) const override; - void setFocused(bool focused) override; -private: - const char * m_message; - bool m_focused; - bool m_even; -}; - -MyFunCell::MyFunCell() : - ChildlessView(), - m_focused(false), - m_even(false) -{ - m_message = "NULL"; -} - -void MyFunCell::drawRect(KDRect rect) const { - KDColor background = m_even ? KDColorRGB(0xEE, 0xEE, 0xEE) : KDColorRGB(0x77,0x77,0x77); - KDFillRect(rect, background); - KDDrawString(m_message, KDPointZero, m_focused); -} - -void MyFunCell::setMessage(const char * message) { - m_message = message; -} - -void MyFunCell::setFocused(bool focused) { - m_focused = focused; - markRectAsDirty(bounds()); -} - -void MyFunCell::setEven(bool even) { - m_even = even; -} - -class ListController : public ViewController, public TableViewDataSource { -public: - ListController(); - - void setActiveCell(int index); - - View * view() override; - const char * title() const override; - bool handleEvent(ion_event_t event) override; - - int numberOfCells() override; - void willDisplayCellForIndex(View * cell, int index) override; - KDCoordinate cellHeight() override; - View * reusableCell(int index) override; - int reusableCellCount() override; -private: - constexpr static int k_totalNumberOfModels = 20; - constexpr static int k_maxNumberOfCells = 10; - // !!! CAUTION: The order here is important - // The cells should be initialized *before* the tableview! - MyFunCell m_cells[k_maxNumberOfCells]; - TableView m_tableView; - const char ** m_messages; - int m_activeCell; - KDCoordinate m_manualScrolling; -}; - -static const char * sMessages[] = { - "AAA 0", "BBB 1", "CCC 2", "DDD 3", "EEE 4", - "FFF 5", "GGG 6", "HHH 7", "III 8", "JJJ 9", - "KKK10", "LLL11", "MMM12", "NNN13", "OOO14", - "PPP15", "QQQ16", "RRR17", "SSS18", "TTT19" -}; - -ListController::ListController() : - ViewController(), - m_tableView(TableView(this)), - m_activeCell(0), - m_manualScrolling(0) -{ - m_messages = sMessages; -} - -View * ListController::view() { - return &m_tableView; -} - -const char * ListController::title() const { - return "List"; -} - -void ListController::setActiveCell(int index) { - if (index < 0 || index >= k_totalNumberOfModels) { - return; - } - - m_activeCell = index; - m_tableView.scrollToRow(index); - MyFunCell * cell = (MyFunCell *)(m_tableView.cellAtIndex(index)); - cell->setParentResponder(this); - App::runningApp()->focus(cell); -} - -bool ListController::handleEvent(ion_event_t event) { - switch (event) { - case DOWN_ARROW: - setActiveCell(m_activeCell+1); - return true; - case UP_ARROW: - setActiveCell(m_activeCell-1); - return true; - case ENTER: - m_manualScrolling += 10; - m_tableView.setContentOffset({0, m_manualScrolling}); - return true; - default: - return false; - } -} - -int ListController::numberOfCells() { - return k_totalNumberOfModels; -}; - -View * ListController::reusableCell(int index) { - assert(index >= 0); - assert(index < k_maxNumberOfCells); - return &m_cells[index]; -} - -int ListController::reusableCellCount() { - return k_maxNumberOfCells; -} - -void ListController::willDisplayCellForIndex(View * cell, int index) { - MyFunCell * myCell = (MyFunCell *)cell; - myCell->setMessage(m_messages[index]); - myCell->setEven(index%2 == 0); -} - -KDCoordinate ListController::cellHeight() { - return 40; -} - -class CursorView : public ChildlessView { -public: - using ChildlessView::ChildlessView; - void drawRect(KDRect rect) const override; -}; - -void CursorView::drawRect(KDRect rect) const { - KDFillRect(rect, KDColorRed); -} - -class GraphView : public View { -public: - GraphView(); - void drawRect(KDRect rect) const override; - void moveCursorRight(); -private: - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - - CursorView m_cursorView; - KDPoint m_cursorPosition; -}; - -GraphView::GraphView() : - View(), - m_cursorView(CursorView()), - m_cursorPosition(KDPointZero) -{ -} - -int GraphView::numberOfSubviews() const { - return 1; -}; - -View * GraphView::subviewAtIndex(int index) { - return &m_cursorView; -} - -void GraphView::moveCursorRight() { - m_cursorPosition.x = m_cursorPosition.x + 2; - layoutSubviews(); -} - -void GraphView::layoutSubviews() { - KDRect cursorFrame; - cursorFrame.origin = m_cursorPosition; - cursorFrame.width = 10; - cursorFrame.height = 10; - m_cursorView.setFrame(cursorFrame); -} - -void GraphView::drawRect(KDRect rect) const { - KDFillRect(rect, KDColorWhite); - KDCoordinate x_grid_step = m_frame.width/10; - KDCoordinate y_grid_step = m_frame.height/10; - KDColor gridColor = KDColorGray(0xEE); - for (KDCoordinate x=m_frame.x; xfocus(&m_view); - } - */ -} - -bool GraphController::handleEvent(ion_event_t event) { - switch (event) { - case ENTER: - m_view.moveCursorRight(); - return true; - default: - return false; - } -} - -class MyTestApp : public App { -public: - MyTestApp(); -protected: - ViewController * rootViewController() override; -private: - GraphController m_graphViewController; - ListController m_listViewController; - TabViewController m_tabViewController; -}; - -MyTestApp::MyTestApp() : - App(), - m_graphViewController(GraphController(KDColorWhite)), - m_listViewController(ListController()), - m_tabViewController(&m_graphViewController, &m_listViewController) -{ -} - -ViewController * MyTestApp::rootViewController() { - return &m_tabViewController; -} - -void ion_app() { - - //KDDrawString("Hello", {0,0}, 0); - - //KDFillRect({0,0,100,100}, 0x55); - //KDFillRect({100,100,100,100}, 0x99); - - /* - KDCoordinate i = 0; - char message[4] = {'F', 'O', 'O', 0}; - while (1) { - KDPoint p = {i, i}; - KDDrawString(message, p, false); - ion_event_t event = ion_get_event(); - if (event < 0x100) { - message[1] = event; - } - i+= 1; - } - */ - - MyTestApp myApp = MyTestApp(); - - myApp.run(); - - /* - int i = 0; - - while(true) { -#if ESCHER_VIEW_LOGGING - std::cout << window << std::endl; -#endif - 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); - KDRect textRect = {0, 0, 50, 50}; - MyTextView * textView = new MyTextView(textRect); - window->addSubview(textView); - - //window->draw(); - - while (1) { - ion_sleep(); - textRect.y = textRect.y+1; - textView->setFrame(textRect); - } - - delete textView; - delete window; - */ -} diff --git a/apps/Makefile b/apps/Makefile new file mode 100644 index 000000000..c781b4af3 --- /dev/null +++ b/apps/Makefile @@ -0,0 +1,9 @@ +include apps/graph/Makefile + +app_objs += $(addprefix apps/,\ + main.o\ +) + +products += $(app_objs) app.elf app.hex app.bin + +app.elf: $(app_objs) diff --git a/apps/graph/Makefile b/apps/graph/Makefile new file mode 100644 index 000000000..bf9d160de --- /dev/null +++ b/apps/graph/Makefile @@ -0,0 +1,8 @@ +app_objs += $(addprefix apps/graph/,\ + graph_app.o\ + graph/cursor_view.o\ + graph/graph_controller.o\ + graph/graph_view.o\ + list/function_cell.o\ + list/list_controller.o\ +) diff --git a/apps/graph/graph/cursor_view.cpp b/apps/graph/graph/cursor_view.cpp new file mode 100644 index 000000000..f635c3185 --- /dev/null +++ b/apps/graph/graph/cursor_view.cpp @@ -0,0 +1,5 @@ +#include "cursor_view.h" + +void CursorView::drawRect(KDRect rect) const { + KDFillRect(rect, KDColorRed); +} diff --git a/apps/graph/graph/cursor_view.h b/apps/graph/graph/cursor_view.h new file mode 100644 index 000000000..2acd60934 --- /dev/null +++ b/apps/graph/graph/cursor_view.h @@ -0,0 +1,12 @@ +#ifndef GRAPH_CURSOR_VIEW_H +#define GRAPH_CURSOR_VIEW_H + +#include + +class CursorView : public ChildlessView { +public: + using ChildlessView::ChildlessView; + void drawRect(KDRect rect) const override; +}; + +#endif diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp new file mode 100644 index 000000000..0788ee909 --- /dev/null +++ b/apps/graph/graph/graph_controller.cpp @@ -0,0 +1,36 @@ +#include "graph_controller.h" + +GraphController::GraphController(KDColor c) : + ViewController(), + //m_view(TextField(buffer, k_bufferSize)) + //m_view(SolidColorView(c)) + m_view(GraphView()) +{ + //m_view.setParentResponder(this); +} + +View * GraphController::view() { + return &m_view; +} + +const char * GraphController::title() const { + return "Graph"; +} + +void GraphController::setFocused(bool focused) { + /* + if (focused) { + App::runningApp()->focus(&m_view); + } + */ +} + +bool GraphController::handleEvent(ion_event_t event) { + switch (event) { + case ENTER: + m_view.moveCursorRight(); + return true; + default: + return false; + } +} diff --git a/apps/graph/graph/graph_controller.h b/apps/graph/graph/graph_controller.h new file mode 100644 index 000000000..3456b23e2 --- /dev/null +++ b/apps/graph/graph/graph_controller.h @@ -0,0 +1,18 @@ +#ifndef GRAPH_GRAPH_CONTROLLER_H +#define GRAPH_GRAPH_CONTROLLER_H + +#include +#include "graph_view.h" + +class GraphController : public ViewController { +public: + GraphController(KDColor c); + View * view() override; + const char * title() const override; + void setFocused(bool focused) override; + bool handleEvent(ion_event_t event) override; +private: + GraphView m_view; +}; + +#endif diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp new file mode 100644 index 000000000..818013218 --- /dev/null +++ b/apps/graph/graph/graph_view.cpp @@ -0,0 +1,58 @@ +#include "graph_view.h" + +GraphView::GraphView() : + View(), + m_cursorView(CursorView()), + m_cursorPosition(KDPointZero) +{ +} + +int GraphView::numberOfSubviews() const { + return 1; +}; + +View * GraphView::subviewAtIndex(int index) { + return &m_cursorView; +} + +void GraphView::moveCursorRight() { + m_cursorPosition.x = m_cursorPosition.x + 2; + layoutSubviews(); +} + +void GraphView::layoutSubviews() { + KDRect cursorFrame; + cursorFrame.origin = m_cursorPosition; + cursorFrame.width = 10; + cursorFrame.height = 10; + m_cursorView.setFrame(cursorFrame); +} + +void GraphView::drawRect(KDRect rect) const { + KDFillRect(rect, KDColorWhite); + KDCoordinate x_grid_step = m_frame.width/10; + KDCoordinate y_grid_step = m_frame.height/10; + KDColor gridColor = KDColorGray(0xEE); + for (KDCoordinate x=0; x +#include "cursor_view.h" + +class GraphView : public View { +public: + GraphView(); + void drawRect(KDRect rect) const override; + void moveCursorRight(); +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + + CursorView m_cursorView; + KDPoint m_cursorPosition; +}; + +#endif diff --git a/apps/graph/graph_app.cpp b/apps/graph/graph_app.cpp new file mode 100644 index 000000000..607a2030b --- /dev/null +++ b/apps/graph/graph_app.cpp @@ -0,0 +1,13 @@ +#include "graph_app.h" + +GraphApp::GraphApp() : + App(), + m_graphViewController(GraphController(KDColorWhite)), + m_listViewController(ListController()), + m_tabViewController(&m_graphViewController, &m_listViewController) +{ +} + +ViewController * GraphApp::rootViewController() { + return &m_tabViewController; +} diff --git a/apps/graph/graph_app.h b/apps/graph/graph_app.h new file mode 100644 index 000000000..b7c2e5e9b --- /dev/null +++ b/apps/graph/graph_app.h @@ -0,0 +1,19 @@ +#ifndef GRAPH_GRAPH_APP_H +#define GRAPH_GRAPH_APP_H + +#include +#include "graph/graph_controller.h" +#include "list/list_controller.h" + +class GraphApp : public App { +public: + GraphApp(); +protected: + ViewController * rootViewController() override; +private: + GraphController m_graphViewController; + ListController m_listViewController; + TabViewController m_tabViewController; +}; + +#endif diff --git a/apps/graph/list/function_cell.cpp b/apps/graph/list/function_cell.cpp new file mode 100644 index 000000000..a602ba137 --- /dev/null +++ b/apps/graph/list/function_cell.cpp @@ -0,0 +1,28 @@ +#include "function_cell.h" + +FunctionCell::FunctionCell() : + ChildlessView(), + m_focused(false), + m_even(false) +{ + m_message = "NULL"; +} + +void FunctionCell::drawRect(KDRect rect) const { + KDColor background = m_even ? KDColorRGB(0xEE, 0xEE, 0xEE) : KDColorRGB(0x77,0x77,0x77); + KDFillRect(rect, background); + KDDrawString(m_message, KDPointZero, m_focused); +} + +void FunctionCell::setMessage(const char * message) { + m_message = message; +} + +void FunctionCell::setFocused(bool focused) { + m_focused = focused; + markRectAsDirty(bounds()); +} + +void FunctionCell::setEven(bool even) { + m_even = even; +} diff --git a/apps/graph/list/function_cell.h b/apps/graph/list/function_cell.h new file mode 100644 index 000000000..51251ad5d --- /dev/null +++ b/apps/graph/list/function_cell.h @@ -0,0 +1,20 @@ +#ifndef GRAPH_FUNCTION_CELL_H +#define GRAPH_FUNCTION_CELL_H + +#include + +class FunctionCell : public ChildlessView, public Responder { +public: + FunctionCell(); + void setMessage(const char * message); + void setEven(bool even); + + void drawRect(KDRect rect) const override; + void setFocused(bool focused) override; +private: + const char * m_message; + bool m_focused; + bool m_even; +}; + +#endif diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp new file mode 100644 index 000000000..c037bb72e --- /dev/null +++ b/apps/graph/list/list_controller.cpp @@ -0,0 +1,79 @@ +#include "list_controller.h" +#include + +static const char * sMessages[] = { + "AAA 0", "BBB 1", "CCC 2", "DDD 3", "EEE 4", + "FFF 5", "GGG 6", "HHH 7", "III 8", "JJJ 9", + "KKK10", "LLL11", "MMM12", "NNN13", "OOO14", + "PPP15", "QQQ16", "RRR17", "SSS18", "TTT19" +}; + +ListController::ListController() : + ViewController(), + m_tableView(TableView(this)), + m_activeCell(0), + m_manualScrolling(0) +{ + m_messages = sMessages; +} + +View * ListController::view() { + return &m_tableView; +} + +const char * ListController::title() const { + return "List"; +} + +void ListController::setActiveCell(int index) { + if (index < 0 || index >= k_totalNumberOfModels) { + return; + } + + m_activeCell = index; + m_tableView.scrollToRow(index); + FunctionCell * cell = (FunctionCell *)(m_tableView.cellAtIndex(index)); + cell->setParentResponder(this); + App::runningApp()->focus(cell); +} + +bool ListController::handleEvent(ion_event_t event) { + switch (event) { + case DOWN_ARROW: + setActiveCell(m_activeCell+1); + return true; + case UP_ARROW: + setActiveCell(m_activeCell-1); + return true; + case ENTER: + m_manualScrolling += 10; + m_tableView.setContentOffset({0, m_manualScrolling}); + return true; + default: + return false; + } +} + +int ListController::numberOfCells() { + return k_totalNumberOfModels; +}; + +View * ListController::reusableCell(int index) { + assert(index >= 0); + assert(index < k_maxNumberOfCells); + return &m_cells[index]; +} + +int ListController::reusableCellCount() { + return k_maxNumberOfCells; +} + +void ListController::willDisplayCellForIndex(View * cell, int index) { + FunctionCell * myCell = (FunctionCell *)cell; + myCell->setMessage(m_messages[index]); + myCell->setEven(index%2 == 0); +} + +KDCoordinate ListController::cellHeight() { + return 40; +} diff --git a/apps/graph/list/list_controller.h b/apps/graph/list/list_controller.h new file mode 100644 index 000000000..770013a4d --- /dev/null +++ b/apps/graph/list/list_controller.h @@ -0,0 +1,34 @@ +#ifndef GRAPH_LIST_CONTROLLER_H +#define GRAPH_LIST_CONTROLLER_H + +#include +#include "function_cell.h" + +class ListController : public ViewController, public TableViewDataSource { +public: + ListController(); + + void setActiveCell(int index); + + View * view() override; + const char * title() const override; + bool handleEvent(ion_event_t event) override; + + int numberOfCells() override; + void willDisplayCellForIndex(View * cell, int index) override; + KDCoordinate cellHeight() override; + View * reusableCell(int index) override; + int reusableCellCount() override; +private: + constexpr static int k_totalNumberOfModels = 20; + constexpr static int k_maxNumberOfCells = 10; + // !!! CAUTION: The order here is important + // The cells should be initialized *before* the tableview! + FunctionCell m_cells[k_maxNumberOfCells]; + TableView m_tableView; + const char ** m_messages; + int m_activeCell; + KDCoordinate m_manualScrolling; +}; + +#endif diff --git a/apps/main.cpp b/apps/main.cpp new file mode 100644 index 000000000..07b779451 --- /dev/null +++ b/apps/main.cpp @@ -0,0 +1,6 @@ +#include "graph/graph_app.h" + +void ion_app() { + GraphApp graphApp = GraphApp(); + graphApp.run(); +}