Merge changes I180fe53a,Ie273b6d7

* changes:
  [escher] Add toolbox event handling in responder [apps] Correct the text field delegate app accordingly
  [apps] Merge toolboxcontroller and node list controller
This commit is contained in:
Émilie Feral
2017-02-20 17:55:01 +01:00
committed by Gerrit
35 changed files with 565 additions and 541 deletions

View File

@@ -16,10 +16,9 @@ app_objs += $(addprefix apps/,\
constant.o\
global_preferences.o\
main.o\
math_toolbox.o\
node.o\
node_list_view_controller.o\
title_bar_view.o\
toolbox_controller.o\
toolbox_leaf_cell.o\
toolbox_node.o\
variable_box_controller.o\

View File

@@ -48,8 +48,8 @@ Context * AppsContainer::globalContext() {
return &m_globalContext;
}
ToolboxController * AppsContainer::toolboxController() {
return &m_toolboxController;
MathToolbox * AppsContainer::mathToolbox() {
return &m_mathToolbox;
}
VariableBoxController * AppsContainer::variableBoxController() {

View File

@@ -10,7 +10,7 @@
#include "settings/app.h"
#include "statistics/app.h"
#include "apps_window.h"
#include "toolbox_controller.h"
#include "math_toolbox.h"
#include "variable_box_controller.h"
#define USE_PIC_VIEW_APP 0
@@ -25,7 +25,7 @@ public:
int numberOfApps();
App * appAtIndex(int index);
Poincare::Context * globalContext();
ToolboxController * toolboxController();
MathToolbox * mathToolbox();
VariableBoxController * variableBoxController();
bool handleEvent(Ion::Events::Event event) override;
void switchTo(App * app) override;
@@ -46,7 +46,7 @@ private:
PicViewApp m_picViewApp;
#endif
Poincare::GlobalContext m_globalContext;
ToolboxController m_toolboxController;
MathToolbox m_mathToolbox;
VariableBoxController m_variableBoxController;
};

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;

273
apps/math_toolbox.cpp Normal file
View File

@@ -0,0 +1,273 @@
#include "math_toolbox.h"
#include <assert.h>
#include <string.h>
/* TODO: find a shorter way to initiate tree models
* We create one model tree: each node keeps the label of the row it refers to
* and the text which would be edited by clicking on the row. When the node is a
* subtree, the edited text is set at nullptr. */
const ToolboxNode calculChildren[4] = {ToolboxNode("diff(,)", "Nombre derive"), ToolboxNode("int(,,)", "Integrale"), ToolboxNode("sum(,,)", "Somme"), ToolboxNode("product(,,)", "Produit")};
const ToolboxNode complexChildren[5] = {ToolboxNode("abs()", "Module"), ToolboxNode("arg()", "Argument"), ToolboxNode("re()", "Partie reelle"), ToolboxNode("im()", "Partie imaginaire"), ToolboxNode("conj()", "Conjugue")};
const ToolboxNode probabilityChildren[4] = {ToolboxNode("binomial()", "Combinaison"), ToolboxNode("permute(,)", "Arrangement"), ToolboxNode("random(,)", "Nombre aleatoire"), ToolboxNode("gamma()", "Fonction gamma")};
const ToolboxNode arithmeticChildren[4] = {ToolboxNode("gcd()", "PGCD"), ToolboxNode("lcm()", "PPCM"), ToolboxNode("rem()", "Reste division euclidienne"), ToolboxNode("quo()","Quotien division euclidienne")};
const ToolboxNode matricesChildren[5] = {ToolboxNode("inverse()", "Inverse"), ToolboxNode("det()", "Determinant"), ToolboxNode("transpose()", "Transposee"), ToolboxNode("trace()", "Trace"), ToolboxNode("dim()", "Taille")};
const ToolboxNode listesChildren[5] = {ToolboxNode("sort<()", "Tri croissant"), ToolboxNode("sort>()", "Tri decroissant"), ToolboxNode("max()", "Maximum"), ToolboxNode("min()", "Minimum"), ToolboxNode("dim()", "Taille")};
const ToolboxNode approximationChildren[4] = {ToolboxNode("floor()", "Partie entiere"), ToolboxNode("frac()", "Partie fractionnaire"), ToolboxNode("ceil()", "Plafond"), ToolboxNode("round(,)", "Arrondi")};
const ToolboxNode trigonometryChildren[6] = {ToolboxNode("cosh()", "cosh"), ToolboxNode("sinh()", "sinh"), ToolboxNode("tanh()", "tanh"), ToolboxNode("acosh()", "acosh"), ToolboxNode("asinh()", "asinh"), ToolboxNode("atanh()", "atanh")};
const ToolboxNode menu[11] = {ToolboxNode("abs()", "Valeur absolue"), ToolboxNode("root(,)", "Racine k-ieme"), ToolboxNode("log(,)", "Logarithme base a"),
ToolboxNode("Calcul", nullptr, calculChildren, 4), ToolboxNode("Nombre complexe", nullptr, complexChildren, 5),
ToolboxNode("Probabilite", nullptr, probabilityChildren, 4), ToolboxNode("Arithmetique", nullptr, arithmeticChildren, 4),
ToolboxNode("Matrice", nullptr, matricesChildren, 5), ToolboxNode("Liste", nullptr, listesChildren, 5),
ToolboxNode("Approximation", nullptr, approximationChildren, 4), ToolboxNode("Trigonometrie", nullptr, trigonometryChildren, 6)};
const ToolboxNode toolboxModel = ToolboxNode("Toolbox", nullptr, menu, 11);
/* State */
MathToolbox::Stack::State::State(int selectedRow, KDCoordinate verticalScroll) :
m_selectedRow(selectedRow),
m_verticalScroll(verticalScroll)
{
}
int MathToolbox::Stack::State::selectedRow() {
return m_selectedRow;
}
KDCoordinate MathToolbox::Stack::State::verticalScroll() {
return m_verticalScroll;
}
bool MathToolbox::Stack::State::isNull(){
if (m_selectedRow == -1) {
return true;
}
return false;
}
/* Stack */
void MathToolbox::Stack::push(int selectedRow, KDCoordinate verticalScroll) {
int i = 0;
while (!m_statesStack[i].isNull() && i < k_maxModelTreeDepth) {
i++;
}
assert(m_statesStack[i].isNull());
m_statesStack[i] = State(selectedRow, verticalScroll);
}
MathToolbox::Stack::State * MathToolbox::Stack::stateAtIndex(int index) {
return &m_statesStack[index];
}
int MathToolbox::Stack::depth() {
int depth = 0;
for (int i = 0; i < k_maxModelTreeDepth; i++) {
depth += (!m_statesStack[i].isNull());
}
return depth;
}
void MathToolbox::Stack::pop() {
int stackDepth = depth();
if (stackDepth == 0) {
return;
}
m_statesStack[stackDepth-1] = State();
}
void MathToolbox::Stack::resetStack() {
for (int i = 0; i < k_maxModelTreeDepth; i++) {
m_statesStack[i] = State();
}
}
/* List Controller */
MathToolbox::ListController::ListController(Responder * parentResponder, SelectableTableView * tableView) :
ViewController(parentResponder),
m_selectableTableView(tableView),
m_firstSelectedRow(0)
{
}
View * MathToolbox::ListController::view() {
return m_selectableTableView;
}
const char * MathToolbox::ListController::title() const {
return toolboxModel.label();
}
void MathToolbox::ListController::didBecomeFirstResponder() {
m_selectableTableView->reloadData();
m_selectableTableView->selectCellAtLocation(0, m_firstSelectedRow);
app()->setFirstResponder(m_selectableTableView);
}
void MathToolbox::ListController::setFirstSelectedRow(int firstSelectedRow) {
m_firstSelectedRow = firstSelectedRow;
}
/* MathToolbox */
MathToolbox::MathToolbox() :
Toolbox(nullptr, &m_listController),
m_selectableTableView(SelectableTableView(&m_listController, this, 0, 0, 0, 0, nullptr, false)),
m_listController(this, &m_selectableTableView),
m_nodeModel(nullptr)
{
}
void MathToolbox::didBecomeFirstResponder() {
m_nodeModel = (ToolboxNode *)rootModel();
StackViewController::didBecomeFirstResponder();
m_stack.resetStack();
m_listController.setFirstSelectedRow(0);
app()->setFirstResponder(&m_listController);
}
bool MathToolbox::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Back) {
return returnToPreviousMenu();
}
if (event == Ion::Events::OK) {
int selectedRow = m_selectableTableView.selectedRow();
ToolboxNode * selectedNode = (ToolboxNode *)m_nodeModel->children(selectedRow);
if (selectedNode->numberOfChildren() == 0) {
return selectLeaf(selectedNode);
}
return selectSubMenu(selectedNode);
}
return false;
}
int MathToolbox::numberOfRows() {
return m_nodeModel->numberOfChildren();
}
TableViewCell * MathToolbox::reusableCell(int index, int type) {
assert(type < 2);
assert(index >= 0);
assert(index < k_maxNumberOfDisplayedRows);
if (type == 0) {
return &m_leafCells[index];
}
return &m_nodeCells[index];
}
int MathToolbox::reusableCellCount(int type) {
assert(type < 2);
return k_maxNumberOfDisplayedRows;
}
void MathToolbox::willDisplayCellForIndex(TableViewCell * cell, int index) {
ToolboxNode * node = (ToolboxNode *)m_nodeModel->children(index);
if (node->numberOfChildren() == 0) {
ToolboxLeafCell * myCell = (ToolboxLeafCell *)cell;
myCell->setLabel(node->label());
myCell->setSubtitle(node->text());
return;
}
MenuListCell * myCell = (MenuListCell *)cell;
myCell->setText(node->label());
}
KDCoordinate MathToolbox::rowHeight(int j) {
if (typeAtLocation(0, j) == 0) {
return k_leafRowHeight;
}
return k_nodeRowHeight;
}
KDCoordinate MathToolbox::cumulatedHeightFromIndex(int j) {
int result = 0;
for (int k = 0; k < j; k++) {
result += rowHeight(k);
}
return result;
}
int MathToolbox::indexFromCumulatedHeight(KDCoordinate offsetY) {
int result = 0;
int j = 0;
while (result < offsetY && j < numberOfRows()) {
result += rowHeight(j++);
}
return (result < offsetY || offsetY == 0) ? j : j - 1;
}
int MathToolbox::typeAtLocation(int i, int j) {
Node * node = (Node *)m_nodeModel->children(j);
if (node->numberOfChildren() == 0) {
return 0;
}
return 1;
}
void MathToolbox::viewWillDisappear() {
m_selectableTableView.deselectTable();
}
TextField * MathToolbox::sender() {
return (TextField *)Toolbox::sender();
}
const ToolboxNode * MathToolbox::rootModel() {
return &toolboxModel;
}
bool MathToolbox::selectLeaf(ToolboxNode * selectedNode){
m_selectableTableView.deselectTable();
ToolboxNode * node = selectedNode;
const char * editedText = node->label();
if (!sender()->isEditing()) {
sender()->setEditing(true);
}
sender()->insertTextAtLocation(editedText, sender()->cursorLocation());
int cursorDelta = 0;
int editedTextLength = strlen(editedText);
for (int i = 0; i < editedTextLength; i++) {
if (editedText[i] == '(') {
cursorDelta = i + 1;
break;
}
}
sender()->setCursorLocation(sender()->cursorLocation()+cursorDelta);
app()->dismissModalViewController();
return true;
}
bool MathToolbox::returnToPreviousMenu() {
m_selectableTableView.deselectTable();
int depth = m_stack.depth();
if (depth == 0) {
app()->dismissModalViewController();
return true;
}
int index = 0;
ToolboxNode * parentNode = (ToolboxNode *)rootModel();
Stack::State * previousState = m_stack.stateAtIndex(index++);;
while (depth-- > 1) {
parentNode = (ToolboxNode *)parentNode->children(previousState->selectedRow());
previousState = m_stack.stateAtIndex(index++);
}
m_selectableTableView.deselectTable();
m_nodeModel = parentNode;
m_listController.setFirstSelectedRow(previousState->selectedRow());
KDPoint scroll = m_selectableTableView.contentOffset();
m_selectableTableView.setContentOffset(KDPoint(scroll.x(), previousState->verticalScroll()));
m_stack.pop();
app()->setFirstResponder(&m_listController);
return true;
}
bool MathToolbox::selectSubMenu(ToolboxNode * selectedNode) {
m_stack.push(m_selectableTableView.selectedRow(), m_selectableTableView.contentOffset().y());
m_selectableTableView.deselectTable();
m_nodeModel = selectedNode;
m_listController.setFirstSelectedRow(0);
app()->setFirstResponder(&m_listController);
return true;
}

