mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[escher][apps] CHange textField API
Change-Id: I766d153b7f7429473f297707a08358051123accc
This commit is contained in:
@@ -9,7 +9,7 @@ App::App(Container * container, Context * context) :
|
||||
m_evaluateContext(EvaluateContext(context, &m_calculationStore)),
|
||||
m_calculationStore(CalculationStore()),
|
||||
m_historyController(HistoryController(&m_editExpressionController, &m_calculationStore)),
|
||||
m_editExpressionController(EditExpressionController(&m_modalViewController, &m_historyController, &m_calculationStore, this))
|
||||
m_editExpressionController(EditExpressionController(&m_modalViewController, &m_historyController, &m_calculationStore))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
EditExpressionController::ContentView::ContentView(TableView * subview, TextFieldDelegate * textFieldDelegate) :
|
||||
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate) :
|
||||
View(),
|
||||
m_mainView(subview),
|
||||
m_textField(nullptr, m_textBody, 255, textFieldDelegate)
|
||||
m_textField(parentResponder, m_textBody, 255, textFieldDelegate)
|
||||
{
|
||||
m_textBody[0] = 0;
|
||||
}
|
||||
@@ -43,13 +43,12 @@ TableView * EditExpressionController::ContentView::mainView() {
|
||||
return m_mainView;
|
||||
}
|
||||
|
||||
EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore, TextFieldDelegate * textFieldDelegate) :
|
||||
EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) :
|
||||
ViewController(parentResponder),
|
||||
m_contentView((TableView *)historyController->view(), textFieldDelegate),
|
||||
m_contentView(this, (TableView *)historyController->view(), this),
|
||||
m_historyController(historyController),
|
||||
m_calculationStore(calculationStore)
|
||||
{
|
||||
m_contentView.textField()->setParentResponder(this);
|
||||
}
|
||||
|
||||
View * EditExpressionController::view() {
|
||||
@@ -69,19 +68,6 @@ void EditExpressionController::setTextBody(const char * text) {
|
||||
}
|
||||
|
||||
bool EditExpressionController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK) {
|
||||
Calculation calculation = Calculation();
|
||||
App * calculationApp = (App *)app();
|
||||
calculation.setContent(textBody(), calculationApp->evaluateContext());
|
||||
m_calculationStore->push(&calculation);
|
||||
m_historyController->reload();
|
||||
m_contentView.mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
|
||||
m_contentView.textField()->setText("");
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Back) {
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
if (m_calculationStore->numberOfCalculations() > 0) {
|
||||
app()->setFirstResponder(m_historyController);
|
||||
@@ -95,9 +81,20 @@ void EditExpressionController::didBecomeFirstResponder() {
|
||||
app()->setFirstResponder(m_contentView.textField());
|
||||
}
|
||||
|
||||
void EditExpressionController::edit(const char * initialContent) {
|
||||
setTextBody(initialContent);
|
||||
app()->setFirstResponder(this);
|
||||
bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField, const char * text) {
|
||||
Calculation calculation = Calculation();
|
||||
App * calculationApp = (App *)app();
|
||||
calculation.setContent(textBody(), calculationApp->evaluateContext());
|
||||
m_calculationStore->push(&calculation);
|
||||
m_historyController->reload();
|
||||
m_contentView.mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
|
||||
m_contentView.textField()->setText("");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,20 +9,21 @@
|
||||
namespace Calculation {
|
||||
class HistoryController;
|
||||
|
||||
class EditExpressionController : public ViewController {
|
||||
class EditExpressionController : public ViewController, public TextFieldDelegate {
|
||||
public:
|
||||
EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore, TextFieldDelegate * textFieldDelegate);
|
||||
EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore);
|
||||
View * view() override;
|
||||
const char * title() const override;
|
||||
void didBecomeFirstResponder() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void edit(const char * initialContent);
|
||||
const char * textBody();
|
||||
void setTextBody(const char * text);
|
||||
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
|
||||
bool textFieldDidFinishEditing(::TextField * textField, const char * text) override;
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(TableView * subview, TextFieldDelegate * textFieldDelegate);
|
||||
ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate);
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
|
||||
@@ -81,9 +81,9 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
|
||||
int focusRow = m_selectableTableView.selectedRow();
|
||||
HistoryViewCell * selectedCell = (HistoryViewCell *)m_selectableTableView.cellAtLocation(0, focusRow);
|
||||
HistoryViewCell::SubviewType subviewType = selectedCell->selectedSubviewType();
|
||||
m_selectableTableView.deselectTable();
|
||||
EditExpressionController * editController = (EditExpressionController *)parentResponder();
|
||||
m_calculationStore->deleteCalculationAtIndex(focusRow);
|
||||
m_selectableTableView.deselectTable();
|
||||
reload();
|
||||
if (numberOfRows()== 0) {
|
||||
app()->setFirstResponder(editController);
|
||||
|
||||
@@ -3,12 +3,20 @@
|
||||
namespace Calculation {
|
||||
|
||||
TextField::TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate) :
|
||||
::TextField(parentResponder, textBuffer, textBufferSize, delegate)
|
||||
::TextField(parentResponder, textBuffer, textBuffer, textBufferSize, delegate)
|
||||
{
|
||||
m_isEditing = true;
|
||||
}
|
||||
|
||||
bool TextField::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::Back) {
|
||||
return false;
|
||||
}
|
||||
if (event == Ion::Events::Ans) {
|
||||
if (!isEditing()) {
|
||||
setEditing(true);
|
||||
setText("");
|
||||
}
|
||||
insertTextAtLocation("ans", cursorLocation());
|
||||
setCursorLocation(cursorLocation() + strlen("ans"));
|
||||
return true;
|
||||
@@ -19,10 +27,18 @@ bool TextField::handleEvent(Ion::Events::Event event) {
|
||||
event == Ion::Events::Minus ||
|
||||
event == Ion::Events::Dot ||
|
||||
event == Ion::Events::Division)) {
|
||||
if (!isEditing()) {
|
||||
setEditing(true);
|
||||
setText("");
|
||||
}
|
||||
insertTextAtLocation("ans", cursorLocation());
|
||||
setCursorLocation(cursorLocation() + strlen("ans"));
|
||||
}
|
||||
return(::TextField::handleEvent(event));
|
||||
}
|
||||
|
||||
void TextField::setEditing(bool isEditing) {
|
||||
m_isEditing = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ class TextField : public ::TextField {
|
||||
public:
|
||||
TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate);
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void setEditing(bool isEditing) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ bool ExpressionTextFieldDelegate::cursorInToken(TextField * textField, const cha
|
||||
}
|
||||
|
||||
bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK) {
|
||||
if (event == Ion::Events::OK && textField->isEditing()) {
|
||||
Expression * exp = Expression::parse(textField->text());
|
||||
if (exp == nullptr) {
|
||||
if (textField->textLength() == 0) {
|
||||
@@ -42,14 +42,14 @@ bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField
|
||||
delete exp;
|
||||
}
|
||||
}
|
||||
if (event == Ion::Events::Toolbox) {
|
||||
if (event == Ion::Events::Toolbox && textField->isEditing()) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
|
||||
ToolboxController * toolboxController = appsContainer->toolboxController();
|
||||
toolboxController->setTextFieldCaller(textField);
|
||||
textField->app()->displayModalViewController(toolboxController, 0.f, 0.f, 50, 50, 0, 50);
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Var) {
|
||||
if (event == Ion::Events::Var && textField->isEditing()) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
|
||||
VariableBoxController * variableBoxController = appsContainer->variableBoxController();
|
||||
variableBoxController->setTextFieldCaller(textField);
|
||||
@@ -57,6 +57,10 @@ bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::XNT) {
|
||||
if (!textField->isEditing()) {
|
||||
textField->setEditing(true);
|
||||
textField->setText("");
|
||||
}
|
||||
if (cursorInToken(textField, "sum(") || cursorInToken(textField, "product(")) {
|
||||
textField->insertTextAtLocation("n", textField->cursorLocation());
|
||||
textField->setCursorLocation(textField->cursorLocation()+strlen("n"));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
FloatParameterController::FloatParameterController(Responder * parentResponder) :
|
||||
ViewController(parentResponder),
|
||||
m_selectableTableView(SelectableTableView(this, this, Metric::TopMargin, Metric::RightMargin,
|
||||
Metric::BottomMargin, Metric::LeftMargin))
|
||||
Metric::BottomMargin, Metric::LeftMargin, this))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,52 +24,27 @@ int FloatParameterController::activeCell() {
|
||||
}
|
||||
|
||||
void FloatParameterController::willDisplayCellForIndex(TableViewCell * cell, int index) {
|
||||
TextMenuListCell * myCell = (TextMenuListCell *) cell;
|
||||
EditableTextMenuListCell * myCell = (EditableTextMenuListCell *) cell;
|
||||
char buffer[Constant::FloatBufferSizeInScientificMode];
|
||||
Float(parameterAtIndex(index)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
myCell->setAccessoryText(buffer);
|
||||
}
|
||||
|
||||
bool FloatParameterController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK) {
|
||||
editParameter();
|
||||
return true;
|
||||
}
|
||||
if (event.hasText()) {
|
||||
editParameter(event.text());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(text)->approximate(*globalContext);
|
||||
setParameterAtIndex(m_selectableTableView.selectedRow(), floatBody);
|
||||
willDisplayCellForIndex(m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(),
|
||||
m_selectableTableView.selectedRow()), activeCell());
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloatParameterController::editParameter(const char * initialText) {
|
||||
/* This code assumes that the active cell remains the one which is edited
|
||||
* until the invocation is performed. This could lead to concurrency issue in
|
||||
* other cases. */
|
||||
char initialTextContent[255];
|
||||
int cursorDelta = 0;
|
||||
if (initialText) {
|
||||
strlcpy(initialTextContent, initialText, sizeof(initialTextContent));
|
||||
cursorDelta = strlen(initialText) > 1 ? -1 : 0;
|
||||
} else {
|
||||
TextMenuListCell * textMenuListCell = (TextMenuListCell *)reusableCell(activeCell());
|
||||
strlcpy(initialTextContent, textMenuListCell->accessoryText(), sizeof(initialTextContent));
|
||||
}
|
||||
int cursorLocation = strlen(initialTextContent) + cursorDelta;
|
||||
EditableTextMenuListCell * cell = (EditableTextMenuListCell *)m_selectableTableView.cellAtLocation(0, activeCell());
|
||||
cell->setParentResponder(&m_selectableTableView);
|
||||
cell->editValue(textFieldDelegate(), initialTextContent, cursorLocation, this,
|
||||
[](void * context, void * sender){
|
||||
FloatParameterController * floatParameterController = (FloatParameterController *)context;
|
||||
int activeCell = floatParameterController->activeCell();
|
||||
EditableTextMenuListCell * cell = (EditableTextMenuListCell *)sender;
|
||||
const char * textBody = cell->editedText();
|
||||
AppsContainer * appsContainer = (AppsContainer *)floatParameterController->app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(textBody)->approximate(*globalContext);
|
||||
floatParameterController->setParameterAtIndex(activeCell, floatBody);
|
||||
floatParameterController->willDisplayCellForIndex(cell, activeCell);
|
||||
});
|
||||
void FloatParameterController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
|
||||
EditableTextMenuListCell * myCell = (EditableTextMenuListCell *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY);
|
||||
myCell->setEditing(false);
|
||||
EditableTextMenuListCell * myNewCell = (EditableTextMenuListCell *)t->cellAtLocation(t->selectedColumn(), t->selectedRow());
|
||||
app()->setFirstResponder(myNewCell);
|
||||
}
|
||||
|
||||
KDCoordinate FloatParameterController::cellHeight() {
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
/* This controller edits float parameter of any model (given through
|
||||
* parameterAtIndex and setParameterAtIndex). */
|
||||
|
||||
class FloatParameterController : public ViewController, public SimpleListViewDataSource {
|
||||
class FloatParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDelegate, public TextFieldDelegate {
|
||||
public:
|
||||
FloatParameterController(Responder * parentResponder);
|
||||
int activeCell();
|
||||
void editParameter(const char * initialText = nullptr);
|
||||
virtual ExpressionTextFieldDelegate * textFieldDelegate() = 0;
|
||||
View * view() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
KDCoordinate cellHeight() override;
|
||||
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
|
||||
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
|
||||
protected:
|
||||
int activeCell();
|
||||
SelectableTableView m_selectableTableView;
|
||||
private:
|
||||
virtual float parameterAtIndex(int index) = 0;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "goto_parameter_controller.h"
|
||||
#include "../app.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace Graph {
|
||||
@@ -9,6 +10,8 @@ GoToParameterController::GoToParameterController(Responder * parentResponder, Gr
|
||||
m_graphView(graphView),
|
||||
m_function(nullptr)
|
||||
{
|
||||
m_abscisseCell.setParentResponder(&m_selectableTableView);
|
||||
m_abscisseCell.setDelegate(this);
|
||||
}
|
||||
|
||||
ExpressionTextFieldDelegate * GoToParameterController::textFieldDelegate() {
|
||||
@@ -46,4 +49,10 @@ int GoToParameterController::reusableCellCount() {
|
||||
void GoToParameterController::setFunction(Function * function) {
|
||||
m_function = function;
|
||||
}
|
||||
|
||||
bool GoToParameterController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
TableViewCell * reusableCell(int index) override;
|
||||
int reusableCellCount() override;
|
||||
void setFunction(Function * function);
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
private:
|
||||
float parameterAtIndex(int index) override;
|
||||
void setParameterAtIndex(int parameterIndex, float f) override;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "window_parameter_controller.h"
|
||||
#include "../app.h"
|
||||
#include "../../apps_container.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace Graph {
|
||||
@@ -13,6 +15,10 @@ WindowParameterController::WindowParameterController(Responder * parentResponder
|
||||
m_windowCells[1].setText("Xmax");
|
||||
m_windowCells[2].setText("Ymin");
|
||||
m_windowCells[3].setText("Ymax");
|
||||
for (int k = 0; k < k_numberOfTextCell; k++) {
|
||||
m_windowCells[k].setParentResponder(&m_selectableTableView);
|
||||
m_windowCells[k].setDelegate(this);
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionTextFieldDelegate * WindowParameterController::textFieldDelegate() {
|
||||
@@ -40,6 +46,31 @@ void WindowParameterController::willDisplayCellForIndex(TableViewCell * cell, in
|
||||
FloatParameterController::willDisplayCellForIndex(cell, index);
|
||||
}
|
||||
|
||||
bool WindowParameterController::textFieldDidFinishEditing(TextField * textField, const char * text) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(text)->approximate(*globalContext);
|
||||
setParameterAtIndex(m_selectableTableView.selectedRow(), floatBody);
|
||||
willDisplayCellForIndex(m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(),
|
||||
m_selectableTableView.selectedRow()), activeCell());
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowParameterController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
|
||||
if (previousSelectedCellX == 0 && previousSelectedCellY >= 0 && previousSelectedCellY !=2) {
|
||||
EditableTextMenuListCell * myCell = (EditableTextMenuListCell *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY);
|
||||
myCell->setEditing(false);
|
||||
app()->setFirstResponder(t);
|
||||
}
|
||||
if (t->selectedColumn() == 0 && t->selectedRow() >= 0 && t->selectedRow() !=2) {
|
||||
EditableTextMenuListCell * myNewCell = (EditableTextMenuListCell *)t->cellAtLocation(t->selectedColumn(), t->selectedRow());
|
||||
if ((t->selectedRow() == 0 || t->selectedRow() == 1) || !m_graphWindow->yAuto()) {
|
||||
app()->setFirstResponder(myNewCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowParameterController::handleEvent(Ion::Events::Event event) {
|
||||
m_graphView->initCursorPosition();
|
||||
if (activeCell() == 2) {
|
||||
@@ -53,7 +84,7 @@ bool WindowParameterController::handleEvent(Ion::Events::Event event) {
|
||||
if (m_graphWindow->yAuto() && (activeCell() == 3 || activeCell() == 4)) {
|
||||
return false;
|
||||
}
|
||||
return FloatParameterController::handleEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
float WindowParameterController::parameterAtIndex(int index) {
|
||||
@@ -109,4 +140,9 @@ int WindowParameterController::reusableCellCount() {
|
||||
return k_numberOfTextCell+1;
|
||||
}
|
||||
|
||||
bool WindowParameterController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@ public:
|
||||
TableViewCell * reusableCell(int index) override;
|
||||
int reusableCellCount() override;
|
||||
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
|
||||
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
private:
|
||||
float parameterAtIndex(int index) override;
|
||||
void setParameterAtIndex(int parameterIndex, float f) override;
|
||||
|
||||
@@ -119,19 +119,10 @@ void ListController::configureFunction(Function * function) {
|
||||
stack->push(&m_parameterController);
|
||||
}
|
||||
|
||||
void ListController::editExpression(FunctionExpressionView * functionCell, const char * initialText) {
|
||||
char initialTextContent[255];
|
||||
int cursorDelta = 0;
|
||||
if (initialText) {
|
||||
strlcpy(initialTextContent, initialText, sizeof(initialTextContent));
|
||||
cursorDelta = strlen(initialText) > 1 ? -1 : 0;
|
||||
} else {
|
||||
strlcpy(initialTextContent, functionCell->function()->text(), sizeof(initialTextContent));
|
||||
}
|
||||
int cursorLocation = strlen(initialTextContent) + cursorDelta;
|
||||
void ListController::editExpression(FunctionExpressionView * functionCell, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
InputViewController * inputController = myApp->inputViewController();
|
||||
inputController->edit(this, initialTextContent, cursorLocation, functionCell,
|
||||
inputController->edit(this, event, functionCell,
|
||||
[](void * context, void * sender){
|
||||
FunctionExpressionView * myCell = (FunctionExpressionView *) context;
|
||||
Function * myFunction = myCell->function();
|
||||
@@ -154,15 +145,11 @@ bool ListController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK) {
|
||||
return handleEnter();
|
||||
}
|
||||
if (event == Ion::Events::XNT && m_selectableTableView.selectedColumn() == 1){
|
||||
FunctionExpressionView * functionCell = (FunctionExpressionView *)(m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()));
|
||||
editExpression(functionCell, "x");
|
||||
}
|
||||
if (!event.hasText() || m_selectableTableView.selectedColumn() == 0) {
|
||||
if ((!event.hasText() && event != Ion::Events::XNT) || m_selectableTableView.selectedColumn() == 0) {
|
||||
return false;
|
||||
}
|
||||
FunctionExpressionView * functionCell = (FunctionExpressionView *)(m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()));
|
||||
editExpression(functionCell, event.text());
|
||||
editExpression(functionCell, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -188,7 +175,7 @@ bool ListController::handleEnter() {
|
||||
return false;
|
||||
}
|
||||
FunctionExpressionView * functionCell = (FunctionExpressionView *)(m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()));
|
||||
editExpression(functionCell);
|
||||
editExpression(functionCell, Ion::Events::OK);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
int reusableCellCount(int type) override;
|
||||
int typeAtLocation(int i, int j) override;
|
||||
void configureFunction(Function * function);
|
||||
void editExpression(FunctionExpressionView * functionCell, const char * initialText = nullptr);
|
||||
void editExpression(FunctionExpressionView * functionCell, Ion::Events::Event event);
|
||||
|
||||
private:
|
||||
static constexpr KDCoordinate k_verticalFunctionMargin = 50-12;
|
||||
|
||||
@@ -1,57 +1,53 @@
|
||||
#include "editable_value_cell.h"
|
||||
#include "../../apps_container.h"
|
||||
#include <assert.h>
|
||||
#include "../app.h"
|
||||
|
||||
namespace Graph {
|
||||
|
||||
EditableValueCell::EditableValueCell() :
|
||||
ValueCell(),
|
||||
EvenOddCell(),
|
||||
Responder(nullptr),
|
||||
m_textField(TextField(this, m_textBody, 255, nullptr)),
|
||||
m_isEditing(false),
|
||||
m_successAction(Invocation(nullptr, nullptr))
|
||||
m_textField(TextField(this, m_textBody, m_draftTextBody, 255, nullptr, 1.0f, 0.5f, KDColorBlack, KDColorWhite))
|
||||
{
|
||||
}
|
||||
|
||||
const char * EditableValueCell::editedText() const {
|
||||
void EditableValueCell::setDelegate(TextFieldDelegate * delegate) {
|
||||
m_textField.setTextFieldDelegate(delegate);
|
||||
}
|
||||
|
||||
void EditableValueCell::reloadCell() {
|
||||
EvenOddCell::reloadCell();
|
||||
m_textField.setBackgroundColor(backgroundColor());
|
||||
}
|
||||
|
||||
const char * EditableValueCell::text() const {
|
||||
return m_textField.text();
|
||||
}
|
||||
|
||||
void EditableValueCell::setText(const char * textContent) {
|
||||
m_textField.setText(textContent);
|
||||
}
|
||||
|
||||
int EditableValueCell::numberOfSubviews() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
View * EditableValueCell::subviewAtIndex(int index) {
|
||||
assert(index == 0);
|
||||
if (m_isEditing) {
|
||||
return &m_textField;
|
||||
}
|
||||
return &m_bufferTextView;
|
||||
return &m_textField;
|
||||
}
|
||||
|
||||
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);
|
||||
void EditableValueCell::didBecomeFirstResponder() {
|
||||
app()->setFirstResponder(&m_textField);
|
||||
m_isEditing = true;
|
||||
m_textField.setText(initialText);
|
||||
m_textField.setCursorLocation(cursorPosition);
|
||||
m_successAction = Invocation(successAction, context);
|
||||
}
|
||||
|
||||
void EditableValueCell::setEditing(bool isEditing) {
|
||||
m_textField.setEditing(isEditing);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,22 +3,24 @@
|
||||
|
||||
#include <escher.h>
|
||||
#include <poincare.h>
|
||||
#include "value_cell.h"
|
||||
|
||||
namespace Graph {
|
||||
class EditableValueCell : public ValueCell, public Responder {
|
||||
class EditableValueCell : public EvenOddCell, public Responder {
|
||||
public:
|
||||
EditableValueCell();
|
||||
const char * editedText() const;
|
||||
void setDelegate(TextFieldDelegate * delegate);
|
||||
void reloadCell() override;
|
||||
const char * text() const;
|
||||
void setText(const char * textContent);
|
||||
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);
|
||||
void didBecomeFirstResponder() override;
|
||||
void setEditing(bool isEditing);
|
||||
private:
|
||||
TextField m_textField;
|
||||
char m_textBody[255];
|
||||
bool m_isEditing;
|
||||
Invocation m_successAction;
|
||||
char m_draftTextBody[255];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "interval_parameter_controller.h"
|
||||
#include "../app.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace Graph {
|
||||
@@ -6,9 +7,9 @@ namespace Graph {
|
||||
IntervalParameterController::IntervalParameterController(Responder * parentResponder, Interval * interval) :
|
||||
FloatParameterController(parentResponder),
|
||||
m_interval(interval),
|
||||
m_intervalStartCell(EditableTextMenuListCell((char*)"X Debut")),
|
||||
m_intervalEndCell(EditableTextMenuListCell((char*)"X Fin")),
|
||||
m_intervalStepCell(EditableTextMenuListCell((char*)"Pas"))
|
||||
m_intervalStartCell(EditableTextMenuListCell((char*)"X Debut", &m_selectableTableView, this)),
|
||||
m_intervalEndCell(EditableTextMenuListCell((char*)"X Fin", &m_selectableTableView, this)),
|
||||
m_intervalStepCell(EditableTextMenuListCell((char*)"Pas", &m_selectableTableView, this))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -70,4 +71,9 @@ int IntervalParameterController::reusableCellCount() {
|
||||
return k_totalNumberOfCell;
|
||||
}
|
||||
|
||||
bool IntervalParameterController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
int numberOfRows() override;
|
||||
TableViewCell * reusableCell(int index) override;
|
||||
int reusableCellCount() override;
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
private:
|
||||
float parameterAtIndex(int index) override;
|
||||
void setParameterAtIndex(int parameterIndex, float f) override;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Graph {
|
||||
ValuesController::ValuesController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header) :
|
||||
ViewController(parentResponder),
|
||||
HeaderViewDelegate(header),
|
||||
m_selectableTableView(SelectableTableView(this, this, k_topMargin, k_rightMargin, k_bottomMargin, k_leftMargin)),
|
||||
m_selectableTableView(SelectableTableView(this, this, k_topMargin, k_rightMargin, k_bottomMargin, k_leftMargin, this)),
|
||||
m_functionStore(functionStore),
|
||||
m_intervalParameterController(IntervalParameterController(this, &m_interval)),
|
||||
m_abscissaParameterController(AbscissaParameterController(this, &m_intervalParameterController)),
|
||||
@@ -24,6 +24,10 @@ ValuesController::ValuesController(Responder * parentResponder, FunctionStore *
|
||||
m_interval.setStart(0);
|
||||
m_interval.setEnd(10);
|
||||
m_interval.setStep(1);
|
||||
for (int k = 0; k < k_maxNumberOfAbscissaCells; k++) {
|
||||
m_abscissaCells[k].setParentResponder(&m_selectableTableView);
|
||||
m_abscissaCells[k].setDelegate(this);
|
||||
}
|
||||
}
|
||||
|
||||
View * ValuesController::view() {
|
||||
@@ -195,26 +199,29 @@ bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (activeColumn() == 0) {
|
||||
editValue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activeRow() == -1) {
|
||||
return headerViewController()->handleEvent(event);
|
||||
}
|
||||
if (event.hasText()) {
|
||||
if (activeColumn() == 0 && activeRow() > 0) {
|
||||
editValue(event.text());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ValuesController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
bool ValuesController::textFieldDidFinishEditing(TextField * textField, const char * text) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(text)->approximate(*globalContext);
|
||||
m_interval.setElement(activeRow()-1, floatBody);
|
||||
willDisplayCellAtLocation(m_selectableTableView.cellAtLocation(activeColumn(), activeRow()), activeColumn(), activeRow());
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ValuesController::configureAbscissa() {
|
||||
StackViewController * stack = stackController();
|
||||
@@ -235,38 +242,16 @@ void ValuesController::configureDerivativeFunction() {
|
||||
stack->push(&m_derivativeParameterController);
|
||||
}
|
||||
|
||||
void ValuesController::editValue(const char * initialText) {
|
||||
/* This code assumes that the active cell remains the one which is edited
|
||||
* until the invocation is performed. This could lead to concurrency issue in
|
||||
* other cases. */
|
||||
char initialTextContent[255];
|
||||
int cursorDelta = 0;
|
||||
if (initialText) {
|
||||
strlcpy(initialTextContent, initialText, sizeof(initialTextContent));
|
||||
cursorDelta = strlen(initialText) > 1 ? -1 : 0;
|
||||
} else {
|
||||
if (activeRow() > m_interval.numberOfElements()) {
|
||||
initialTextContent[0] = 0;
|
||||
} else {
|
||||
Float(m_interval.element(activeRow()-1)).convertFloatToText(initialTextContent, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
}
|
||||
void ValuesController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
|
||||
if (previousSelectedCellX == 0 && previousSelectedCellY > 0) {
|
||||
EditableValueCell * myCell = (EditableValueCell *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY);
|
||||
myCell->setEditing(false);
|
||||
app()->setFirstResponder(t);
|
||||
}
|
||||
if (t->selectedRow() > 0 && t->selectedColumn() == 0) {
|
||||
EditableValueCell * myCell = (EditableValueCell *)t->cellAtLocation(t->selectedColumn(), t->selectedRow());
|
||||
app()->setFirstResponder(myCell);
|
||||
}
|
||||
int cursorLocation = strlen(initialTextContent) + cursorDelta;
|
||||
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();
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
int ValuesController::typeAtLocation(int i, int j) {
|
||||
|
||||
@@ -15,19 +15,17 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
class ValuesController : public ViewController, public HeaderViewDelegate, public TableViewDataSource, public AlternateEmptyViewDelegate {
|
||||
class ValuesController : public ViewController, public HeaderViewDelegate, public TableViewDataSource, public AlternateEmptyViewDelegate, public SelectableTableViewDelegate, public TextFieldDelegate {
|
||||
public:
|
||||
ValuesController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header);
|
||||
|
||||
int activeRow();
|
||||
int activeColumn();
|
||||
Interval * interval();
|
||||
void editValue(const char * initialText = nullptr);
|
||||
|
||||
View * view() override;
|
||||
const char * title() const override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
|
||||
|
||||
ViewController * intervalParameterController();
|
||||
int numberOfButtons() const override;
|
||||
Button * buttonAtIndex(int index) override;
|
||||
@@ -48,6 +46,8 @@ public:
|
||||
bool isEmpty() override;
|
||||
const char * emptyMessage() override;
|
||||
Responder * defaultController() override;
|
||||
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
|
||||
|
||||
|
||||
static constexpr KDCoordinate k_topMargin = 10;
|
||||
static constexpr KDCoordinate k_bottomMargin = 5;
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
static constexpr KDCoordinate k_ordinateCellWidth = 100;
|
||||
|
||||
private:
|
||||
int activeRow();
|
||||
int activeColumn();
|
||||
Function * functionAtColumn(int i);
|
||||
bool isDerivativeColumn(int i);
|
||||
Responder * tabController() const;
|
||||
|
||||
@@ -12,6 +12,8 @@ CalculationController::ContentView::ContentView(Responder * parentResponder, Law
|
||||
{
|
||||
for (int k = 0; k < k_maxNumberOfEditableFields; k++) {
|
||||
m_calculationCell[k].setParentResponder(parentResponder);
|
||||
CalculationController * parentController = (CalculationController *)parentResponder;
|
||||
m_calculationCell[k].setDelegate(parentController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,14 +60,17 @@ View * CalculationController::ContentView::subviewAtIndex(int index) {
|
||||
return &m_text[2];
|
||||
}
|
||||
if (index == 3 || index == 5 || index == 7) {
|
||||
char buffer[Constant::FloatBufferSizeInScientificMode];
|
||||
Float(m_law->calculationElementAtIndex((index - 3)/2)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
m_calculationCell[(index - 3)/2].setText(buffer);
|
||||
return &m_calculationCell[(index - 3)/2];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CalculationController::ContentView::willDisplayEditableCellAtIndex(int index) {
|
||||
char buffer[Constant::FloatBufferSizeInScientificMode];
|
||||
Float(m_law->calculationElementAtIndex(index)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
m_calculationCell[index].setText(buffer);
|
||||
}
|
||||
|
||||
void CalculationController::ContentView::layoutSubviews() {
|
||||
markRectAsDirty(bounds());
|
||||
KDCoordinate xCoordinate = 0;
|
||||
@@ -97,6 +102,10 @@ void CalculationController::ContentView::layoutSubviews() {
|
||||
m_text[2].setFrame(KDRect(xCoordinate, 0, numberOfCharacters*k_charWidth, ImageTableView::k_imageHeight));
|
||||
xCoordinate += numberOfCharacters*k_charWidth + k_textMargin;
|
||||
m_calculationCell[2].setFrame(KDRect(xCoordinate, 0, k_textFieldWidth, ImageTableView::k_imageHeight));
|
||||
|
||||
for (int k = 0; k < k_maxNumberOfEditableFields; k++) {
|
||||
willDisplayEditableCellAtIndex(k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,37 +142,12 @@ const char * CalculationController::title() const {
|
||||
}
|
||||
|
||||
bool CalculationController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK && m_highlightedSubviewIndex == 0) {
|
||||
m_contentView.imageTableView()->select(true);
|
||||
app()->setFirstResponder(m_contentView.imageTableView());
|
||||
return true;
|
||||
}
|
||||
if ((event == Ion::Events::OK || event.hasText()) && m_highlightedSubviewIndex > 0) {
|
||||
App * myApp = (App *)app();
|
||||
EditableTextCell * calculCell = m_contentView.calculationCellAtIndex(m_highlightedSubviewIndex-1);
|
||||
const char * initialText = calculCell->text();
|
||||
if (event.hasText()) {
|
||||
initialText = event.text();
|
||||
}
|
||||
calculCell->editValue(myApp, initialText, strlen(calculCell->text()), this,
|
||||
[](void * context, void * sender){
|
||||
CalculationController * calculationController = (CalculationController *)context;
|
||||
Law * law = calculationController->law();
|
||||
int highlightedSubviewIndex = calculationController->highlightedSubviewIndex();
|
||||
EditableTextCell * cell = (EditableTextCell *)sender;
|
||||
const char * textBody = cell->editedText();
|
||||
AppsContainer * appsContainer = (AppsContainer *)calculationController->app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(textBody)->approximate(*globalContext);
|
||||
law->setCalculationElementAtIndex(floatBody, highlightedSubviewIndex-1);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((event == Ion::Events::Left && m_highlightedSubviewIndex > 0) || (event == Ion::Events::Right && m_highlightedSubviewIndex < ContentView::k_maxNumberOfEditableFields - 1)) {
|
||||
if (m_highlightedSubviewIndex == 0) {
|
||||
app()->setFirstResponder(this);
|
||||
m_contentView.imageTableView()->select(false);
|
||||
m_contentView.imageTableView()->setHighlight(false);
|
||||
m_contentView.layoutSubviews();
|
||||
} else {
|
||||
EditableTextCell * calculCell = m_contentView.calculationCellAtIndex(m_highlightedSubviewIndex-1);
|
||||
calculCell->setHighlighted(false);
|
||||
@@ -172,14 +156,38 @@ bool CalculationController::handleEvent(Ion::Events::Event event) {
|
||||
if (m_highlightedSubviewIndex > 0) {
|
||||
EditableTextCell * newCalculCell = m_contentView.calculationCellAtIndex(m_highlightedSubviewIndex-1);
|
||||
newCalculCell->setHighlighted(true);
|
||||
app()->setFirstResponder(newCalculCell);
|
||||
} else {
|
||||
m_contentView.imageTableView()->setHighlight(true);
|
||||
app()->setFirstResponder(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::OK && m_highlightedSubviewIndex == 0) {
|
||||
m_contentView.imageTableView()->select(true);
|
||||
app()->setFirstResponder(m_contentView.imageTableView());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CalculationController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
bool CalculationController::textFieldDidFinishEditing(TextField * textField, const char * text) {
|
||||
AppsContainer * appsContainer = (AppsContainer *)app()->container();
|
||||
Context * globalContext = appsContainer->context();
|
||||
float floatBody = Expression::parse(text)->approximate(*globalContext);
|
||||
m_law->setCalculationElementAtIndex(floatBody, m_highlightedSubviewIndex-1);
|
||||
for (int k = 0; k < ContentView::k_maxNumberOfEditableFields; k++) {
|
||||
m_contentView.willDisplayEditableCellAtIndex(k);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CalculationController::didBecomeFirstResponder() {
|
||||
m_contentView.layoutSubviews();
|
||||
for (int subviewIndex = 0; subviewIndex < 2; subviewIndex++) {
|
||||
@@ -190,6 +198,7 @@ void CalculationController::didBecomeFirstResponder() {
|
||||
m_contentView.imageTableView()->setHighlight(false);
|
||||
EditableTextCell * calculCell = m_contentView.calculationCellAtIndex(m_highlightedSubviewIndex-1);
|
||||
calculCell->setHighlighted(true);
|
||||
app()->setFirstResponder(calculCell);
|
||||
} else {
|
||||
m_contentView.imageTableView()->setHighlight(true);
|
||||
}
|
||||
@@ -200,10 +209,6 @@ Law * CalculationController::law() {
|
||||
return m_law;
|
||||
}
|
||||
|
||||
int CalculationController::highlightedSubviewIndex() const {
|
||||
return m_highlightedSubviewIndex;
|
||||
}
|
||||
|
||||
void CalculationController::selectSubview(int subviewIndex) {
|
||||
m_highlightedSubviewIndex = subviewIndex;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace Probability {
|
||||
|
||||
class CalculationController : public ViewController {
|
||||
class CalculationController : public ViewController, public TextFieldDelegate {
|
||||
public:
|
||||
CalculationController(Responder * parentResponder, Law * law);
|
||||
View * view() override;
|
||||
@@ -16,8 +16,9 @@ public:
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
Law * law();
|
||||
int highlightedSubviewIndex() const;
|
||||
void selectSubview(int subviewIndex);
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
@@ -27,6 +28,7 @@ private:
|
||||
LawCurveView * lawCurveView();
|
||||
ImageTableView * imageTableView();
|
||||
EditableTextCell * calculationCellAtIndex(int index);
|
||||
void willDisplayEditableCellAtIndex(int index);
|
||||
constexpr static int k_maxNumberOfEditableFields = 3;
|
||||
private:
|
||||
constexpr static KDCoordinate k_textFieldWidth = 35;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "parameters_controller.h"
|
||||
#include "../constant.h"
|
||||
#include "app.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -74,6 +75,10 @@ ParametersController::ParametersController(Responder * parentResponder, Law * la
|
||||
m_buttonSelected(false),
|
||||
m_calculationController(CalculationController(nullptr, law))
|
||||
{
|
||||
for (int k = 0; k < k_maxNumberOfCells; k++) {
|
||||
m_menuListCell[k].setParentResponder(&m_selectableTableView);
|
||||
m_menuListCell[k].setDelegate(this);
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionTextFieldDelegate * ParametersController::textFieldDelegate() {
|
||||
@@ -150,7 +155,7 @@ int ParametersController::numberOfRows() {
|
||||
};
|
||||
|
||||
void ParametersController::willDisplayCellForIndex(TableViewCell * cell, int index) {
|
||||
TextMenuListCell * myCell = (TextMenuListCell *) cell;
|
||||
EditableTextMenuListCell * myCell = (EditableTextMenuListCell *) cell;
|
||||
myCell->setText(m_law->parameterNameAtIndex(index));
|
||||
FloatParameterController::willDisplayCellForIndex(cell, index);
|
||||
}
|
||||
@@ -173,5 +178,10 @@ void ParametersController::setParameterAtIndex(int parameterIndex, float f) {
|
||||
m_law->setParameterAtIndex(f, parameterIndex);
|
||||
}
|
||||
|
||||
bool ParametersController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
App * myApp = (App *)app();
|
||||
return myApp->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
|
||||
TableViewCell * reusableCell(int index) override;
|
||||
int reusableCellCount() override;
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
private:
|
||||
float parameterAtIndex(int index) override;
|
||||
void setParameterAtIndex(int parameterIndex, float f) override;
|
||||
@@ -43,7 +44,8 @@ private:
|
||||
PointerTextView m_secondParameterDefinition;
|
||||
SelectableTableView * m_selectableTableView;
|
||||
};
|
||||
EditableTextMenuListCell m_menuListCell[2];
|
||||
constexpr static int k_maxNumberOfCells = 2;
|
||||
EditableTextMenuListCell m_menuListCell[k_maxNumberOfCells];
|
||||
ContentView m_contentView;
|
||||
Law * m_law;
|
||||
bool m_buttonSelected;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef ESCHER_EDITABLE_TEXT_CELL_H
|
||||
#define ESCHER_EDITABLE_TEXT_CELL_H
|
||||
|
||||
#include <escher/buffer_text_view.h>
|
||||
#include <escher/invocation.h>
|
||||
#include <escher/responder.h>
|
||||
#include <escher/table_view_cell.h>
|
||||
#include <escher/text_field_delegate.h>
|
||||
@@ -10,25 +8,22 @@
|
||||
|
||||
class EditableTextCell : public TableViewCell, public Responder {
|
||||
public:
|
||||
EditableTextCell(Responder * parentResponder = nullptr);
|
||||
EditableTextCell(Responder * parentResponder = nullptr, TextFieldDelegate * delegate = nullptr);
|
||||
void setDelegate(TextFieldDelegate * delegate);
|
||||
void reloadCell() override;
|
||||
const char * editedText() const;
|
||||
const char * text() const;
|
||||
void setText(const char * textContent);
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void editValue(TextFieldDelegate * textFieldDelegate, const char * initialText, int cursorLocation, void * context, Invocation::Action successAction);
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
void setEditing(bool isEditing);
|
||||
private:
|
||||
constexpr static KDCoordinate k_textHeight = 12;
|
||||
constexpr static KDCoordinate k_separatorThickness = 1;
|
||||
TextField m_textField;
|
||||
char m_textBody[255];
|
||||
bool m_isEditing;
|
||||
Invocation m_successAction;
|
||||
BufferTextView m_bufferText;
|
||||
char m_draftTextBody[255];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
#ifndef ESCHER_EDITABLE_TEXT_MENU_LIST_CELL_H
|
||||
#define ESCHER_EDITABLE_TEXT_MENU_LIST_CELL_H
|
||||
|
||||
#include <escher/text_menu_list_cell.h>
|
||||
#include <escher/text_field.h>
|
||||
#include <escher/invocation.h>
|
||||
#include <escher/editable_text_cell.h>
|
||||
#include <escher/menu_list_cell.h>
|
||||
#include <escher/responder.h>
|
||||
|
||||
class EditableTextMenuListCell : public Responder, public TextMenuListCell {
|
||||
class EditableTextMenuListCell : public Responder, public MenuListCell {
|
||||
public:
|
||||
EditableTextMenuListCell(char * label = nullptr);
|
||||
EditableTextMenuListCell(char * label = nullptr, Responder * parentResponder = nullptr, TextFieldDelegate * textFieldDelegate = nullptr);
|
||||
void setDelegate(TextFieldDelegate * delegate);
|
||||
View * accessoryView() const override;
|
||||
const char * editedText() const;
|
||||
void layoutSubviews() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void editValue(TextFieldDelegate * textFieldDelegate, const char * initialText, int cursorLocation, void * context, Invocation::Action successAction);
|
||||
void didBecomeFirstResponder() override;
|
||||
void setEditing(bool isEditing);
|
||||
void reloadCell() override;
|
||||
void setAccessoryText(const char * text);
|
||||
void setTextColor(KDColor color) override;
|
||||
private:
|
||||
constexpr static KDCoordinate k_textWidth = 7*7;
|
||||
constexpr static KDCoordinate k_textHeight = 12;
|
||||
TextField m_textField;
|
||||
char m_textBody[255];
|
||||
bool m_isEditing;
|
||||
Invocation m_successAction;
|
||||
char m_draftTextBody[255];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
#include <escher/text_field.h>
|
||||
#include <escher/text_field_delegate.h>
|
||||
|
||||
class InputViewController : public ModalViewController {
|
||||
class InputViewController : public ModalViewController, TextFieldDelegate {
|
||||
public:
|
||||
InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate = nullptr);
|
||||
InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate);
|
||||
const char * title() const override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void edit(Responder * caller, const char * initialContent, int cursorPosition, void * context, Invocation::Action successAction, Invocation::Action failureAction);
|
||||
void edit(Responder * caller, Ion::Events::Event event, void * context, Invocation::Action successAction, Invocation::Action failureAction);
|
||||
const char * textBody();
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
|
||||
bool textFieldDidAbortEditing(TextField * textField, const char * text) override;
|
||||
private:
|
||||
class TextFieldController : public ViewController {
|
||||
public:
|
||||
@@ -24,11 +26,10 @@ private:
|
||||
TextField m_textField;
|
||||
char m_textBody[255];
|
||||
};
|
||||
void showInput();
|
||||
void setTextBody(const char * text);
|
||||
TextFieldController m_textFieldController;
|
||||
Invocation m_successAction;
|
||||
Invocation m_failureAction;
|
||||
TextFieldDelegate * m_textFieldDelegate;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
class TextField : public View, public Responder {
|
||||
public:
|
||||
TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate = nullptr);
|
||||
TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize, TextFieldDelegate * delegate = nullptr,
|
||||
float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite);
|
||||
// View
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
// Responder
|
||||
@@ -24,17 +25,28 @@ public:
|
||||
void setCursorLocation(int location);
|
||||
void insertTextAtLocation(const char * text, int location);
|
||||
KDSize minimalSizeForOptimalDisplay() override;
|
||||
protected:
|
||||
void setBackgroundColor(KDColor backgroundColor);
|
||||
void setTextColor(KDColor textColor);
|
||||
void setAlignment(float horizontalAlignment, float verticalAlignment);
|
||||
void reload();
|
||||
bool isEditing() const;
|
||||
virtual void setEditing(bool isEditing);
|
||||
protected:
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * className() const override;
|
||||
#endif
|
||||
bool m_isEditing;
|
||||
char * m_textBuffer;
|
||||
char * m_draftTextBuffer;
|
||||
size_t m_currentTextLength;
|
||||
size_t m_currentCursorLocation;
|
||||
private:
|
||||
size_t m_textBufferSize;
|
||||
TextFieldDelegate * m_delegate;
|
||||
float m_horizontalAlignment;
|
||||
float m_verticalAlignment;
|
||||
KDColor m_textColor;
|
||||
KDColor m_backgroundColor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,8 @@ class TextField;
|
||||
class TextFieldDelegate {
|
||||
public:
|
||||
virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) = 0;
|
||||
virtual bool textFieldDidFinishEditing(TextField * textField, const char * text) {return false;};
|
||||
virtual bool textFieldDidAbortEditing(TextField * textField, const char * text) {return false;};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,32 +3,29 @@
|
||||
#include <escher/palette.h>
|
||||
#include <assert.h>
|
||||
|
||||
EditableTextCell::EditableTextCell(Responder * parentResponder) :
|
||||
EditableTextCell::EditableTextCell(Responder * parentResponder, TextFieldDelegate * delegate) :
|
||||
TableViewCell(),
|
||||
Responder(parentResponder),
|
||||
m_textField(TextField(this, m_textBody, 255, nullptr)),
|
||||
m_isEditing(false),
|
||||
m_successAction(Invocation(nullptr, nullptr)),
|
||||
m_bufferText(BufferTextView())
|
||||
m_textField(TextField(this, m_textBody, m_draftTextBody, 255, delegate))
|
||||
{
|
||||
}
|
||||
|
||||
void EditableTextCell::setDelegate(TextFieldDelegate * delegate) {
|
||||
m_textField.setTextFieldDelegate(delegate);
|
||||
}
|
||||
|
||||
void EditableTextCell::reloadCell() {
|
||||
TableViewCell::reloadCell();
|
||||
KDColor backgroundColor = isHighlighted()? Palette::FocusCellBackgroundColor : Palette::CellBackgroundColor;
|
||||
m_bufferText.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
const char * EditableTextCell::editedText() const {
|
||||
return m_textField.text();
|
||||
m_textField.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
const char * EditableTextCell::text() const {
|
||||
return m_bufferText.text();
|
||||
return m_textField.text();
|
||||
}
|
||||
|
||||
void EditableTextCell::setText(const char * text) {
|
||||
m_bufferText.setText(text);
|
||||
m_textField.setText(text);
|
||||
}
|
||||
|
||||
int EditableTextCell::numberOfSubviews() const {
|
||||
@@ -37,42 +34,20 @@ int EditableTextCell::numberOfSubviews() const {
|
||||
|
||||
View * EditableTextCell::subviewAtIndex(int index) {
|
||||
assert(index == 0);
|
||||
if (m_isEditing) {
|
||||
return &m_textField;
|
||||
}
|
||||
return &m_bufferText;
|
||||
return &m_textField;
|
||||
}
|
||||
|
||||
void EditableTextCell::layoutSubviews() {
|
||||
KDCoordinate width = bounds().width();
|
||||
KDCoordinate height = bounds().height();
|
||||
m_textField.setFrame(KDRect(k_separatorThickness, (height - k_textHeight)/2, width - k_separatorThickness, k_textHeight));
|
||||
m_bufferText.setFrame(KDRect(k_separatorThickness, (height - k_textHeight)/2, width - k_separatorThickness, k_textHeight));
|
||||
}
|
||||
|
||||
void EditableTextCell::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDColor backgroundColor = isHighlighted() ? Palette::FocusCellBackgroundColor : Palette::CellBackgroundColor;
|
||||
ctx->fillRect(rect, backgroundColor);
|
||||
}
|
||||
|
||||
bool EditableTextCell::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 EditableTextCell::editValue(TextFieldDelegate * textFieldDelegate, const char * initialText, int cursorPosition, void * context, Invocation::Action successAction) {
|
||||
markRectAsDirty(bounds());
|
||||
m_textField.setTextFieldDelegate(textFieldDelegate);
|
||||
void EditableTextCell::didBecomeFirstResponder() {
|
||||
app()->setFirstResponder(&m_textField);
|
||||
m_isEditing = true;
|
||||
m_textField.setText(initialText);
|
||||
m_textField.setCursorLocation(cursorPosition);
|
||||
m_successAction = Invocation(successAction, context);
|
||||
}
|
||||
|
||||
void EditableTextCell::setEditing(bool isEditing) {
|
||||
m_textField.setEditing(isEditing);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
#include <escher/editable_text_menu_list_cell.h>
|
||||
#include <escher/app.h>
|
||||
|
||||
EditableTextMenuListCell::EditableTextMenuListCell(char * label) :
|
||||
Responder(nullptr),
|
||||
TextMenuListCell(label),
|
||||
m_textField(TextField(this, m_textBody, 255, nullptr)),
|
||||
m_isEditing(false),
|
||||
m_successAction(Invocation(nullptr, nullptr))
|
||||
EditableTextMenuListCell::EditableTextMenuListCell(char * label, Responder * parentResponder, TextFieldDelegate * textFieldDelegate) :
|
||||
Responder(parentResponder),
|
||||
MenuListCell(label),
|
||||
m_textField(TextField(this, m_textBody, m_draftTextBody, 255, textFieldDelegate))
|
||||
{
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::setDelegate(TextFieldDelegate * delegate) {
|
||||
m_textField.setTextFieldDelegate(delegate);
|
||||
}
|
||||
|
||||
View * EditableTextMenuListCell::accessoryView() const {
|
||||
if (m_isEditing) {
|
||||
return (View *)&m_textField;
|
||||
}
|
||||
return (View *)&m_accessoryView;
|
||||
return (View *)&m_textField;
|
||||
}
|
||||
|
||||
const char * EditableTextMenuListCell::editedText() const {
|
||||
@@ -22,32 +21,31 @@ const char * EditableTextMenuListCell::editedText() const {
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::layoutSubviews() {
|
||||
TextMenuListCell::layoutSubviews();
|
||||
MenuListCell::layoutSubviews();
|
||||
KDCoordinate width = bounds().width();
|
||||
KDCoordinate height = bounds().height();
|
||||
m_textField.setFrame(KDRect(width - k_textWidth - k_separatorThickness, (height - k_textHeight)/2, k_textWidth - k_separatorThickness, k_textHeight));
|
||||
m_accessoryView.setFrame(KDRect(width - k_textWidth - k_separatorThickness, (height - k_textHeight)/2, k_textWidth - k_separatorThickness, k_textHeight));
|
||||
}
|
||||
|
||||
bool EditableTextMenuListCell::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 EditableTextMenuListCell::editValue(TextFieldDelegate * textFieldDelegate, const char * initialText, int cursorPosition, void * context, Invocation::Action successAction) {
|
||||
markRectAsDirty(bounds());
|
||||
m_textField.setTextFieldDelegate(textFieldDelegate);
|
||||
void EditableTextMenuListCell::didBecomeFirstResponder() {
|
||||
app()->setFirstResponder(&m_textField);
|
||||
m_isEditing = true;
|
||||
m_textField.setText(initialText);
|
||||
m_textField.setCursorLocation(cursorPosition);
|
||||
m_successAction = Invocation(successAction, context);
|
||||
}
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::setEditing(bool isEditing) {
|
||||
m_textField.setEditing(isEditing);
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::reloadCell() {
|
||||
MenuListCell::reloadCell();
|
||||
KDColor backgroundColor = isHighlighted()? Palette::FocusCellBackgroundColor : Palette::CellBackgroundColor;
|
||||
m_textField.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::setAccessoryText(const char * text) {
|
||||
m_textField.setText(text);
|
||||
}
|
||||
|
||||
void EditableTextMenuListCell::setTextColor(KDColor color) {
|
||||
m_textField.setTextColor(color);
|
||||
MenuListCell::setTextColor(color);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
InputViewController::TextFieldController::TextFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate) :
|
||||
ViewController(parentResponder),
|
||||
m_textField(parentResponder, m_textBody, 255, textFieldDelegate)
|
||||
m_textField(parentResponder, m_textBody, m_textBody, 255, textFieldDelegate)
|
||||
{
|
||||
m_textBody[0] = 0;
|
||||
}
|
||||
@@ -23,9 +23,10 @@ TextField * InputViewController::TextFieldController::textField() {
|
||||
|
||||
InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate) :
|
||||
ModalViewController(parentResponder, child),
|
||||
m_textFieldController(TextFieldController(this, textFieldDelegate)),
|
||||
m_textFieldController(TextFieldController(this, this)),
|
||||
m_successAction(Invocation(nullptr, nullptr)),
|
||||
m_failureAction(Invocation(nullptr, nullptr))
|
||||
m_failureAction(Invocation(nullptr, nullptr)),
|
||||
m_textFieldDelegate(textFieldDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -37,35 +38,27 @@ const char * InputViewController::textBody() {
|
||||
return m_textFieldController.textField()->text();
|
||||
}
|
||||
|
||||
void InputViewController::showInput() {
|
||||
void InputViewController::edit(Responder * caller, Ion::Events::Event event, void * context, Invocation::Action successAction, Invocation::Action failureAction) {
|
||||
m_successAction = Invocation(successAction, context);
|
||||
m_failureAction = Invocation(failureAction, context);
|
||||
m_textFieldController.textField()->handleEvent(event);
|
||||
displayModalViewController(&m_textFieldController, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void InputViewController::setTextBody(const char * text) {
|
||||
m_textFieldController.textField()->setText(text);
|
||||
bool InputViewController::textFieldDidFinishEditing(TextField * textField, const char * text) {
|
||||
m_successAction.perform(this);
|
||||
m_textFieldController.textField()->setText("");
|
||||
dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputViewController::handleEvent(Ion::Events::Event event) {
|
||||
if (!isDisplayingModal()) {
|
||||
return false;
|
||||
}
|
||||
if (event == Ion::Events::OK) {
|
||||
m_successAction.perform(this);
|
||||
dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Back) {
|
||||
m_failureAction.perform(this);
|
||||
dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool InputViewController::textFieldDidAbortEditing(TextField * textField, const char * text) {
|
||||
m_failureAction.perform(this);
|
||||
m_textFieldController.textField()->setText("");
|
||||
dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputViewController::edit(Responder * caller, const char * initialContent, int cursorPosition, void * context, Invocation::Action successAction, Invocation::Action failureAction) {
|
||||
m_successAction = Invocation(successAction, context);
|
||||
m_failureAction = Invocation(failureAction, context);
|
||||
setTextBody(initialContent);
|
||||
m_textFieldController.textField()->setCursorLocation(cursorPosition);
|
||||
showInput();
|
||||
bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||
return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,13 @@ void SelectableTableView::deselectTable() {
|
||||
TableViewCell * previousCell = cellAtLocation(m_selectedCellX, m_selectedCellY);
|
||||
previousCell->setHighlighted(false);
|
||||
}
|
||||
int previousSelectedCellX = m_selectedCellX;
|
||||
int previousSelectedCellY = m_selectedCellY;
|
||||
m_selectedCellX = 0;
|
||||
m_selectedCellY = -1;
|
||||
if (m_delegate) {
|
||||
m_delegate->tableViewDidChangeSelection(this, previousSelectedCellX, previousSelectedCellY);
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectableTableView::selectCellAtLocation(int i, int j) {
|
||||
|
||||
@@ -1,22 +1,38 @@
|
||||
#include <escher/text_field.h>
|
||||
#include <assert.h>
|
||||
|
||||
TextField::TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate) :
|
||||
TextField::TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer,
|
||||
size_t textBufferSize, TextFieldDelegate * delegate,
|
||||
float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) :
|
||||
View(),
|
||||
Responder(parentResponder),
|
||||
m_isEditing(false),
|
||||
m_textBuffer(textBuffer),
|
||||
m_draftTextBuffer(draftTextBuffer),
|
||||
m_currentTextLength(0),
|
||||
m_currentCursorLocation(0),
|
||||
m_textBufferSize(textBufferSize),
|
||||
m_delegate(delegate)
|
||||
m_delegate(delegate),
|
||||
m_horizontalAlignment(horizontalAlignment),
|
||||
m_verticalAlignment(verticalAlignment),
|
||||
m_textColor(textColor),
|
||||
m_backgroundColor(backgroundColor)
|
||||
{
|
||||
}
|
||||
|
||||
/* View */
|
||||
const char * TextField::text() const {
|
||||
if (m_isEditing) {
|
||||
return (const char *)m_draftTextBuffer;
|
||||
}
|
||||
return (const char *)m_textBuffer;
|
||||
}
|
||||
|
||||
void TextField::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(rect, KDColorWhite);
|
||||
ctx->drawString(m_textBuffer, KDPointZero);
|
||||
ctx->fillRect(rect, m_backgroundColor);
|
||||
KDSize textSize = KDText::stringSize(text());
|
||||
KDPoint origin(m_horizontalAlignment*(m_frame.width() - textSize.width()),
|
||||
m_verticalAlignment*(m_frame.height() - textSize.height()));
|
||||
ctx->drawString(text(), origin, m_textColor, m_backgroundColor);
|
||||
}
|
||||
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
@@ -25,13 +41,29 @@ const char * TextField::className() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
void TextField::reload() {
|
||||
KDSize sizeText = KDText::stringSize(m_textBuffer);
|
||||
KDRect dirtyZone(0, 0, sizeText.width(), sizeText.height());
|
||||
markRectAsDirty(dirtyZone);
|
||||
void TextField::setBackgroundColor(KDColor backgroundColor) {
|
||||
m_backgroundColor = backgroundColor;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
/* Responder */
|
||||
void TextField::setTextColor(KDColor textColor) {
|
||||
m_textColor = textColor;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
void TextField::setAlignment(float horizontalAlignment, float verticalAlignment) {
|
||||
m_horizontalAlignment = horizontalAlignment;
|
||||
m_verticalAlignment = verticalAlignment;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
void TextField::reload() {
|
||||
KDSize textSize = KDText::stringSize(text());
|
||||
KDPoint origin(m_horizontalAlignment*(m_frame.width() - textSize.width()),
|
||||
m_verticalAlignment*(m_frame.height() - textSize.height()));
|
||||
KDRect dirtyZone(origin, textSize);
|
||||
markRectAsDirty(dirtyZone);
|
||||
}
|
||||
|
||||
bool TextField::handleEvent(Ion::Events::Event event) {
|
||||
if (m_delegate) {
|
||||
@@ -39,43 +71,63 @@ bool TextField::handleEvent(Ion::Events::Event event) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event == Ion::Events::Left) {
|
||||
if (event == Ion::Events::OK) {
|
||||
if (m_isEditing) {
|
||||
strlcpy(m_textBuffer, m_draftTextBuffer, m_textBufferSize);
|
||||
setEditing(false);
|
||||
m_delegate->textFieldDidFinishEditing(this, text());
|
||||
return true;
|
||||
}
|
||||
setEditing(true);
|
||||
strlcpy(m_draftTextBuffer, m_textBuffer, m_textBufferSize);
|
||||
setCursorLocation(strlen(m_draftTextBuffer));
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Left && m_isEditing) {
|
||||
if (m_currentCursorLocation > 0) {
|
||||
m_currentCursorLocation--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Right) {
|
||||
if (event == Ion::Events::Right && m_isEditing) {
|
||||
if (m_currentCursorLocation < m_currentTextLength) {
|
||||
m_currentCursorLocation++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Backspace) {
|
||||
if (event == Ion::Events::Backspace && m_isEditing) {
|
||||
if (m_currentCursorLocation > 0) {
|
||||
reload();
|
||||
m_currentTextLength--;
|
||||
m_currentCursorLocation--;
|
||||
for (int k = m_currentCursorLocation; k < m_currentTextLength; k ++) {
|
||||
m_textBuffer[k] = m_textBuffer[k+1];
|
||||
m_draftTextBuffer[k] = m_draftTextBuffer[k+1];
|
||||
}
|
||||
m_textBuffer[m_currentTextLength] = 0;
|
||||
m_draftTextBuffer[m_currentTextLength] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (event.hasText()) {
|
||||
insertTextAtLocation(event.text(), cursorLocation());
|
||||
if (m_isEditing) {
|
||||
insertTextAtLocation(event.text(), cursorLocation());
|
||||
} else {
|
||||
strlcpy(m_draftTextBuffer, event.text(), m_textBufferSize);
|
||||
m_currentTextLength = strlen(event.text());
|
||||
setCursorLocation(0);
|
||||
}
|
||||
int cursorDelta = strlen(event.text()) > 1 ? -1 : 0;
|
||||
setCursorLocation(cursorLocation() + strlen(event.text()) + cursorDelta);
|
||||
setEditing(true);
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Back && m_isEditing) {
|
||||
m_delegate->textFieldDidAbortEditing(this, text());
|
||||
setEditing(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * TextField::text() const {
|
||||
return (const char *)m_textBuffer;
|
||||
}
|
||||
|
||||
int TextField::textLength() const {
|
||||
assert(strlen(text()) == m_currentTextLength);
|
||||
return m_currentTextLength;
|
||||
@@ -83,9 +135,13 @@ int TextField::textLength() const {
|
||||
|
||||
void TextField::setText(const char * text) {
|
||||
reload();
|
||||
strlcpy(m_textBuffer, text, m_textBufferSize);
|
||||
m_currentCursorLocation = strlen(text);
|
||||
m_currentTextLength = m_currentCursorLocation;
|
||||
if (m_isEditing) {
|
||||
strlcpy(m_draftTextBuffer, text, m_textBufferSize);
|
||||
m_currentCursorLocation = strlen(text);
|
||||
m_currentTextLength = m_currentCursorLocation;
|
||||
} else {
|
||||
strlcpy(m_textBuffer, text, m_textBufferSize);
|
||||
}
|
||||
reload();
|
||||
}
|
||||
|
||||
@@ -105,19 +161,31 @@ void TextField::insertTextAtLocation(const char * text, int location) {
|
||||
return;
|
||||
}
|
||||
for (int k = m_currentTextLength; k >= location && k >= 0; k--) {
|
||||
m_textBuffer[k+textSize] = m_textBuffer[k];
|
||||
m_draftTextBuffer[k+textSize] = m_draftTextBuffer[k];
|
||||
}
|
||||
strlcpy(&m_textBuffer[location], text, textSize);
|
||||
m_textBuffer[location+textSize-1] = text[textSize-1];
|
||||
strlcpy(&m_draftTextBuffer[location], text, textSize);
|
||||
m_draftTextBuffer[location+textSize-1] = text[textSize-1];
|
||||
m_currentTextLength += textSize;
|
||||
reload();
|
||||
}
|
||||
|
||||
KDSize TextField::minimalSizeForOptimalDisplay() {
|
||||
KDSize textSize = KDText::stringSize(m_textBuffer);
|
||||
KDSize textSize = KDText::stringSize(m_draftTextBuffer);
|
||||
return KDSize(0, textSize.height());
|
||||
}
|
||||
|
||||
void TextField::setTextFieldDelegate(TextFieldDelegate * delegate) {
|
||||
m_delegate = delegate;
|
||||
}
|
||||
|
||||
bool TextField::isEditing() const {
|
||||
return m_isEditing;
|
||||
}
|
||||
|
||||
void TextField::setEditing(bool isEditing) {
|
||||
if (m_isEditing == isEditing) {
|
||||
return;
|
||||
}
|
||||
m_isEditing = isEditing;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user