From 0e0bbddebc98dbd98a1ac53163777aeb85fe7099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 5 Dec 2016 10:04:22 +0100 Subject: [PATCH] [apps/graph/values] Edit abscissa values directly in their cell Change-Id: I9f15f828c38edb8e06c7ca7d1956c4c9fa479994 --- apps/graph/Makefile | 1 + apps/graph/values/editable_value_cell.cpp | 71 +++++++++++++++++++++++ apps/graph/values/editable_value_cell.h | 29 +++++++++ apps/graph/values/values_controller.cpp | 47 +++++++++------ apps/graph/values/values_controller.h | 4 +- 5 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 apps/graph/values/editable_value_cell.cpp create mode 100644 apps/graph/values/editable_value_cell.h diff --git a/apps/graph/Makefile b/apps/graph/Makefile index ca3fdbc61..fcd12e08c 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -20,6 +20,7 @@ app_objs += $(addprefix apps/graph/,\ list/parameter_controller.o\ values/abscissa_parameter_controller.o\ values/derivative_parameter_controller.o\ + values/editable_value_cell.o\ values/function_parameter_controller.o\ values/interval.o\ values/interval_parameter_controller.o\ diff --git a/apps/graph/values/editable_value_cell.cpp b/apps/graph/values/editable_value_cell.cpp new file mode 100644 index 000000000..9f8f44e48 --- /dev/null +++ b/apps/graph/values/editable_value_cell.cpp @@ -0,0 +1,71 @@ +#include "editable_value_cell.h" +#include +#include "../app.h" + +namespace Graph { + +EditableValueCell::EditableValueCell() : + EvenOddCell(), + Responder(nullptr), + m_bufferTextView(BufferTextView(1.0f, 0.5f)), + m_textField(TextField(this, m_textBody, 255, nullptr)), + m_isEditing(false), + m_successAction(Invocation(nullptr, nullptr)) +{ +} + +void EditableValueCell::reloadCell() { + EvenOddCell::reloadCell(); + m_bufferTextView.setBackgroundColor(backgroundColor()); +} + +void EditableValueCell::setText(const char * textContent) { + m_bufferTextView.setText(textContent); +} + +const char * EditableValueCell::editedText() const { + return m_textField.text(); +} + +int EditableValueCell::numberOfSubviews() const { + return 1; +} + +View * EditableValueCell::subviewAtIndex(int index) { + assert(index == 0); + if (m_isEditing) { + return &m_textField; + } + return &m_bufferTextView; +} + +void EditableValueCell::layoutSubviews() { + m_bufferTextView.setFrame(bounds()); + m_textField.setFrame(bounds()); +} + +bool EditableValueCell::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::OK) { + m_isEditing = false; + m_successAction.perform(this); + app()->setFirstResponder(parentResponder()); + return true; + } + m_isEditing = false; + app()->setFirstResponder(parentResponder()); + return false; +} + + +void EditableValueCell::editValue(const char * initialText, int cursorPosition, void * context, Invocation::Action successAction) { + markRectAsDirty(bounds()); + App * myApp = (App *)app(); + m_textField.setTextFieldDelegate(myApp); + app()->setFirstResponder(&m_textField); + m_isEditing = true; + m_textField.setText(initialText); + m_textField.setCursorLocation(cursorPosition); + m_successAction = Invocation(successAction, context); +} + +} diff --git a/apps/graph/values/editable_value_cell.h b/apps/graph/values/editable_value_cell.h new file mode 100644 index 000000000..6f8cebd99 --- /dev/null +++ b/apps/graph/values/editable_value_cell.h @@ -0,0 +1,29 @@ +#ifndef GRAPH_EDITABLE_VALUE_CELL_H +#define GRAPH_EDITABLE_VALUE_CELL_H + +#include +#include + +namespace Graph { +class EditableValueCell : public EvenOddCell, public Responder { +public: + EditableValueCell(); + void reloadCell() override; + void setText(const char * textContent); + const char * editedText() const; + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + bool handleEvent(Ion::Events::Event event) override; + void editValue(const char * initialText, int cursorLocation, void * context, Invocation::Action successAction); +protected: + BufferTextView m_bufferTextView; + TextField m_textField; + char m_textBody[255]; + bool m_isEditing; + Invocation m_successAction; +}; + +} + +#endif diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp index f62b52188..15566244b 100644 --- a/apps/graph/values/values_controller.cpp +++ b/apps/graph/values/values_controller.cpp @@ -143,11 +143,6 @@ Interval * ValuesController::interval() { return &m_interval; } -ValueCell * ValuesController::abscisseCellAtRow(int rowIndex) { - assert(rowIndex > 0 && rowIndex < numberOfRows()); - return &m_floatCells[rowIndex]; -} - void ValuesController::didBecomeFirstResponder() { headerViewController()->setSelectedButton(-1); if (m_selectableTableView.selectedRow() == -1) { @@ -257,23 +252,21 @@ void ValuesController::editValue(const char * initialText) { } } int cursorLocation = strlen(initialTextContent) + cursorDelta; - App * myApp = (App *)app(); - InputViewController * inputController = myApp->inputViewController(); - inputController->edit(this, initialTextContent, cursorLocation, this, + + EditableValueCell * cell = (EditableValueCell *)m_selectableTableView.cellAtLocation(0, activeRow()); + cell->setParentResponder(&m_selectableTableView); + cell->editValue(initialTextContent, cursorLocation, this, [](void * context, void * sender){ ValuesController * valuesController = (ValuesController *)context; int activeRow = valuesController->activeRow(); int activeColumn = valuesController->activeColumn(); - ValueCell * cell = valuesController->abscisseCellAtRow(activeRow); - InputViewController * myInputViewController = (InputViewController *)sender; - const char * textBody = myInputViewController->textBody(); + EditableValueCell * cell = (EditableValueCell *)sender; + const char * textBody = cell->editedText(); AppsContainer * appsContainer = (AppsContainer *)valuesController->app()->container(); Context * globalContext = appsContainer->context(); float floatBody = Expression::parse(textBody)->approximate(*globalContext); valuesController->interval()->setElement(activeRow-1, floatBody); valuesController->willDisplayCellAtLocation(cell, activeColumn, activeRow); - }, - [](void * context, void * sender){ }); } @@ -284,7 +277,10 @@ int ValuesController::typeAtLocation(int i, int j) { } return 1; } - return 2; + if (i == 0) { + return 2; + } + return 3; } TableViewCell * ValuesController::reusableCell(int index, int type) { @@ -297,6 +293,9 @@ TableViewCell * ValuesController::reusableCell(int index, int type) { assert(index < k_maxNumberOfFunctions); return &m_functionTitleCells[index]; case 2: + assert(index < k_maxNumberOfCells); + return &m_abscissaCells[index]; + case 3: assert(index < k_maxNumberOfCells); return &m_floatCells[index]; default: @@ -312,6 +311,8 @@ int ValuesController::reusableCellCount(int type) { case 1: return k_maxNumberOfFunctions; case 2: + return k_maxNumberOfAbscissaCells; + case 3: return k_maxNumberOfCells; default: assert(false); @@ -346,8 +347,7 @@ void ValuesController::willDisplayCellAtLocation(TableViewCell * cell, int i, in myFunctionCell->setOrientation(FunctionTitleCell::Orientation::HorizontalIndicator); return; } - // The cell is a value cell: - ValueCell * myValueCell = (ValueCell *)cell; + // The cell is not a title cell char buffer[Constant::FloatBufferSizeInScientificMode]; // Special case 1: last row if (j == numberOfRows() - 1) { @@ -356,16 +356,25 @@ void ValuesController::willDisplayCellAtLocation(TableViewCell * cell, int i, in int numberOfIntervalElements = m_interval.numberOfElements(); if (numberOfIntervalElements < Interval::k_maxNumberOfElements) { buffer[0] = 0; - myValueCell->setText(buffer); + if (i == 0) { + EditableValueCell * myEditableValueCell = (EditableValueCell *)cell; + myEditableValueCell->setText(buffer); + } else { + ValueCell * myValueCell = (ValueCell *)cell; + myValueCell->setText(buffer); + } return; } } - // Special case 2: first column + // Special case: first column if (i == 0){ + EditableValueCell * myEditableValueCell = (EditableValueCell *)cell; Float(m_interval.element(j-1)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - myValueCell->setText(buffer); + myEditableValueCell->setText(buffer); return; } + // The cell is a value cell: + ValueCell * myValueCell = (ValueCell *)cell; Function * function = functionAtColumn(i); float x = m_interval.element(j-1); App * graphApp = (Graph::App *)app(); diff --git a/apps/graph/values/values_controller.h b/apps/graph/values/values_controller.h index ece2c2819..9d2eeae82 100644 --- a/apps/graph/values/values_controller.h +++ b/apps/graph/values/values_controller.h @@ -5,6 +5,7 @@ #include "../function_store.h" #include "../function_title_cell.h" #include "value_cell.h" +#include "editable_value_cell.h" #include "title_cell.h" #include "interval.h" #include "abscissa_parameter_controller.h" @@ -21,7 +22,6 @@ public: int activeRow(); int activeColumn(); Interval * interval(); - ValueCell * abscisseCellAtRow(int rowIndex); void editValue(const char * initialText = nullptr); View * view() override; @@ -65,6 +65,7 @@ private: void configureAbscissa(); void configureFunction(); void configureDerivativeFunction(); + constexpr static int k_maxNumberOfAbscissaCells = 8; constexpr static int k_maxNumberOfCells = 40; constexpr static int k_maxNumberOfFunctions = 5; // !!! CAUTION: The order here is important @@ -73,6 +74,7 @@ private: TitleCell m_abscissaTitleCell; FunctionTitleCell m_functionTitleCells[k_maxNumberOfFunctions]; ValueCell m_floatCells[k_maxNumberOfCells]; + EditableValueCell m_abscissaCells[k_maxNumberOfAbscissaCells]; FunctionStore * m_functionStore; Interval m_interval; IntervalParameterController m_intervalParameterController;