77
apps/math_toolbox.h Normal file
View File

@@ -0,0 +1,77 @@
#ifndef APPS_MATH_TOOLBOX_H
#define APPS_MATH_TOOLBOX_H
#include <escher.h>
#include "toolbox_node.h"
#include "toolbox_leaf_cell.h"
/* m_nodeModel points at the node of the tree (describing the whole model)
* where we are located. It enables to know which rows are leaves and which are
* subtrees. */
class MathToolbox : public Toolbox, public ListViewDataSource {
public:
MathToolbox();
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
int numberOfRows() override;
TableViewCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
KDCoordinate rowHeight(int j) override;
KDCoordinate cumulatedHeightFromIndex(int j) override;
int indexFromCumulatedHeight(KDCoordinate offsetY) override;
int typeAtLocation(int i, int j) override;
void viewWillDisappear() override;
private:
class Stack {
public:
class State {
public:
State(int selectedRow = -1, KDCoordinate verticalScroll = 0);
bool isNull();
int selectedRow();
KDCoordinate verticalScroll();
private:
int m_selectedRow;
KDCoordinate m_verticalScroll;
};
void push(int selectedRow, KDCoordinate verticalScroll);
void pop();
State * stateAtIndex(int index);
int depth();
void resetStack();
private:
constexpr static int k_maxModelTreeDepth = 2;
State m_statesStack[k_maxModelTreeDepth];
};
class ListController : public ViewController {
public:
ListController(Responder * parentResponder, SelectableTableView * tableView);
const char * title() const override;
View * view() override;
void didBecomeFirstResponder() override;
void setFirstSelectedRow(int firstSelectedRow);
private:
SelectableTableView * m_selectableTableView;
int m_firstSelectedRow;
};
constexpr static KDCoordinate k_nodeRowHeight = 40;
constexpr static KDCoordinate k_leafRowHeight = 40;
constexpr static int k_maxNumberOfDisplayedRows = 6; //240/40
TextField * sender() override;
const ToolboxNode * rootModel();
bool selectLeaf(ToolboxNode * selectedNode);
bool selectSubMenu(ToolboxNode * selectedNode);
bool returnToPreviousMenu();
Stack m_stack;
ToolboxLeafCell m_leafCells[k_maxNumberOfDisplayedRows];
ChevronMenuListCell m_nodeCells[k_maxNumberOfDisplayedRows];
SelectableTableView m_selectableTableView;
ListController m_listController;
ToolboxNode * m_nodeModel;
};
#endif

