[escher] Add toolbox event handling in responder [apps] Correct the text

field delegate app accordingly

Change-Id: I180fe53aaa1e0929b357d3985f584937fba2ecca
This commit is contained in:
Émilie Feral
2017-02-15 17:53:13 +01:00
parent 5b73eed76a
commit c584d1fb4e
22 changed files with 175 additions and 136 deletions

View File

@@ -3,6 +3,8 @@
#include "../apps_container.h"
#include <assert.h>
using namespace Shared;
namespace Calculation {
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate) :
@@ -75,11 +77,6 @@ void EditExpressionController::didBecomeFirstResponder() {
app()->setFirstResponder(m_contentView.textField());
}
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) {
App * calculationApp = (App *)app();
m_calculationStore->push(textBody(), calculationApp->localContext());
@@ -89,4 +86,8 @@ bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField
return true;
}
TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() {
return (App *)app();
}
}

View File

@@ -5,11 +5,12 @@
#include "history_controller.h"
#include "calculation_store.h"
#include "text_field.h"
#include "../shared/text_field_delegate.h"
namespace Calculation {
class HistoryController;
class EditExpressionController : public ViewController, public TextFieldDelegate {
class EditExpressionController : public ViewController, public Shared::TextFieldDelegate {
public:
EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore);
View * view() override;
@@ -18,7 +19,6 @@ public:
bool handleEvent(Ion::Events::Event event) override;
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 {
@@ -35,6 +35,7 @@ private:
TextField m_textField;
char m_textBody[255];
};
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
ContentView m_contentView;
HistoryController * m_historyController;
CalculationStore * m_calculationStore;

View File

@@ -7,6 +7,7 @@
#include <assert.h>
using namespace Poincare;
using namespace Shared;
namespace Probability {
@@ -198,11 +199,6 @@ bool CalculationController::handleEvent(Ion::Events::Event event) {
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) {
App * probaApp = (App *)app();
Context * globalContext = probaApp->container()->globalContext();
@@ -251,4 +247,8 @@ void CalculationController::updateTitle() {
m_titleBuffer[currentChar-1] = 0;
}
TextFieldDelegateApp * CalculationController::textFieldDelegateApp() {
return (App *)app();
}
}

View File

@@ -6,10 +6,11 @@
#include "law_curve_view.h"
#include "image_table_view.h"
#include "calculation/calculation.h"
#include "../shared/text_field_delegate.h"
namespace Probability {
class CalculationController : public ViewController, public TextFieldDelegate {
class CalculationController : public ViewController, public Shared::TextFieldDelegate {
public:
CalculationController(Responder * parentResponder);
View * view() override;
@@ -20,10 +21,10 @@ public:
bool handleEvent(Ion::Events::Event event) override;
void didBecomeFirstResponder() override;
void selectSubview(int subviewIndex);
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
private:
void updateTitle();
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
Calculation * m_calculation;
class ContentView : public View {
public:

View File

@@ -5,7 +5,6 @@ app_objs += $(addprefix apps/shared/,\
curve_view_cursor.o\
curve_view_range.o\
editable_cell_table_view_controller.o\
expression_text_field_delegate.o\
float_pair_store.o\
float_parameter_controller.o\
function.o\
@@ -20,6 +19,7 @@ app_objs += $(addprefix apps/shared/,\
range_parameter_controller.o\
store_controller.o\
store_parameter_controller.o\
text_field_delegate.o\
text_field_delegate_app.o\
zoom_parameter_controller.o\
)

View File

@@ -19,11 +19,6 @@ View * EditableCellTableViewController::view() {
return &m_selectableTableView;
}
bool EditableCellTableViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
return myApp->textFieldDidReceiveEvent(textField, event);
}
bool EditableCellTableViewController::textFieldDidFinishEditing(TextField * textField, const char * text) {
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
Context * globalContext = appsContainer->globalContext();
@@ -105,9 +100,12 @@ void EditableCellTableViewController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_selectableTableView);
}
void EditableCellTableViewController::viewWillAppear() {
m_selectableTableView.reloadData();
}
TextFieldDelegateApp * EditableCellTableViewController::textFieldDelegateApp() {
return (TextFieldDelegateApp *)app();
}
}

View File

@@ -3,6 +3,7 @@
#include <escher.h>
#include <poincare.h>
#include "text_field_delegate.h"
namespace Shared {
@@ -12,7 +13,6 @@ public:
KDCoordinate rightMargin, KDCoordinate bottomMargin, KDCoordinate leftMargin);
virtual View * view() override;
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
@@ -27,6 +27,7 @@ public:
protected:
SelectableTableView m_selectableTableView;
private:
TextFieldDelegateApp * textFieldDelegateApp() override;
static constexpr KDCoordinate k_cellHeight = 20;
virtual bool cellAtLocationIsEditable(int columnIndex, int rowIndex) = 0;
virtual void setDataAtLocation(float floatBody, int columnIndex, int rowIndex) = 0;

View File

@@ -1,83 +0,0 @@
#include "expression_text_field_delegate.h"
#include "../apps_container.h"
#include <math.h>
#include <string.h>
using namespace Poincare;
namespace Shared {
const char * ExpressionTextFieldDelegate::XNT() {
return "x";
}
bool ExpressionTextFieldDelegate::cursorInToken(TextField * textField, const char * token) {
const char * text = textField->text();
int location = textField->cursorLocation();
int tokenLength = strlen(token);
while (text[location] != '(') {
location --;
}
if (location - tokenLength < 0) {
return false;
}
char previousToken[10];
strlcpy(previousToken, text+location-tokenLength, tokenLength+1);
if (strcmp(previousToken, token) == 0) {
return true;
}
return false;
}
bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
if (event == Ion::Events::OK && textField->isEditing()) {
Expression * exp = Expression::parse(textField->text());
if (exp == nullptr) {
if (textField->textLength() == 0) {
return true;
}
textField->app()->displayWarning("Attention a la syntaxe jeune padawan");
return true;
}
Expression * evaluation = exp->evaluate(*localContext());
if (evaluation == nullptr) {
delete exp;
textField->app()->displayWarning("Relis ton cours de maths, veux tu?");
return true;
} else {
delete evaluation;
delete exp;
}
}
if (event == Ion::Events::Toolbox) {
AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
MathToolbox * toolboxController = appsContainer->mathToolbox();
toolboxController->setSender(textField);
textField->app()->displayModalViewController(toolboxController, 0.f, 0.f, 50, 50, 0, 50);
return true;
}
if (event == Ion::Events::Var) {
AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
VariableBoxController * variableBoxController = appsContainer->variableBoxController();
variableBoxController->setTextFieldCaller(textField);
textField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, 50, 50, 0, 50);
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"));
return true;
}
textField->insertTextAtLocation(XNT(), textField->cursorLocation());
textField->setCursorLocation(textField->cursorLocation()+strlen(XNT()));
return true;
}
return false;
}
}

View File

@@ -1,20 +0,0 @@
#ifndef SHARED_EXPRESSION_TEXT_FIELD_DELEGATE_H
#define SHARED_EXPRESSION_TEXT_FIELD_DELEGATE_H
#include <escher.h>
#include <poincare.h>
namespace Shared {
class ExpressionTextFieldDelegate : public TextFieldDelegate {
public:
virtual Poincare::Context * localContext() = 0;
virtual const char * XNT();
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
private:
bool cursorInToken(TextField * textField, const char * token);
};
}
#endif

View File

@@ -45,11 +45,6 @@ bool FloatParameterController::textFieldDidFinishEditing(TextField * textField,
return true;
}
bool FloatParameterController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
return myApp->textFieldDidReceiveEvent(textField, event);
}
void FloatParameterController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
EditableTextMenuListCell * myCell = (EditableTextMenuListCell *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY);
myCell->setEditing(false);
@@ -57,6 +52,10 @@ void FloatParameterController::tableViewDidChangeSelection(SelectableTableView *
app()->setFirstResponder(myNewCell);
}
TextFieldDelegateApp * FloatParameterController::textFieldDelegateApp() {
return (TextFieldDelegateApp *)app();
}
KDCoordinate FloatParameterController::cellHeight() {
return Metric::ParameterCellHeight;
}

View File

@@ -2,7 +2,7 @@
#define SHARED_FLOAT_PARAMETER_CONTROLLER_H
#include <escher.h>
#include "expression_text_field_delegate.h"
#include "text_field_delegate.h"
namespace Shared {
@@ -17,12 +17,12 @@ public:
KDCoordinate cellHeight() override;
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text) override;
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
protected:
int activeCell();
SelectableTableView m_selectableTableView;
private:
TextFieldDelegateApp * textFieldDelegateApp() override;
virtual float parameterAtIndex(int index) = 0;
virtual void setParameterAtIndex(int parameterIndex, float f) = 0;
};

