#include "store_controller.h" #include "../apps_container.h" #include "../constant.h" #include using namespace Poincare; namespace Shared { StoreController::StoreController(Responder * parentResponder, FloatPairStore * store, ButtonRowController * header) : EditableCellTableViewController(parentResponder), ButtonRowDelegate(header, nullptr), m_editableCells{}, m_store(store), m_storeParameterController(this, store) { } bool StoreController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container(); Context * globalContext = appsContainer->globalContext(); double floatBody = Expression::approximateToScalar(text, *globalContext); if (std::isnan(floatBody) || std::isinf(floatBody)) { app()->displayWarning(I18n::Message::UndefinedValue); return false; } if (!setDataAtLocation(floatBody, selectedColumn(), selectedRow())) { app()->displayWarning(I18n::Message::ForbiddenValue); return false; } // FIXME Find out if redrawing errors can be suppressed without always reloading all the data selectableTableView()->reloadData(); if (event == Ion::Events::EXE || event == Ion::Events::OK) { selectableTableView()->selectCellAtLocation(selectedColumn(), selectedRow()+1); } else { selectableTableView()->handleEvent(event); } return true; } const char * StoreController::title() { return I18n::translate(I18n::Message::DataTab); } int StoreController::numberOfColumns() { return k_numberOfColumnsPerSeries * FloatPairStore::k_numberOfSeries; } KDCoordinate StoreController::columnWidth(int i) { return k_cellWidth; } KDCoordinate StoreController::cumulatedWidthFromIndex(int i) { return i*k_cellWidth; } int StoreController::indexFromCumulatedWidth(KDCoordinate offsetX) { return (offsetX-1) / k_cellWidth; } HighlightCell * StoreController::reusableCell(int index, int type) { assert(index >= 0); switch (type) { case k_titleCellType: assert(index < k_numberOfTitleCells); return titleCells(index); case k_editableCellType: assert(index < k_maxNumberOfEditableCells); return m_editableCells[index]; default: assert(false); return nullptr; } } int StoreController::reusableCellCount(int type) { return type == k_titleCellType ? k_numberOfTitleCells : k_maxNumberOfEditableCells; } int StoreController::typeAtLocation(int i, int j) { return j == 0 ? k_titleCellType : k_editableCellType; } void StoreController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { // Handle empty cells if (j > 0 && j > m_store->numberOfPairsOfSeries(seriesAtColumn(i)) && j < numberOfRows() - 1) { ((EvenOddCell *)cell)->setEven(j%2 == 0); assert(cellAtLocationIsEditable(i, j)); ((EvenOddEditableTextCell *)cell)->editableTextCell()->textField()->setText(""); return; } willDisplayCellAtLocationWithDisplayMode(cell, i, j, PrintFloat::Mode::Decimal); } void StoreController::didBecomeFirstResponder() { if (selectedRow() < 0 || selectedColumn() < 0) { selectCellAtLocation(0, 0); } EditableCellTableViewController::didBecomeFirstResponder(); } bool StoreController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Up) { selectableTableView()->deselectTable(); assert(selectedRow() == -1); app()->setFirstResponder(tabController()); return true; } assert(selectedColumn() >= 0 && selectedColumn() < numberOfColumns()); int series = seriesAtColumn(selectedColumn()); if ((event == Ion::Events::OK || event == Ion::Events::EXE) && selectedRow() == 0) { m_storeParameterController.selectXColumn(selectedColumn()%k_numberOfColumnsPerSeries == 0); m_storeParameterController.selectSeries(series); StackViewController * stack = ((StackViewController *)parentResponder()->parentResponder()); stack->push(&m_storeParameterController); return true; } if (event == Ion::Events::Backspace) { if (selectedRow() == 0 || selectedRow() == numberOfRows()-1) { return false; } m_store->deletePairOfSeriesAtIndex(series, selectedRow()-1); selectableTableView()->reloadData(); return true; } return false; } Responder * StoreController::tabController() const { return (parentResponder()->parentResponder()->parentResponder()); } bool StoreController::cellAtLocationIsEditable(int columnIndex, int rowIndex) { if (rowIndex > 0) { return true; } return false; } bool StoreController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) { m_store->set(floatBody, seriesAtColumn(columnIndex), columnIndex%k_numberOfColumnsPerSeries, rowIndex-1); return true; } double StoreController::dataAtLocation(int columnIndex, int rowIndex) { return m_store->get(seriesAtColumn(columnIndex), columnIndex%k_numberOfColumnsPerSeries, rowIndex-1); } int StoreController::numberOfElements() { int result = 0; for (int i = 0; i < FloatPairStore::k_numberOfSeries; i++) { result = max(result, m_store->numberOfPairsOfSeries(i)); } return result; } int StoreController::maxNumberOfElements() const { return FloatPairStore::k_numberOfSeries * FloatPairStore::k_maxNumberOfPairs; } View * StoreController::loadView() { SelectableTableView * tableView = (SelectableTableView*)EditableCellTableViewController::loadView(); for (int i = 0; i < k_maxNumberOfEditableCells; i++) { m_editableCells[i] = new EvenOddEditableTextCell(tableView, this, m_draftTextBuffer); } return tableView; } void StoreController::unloadView(View * view) { for (int i = 0; i < k_maxNumberOfEditableCells; i++) { delete m_editableCells[i]; m_editableCells[i] = nullptr; } EditableCellTableViewController::unloadView(view); } }