View File

@@ -1,119 +0,0 @@
#include "node_list_view_controller.h"
#include "toolbox_node.h"
#include <assert.h>
#include <string.h>
NodeListViewController::NodeListViewController(Responder * parentResponder) :
ViewController(parentResponder),
m_selectableTableView(SelectableTableView(this, this, 0, 0, 0, 0, nullptr, false)),
m_nodeModel(nullptr),
m_firstSelectedRow(0)
{
}
View * NodeListViewController::view() {
return &m_selectableTableView;
}
const char * NodeListViewController::title() const {
return m_nodeModel->label();
}
Node * NodeListViewController::nodeModel() {
return m_nodeModel;
}
void NodeListViewController::setNodeModel(Node * nodeModel) {
m_nodeModel = nodeModel;
m_selectableTableView.reloadData();
}
void NodeListViewController::setFirstSelectedRow(int firstSelectedRow) {
m_firstSelectedRow = firstSelectedRow;
}
int NodeListViewController::selectedRow() {
return m_selectableTableView.selectedRow();
}
void NodeListViewController::setVerticalScroll(KDCoordinate verticalScroll) {
KDPoint scroll = m_selectableTableView.contentOffset();
m_selectableTableView.setContentOffset(KDPoint(scroll.x(), verticalScroll));
}
KDCoordinate NodeListViewController::verticalScroll() {
return m_selectableTableView.contentOffset().y();
}
void NodeListViewController::deselectTable() {
m_selectableTableView.deselectTable();
}
void NodeListViewController::didBecomeFirstResponder() {
m_selectableTableView.reloadData();
m_selectableTableView.selectCellAtLocation(0, m_firstSelectedRow);
app()->setFirstResponder(&m_selectableTableView);
}
int NodeListViewController::numberOfRows() {
return m_nodeModel->numberOfChildren();
}
TableViewCell * NodeListViewController::reusableCell(int index, int type) {
assert(type < 2);
assert(index >= 0);
assert(index < k_maxNumberOfDisplayedRows);
if (type == 0) {
return &m_leafCells[index];
}
return &m_nodeCells[index];
}
int NodeListViewController::reusableCellCount(int type) {
assert(type < 2);
return k_maxNumberOfDisplayedRows;
}
void NodeListViewController::willDisplayCellForIndex(TableViewCell * cell, int index) {
ToolboxNode * node = (ToolboxNode *)m_nodeModel->children(index);
if (node->numberOfChildren() == 0) {
ToolboxLeafCell * myCell = (ToolboxLeafCell *)cell;
myCell->setLabel(node->label());
myCell->setSubtitle(node->text());
return;
}
MenuListCell * myCell = (MenuListCell *)cell;
myCell->setText(node->label());
}
KDCoordinate NodeListViewController::rowHeight(int j) {
if (typeAtLocation(0, j) == 0) {
return k_leafRowHeight;
}
return k_nodeRowHeight;
}
KDCoordinate NodeListViewController::cumulatedHeightFromIndex(int j) {
int result = 0;
for (int k = 0; k < j; k++) {
result += rowHeight(k);
}
return result;
}
int NodeListViewController::indexFromCumulatedHeight(KDCoordinate offsetY) {
int result = 0;
int j = 0;
while (result < offsetY && j < numberOfRows()) {
result += rowHeight(j++);
}
return (result < offsetY || offsetY == 0) ? j : j - 1;
}
int NodeListViewController::typeAtLocation(int i, int j) {
Node * node = (Node *)m_nodeModel->children(j);
if (node->numberOfChildren() == 0) {
return 0;
}
return 1;
}