View File

@@ -0,0 +1,15 @@
#include "text_field_delegate.h"
using namespace Poincare;
namespace Shared {
bool TextFieldDelegate::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) {
return textFieldDelegateApp()->textFieldDidReceiveEvent(textField, event);
}
Toolbox * TextFieldDelegate::toolboxForTextField(::TextField * textField) {
return textFieldDelegateApp()->toolboxForTextField(textField);
}
}

View File

@@ -0,0 +1,20 @@
#ifndef SHARED_TEXT_FIELD_DELEGATE_H
#define SHARED_TEXT_FIELD_DELEGATE_H
#include <escher.h>
#include "text_field_delegate_app.h"
#include <poincare.h>
namespace Shared {
class TextFieldDelegate : public ::TextFieldDelegate {
public:
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
Toolbox * toolboxForTextField(TextField * textField) override;
private:
virtual TextFieldDelegateApp * textFieldDelegateApp() = 0;
};
}
#endif

View File

@@ -1,5 +1,7 @@
#include "text_field_delegate_app.h"
#include "../apps_container.h"
#include <math.h>
#include <string.h>
using namespace Poincare;
@@ -8,7 +10,7 @@ namespace Shared {
TextFieldDelegateApp::TextFieldDelegateApp(Container * container, ViewController * rootViewController, const char * name,
const char * upperName, const Image * icon) :
::App(container, rootViewController, name, upperName, icon),
ExpressionTextFieldDelegate()
TextFieldDelegate()
{
}
@@ -20,4 +22,74 @@ AppsContainer * TextFieldDelegateApp::container() {
return (AppsContainer *)app()->container();
}
const char * TextFieldDelegateApp::XNT() {
return "x";
}
bool TextFieldDelegateApp::cursorInToken(TextField * textField, const char * token) {
const char * text = textField->text();
int location = textField->cursorLocation();
int tokenLength = strlen(token);
while (text[location] != '(') {
location --;
}
if (location - tokenLength < 0) {
return false;
}
char previousToken[10];
strlcpy(previousToken, text+location-tokenLength, tokenLength+1);
if (strcmp(previousToken, token) == 0) {
return true;
}
return false;
}
bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
if (event == Ion::Events::OK && textField->isEditing()) {
Expression * exp = Expression::parse(textField->text());
if (exp == nullptr) {
if (textField->textLength() == 0) {
return true;
}
textField->app()->displayWarning("Attention a la syntaxe jeune padawan");
return true;
}
Expression * evaluation = exp->evaluate(*localContext());
if (evaluation == nullptr) {
delete exp;
textField->app()->displayWarning("Relis ton cours de maths, veux tu?");
return true;
} else {
delete evaluation;
delete exp;
}
}
if (event == Ion::Events::Var) {
AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
VariableBoxController * variableBoxController = appsContainer->variableBoxController();
variableBoxController->setTextFieldCaller(textField);
textField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, 50, 50, 0, 50);
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"));
return true;
}
textField->insertTextAtLocation(XNT(), textField->cursorLocation());
textField->setCursorLocation(textField->cursorLocation()+strlen(XNT()));
return true;
}
return false;
}
Toolbox * TextFieldDelegateApp::toolboxForTextField(TextField * textField) {
return container()->mathToolbox();
}
}

