diff --git a/apps/Makefile b/apps/Makefile index 7bcd54eec..b4b710f87 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -36,11 +36,9 @@ app_objs += $(addprefix apps/,\ lock_view.o\ main.o\ math_toolbox.o\ - node.o\ shift_alpha_lock_view.o\ suspend_timer.o\ title_bar_view.o\ - toolbox_node.o\ usb_timer.o\ variable_box_controller.o\ variable_box_leaf_cell.o\ diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 53fa83839..54a59591f 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -7,270 +7,69 @@ * and the text which would be edited by clicking on the row. When the node is a * subtree, the edited text is set at I18n::Message::Default. */ -const ToolboxNode calculChildren[4] = {ToolboxNode(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommand), ToolboxNode(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommand), ToolboxNode(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommand), ToolboxNode(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommand)}; -const ToolboxNode complexChildren[5] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommand), ToolboxNode(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommand), ToolboxNode(I18n::Message::ReCommandWithArg, I18n::Message::RealPart, I18n::Message::ReCommand), ToolboxNode(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommand), ToolboxNode(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommand)}; -const ToolboxNode probabilityChildren[2] = {ToolboxNode(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommand), ToolboxNode(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommand)}; -const ToolboxNode arithmeticChildren[4] = {ToolboxNode(I18n::Message::GcdCommandWithArg, I18n::Message::GreatCommonDivisor, I18n::Message::GcdCommand),ToolboxNode(I18n::Message::LcmCommandWithArg, I18n::Message::LeastCommonMultiple, I18n::Message::LcmCommand), ToolboxNode(I18n::Message::RemCommandWithArg, I18n::Message::Remainder, I18n::Message::RemCommand), ToolboxNode(I18n::Message::QuoCommandWithArg, I18n::Message::Quotient, I18n::Message::QuoCommand)}; +const ToolboxMessageTree calculChildren[4] = {ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommand), ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommand), ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommand), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommand)}; +const ToolboxMessageTree complexChildren[5] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommand), ToolboxMessageTree(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommand), ToolboxMessageTree(I18n::Message::ReCommandWithArg, I18n::Message::RealPart, I18n::Message::ReCommand), ToolboxMessageTree(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommand), ToolboxMessageTree(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommand)}; +const ToolboxMessageTree probabilityChildren[2] = {ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommand), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommand)}; +const ToolboxMessageTree arithmeticChildren[4] = {ToolboxMessageTree(I18n::Message::GcdCommandWithArg, I18n::Message::GreatCommonDivisor, I18n::Message::GcdCommand),ToolboxMessageTree(I18n::Message::LcmCommandWithArg, I18n::Message::LeastCommonMultiple, I18n::Message::LcmCommand), ToolboxMessageTree(I18n::Message::RemCommandWithArg, I18n::Message::Remainder, I18n::Message::RemCommand), ToolboxMessageTree(I18n::Message::QuoCommandWithArg, I18n::Message::Quotient, I18n::Message::QuoCommand)}; #if MATRICES_ARE_DEFINED -const ToolboxNode matricesChildren[5] = {ToolboxNode(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse, I18n::Message::InverseCommand), ToolboxNode(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant, I18n::Message::DeterminantCommand), ToolboxNode(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose, I18n::Message::TransposeCommand), ToolboxNode(I18n::Message::TraceCommandWithArg, I18n::Message::Trace, I18n::Message::TraceCommand), ToolboxNode(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension, I18n::Message::DimensionCommand)}; +const ToolboxMessageTree matricesChildren[5] = {ToolboxMessageTree(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse, I18n::Message::InverseCommand), ToolboxMessageTree(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant, I18n::Message::DeterminantCommand), ToolboxMessageTree(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose, I18n::Message::TransposeCommand), ToolboxMessageTree(I18n::Message::TraceCommandWithArg, I18n::Message::Trace, I18n::Message::TraceCommand), ToolboxMessageTree(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension, I18n::Message::DimensionCommand)}; #endif #if LIST_ARE_DEFINED -const ToolboxNode listesChildren[5] = {ToolboxNode(I18n::Message::SortCommandWithArg, I18n::Message::Sort, I18n::Message::SortCommand), ToolboxNode(I18n::Message::InvSortCommandWithArg, I18n::Message::InvSort, I18n::Message::InvSortCommand), ToolboxNode(I18n::Message::MaxCommandWithArg, I18n::Message::Maximum, I18n::Message::MaxCommand), ToolboxNode(I18n::Message::MinCommandWithArg, I18n::Message::Minimum, I18n::Message::MinCommand), ToolboxNode(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension, I18n::Message::DimensionCommand)}; +const ToolboxMessageTree listesChildren[5] = {ToolboxMessageTree(I18n::Message::SortCommandWithArg, I18n::Message::Sort, I18n::Message::SortCommand), ToolboxMessageTree(I18n::Message::InvSortCommandWithArg, I18n::Message::InvSort, I18n::Message::InvSortCommand), ToolboxMessageTree(I18n::Message::MaxCommandWithArg, I18n::Message::Maximum, I18n::Message::MaxCommand), ToolboxMessageTree(I18n::Message::MinCommandWithArg, I18n::Message::Minimum, I18n::Message::MinCommand), ToolboxMessageTree(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension, I18n::Message::DimensionCommand)}; #endif -const ToolboxNode approximationChildren[4] = {ToolboxNode(I18n::Message::FloorCommandWithArg, I18n::Message::Floor, I18n::Message::FloorCommand), ToolboxNode(I18n::Message::FracCommandWithArg, I18n::Message::FracPart, I18n::Message::FracCommand), ToolboxNode(I18n::Message::CeilCommandWithArg, I18n::Message::Ceiling, I18n::Message::CeilCommand), ToolboxNode(I18n::Message::RoundCommandWithArg, I18n::Message::Rounding, I18n::Message::RoundCommand)}; -const ToolboxNode trigonometryChildren[6] = {ToolboxNode(I18n::Message::CoshCommandWithArg, I18n::Message::HyperbolicCosine, I18n::Message::CoshCommand), ToolboxNode(I18n::Message::SinhCommandWithArg, I18n::Message::HyperbolicSine, I18n::Message::SinhCommand), ToolboxNode(I18n::Message::TanhCommandWithArg, I18n::Message::HyperbolicTangent, I18n::Message::TanhCommand), ToolboxNode(I18n::Message::AcoshCommandWithArg, I18n::Message::InverseHyperbolicCosine, I18n::Message::AcoshCommand), ToolboxNode(I18n::Message::AsinhCommandWithArg, I18n::Message::InverseHyperbolicSine, I18n::Message::AsinhCommand), ToolboxNode(I18n::Message::AtanhCommandWithArg, I18n::Message::InverseHyperbolicTangent, I18n::Message::AtanhCommand)}; -const ToolboxNode predictionChildren[3] = {ToolboxNode(I18n::Message::Prediction95CommandWithArg, I18n::Message::Prediction95, I18n::Message::Prediction95Command), ToolboxNode(I18n::Message::PredictionCommandWithArg, I18n::Message::Prediction, I18n::Message::PredictionCommand), ToolboxNode(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommand)}; +const ToolboxMessageTree approximationChildren[4] = {ToolboxMessageTree(I18n::Message::FloorCommandWithArg, I18n::Message::Floor, I18n::Message::FloorCommand), ToolboxMessageTree(I18n::Message::FracCommandWithArg, I18n::Message::FracPart, I18n::Message::FracCommand), ToolboxMessageTree(I18n::Message::CeilCommandWithArg, I18n::Message::Ceiling, I18n::Message::CeilCommand), ToolboxMessageTree(I18n::Message::RoundCommandWithArg, I18n::Message::Rounding, I18n::Message::RoundCommand)}; +const ToolboxMessageTree trigonometryChildren[6] = {ToolboxMessageTree(I18n::Message::CoshCommandWithArg, I18n::Message::HyperbolicCosine, I18n::Message::CoshCommand), ToolboxMessageTree(I18n::Message::SinhCommandWithArg, I18n::Message::HyperbolicSine, I18n::Message::SinhCommand), ToolboxMessageTree(I18n::Message::TanhCommandWithArg, I18n::Message::HyperbolicTangent, I18n::Message::TanhCommand), ToolboxMessageTree(I18n::Message::AcoshCommandWithArg, I18n::Message::InverseHyperbolicCosine, I18n::Message::AcoshCommand), ToolboxMessageTree(I18n::Message::AsinhCommandWithArg, I18n::Message::InverseHyperbolicSine, I18n::Message::AsinhCommand), ToolboxMessageTree(I18n::Message::AtanhCommandWithArg, I18n::Message::InverseHyperbolicTangent, I18n::Message::AtanhCommand)}; +const ToolboxMessageTree predictionChildren[3] = {ToolboxMessageTree(I18n::Message::Prediction95CommandWithArg, I18n::Message::Prediction95, I18n::Message::Prediction95Command), ToolboxMessageTree(I18n::Message::PredictionCommandWithArg, I18n::Message::Prediction, I18n::Message::PredictionCommand), ToolboxMessageTree(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommand)}; #if LIST_ARE_DEFINED -const ToolboxNode menu[12] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), +const ToolboxMessageTree menu[12] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), #elif MATRICES_ARE_DEFINED -const ToolboxNode menu[11] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), +const ToolboxMessageTree menu[11] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), #else -const ToolboxNode menu[10] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), +const ToolboxMessageTree menu[10] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommand), #endif - ToolboxNode(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommand), - ToolboxNode(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommand), - ToolboxNode(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), - ToolboxNode(I18n::Message::ComplexNumber, I18n::Message::Default, I18n::Message::Default, complexChildren, 5), - ToolboxNode(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), - ToolboxNode(I18n::Message::Arithmetic, I18n::Message::Default, I18n::Message::Default, arithmeticChildren, 4), + ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommand), + ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommand), + ToolboxMessageTree(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), + ToolboxMessageTree(I18n::Message::ComplexNumber, I18n::Message::Default, I18n::Message::Default, complexChildren, 5), + ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), + ToolboxMessageTree(I18n::Message::Arithmetic, I18n::Message::Default, I18n::Message::Default, arithmeticChildren, 4), #if MATRICES_ARE_DEFINED - ToolboxNode(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 5), + ToolboxMessageTree(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 5), #endif #if LIST_ARE_DEFINED - ToolboxNode(I18n::Message::Lists, I18n::Message::Default, I18n::Message::Default, listesChildren, 5), + ToolboxMessageTree(I18n::Message::Lists, I18n::Message::Default, I18n::Message::Default, listesChildren, 5), #endif - ToolboxNode(I18n::Message::Approximation, I18n::Message::Default, I18n::Message::Default, approximationChildren, 4), - ToolboxNode(I18n::Message::HyperbolicTrigonometry, I18n::Message::Default, I18n::Message::Default, trigonometryChildren, 6), - ToolboxNode(I18n::Message::Fluctuation, I18n::Message::Default, I18n::Message::Default, predictionChildren, 3)}; + ToolboxMessageTree(I18n::Message::Approximation, I18n::Message::Default, I18n::Message::Default, approximationChildren, 4), + ToolboxMessageTree(I18n::Message::HyperbolicTrigonometry, I18n::Message::Default, I18n::Message::Default, trigonometryChildren, 6), + ToolboxMessageTree(I18n::Message::Fluctuation, I18n::Message::Default, I18n::Message::Default, predictionChildren, 3)}; #if LIST_ARE_DEFINED -const ToolboxNode toolboxModel = ToolboxNode(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 12); +const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 12); #elif MATRICES_ARE_DEFINED -const ToolboxNode toolboxModel = ToolboxNode(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 11); +const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 11); #else -const ToolboxNode toolboxModel = ToolboxNode(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 10); +const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 10); #endif -/* State */ - -MathToolbox::Stack::State::State(int selectedRow, KDCoordinate verticalScroll) : - m_selectedRow(selectedRow), - m_verticalScroll(verticalScroll) +MathToolbox::MathToolbox() : Toolbox(nullptr, I18n::translate(rootModel()->label())) { } -int MathToolbox::Stack::State::selectedRow() { - return m_selectedRow; -} - -KDCoordinate MathToolbox::Stack::State::verticalScroll() { - return m_verticalScroll; -} - -bool MathToolbox::Stack::State::isNull(){ - if (m_selectedRow == -1) { - return true; - } - return false; -} - -/* Stack */ - -void MathToolbox::Stack::push(int selectedRow, KDCoordinate verticalScroll) { - int i = 0; - while (!m_statesStack[i].isNull() && i < k_maxModelTreeDepth) { - i++; - } - assert(m_statesStack[i].isNull()); - m_statesStack[i] = State(selectedRow, verticalScroll); -} - -MathToolbox::Stack::State * MathToolbox::Stack::stateAtIndex(int index) { - return &m_statesStack[index]; -} - -int MathToolbox::Stack::depth() { - int depth = 0; - for (int i = 0; i < k_maxModelTreeDepth; i++) { - depth += (!m_statesStack[i].isNull()); - } - return depth; -} - -void MathToolbox::Stack::pop() { - int stackDepth = depth(); - if (stackDepth == 0) { - return; - } - m_statesStack[stackDepth-1] = State(); -} - -void MathToolbox::Stack::resetStack() { - for (int i = 0; i < k_maxModelTreeDepth; i++) { - m_statesStack[i] = State(); - } -} - -/* List Controller */ - -MathToolbox::ListController::ListController(Responder * parentResponder, SelectableTableView * tableView) : - ViewController(parentResponder), - m_selectableTableView(tableView), - m_firstSelectedRow(0) -{ -} - -View * MathToolbox::ListController::view() { - return m_selectableTableView; -} - -const char * MathToolbox::ListController::title() { - return I18n::translate(toolboxModel.label()); -} - -void MathToolbox::ListController::didBecomeFirstResponder() { - m_selectableTableView->reloadData(); - m_selectableTableView->selectCellAtLocation(0, m_firstSelectedRow); - app()->setFirstResponder(m_selectableTableView); -} - -void MathToolbox::ListController::setFirstSelectedRow(int firstSelectedRow) { - m_firstSelectedRow = firstSelectedRow; -} - -/* MathToolbox */ - -MathToolbox::MathToolbox() : - Toolbox(nullptr, &m_listController), - m_selectableTableView(&m_listController, this, 0, 1, 0, 0, 0, 0, this, nullptr, false), - m_listController(this, &m_selectableTableView), - m_nodeModel(nullptr) -{ -} - -void MathToolbox::didBecomeFirstResponder() { - app()->setFirstResponder(&m_listController); -} - -bool MathToolbox::handleEvent(Ion::Events::Event event) { - return handleEventForRow(event, selectedRow()); -} - -int MathToolbox::numberOfRows() { - if (m_nodeModel == nullptr) { - m_nodeModel = (ToolboxNode *)rootModel(); - } - return m_nodeModel->numberOfChildren(); -} - -HighlightCell * MathToolbox::reusableCell(int index, int type) { - assert(type < 2); - assert(index >= 0); - assert(index < k_maxNumberOfDisplayedRows); - if (type == 0) { - return &m_leafCells[index]; - } - return &m_nodeCells[index]; -} - -int MathToolbox::reusableCellCount(int type) { - return k_maxNumberOfDisplayedRows; -} - -void MathToolbox::willDisplayCellForIndex(HighlightCell * cell, int index) { - ToolboxNode * node = (ToolboxNode *)m_nodeModel->children(index); - if (node->numberOfChildren() == 0) { - MessageTableCellWithMessage * myCell = (MessageTableCellWithMessage *)cell; - myCell->setMessage(node->label()); - myCell->setAccessoryMessage(node->text()); - myCell->setAccessoryTextColor(Palette::GreyDark); - return; - } - MessageTableCell * myCell = (MessageTableCell *)cell; - myCell->setMessage(node->label()); -} - KDCoordinate MathToolbox::rowHeight(int j) { - if (typeAtLocation(0, j) == 0) { + if (typeAtLocation(0, j) == Toolbox::LeafCellType) { return k_leafRowHeight; } return k_nodeRowHeight; } -KDCoordinate MathToolbox::cumulatedHeightFromIndex(int j) { - int result = 0; - for (int k = 0; k < j; k++) { - result += rowHeight(k); - } - return result; -} - -int MathToolbox::indexFromCumulatedHeight(KDCoordinate offsetY) { - int result = 0; - int j = 0; - while (result < offsetY && j < numberOfRows()) { - result += rowHeight(j++); - } - return (result < offsetY || offsetY == 0) ? j : j - 1; -} - -int MathToolbox::typeAtLocation(int i, int j) { - Node * node = (Node *)m_nodeModel->children(j); - if (node->numberOfChildren() == 0) { - return 0; - } - return 1; -} - -void MathToolbox::viewWillAppear() { - Toolbox::viewWillAppear(); - m_nodeModel = (ToolboxNode *)rootModel(); - m_selectableTableView.reloadData(); - m_stack.resetStack(); - m_listController.setFirstSelectedRow(0); -} - -void MathToolbox::viewDidDisappear() { - Toolbox::viewDidDisappear(); - m_selectableTableView.deselectTable(); -} - -int MathToolbox::stackDepth() { - return m_stack.depth(); -} - TextField * MathToolbox::sender() { return (TextField *)Toolbox::sender(); } -bool MathToolbox::handleEventForRow(Ion::Events::Event event, int selectedRow) { - int depth = m_stack.depth(); - if (event == Ion::Events::Back && depth == 0) { - m_selectableTableView.deselectTable(); - app()->dismissModalViewController(); - return true; - } - if ((event == Ion::Events::Back || event == Ion::Events::Left) && depth > 0) { - return returnToPreviousMenu(); - } - ToolboxNode * selectedNode = (ToolboxNode *)m_nodeModel->children(selectedRow); - if ((event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) && selectedNode->numberOfChildren() > 0) { - return selectSubMenu(selectedNode); - } - if ((event == Ion::Events::OK || event == Ion::Events::EXE) && selectedNode->numberOfChildren() == 0) { - return selectLeaf(selectedNode); - } - return false; -} - -const ToolboxNode * MathToolbox::rootModel() { - return &toolboxModel; -} - -bool MathToolbox::selectLeaf(ToolboxNode * selectedNode){ +bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { m_selectableTableView.deselectTable(); - ToolboxNode * node = selectedNode; - const char * editedText = I18n::translate(node->insertedText()); + ToolboxMessageTree * messageTree = selectedMessageTree; + const char * editedText = I18n::translate(messageTree->insertedText()); if (!sender()->isEditing()) { sender()->setEditing(true); } @@ -288,31 +87,20 @@ bool MathToolbox::selectLeaf(ToolboxNode * selectedNode){ return true; } -bool MathToolbox::returnToPreviousMenu() { - m_selectableTableView.deselectTable(); - int depth = m_stack.depth(); - int index = 0; - ToolboxNode * parentNode = (ToolboxNode *)rootModel(); - Stack::State * previousState = m_stack.stateAtIndex(index++);; - while (depth-- > 1) { - parentNode = (ToolboxNode *)parentNode->children(previousState->selectedRow()); - previousState = m_stack.stateAtIndex(index++); - } - m_selectableTableView.deselectTable(); - m_nodeModel = parentNode; - m_listController.setFirstSelectedRow(previousState->selectedRow()); - KDPoint scroll = m_selectableTableView.contentOffset(); - m_selectableTableView.setContentOffset(KDPoint(scroll.x(), previousState->verticalScroll())); - m_stack.pop(); - app()->setFirstResponder(&m_listController); - return true; +const ToolboxMessageTree * MathToolbox::rootModel() { + return &toolboxModel; } -bool MathToolbox::selectSubMenu(ToolboxNode * selectedNode) { - m_stack.push(selectedRow(), m_selectableTableView.contentOffset().y()); - m_selectableTableView.deselectTable(); - m_nodeModel = selectedNode; - m_listController.setFirstSelectedRow(0); - app()->setFirstResponder(&m_listController); - return true; +MessageTableCellWithMessage * MathToolbox::leafCellAtIndex(int index) { + assert(index > 0 && index < k_maxNumberOfDisplayedRows); + return &m_leafCells[index]; +} + +MessageTableCellWithChevron* MathToolbox::nodeCellAtIndex(int index) { + assert(index > 0 && index < k_maxNumberOfDisplayedRows); + return &m_nodeCells[index]; +} + +int MathToolbox::maxNumberOfDisplayedRows() { + return k_maxNumberOfDisplayedRows; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 95b30de74..1d0171652 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -3,79 +3,25 @@ #define MATRICES_ARE_DEFINED 1 #include -#include "toolbox_node.h" +#include -/* m_nodeModel points at the node of the tree (describing the whole model) - * where we are located. It enables to know which rows are leaves and which are - * subtrees. */ - -class MathToolbox : public Toolbox, public ListViewDataSource, public SelectableTableViewDataSource { +class MathToolbox : public Toolbox { public: MathToolbox(); - void didBecomeFirstResponder() override; - bool handleEvent(Ion::Events::Event event) override; - - int numberOfRows() override; - HighlightCell * reusableCell(int index, int type) override; - int reusableCellCount(int type) override; - void willDisplayCellForIndex(HighlightCell * cell, int index) override; - KDCoordinate rowHeight(int j) override; - KDCoordinate cumulatedHeightFromIndex(int j) override; - int indexFromCumulatedHeight(KDCoordinate offsetY) override; - int typeAtLocation(int i, int j) override; - - void viewWillAppear() override; - void viewDidDisappear() override; protected: - int stackDepth(); + KDCoordinate rowHeight(int j) override; TextField * sender() override; - bool handleEventForRow(Ion::Events::Event event, int selectedRow); - SelectableTableView m_selectableTableView; - constexpr static int k_maxNumberOfDisplayedRows = 6; //240/40 + bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; + const ToolboxMessageTree * rootModel() override; + MessageTableCellWithMessage * leafCellAtIndex(int index) override; + MessageTableCellWithChevron* nodeCellAtIndex(int index) override; + int maxNumberOfDisplayedRows() override; + constexpr static int k_maxNumberOfDisplayedRows = 6; // = 240/40 private: - class Stack { - public: - class State { - public: - State(int selectedRow = -1, KDCoordinate verticalScroll = 0); - bool isNull(); - int selectedRow(); - KDCoordinate verticalScroll(); - private: - int m_selectedRow; - KDCoordinate m_verticalScroll; - }; - void push(int selectedRow, KDCoordinate verticalScroll); - void pop(); - State * stateAtIndex(int index); - int depth(); - void resetStack(); - private: - constexpr static int k_maxModelTreeDepth = 2; - State m_statesStack[k_maxModelTreeDepth]; - }; - class ListController : public ViewController { - public: - ListController(Responder * parentResponder, SelectableTableView * tableView); - const char * title() override; - View * view() override; - void didBecomeFirstResponder() override; - void setFirstSelectedRow(int firstSelectedRow); - private: - SelectableTableView * m_selectableTableView; - int m_firstSelectedRow; - }; constexpr static KDCoordinate k_nodeRowHeight = 40; constexpr static KDCoordinate k_leafRowHeight = 40; - const ToolboxNode * rootModel(); - bool selectLeaf(ToolboxNode * selectedNode); - bool selectSubMenu(ToolboxNode * selectedNode); - bool returnToPreviousMenu(); - Stack m_stack; MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows]; - ListController m_listController; - ToolboxNode * m_nodeModel; }; #endif diff --git a/apps/node.cpp b/apps/node.cpp deleted file mode 100644 index 7d8ccf5cd..000000000 --- a/apps/node.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "node.h" - -int Node::numberOfChildren() const { - return m_numberOfChildren; -} - -I18n::Message Node::label() const { - return m_label; -} - -bool Node::isNull() const { - return (m_label == I18n::Message::Default); -} diff --git a/apps/node.h b/apps/node.h deleted file mode 100644 index cfee895f5..000000000 --- a/apps/node.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef APPS_NODE_H -#define APPS_NODE_H - -#include "i18n.h" - -class Node { -public: - constexpr Node(I18n::Message label = I18n::Message::Default, int numberOfChildren = 0) : - m_label(label), - m_numberOfChildren(numberOfChildren) - { - }; - virtual const Node * children(int index) const = 0; - I18n::Message label() const; - int numberOfChildren() const; - bool isNull() const; -protected: - I18n::Message m_label; - int m_numberOfChildren; -}; - -#endif - diff --git a/apps/settings/Makefile b/apps/settings/Makefile index 246f49fbd..ac039b8e7 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -5,7 +5,7 @@ app_objs += $(addprefix apps/settings/,\ app.o\ language_controller.o\ main_controller.o\ - settings_node.o\ + settings_message_tree.o\ sub_controller.o\ ) diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 5b3a8297a..cb1793b83 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -10,27 +10,27 @@ using namespace Poincare; namespace Settings { -const SettingsNode angleChildren[2] = {SettingsNode(I18n::Message::Degres), SettingsNode(I18n::Message::Radian)}; -const SettingsNode FloatDisplayModeChildren[2] = {SettingsNode(I18n::Message::Auto), SettingsNode(I18n::Message::Scientific)}; -const SettingsNode complexFormatChildren[2] = {SettingsNode(I18n::Message::Default), SettingsNode(I18n::Message::Default)}; -const SettingsNode examChildren[1] = {SettingsNode(I18n::Message::ActivateExamMode)}; -const SettingsNode aboutChildren[3] = {SettingsNode(I18n::Message::SoftwareVersion), SettingsNode(I18n::Message::SerialNumber), SettingsNode(I18n::Message::FccId)}; +const SettingsMessageTree angleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)}; +const SettingsMessageTree FloatDisplayModeChildren[2] = {SettingsMessageTree(I18n::Message::Auto), SettingsMessageTree(I18n::Message::Scientific)}; +const SettingsMessageTree complexFormatChildren[2] = {SettingsMessageTree(I18n::Message::Default), SettingsMessageTree(I18n::Message::Default)}; +const SettingsMessageTree examChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; +const SettingsMessageTree aboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; #if OS_WITH_SOFTWARE_UPDATE_PROMPT -const SettingsNode menu[8] = +const SettingsMessageTree menu[8] = #else -const SettingsNode menu[7] = +const SettingsMessageTree menu[7] = #endif - {SettingsNode(I18n::Message::AngleUnit, angleChildren, 2), SettingsNode(I18n::Message::DisplayMode, FloatDisplayModeChildren, 2), SettingsNode(I18n::Message::ComplexFormat, complexFormatChildren, 2), - SettingsNode(I18n::Message::Brightness), SettingsNode(I18n::Message::Language), SettingsNode(I18n::Message::ExamMode, examChildren, 1), + {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), SettingsMessageTree(I18n::Message::DisplayMode, FloatDisplayModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), + SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), SettingsMessageTree(I18n::Message::ExamMode, examChildren, 1), #if OS_WITH_SOFTWARE_UPDATE_PROMPT - SettingsNode(I18n::Message::UpdatePopUp), + SettingsMessageTree(I18n::Message::UpdatePopUp), #endif - SettingsNode(I18n::Message::About, aboutChildren, 3)}; + SettingsMessageTree(I18n::Message::About, aboutChildren, 3)}; #if OS_WITH_SOFTWARE_UPDATE_PROMPT -const SettingsNode model = SettingsNode(I18n::Message::SettingsApp, menu, 8); +const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 8); #else -const SettingsNode model = SettingsNode(I18n::Message::SettingsApp, menu, 7); +const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 7); #endif MainController::MainController(Responder * parentResponder) : @@ -43,7 +43,7 @@ MainController::MainController(Responder * parentResponder) : m_complexFormatLayout(nullptr), m_selectableTableView(this, this, 0, 1, Metric::CommonTopMargin, Metric::CommonRightMargin, Metric::CommonBottomMargin, Metric::CommonLeftMargin, this), - m_nodeModel((Node *)&model), + m_messageTreeModel((MessageTree *)&model), m_subController(this), m_languageController(this, 13) { @@ -59,7 +59,7 @@ MainController::~MainController() { } } const char * MainController::title() { - return I18n::translate(m_nodeModel->label()); + return I18n::translate(m_messageTreeModel->label()); } View * MainController::view() { @@ -74,9 +74,9 @@ void MainController::didBecomeFirstResponder() { } bool MainController::handleEvent(Ion::Events::Event event) { - if (m_nodeModel->children(selectedRow())->numberOfChildren() == 0) { + if (m_messageTreeModel->children(selectedRow())->numberOfChildren() == 0) { #if OS_WITH_SOFTWARE_UPDATE_PROMPT - if (m_nodeModel->children(selectedRow())->label() == I18n::Message::UpdatePopUp) { + if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::UpdatePopUp) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { GlobalPreferences::sharedGlobalPreferences()->setShowUpdatePopUp(!GlobalPreferences::sharedGlobalPreferences()->showUpdatePopUp()); m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); @@ -85,7 +85,7 @@ bool MainController::handleEvent(Ion::Events::Event event) { return false; } #endif - if (m_nodeModel->children(selectedRow())->label() == I18n::Message::Brightness) { + if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::Brightness) { if (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus) { int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? delta : -delta; @@ -95,7 +95,7 @@ bool MainController::handleEvent(Ion::Events::Event event) { } return false; } - if (m_nodeModel->children(selectedRow())->label() == I18n::Message::Language) { + if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::Language) { if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { stackController()->push(&m_languageController); return true; @@ -104,7 +104,7 @@ bool MainController::handleEvent(Ion::Events::Event event) { } } if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { - m_subController.setNodeModel(m_nodeModel->children(selectedRow())); + m_subController.setMessageTreeModel(m_messageTreeModel->children(selectedRow())); StackViewController * stack = stackController(); stack->push(&m_subController); return true; @@ -113,7 +113,7 @@ bool MainController::handleEvent(Ion::Events::Event event) { } int MainController::numberOfRows() { - return m_nodeModel->numberOfChildren(); + return m_messageTreeModel->numberOfChildren(); }; KDCoordinate MainController::rowHeight(int j) { @@ -170,7 +170,7 @@ int MainController::typeAtLocation(int i, int j) { void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCell * myCell = (MessageTableCell *)cell; - myCell->setMessage(m_nodeModel->children(index)->label()); + myCell->setMessage(m_messageTreeModel->children(index)->label()); if (index == 2) { if (m_complexFormatLayout) { @@ -211,13 +211,13 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell; switch (index) { case 0: - myTextCell->setSubtitle(m_nodeModel->children(index)->children((int)Preferences::sharedPreferences()->angleUnit())->label()); + myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->angleUnit())->label()); break; case 1: - myTextCell->setSubtitle(m_nodeModel->children(index)->children((int)Preferences::sharedPreferences()->displayMode())->label()); + myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->displayMode())->label()); break; case 4: - myTextCell->setSubtitle(m_nodeModel->children(index)->children((int)GlobalPreferences::sharedGlobalPreferences()->language()-1)->label()); + myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)GlobalPreferences::sharedGlobalPreferences()->language()-1)->label()); break; default: myTextCell->setSubtitle(I18n::Message::Default); diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 7613b2ffb..c134f6c16 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -3,7 +3,7 @@ #include #include "sub_controller.h" -#include "settings_node.h" +#include "settings_message_tree.h" #include "language_controller.h" namespace Settings { @@ -43,7 +43,7 @@ private: MessageTableCellWithGauge m_brightnessCell; Poincare::ExpressionLayout * m_complexFormatLayout; SelectableTableView m_selectableTableView; - Node * m_nodeModel; + MessageTree * m_messageTreeModel; SubController m_subController; LanguageController m_languageController; }; diff --git a/apps/settings/settings_message_tree.cpp b/apps/settings/settings_message_tree.cpp new file mode 100644 index 000000000..f481eb543 --- /dev/null +++ b/apps/settings/settings_message_tree.cpp @@ -0,0 +1,9 @@ +#include "settings_message_tree.h" + +namespace Settings { + +const MessageTree * SettingsMessageTree::children(int index) const { + return &m_children[index]; +} + +} diff --git a/apps/settings/settings_message_tree.h b/apps/settings/settings_message_tree.h new file mode 100644 index 000000000..7d2df12cd --- /dev/null +++ b/apps/settings/settings_message_tree.h @@ -0,0 +1,23 @@ +#ifndef SETTINGS_MESSAGE_TREE_H +#define SETTINGS_MESSAGE_TREE_H +#include +#include + +namespace Settings { + +class SettingsMessageTree : public MessageTree { +public: + constexpr SettingsMessageTree(I18n::Message label = I18n::Message::Default, const SettingsMessageTree * children = nullptr, int numberOfChildren = 0) : + MessageTree(label, numberOfChildren), + m_children(children) + { + }; + const MessageTree * children(int index) const override; +private: + const SettingsMessageTree * m_children; +}; + +} + +#endif + diff --git a/apps/settings/settings_node.cpp b/apps/settings/settings_node.cpp deleted file mode 100644 index 8c47204a9..000000000 --- a/apps/settings/settings_node.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "settings_node.h" - -namespace Settings { - -const Node * SettingsNode::children(int index) const { - return &m_children[index]; -} - -} diff --git a/apps/settings/settings_node.h b/apps/settings/settings_node.h deleted file mode 100644 index 527b575d0..000000000 --- a/apps/settings/settings_node.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SETTINGS_NODE_H -#define SETTINGS_NODE_H - -#include "../node.h" - -namespace Settings { - -class SettingsNode : public Node { -public: - constexpr SettingsNode(I18n::Message label = I18n::Message::Default, const SettingsNode * children = nullptr, int numberOfChildren = 0) : - Node(label, numberOfChildren), - m_children(children) - { - }; - const Node * children(int index) const override; -private: - const SettingsNode * m_children; -}; - -} - -#endif - diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp index 2a9aea5fe..e89c03945 100644 --- a/apps/settings/sub_controller.cpp +++ b/apps/settings/sub_controller.cpp @@ -13,7 +13,7 @@ SubController::SubController(Responder * parentResponder) : ViewController(parentResponder), m_selectableTableView(this, this, 0, 1, k_topBottomMargin, Metric::CommonRightMargin, k_topBottomMargin, Metric::CommonLeftMargin, this), - m_nodeModel(nullptr) + m_messageTreeModel(nullptr) { for (int i = 0; i < k_totalNumberOfCell; i++) { m_cells[i].setMessageFontSize(KDText::FontSize::Large); @@ -40,8 +40,8 @@ SubController::~SubController() { } const char * SubController::title() { - if (m_nodeModel) { - return I18n::translate(m_nodeModel->label()); + if (m_messageTreeModel) { + return I18n::translate(m_messageTreeModel->label()); } return ""; } @@ -52,12 +52,12 @@ View * SubController::view() { void SubController::didEnterResponderChain(Responder * previousResponder) { if (previousResponder->commonAncestorWith(this) == parentResponder()) { - /* We want to select the prefered setting node only when the previous page + /* We want to select the prefered SettingMessageTree only when the previous page * was the main setting page. We do not to change the selection when * dismissing a pop-up for instance. */ - selectCellAtLocation(0, valueIndexForPreference(m_nodeModel->label())); + selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); } - if (m_nodeModel->label() == I18n::Message::ExamMode) { + if (m_messageTreeModel->label() == I18n::Message::ExamMode) { m_selectableTableView.reloadData(); } app()->setFirstResponder(&m_selectableTableView); @@ -66,13 +66,13 @@ void SubController::didEnterResponderChain(Responder * previousResponder) { bool SubController::handleEvent(Ion::Events::Event event) { /* We hide here the activation hardware test app: in the menu "about", by * clicking on '6' on the last row. */ - if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && m_nodeModel->label() == I18n::Message::About && selectedRow() == numberOfRows()-1) { + if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && m_messageTreeModel->label() == I18n::Message::About && selectedRow() == numberOfRows()-1) { app()->displayModalViewController(&m_hardwareTestPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin); return true; } if (event == Ion::Events::OK || event == Ion::Events::EXE) { /* Behavious of "Exam mode" menu*/ - if (m_nodeModel->label() == I18n::Message::ExamMode) { + if (m_messageTreeModel->label() == I18n::Message::ExamMode) { if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { return false; } @@ -81,7 +81,7 @@ bool SubController::handleEvent(Ion::Events::Event event) { return true; } /* Behaviour of "About" menu */ - if (m_nodeModel->label() == I18n::Message::About) { + if (m_messageTreeModel->label() == I18n::Message::About) { if (selectedRow() == 0) { MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell(); if (strcmp(myCell->accessoryText(), Ion::patchLevel()) == 0) { @@ -94,7 +94,7 @@ bool SubController::handleEvent(Ion::Events::Event event) { return false; } /* Generic behaviour of preference menu*/ - setPreferenceWithValueIndex(m_nodeModel->label(), selectedRow()); + setPreferenceWithValueIndex(m_messageTreeModel->label(), selectedRow()); AppsContainer * myContainer = (AppsContainer * )app()->container(); myContainer->refreshPreferences(); StackViewController * stack = stackController(); @@ -109,8 +109,8 @@ bool SubController::handleEvent(Ion::Events::Event event) { } int SubController::numberOfRows() { - if (m_nodeModel) { - return m_nodeModel->numberOfChildren(); + if (m_messageTreeModel) { + return m_messageTreeModel->numberOfChildren(); } return 0; } @@ -118,14 +118,14 @@ int SubController::numberOfRows() { HighlightCell * SubController::reusableCell(int index) { assert(index >= 0); assert(index < k_totalNumberOfCell); - if (m_nodeModel->label() == I18n::Message::ComplexFormat) { + if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { return &m_complexFormatCells[index]; } return &m_cells[index]; } int SubController::reusableCellCount() { - if (m_nodeModel->label() == I18n::Message::ComplexFormat) { + if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { return 2; } return k_totalNumberOfCell; @@ -136,17 +136,17 @@ KDCoordinate SubController::cellHeight() { } void SubController::willDisplayCellForIndex(HighlightCell * cell, int index) { - if (m_nodeModel->label() == I18n::Message::ComplexFormat) { + if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { return; } MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; - myCell->setMessage(m_nodeModel->children(index)->label()); + myCell->setMessage(m_messageTreeModel->children(index)->label()); myCell->setMessageFontSize(KDText::FontSize::Large); myCell->setAccessoryText(""); - if (m_nodeModel->label() == I18n::Message::ExamMode && GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + if (m_messageTreeModel->label() == I18n::Message::ExamMode && GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { myCell->setMessage(I18n::Message::ExamModeActive); } - if (m_nodeModel->label() == I18n::Message::About) { + if (m_messageTreeModel->label() == I18n::Message::About) { myCell->setMessageFontSize(KDText::FontSize::Small); const char * accessoryMessage = Ion::softwareVersion(); switch (index) { @@ -167,8 +167,8 @@ void SubController::willDisplayCellForIndex(HighlightCell * cell, int index) { } } -void SubController::setNodeModel(const Node * nodeModel) { - m_nodeModel = (Node *)nodeModel; +void SubController::setMessageTreeModel(const MessageTree * messageTreeModel) { + m_messageTreeModel = (MessageTree *)messageTreeModel; } void SubController::viewWillAppear() { diff --git a/apps/settings/sub_controller.h b/apps/settings/sub_controller.h index e3e580879..5e4c81d67 100644 --- a/apps/settings/sub_controller.h +++ b/apps/settings/sub_controller.h @@ -2,7 +2,7 @@ #define SETTINGS_SUB_CONTROLLER_H #include -#include "settings_node.h" +#include "settings_message_tree.h" #include "../hardware_test/pop_up_controller.h" namespace Settings { @@ -24,7 +24,7 @@ public: HighlightCell * reusableCell(int index) override; int reusableCellCount() override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; - void setNodeModel(const Node * nodeModel); + void setMessageTreeModel(const MessageTree * messageTreeModel); void viewWillAppear() override; void viewDidDisappear() override; private: @@ -37,7 +37,7 @@ private: ExpressionTableCell m_complexFormatCells[2]; Poincare::ExpressionLayout * m_complexFormatLayout[2]; SelectableTableView m_selectableTableView; - Node * m_nodeModel; + MessageTree * m_messageTreeModel; HardwareTest::PopUpController m_hardwareTestPopUpController; }; diff --git a/apps/toolbox_node.cpp b/apps/toolbox_node.cpp deleted file mode 100644 index f9faf1cd4..000000000 --- a/apps/toolbox_node.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "toolbox_node.h" - -I18n::Message ToolboxNode::text() const { - return m_text; -} - -I18n::Message ToolboxNode::insertedText() const { - return m_insertedText; -} - -const Node * ToolboxNode::children(int index) const { - return &m_children[index]; -} diff --git a/apps/toolbox_node.h b/apps/toolbox_node.h deleted file mode 100644 index 2eae68043..000000000 --- a/apps/toolbox_node.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef APPS_TOOLBOX_NODE_H -#define APPS_TOOLBOX_NODE_H - -#include "node.h" - -class ToolboxNode : public Node { -public: - constexpr ToolboxNode(I18n::Message label = I18n::Message::Default, I18n::Message text = I18n::Message::Default, I18n::Message insertedText = I18n::Message::Default, const ToolboxNode * children = nullptr, int numberOfChildren = 0) : - Node(label, numberOfChildren), - m_children(children), - m_text(text), - m_insertedText(insertedText) - { - }; - const Node * children(int index) const override; - I18n::Message text() const; - I18n::Message insertedText() const; -private: - const ToolboxNode * m_children; - I18n::Message m_text; - I18n::Message m_insertedText; -}; - -#endif - diff --git a/escher/Makefile b/escher/Makefile index 22d2f66ce..3530313b3 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -37,6 +37,7 @@ objs += $(addprefix escher/src/,\ message_table_cell_with_message.o\ message_table_cell_with_switch.o\ message_text_view.o\ + message_tree.o\ modal_view_controller.o\ palette.o\ responder.o\ @@ -66,8 +67,9 @@ objs += $(addprefix escher/src/,\ text_field.o\ text_view.o\ tiled_view.o\ - toolbox.o\ timer.o\ + toolbox.o\ + toolbox_message_tree.o\ view.o\ view_controller.o\ warning_controller.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 0dec5ecc3..c00e02c52 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,7 @@ #include #include #include +#include #include #include #include diff --git a/escher/include/escher/message_tree.h b/escher/include/escher/message_tree.h new file mode 100644 index 000000000..7ddd88973 --- /dev/null +++ b/escher/include/escher/message_tree.h @@ -0,0 +1,23 @@ +#ifndef ESCHER_MESSAGE_TREE_H +#define ESCHER_MESSAGE_TREE_H + +#include + +class MessageTree { +public: + constexpr MessageTree(I18n::Message label = (I18n::Message)0, int numberOfChildren = 0) : + m_label(label), + m_numberOfChildren(numberOfChildren) + { + }; + virtual const MessageTree * children(int index) const = 0; + I18n::Message label() const; + int numberOfChildren() const; + bool isNull() const; +protected: + I18n::Message m_label; + int m_numberOfChildren; +}; + +#endif + diff --git a/escher/include/escher/toolbox.h b/escher/include/escher/toolbox.h index f924e93d1..59d985030 100644 --- a/escher/include/escher/toolbox.h +++ b/escher/include/escher/toolbox.h @@ -1,19 +1,92 @@ #ifndef ESCHER_TOOLBOX_H #define ESCHER_TOOLBOX_H +#include +#include +#include +#include +#include #include +#include -class Toolbox : public StackViewController { +class Toolbox : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource { public: - Toolbox(Responder * parentResponder, ViewController * rootViewController); + Toolbox(Responder * parentResponder, const char * title = 0); void setSender(Responder * sender); + + // StackViewController + bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; void viewWillAppear() override; void viewDidDisappear() override; + + //ListViewDataSource + int numberOfRows() override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + int typeAtLocation(int i, int j) override; + protected: + class Stack { + public: + class State { + public: + State(int selectedRow = -1, KDCoordinate verticalScroll = 0); + bool isNull(); + int selectedRow() { return m_selectedRow; } + KDCoordinate verticalScroll() { return m_verticalScroll; } + private: + int m_selectedRow; + KDCoordinate m_verticalScroll; + }; + void push(int selectedRow, KDCoordinate verticalScroll); + void pop(); + State * stateAtIndex(int index); + int depth(); + void resetStack(); + private: + constexpr static int k_maxModelTreeDepth = 3; + State m_statesStack[k_maxModelTreeDepth]; + }; + + class ListController : public ViewController { + public: + ListController(Responder * parentResponder, SelectableTableView * tableView, const char * title); + const char * title() override; + View * view() override; + void didBecomeFirstResponder() override; + void setFirstSelectedRow(int firstSelectedRow); + private: + SelectableTableView * m_selectableTableView; + int m_firstSelectedRow; + const char * m_title; + }; + + static constexpr int LeafCellType = 0; + static constexpr int NodeCellType = 1; + int stackDepth(); + bool handleEventForRow(Ion::Events::Event event, int selectedRow); + bool selectSubMenu(ToolboxMessageTree * selectedMessageTree); + bool returnToPreviousMenu(); virtual Responder * sender(); + virtual bool selectLeaf(ToolboxMessageTree * selectedMessageTree) = 0; + virtual const ToolboxMessageTree * rootModel() = 0; + virtual MessageTableCellWithMessage * leafCellAtIndex(int index) = 0; + virtual MessageTableCellWithChevron * nodeCellAtIndex(int index) = 0; + virtual int maxNumberOfDisplayedRows() = 0; + SelectableTableView m_selectableTableView; + Stack m_stack; + ListController m_listController; + ToolboxMessageTree * m_messageTreeModel; + /* m_messageTreeModel points at the messageTree of the tree (describing the + * whole model) where we are located. It enables to know which rows are leaves + * and which are subtrees. */ + private: Responder * m_sender; }; - #endif diff --git a/escher/include/escher/toolbox_message_tree.h b/escher/include/escher/toolbox_message_tree.h new file mode 100644 index 000000000..10e5cb336 --- /dev/null +++ b/escher/include/escher/toolbox_message_tree.h @@ -0,0 +1,25 @@ +#ifndef ESCHER_TOOLBOX_MESSAGE_TREE_H +#define ESCHER_TOOLBOX_MESSAGE_TREE_H + +#include + +class ToolboxMessageTree : public MessageTree { +public: + constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0) : + MessageTree(label, numberOfChildren), + m_children(children), + m_text(text), + m_insertedText(insertedText) + { + }; + const MessageTree * children(int index) const override; + I18n::Message text() const; + I18n::Message insertedText() const; +private: + const ToolboxMessageTree * m_children; + I18n::Message m_text; + I18n::Message m_insertedText; +}; + +#endif + diff --git a/escher/src/message_tree.cpp b/escher/src/message_tree.cpp new file mode 100644 index 000000000..59bd96901 --- /dev/null +++ b/escher/src/message_tree.cpp @@ -0,0 +1,13 @@ +#include + +int MessageTree::numberOfChildren() const { + return m_numberOfChildren; +} + +I18n::Message MessageTree::label() const { + return m_label; +} + +bool MessageTree::isNull() const { + return (m_label == (I18n::Message)0); +} diff --git a/escher/src/toolbox.cpp b/escher/src/toolbox.cpp index 394ce19e6..9f79aa464 100644 --- a/escher/src/toolbox.cpp +++ b/escher/src/toolbox.cpp @@ -1,7 +1,94 @@ #include +#include +#include -Toolbox::Toolbox(Responder * parentResponder, ViewController * rootViewController) : - StackViewController(parentResponder, rootViewController, true, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark), +/* State */ + +Toolbox::Stack::State::State(int selectedRow, KDCoordinate verticalScroll) : + m_selectedRow(selectedRow), + m_verticalScroll(verticalScroll) +{ +} + +bool Toolbox::Stack::State::isNull(){ + if (m_selectedRow == -1) { + return true; + } + return false; +} + +/* Stack */ + +void Toolbox::Stack::push(int selectedRow, KDCoordinate verticalScroll) { + int i = 0; + while (!m_statesStack[i].isNull() && i < k_maxModelTreeDepth) { + i++; + } + assert(m_statesStack[i].isNull()); + m_statesStack[i] = State(selectedRow, verticalScroll); +} + +Toolbox::Stack::State * Toolbox::Stack::stateAtIndex(int index) { + return &m_statesStack[index]; +} + +int Toolbox::Stack::depth() { + int depth = 0; + for (int i = 0; i < k_maxModelTreeDepth; i++) { + depth += (!m_statesStack[i].isNull()); + } + return depth; +} + +void Toolbox::Stack::pop() { + int stackDepth = depth(); + if (stackDepth == 0) { + return; + } + m_statesStack[stackDepth-1] = State(); +} + +void Toolbox::Stack::resetStack() { + for (int i = 0; i < k_maxModelTreeDepth; i++) { + m_statesStack[i] = State(); + } +} + +/* List Controller */ + +Toolbox::ListController::ListController(Responder * parentResponder, SelectableTableView * tableView, const char * title) : + ViewController(parentResponder), + m_selectableTableView(tableView), + m_firstSelectedRow(0), + m_title(title) +{ +} + +const char * Toolbox::ListController::title() { + return m_title; +} + +View * Toolbox::ListController::view() { + return m_selectableTableView; +} + +void Toolbox::ListController::didBecomeFirstResponder() { + m_selectableTableView->reloadData(); + m_selectableTableView->selectCellAtLocation(0, m_firstSelectedRow); + app()->setFirstResponder(m_selectableTableView); +} + +void Toolbox::ListController::setFirstSelectedRow(int firstSelectedRow) { + m_firstSelectedRow = firstSelectedRow; +} + +/* Toolbox */ + +Toolbox::Toolbox(Responder * parentResponder, const char * title) : + StackViewController(parentResponder, &m_listController, true, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark), + m_selectableTableView(&m_listController, this, 0, 1, 0, 0, 0, 0, this, nullptr, false), + m_listController(this, &m_selectableTableView, title), + m_messageTreeModel(nullptr), m_sender(nullptr) { } @@ -10,12 +97,141 @@ void Toolbox::setSender(Responder * sender) { m_sender = sender; } +bool Toolbox::handleEvent(Ion::Events::Event event) { + return handleEventForRow(event, selectedRow()); +} + +void Toolbox::didBecomeFirstResponder() { + app()->setFirstResponder(&m_listController); +} + void Toolbox::viewWillAppear() { StackViewController::viewWillAppear(); + m_messageTreeModel = (ToolboxMessageTree *)rootModel(); + m_selectableTableView.reloadData(); + m_stack.resetStack(); + m_listController.setFirstSelectedRow(0); } void Toolbox::viewDidDisappear() { StackViewController::viewDidDisappear(); + m_selectableTableView.deselectTable(); +} + +int Toolbox::numberOfRows() { + if (m_messageTreeModel == nullptr) { + m_messageTreeModel = (ToolboxMessageTree *)rootModel(); + } + return m_messageTreeModel->numberOfChildren(); +} + +HighlightCell * Toolbox::reusableCell(int index, int type) { + assert(type < 2); + assert(index >= 0); + assert(index < maxNumberOfDisplayedRows()); + if (type == LeafCellType) { + return leafCellAtIndex(index); + } + return nodeCellAtIndex(index); +} + +int Toolbox::reusableCellCount(int type) { + return maxNumberOfDisplayedRows(); +} + +void Toolbox::willDisplayCellForIndex(HighlightCell * cell, int index) { + ToolboxMessageTree * messageTree = (ToolboxMessageTree *)m_messageTreeModel->children(index); + if (messageTree->numberOfChildren() == 0) { + MessageTableCellWithMessage * myCell = (MessageTableCellWithMessage *)cell; + myCell->setMessage(messageTree->label()); + myCell->setAccessoryMessage(messageTree->text()); + myCell->setAccessoryTextColor(Palette::GreyDark); + return; + } + MessageTableCell * myCell = (MessageTableCell *)cell; + myCell->setMessage(messageTree->label()); +} + +KDCoordinate Toolbox::cumulatedHeightFromIndex(int j) { + int result = 0; + for (int k = 0; k < j; k++) { + result += rowHeight(k); + } + return result; +} + +int Toolbox::indexFromCumulatedHeight(KDCoordinate offsetY) { + int result = 0; + int j = 0; + while (result < offsetY && j < numberOfRows()) { + result += rowHeight(j++); + } + return (result < offsetY || offsetY == 0) ? j : j - 1; +} + +int Toolbox::typeAtLocation(int i, int j) { + MessageTree * messageTree = (MessageTree *)m_messageTreeModel->children(j); + if (messageTree->numberOfChildren() == 0) { + return LeafCellType; + } + return NodeCellType; +} + +int Toolbox::stackDepth() { + return m_stack.depth(); +} + +bool Toolbox::handleEventForRow(Ion::Events::Event event, int selectedRow) { + int depth = m_stack.depth(); + if (event == Ion::Events::Back && depth == 0) { + m_selectableTableView.deselectTable(); + app()->dismissModalViewController(); + return true; + } + if ((event == Ion::Events::Back || event == Ion::Events::Left) && depth > 0) { + return returnToPreviousMenu(); + } + ToolboxMessageTree * selectedMessageTree = (ToolboxMessageTree *)m_messageTreeModel->children(selectedRow); + if ((event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) && selectedMessageTree->numberOfChildren() > 0) { + return selectSubMenu(selectedMessageTree); + } + if ((event == Ion::Events::OK || event == Ion::Events::EXE) && selectedMessageTree->numberOfChildren() == 0) { + return selectLeaf(selectedMessageTree); + } + return false; +} + +bool Toolbox::selectSubMenu(ToolboxMessageTree * selectedMessageTree) { + m_stack.push(selectedRow(), m_selectableTableView.contentOffset().y()); + m_selectableTableView.deselectTable(); + m_messageTreeModel = selectedMessageTree; + m_listController.setFirstSelectedRow(0); + app()->setFirstResponder(&m_listController); + return true; +} + +bool Toolbox::returnToPreviousMenu() { + m_selectableTableView.deselectTable(); + int depth = m_stack.depth(); + int index = 0; + // We want to get the current ToolboxMessageTree's parent ToolboxMessageTree, + // but there is no ToolboxMessageTree::getParent() method. We thus have to + // start from the root ToolboxMessageTree and sequentially get the selected + // child until it has the wanted depth. + ToolboxMessageTree * parentMessageTree = (ToolboxMessageTree *)rootModel(); + Stack::State * previousState = m_stack.stateAtIndex(index++);; + while (depth-- > 1) { + parentMessageTree = (ToolboxMessageTree *)parentMessageTree->children(previousState->selectedRow()); + previousState = m_stack.stateAtIndex(index++); + } + m_selectableTableView.deselectTable(); + m_messageTreeModel = parentMessageTree; + m_listController.setFirstSelectedRow(previousState->selectedRow()); + KDPoint scroll = m_selectableTableView.contentOffset(); + m_selectableTableView.setContentOffset(KDPoint(scroll.x(), previousState->verticalScroll())); + m_stack.pop(); + app()->setFirstResponder(&m_listController); + return true; } Responder * Toolbox::sender() { diff --git a/escher/src/toolbox_message_tree.cpp b/escher/src/toolbox_message_tree.cpp new file mode 100644 index 000000000..595e7e300 --- /dev/null +++ b/escher/src/toolbox_message_tree.cpp @@ -0,0 +1,13 @@ +#include + +I18n::Message ToolboxMessageTree::text() const { + return m_text; +} + +I18n::Message ToolboxMessageTree::insertedText() const { + return m_insertedText; +} + +const MessageTree * ToolboxMessageTree::children(int index) const { + return &m_children[index]; +}