View File

@@ -1,48 +0,0 @@
#ifndef APPS_NODE_LIST_VIEW_CONTROLLER_H
#define APPS_NODE_LIST_VIEW_CONTROLLER_H
#include <escher.h>
#include "node.h"
#include "toolbox_leaf_cell.h"
/* m_nodeModel points at the node of the tree (describing the whole model)
* where we are located. It enables to know which rows are leaves and which are
* subtrees. */
class NodeNavigationController;
class NodeListViewController : public ViewController, public ListViewDataSource {
public:
NodeListViewController(Responder * parentResponder);
View * view() override;
const char * title() const override;
void didBecomeFirstResponder() override;
int numberOfRows() override;
TableViewCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
KDCoordinate rowHeight(int j) override;
KDCoordinate cumulatedHeightFromIndex(int j) override;
int indexFromCumulatedHeight(KDCoordinate offsetY) override;
int typeAtLocation(int i, int j) override;
void setNodeModel(Node * nodeModel);
Node * nodeModel();
void setFirstSelectedRow(int firstSelectedRow);
int selectedRow();
void setVerticalScroll(KDCoordinate verticalScroll);
KDCoordinate verticalScroll();
void deselectTable();
private:
constexpr static KDCoordinate k_nodeRowHeight = 40;
constexpr static KDCoordinate k_leafRowHeight = 40;
constexpr static int k_maxNumberOfDisplayedRows = 6; //240/40
ToolboxLeafCell m_leafCells[k_maxNumberOfDisplayedRows];
ChevronMenuListCell m_nodeCells[k_maxNumberOfDisplayedRows];
SelectableTableView m_selectableTableView;
Node * m_nodeModel;
int m_firstSelectedRow;
};
#endif

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();
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) {
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

@@ -1,184 +0,0 @@
#include "toolbox_controller.h"
#include "toolbox_node.h"
#include <assert.h>
/* TODO: find a shorter way to initiate tree models
* We create one model tree: each node keeps the label of the row it refers to
* and the text which would be edited by clicking on the row. When the node is a
* subtree, the edited text is set at nullptr. */
const ToolboxNode calculChildren[4] = {ToolboxNode("diff(,)", "Nombre derive"), ToolboxNode("int(,,)", "Integrale"), ToolboxNode("sum(,,)", "Somme"), ToolboxNode("product(,,)", "Produit")};
const ToolboxNode complexChildren[5] = {ToolboxNode("abs()", "Module"), ToolboxNode("arg()", "Argument"), ToolboxNode("re()", "Partie reelle"), ToolboxNode("im()", "Partie imaginaire"), ToolboxNode("conj()", "Conjugue")};
const ToolboxNode probabilityChildren[4] = {ToolboxNode("binomial()", "Combinaison"), ToolboxNode("permute(,)", "Arrangement"), ToolboxNode("random(,)", "Nombre aleatoire"), ToolboxNode("gamma()", "Fonction gamma")};
const ToolboxNode arithmeticChildren[4] = {ToolboxNode("gcd()", "PGCD"), ToolboxNode("lcm()", "PPCM"), ToolboxNode("rem()", "Reste division euclidienne"), ToolboxNode("quo()","Quotien division euclidienne")};
const ToolboxNode matricesChildren[5] = {ToolboxNode("inverse()", "Inverse"), ToolboxNode("det()", "Determinant"), ToolboxNode("transpose()", "Transposee"), ToolboxNode("trace()", "Trace"), ToolboxNode("dim()", "Taille")};
const ToolboxNode listesChildren[5] = {ToolboxNode("sort<()", "Tri croissant"), ToolboxNode("sort>()", "Tri decroissant"), ToolboxNode("max()", "Maximum"), ToolboxNode("min()", "Minimum"), ToolboxNode("dim()", "Taille")};
const ToolboxNode approximationChildren[4] = {ToolboxNode("floor()", "Partie entiere"), ToolboxNode("frac()", "Partie fractionnaire"), ToolboxNode("ceil()", "Plafond"), ToolboxNode("round(,)", "Arrondi")};
const ToolboxNode trigonometryChildren[6] = {ToolboxNode("cosh()", "cosh"), ToolboxNode("sinh()", "sinh"), ToolboxNode("tanh()", "tanh"), ToolboxNode("acosh()", "acosh"), ToolboxNode("asinh()", "asinh"), ToolboxNode("atanh()", "atanh")};
const ToolboxNode menu[11] = {ToolboxNode("abs()", "Valeur absolue"), ToolboxNode("root(,)", "Racine k-ieme"), ToolboxNode("log(,)", "Logarithme base a"),
ToolboxNode("Calcul", nullptr, calculChildren, 4), ToolboxNode("Nombre complexe", nullptr, complexChildren, 5),
ToolboxNode("Probabilite", nullptr, probabilityChildren, 4), ToolboxNode("Arithmetique", nullptr, arithmeticChildren, 4),
ToolboxNode("Matrice", nullptr, matricesChildren, 5), ToolboxNode("Liste", nullptr, listesChildren, 5),
ToolboxNode("Approximation", nullptr, approximationChildren, 4), ToolboxNode("Trigonometrie", nullptr, trigonometryChildren, 6)};
const ToolboxNode toolboxModel = ToolboxNode("Toolbox", nullptr, menu, 11);
/* State */
ToolboxController::Stack::State::State(int selectedRow, KDCoordinate verticalScroll) :
m_selectedRow(selectedRow),
m_verticalScroll(verticalScroll)
{
}
int ToolboxController::Stack::State::selectedRow() {
return m_selectedRow;
}
KDCoordinate ToolboxController::Stack::State::verticalScroll() {
return m_verticalScroll;
}
bool ToolboxController::Stack::State::isNull(){
if (m_selectedRow == -1) {
return true;
}
return false;
}
/* Stack */
void ToolboxController::Stack::push(int selectedRow, KDCoordinate verticalScroll) {
int i = 0;
while (!m_statesStack[i].isNull() && i < k_maxModelTreeDepth) {
i++;
}
assert(m_statesStack[i].isNull());
m_statesStack[i] = State(selectedRow, verticalScroll);
}
ToolboxController::Stack::State * ToolboxController::Stack::stateAtIndex(int index) {
return &m_statesStack[index];
}
int ToolboxController::Stack::depth() {
int depth = 0;
for (int i = 0; i < k_maxModelTreeDepth; i++) {
depth += (!m_statesStack[i].isNull());
}
return depth;
}
void ToolboxController::Stack::pop() {
int stackDepth = depth();
if (stackDepth == 0) {
return;
}
m_statesStack[stackDepth-1] = State();
}
void ToolboxController::Stack::resetStack() {
for (int i = 0; i < k_maxModelTreeDepth; i++) {
m_statesStack[i] = State();
}
}
/* ToolboxController */
ToolboxController::ToolboxController() :
StackViewController(nullptr, &m_listViewController, true, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark),
m_listViewController(NodeListViewController(this))
{
}
const char * ToolboxController::title() const {
return "ToolboxController";
}
bool ToolboxController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Back) {
return returnToPreviousMenu();
}
if (event == Ion::Events::OK) {
int selectedRow = m_listViewController.selectedRow();
Node * selectedNode = (Node *)m_listViewController.nodeModel()->children(selectedRow);
if (selectedNode->numberOfChildren() == 0) {
return selectLeaf(selectedNode);
}
return selectSubMenu(selectedNode);
}
return false;
}
void ToolboxController::didBecomeFirstResponder() {
m_listViewController.setNodeModel(rootModel());
StackViewController::didBecomeFirstResponder();
m_stack.resetStack();
m_listViewController.setFirstSelectedRow(0);
app()->setFirstResponder(&m_listViewController);
}
void ToolboxController::viewWillDisappear() {
m_listViewController.deselectTable();
}
void ToolboxController::setTextFieldCaller(TextField * textField) {
m_textFieldCaller = textField;
}
Node * ToolboxController::rootModel() {
return (Node *)&toolboxModel;
}
bool ToolboxController::selectLeaf(Node * selectedNode){
m_listViewController.deselectTable();
ToolboxNode * node = (ToolboxNode *)selectedNode;
const char * editedText = node->label();
if (!m_textFieldCaller->isEditing()) {
m_textFieldCaller->setEditing(true);
}
m_textFieldCaller->insertTextAtLocation(editedText, m_textFieldCaller->cursorLocation());
int cursorDelta = 0;
int editedTextLength = strlen(editedText);
for (int i = 0; i < editedTextLength; i++) {
if (editedText[i] == '(') {
cursorDelta = i + 1;
break;
}
}
m_textFieldCaller->setCursorLocation(m_textFieldCaller->cursorLocation()+cursorDelta);
app()->dismissModalViewController();
return true;
}
bool ToolboxController::returnToPreviousMenu() {
m_listViewController.deselectTable();
int depth = m_stack.depth();
if (depth == 0) {
app()->dismissModalViewController();
return true;
}
int index = 0;
Node * parentNode = rootModel();
Stack::State * previousState = m_stack.stateAtIndex(index++);;
while (depth-- > 1) {
parentNode = (Node *)parentNode->children(previousState->selectedRow());
previousState = m_stack.stateAtIndex(index++);
}
m_listViewController.deselectTable();
m_listViewController.setNodeModel(parentNode);
m_listViewController.setFirstSelectedRow(previousState->selectedRow());
m_listViewController.setVerticalScroll(previousState->verticalScroll());
m_stack.pop();
app()->setFirstResponder(&m_listViewController);
return true;
}
bool ToolboxController::selectSubMenu(Node * selectedNode) {
m_stack.push(m_listViewController.selectedRow(), m_listViewController.verticalScroll());
m_listViewController.deselectTable();
m_listViewController.setNodeModel(selectedNode);
m_listViewController.setFirstSelectedRow(0);
app()->setFirstResponder(&m_listViewController);
return true;
}

