From b4eb64ea76235aacd3d6eb69675e2f8799c560cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 7 Oct 2016 15:15:20 +0200 Subject: [PATCH] [apps/graph/values] add a controller of the table of values Change-Id: Ie294d85c3c31871372cf82ae9828382adb55d1ef --- apps/graph/Makefile | 1 + apps/graph/values/values_controller.cpp | 187 ++++++++++++++++++++++++ apps/graph/values/values_controller.h | 53 +++++++ 3 files changed, 241 insertions(+) create mode 100644 apps/graph/values/values_controller.cpp create mode 100644 apps/graph/values/values_controller.h diff --git a/apps/graph/Makefile b/apps/graph/Makefile index 9fff1ab1d..263d855d7 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -14,6 +14,7 @@ app_objs += $(addprefix apps/graph/,\ values/float_to_string.o\ values/title_cell.o\ values/value_cell.o\ + values/values_controller.o\ ) inline_images += apps/graph/graph_icon.png diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp new file mode 100644 index 000000000..9fc911c53 --- /dev/null +++ b/apps/graph/values/values_controller.cpp @@ -0,0 +1,187 @@ +#include "values_controller.h" +#include + +ValuesController::ValuesController(Responder * parentResponder, Graph::FunctionStore * functionStore) : + ViewController(parentResponder), + m_tableView(TableView(this, k_topMargin, 0, k_bottomMargin, 0)), + m_activeCellX(0), + m_activeCellY(-1), + m_functionStore(functionStore) +{ +} + +View * ValuesController::view() { + return &m_tableView; +} + +const char * ValuesController::title() const { + return "Valeurs"; +} + +Responder * ValuesController::tabController() const{ + return (parentResponder()->parentResponder()); +} + +int ValuesController::numberOfRows() { + return 4; +}; + +int ValuesController::numberOfColumns() { + return 1+m_functionStore->numberOfActiveFunctions(); +}; + +KDCoordinate ValuesController::rowHeight(int j) { + return k_cellHeight; +} + +KDCoordinate ValuesController::columnWidth(int i) { + switch (i) { + case 0: + return k_abscissaCellWidth; + default: + return k_ordinateCellWidth; + } +} + +KDCoordinate ValuesController::cumulatedWidthFromIndex(int i) { + if (i == 0) { + return 0; + } else { + return k_abscissaCellWidth + (i-1)*k_ordinateCellWidth; + } +} + +KDCoordinate ValuesController::cumulatedHeightFromIndex(int j) { + return j*k_cellHeight; +} + +int ValuesController::indexFromCumulatedWidth(KDCoordinate offsetX) { + if (offsetX <= k_abscissaCellWidth) { + return 0; + } else { + int index = 0; + while ((k_abscissaCellWidth+index*k_ordinateCellWidth) <= offsetX) { + index++; + } + return index; + } +} + +int ValuesController::indexFromCumulatedHeight(KDCoordinate offsetY) { + int index = 0; + while (index*k_cellHeight <= offsetY) { + index++; + } + return index-1; +} + +void ValuesController::setActiveCell(int i, int j) { + if (i < 0 || i >= numberOfColumns()) { + return; + } + if (j < -1 || j >= numberOfRows()) { + return; + } + + if (m_activeCellY >= 0) { + EvenOddCell * previousCell = (EvenOddCell *)(m_tableView.cellAtLocation(m_activeCellX, m_activeCellY)); + previousCell->setHighlighted(false); + } + + m_activeCellX = i; + m_activeCellY = j; + if (m_activeCellY >= 0) { + m_tableView.scrollToCell(i, j); + EvenOddCell * cell = (EvenOddCell *)(m_tableView.cellAtLocation(i, j)); + cell->setHighlighted(true); + } +} + +void ValuesController::didBecomeFirstResponder() { + if (m_activeCellY == -1) { + setActiveCell(0,0); + } else { + if (m_activeCellX < m_functionStore->numberOfActiveFunctions()) { + setActiveCell(m_activeCellX, m_activeCellY); + } else { + setActiveCell(m_functionStore->numberOfActiveFunctions(), m_activeCellY); + } + } +} + +bool ValuesController::handleEvent(Ion::Events::Event event) { + switch (event) { + case Ion::Events::Event::DOWN_ARROW: + setActiveCell(m_activeCellX, m_activeCellY+1); + return true; + case Ion::Events::Event::UP_ARROW: + setActiveCell(m_activeCellX, m_activeCellY-1); + if (m_activeCellY == -1) { + app()->setFirstResponder(tabController()); + } + return true; + case Ion::Events::Event::LEFT_ARROW: + setActiveCell(m_activeCellX-1, m_activeCellY); + return true; + case Ion::Events::Event::RIGHT_ARROW: + setActiveCell(m_activeCellX+1, m_activeCellY); + return true; + case Ion::Events::Event::ENTER: + return false; + default: + return false; + } +} + +int ValuesController::typeAtLocation(int i, int j) { + if (j == 0) { + return 0; + } else { + return 1; + } +} + +View * ValuesController::reusableCell(int index, int type) { + assert(index >= 0); + switch (type) { + case 0: + assert(index < k_maxNumberOfColumns); + return &m_titleCells[index]; + case 1: + assert(index < k_maxNumberOfCells); + return &m_floatCells[index]; + default: + assert(false); + break; + } +} + +int ValuesController::reusableCellCount(int type) { + switch (type) { + case 0: + return k_maxNumberOfColumns; + case 1: + return k_maxNumberOfCells; + default: + assert(false); + break; + } +} + +void ValuesController::willDisplayCellAtLocation(View * cell, int i, int j) { + if (j == 0) { + TitleCell * myCell = (TitleCell *)cell; + myCell->setEven(j%2 == 0); + if (i == 0) { + myCell->setText("x"); + } else { + Graph::Function * function = m_functionStore->activeFunctionAtIndex(i-1); + myCell->setText(function->name()); + } + } else { + ValueCell * myCell = (ValueCell *)cell; + myCell->setFloat(12.33f); + myCell->setEven(j%2 == 0); + } +} + diff --git a/apps/graph/values/values_controller.h b/apps/graph/values/values_controller.h new file mode 100644 index 000000000..014d2988c --- /dev/null +++ b/apps/graph/values/values_controller.h @@ -0,0 +1,53 @@ +#ifndef GRAPH_VALUES_CONTROLLER_H +#define GRAPH_VALUES_CONTROLLER_H + +#include +#include "../function_store.h" +#include "value_cell.h" +#include "title_cell.h" + +class ValuesController : public ViewController, public TableViewDataSource { +public: + ValuesController(Responder * parentResponder, Graph::FunctionStore * functionStore); + + void setActiveCell(int i, int j); + + View * view() override; + const char * title() const override; + bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; + + int numberOfRows() override; + int numberOfColumns() override; + void willDisplayCellAtLocation(View * cell, int i, int j) override; + KDCoordinate columnWidth(int i) override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedWidthFromIndex(int i) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedWidth(KDCoordinate offsetX) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + View * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; + + static constexpr KDCoordinate k_topMargin = 10; + static constexpr KDCoordinate k_bottomMargin = 5; + static constexpr KDCoordinate k_cellHeight = 30; + static constexpr KDCoordinate k_abscissaCellWidth = 150; + static constexpr KDCoordinate k_ordinateCellWidth = 100; + +private: + Responder * tabController() const; + constexpr static int k_maxNumberOfCells = 40; + constexpr static int k_maxNumberOfColumns = 5; + // !!! CAUTION: The order here is important + // The cells should be initialized *before* the TableView! + TitleCell m_titleCells[k_maxNumberOfColumns]; + ValueCell m_floatCells[k_maxNumberOfCells]; + TableView m_tableView; + int m_activeCellX; + int m_activeCellY; + Graph::FunctionStore * m_functionStore; +}; + +#endif