View File

@@ -2,17 +2,22 @@
#define SHARED_TEXT_FIELD_DELEGATE_APP_H
#include <escher.h>
#include "expression_text_field_delegate.h"
#include <poincare.h>
class AppsContainer;
namespace Shared {
class TextFieldDelegateApp : public ::App, public ExpressionTextFieldDelegate {
class TextFieldDelegateApp : public ::App, public TextFieldDelegate {
public:
TextFieldDelegateApp(Container * container, ViewController * rootViewController, const char * name = nullptr, const char * upperName = nullptr, const Image * icon = nullptr);
virtual Poincare::Context * localContext() override;
virtual Poincare::Context * localContext();
AppsContainer * container();
virtual const char * XNT();
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
Toolbox * toolboxForTextField(TextField * textField) override;
private:
bool cursorInToken(TextField * textField, const char * token);
};
}

View File

@@ -15,6 +15,7 @@ public:
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;
Toolbox * toolboxForTextField(TextField * textFied) override;
private:
class TextFieldController : public ViewController {
public:

View File

@@ -4,6 +4,7 @@
#include <ion.h>
class App;
class Toolbox;
class Responder {
public:
@@ -15,6 +16,7 @@ public:
Responder * parentResponder() const;
void setParentResponder(Responder * responder);
App * app();
virtual Toolbox * toolbox();
private:
Responder * m_parentResponder;
};

View File

@@ -11,6 +11,7 @@ public:
TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize,
TextFieldDelegate * delegate = nullptr, KDText::FontSize size = KDText::FontSize::Large, float horizontalAlignment = 0.0f,
float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite);
Toolbox * toolbox() override;
// View
void drawRect(KDContext * ctx, KDRect rect) const override;
// Responder

View File

@@ -8,6 +8,7 @@ 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;};
virtual Toolbox * toolboxForTextField(TextField * textFied) = 0;
};
#endif