View File

@@ -1,47 +0,0 @@
#ifndef APPS_TOOLBOX_CONTROLLER_H
#define APPS_TOOLBOX_CONTROLLER_H
#include <escher.h>
#include "node.h"
#include "node_list_view_controller.h"
class ToolboxController : public StackViewController {
public:
ToolboxController();
const char * title() const override;
bool handleEvent(Ion::Events::Event event) override;
void didBecomeFirstResponder() override;
void viewWillDisappear() override;
void setTextFieldCaller(TextField * textField);
private:
class Stack {
public:
class State {
public:
State(int selectedRow = -1, KDCoordinate verticalScroll = 0);
bool isNull();
int selectedRow();
KDCoordinate verticalScroll();
private:
int m_selectedRow;
KDCoordinate m_verticalScroll;
};
void push(int selectedRow, KDCoordinate verticalScroll);
void pop();
State * stateAtIndex(int index);
int depth();
void resetStack();
private:
constexpr static int k_maxModelTreeDepth = 2;
State m_statesStack[k_maxModelTreeDepth];
};
TextField * m_textFieldCaller;
NodeListViewController m_listViewController;
Node * rootModel();
bool selectLeaf(Node * selectedNode);
bool selectSubMenu(Node * selectedNode);
bool returnToPreviousMenu();
Stack m_stack;
};
#endif

View File

@@ -52,6 +52,7 @@ objs += $(addprefix escher/src/,\
text_menu_list_cell.o\
text_view.o\
tiled_view.o\
toolbox.o\
view.o\
view_controller.o\
warning_controller.o\

View File

@@ -53,6 +53,7 @@
#include <escher/table_view_cell.h>
#include <escher/table_view_data_source.h>
#include <escher/tiled_view.h>
#include <escher/toolbox.h>
#include <escher/view.h>
#include <escher/view_controller.h>
#include <escher/warning_controller.h>

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

@@ -0,0 +1,17 @@
#ifndef ESCHER_TOOLBOX_H
#define ESCHER_TOOLBOX_H
#include <escher/stack_view_controller.h>
class Toolbox : public StackViewController {
public:
Toolbox(Responder * parentResponder, ViewController * rootViewController);
void setSender(Responder * sender);
protected:
virtual Responder * sender();
private:
Responder * m_sender;
};
#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;

15
escher/src/toolbox.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include <escher/toolbox.h>
Toolbox::Toolbox(Responder * parentResponder, ViewController * rootViewController) :
StackViewController(parentResponder, rootViewController, true, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark),
m_sender(nullptr)
{
}
void Toolbox::setSender(Responder * sender) {
m_sender = sender;
}
Responder * Toolbox::sender() {
return m_sender;
}