View File

@@ -64,3 +64,7 @@ bool InputViewController::textFieldDidAbortEditing(TextField * textField, const
bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event);
}
Toolbox * InputViewController::toolboxForTextField(TextField * textField) {
return m_textFieldDelegate->toolboxForTextField(textField);
}

View File

@@ -1,5 +1,6 @@
#include <escher/responder.h>
#include <escher/app.h>
#include <escher/toolbox.h>
#include <assert.h>
Responder::Responder(Responder * parentResponder) :
@@ -16,6 +17,11 @@ void Responder::setParentResponder(Responder * responder) {
}
bool Responder::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Toolbox && toolbox() != nullptr) {
toolbox()->setSender(this);
app()->displayModalViewController(toolbox(), 0.f, 0.f, 50, 50, 0, 50);
return true;
}
return false;
}
@@ -38,3 +44,7 @@ App * Responder::app() {
assert(result->m_magic == App::Magic); // Poor man's RTTI
return result;
}
Toolbox * Responder::toolbox() {
return nullptr;
}

View File

@@ -21,6 +21,13 @@ TextField::TextField(Responder * parentResponder, char * textBuffer, char * draf
{
}
Toolbox * TextField::toolbox() {
if (m_delegate) {
return m_delegate->toolboxForTextField(this);
}
return nullptr;
}
const char * TextField::text() const {
if (m_isEditing) {
return (const char *)m_draftTextBuffer;
@@ -67,6 +74,9 @@ void TextField::reload() {
}
bool TextField::handleEvent(Ion::Events::Event event) {
if (Responder::handleEvent(event)) {
return true;
}
if (m_delegate) {
if (m_delegate->textFieldDidReceiveEvent(this, event)) {
return true;