From 01e433a9f2582bd1d429126676718cccf3abdfac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 19 Oct 2018 14:31:50 +0200 Subject: [PATCH] [escher] Clean Field and Input class hierarchy: Class hierarchy: - InputEventHandler - TextInput - EditableField derives from InputEventHandler - LayoutField, TextField and ExpressioField derives from EditableField - TextArea and TextField derives from TextInput --- apps/code/app.cpp | 4 ++-- apps/code/app.h | 2 +- apps/code/console_controller.cpp | 2 +- apps/code/console_controller.h | 2 +- apps/code/editor_controller.cpp | 2 +- apps/code/editor_controller.h | 2 +- apps/code/menu_controller.h | 2 +- apps/code/variable_box_controller.cpp | 10 +++++----- apps/code/variable_box_controller.h | 6 +++--- apps/sequence/list/list_controller.cpp | 4 ++-- apps/sequence/list/list_controller.h | 4 ++-- apps/shared/text_field_delegate.cpp | 2 +- apps/shared/text_field_delegate.h | 2 +- apps/shared/text_field_delegate_app.cpp | 10 +++++----- apps/shared/text_field_delegate_app.h | 6 +++--- escher/Makefile | 1 + escher/include/escher.h | 3 ++- .../escher/{field.h => editable_field.h} | 7 ++++--- escher/include/escher/expression_field.h | 8 +++++--- escher/include/escher/input_event_handler.h | 15 +++++++++++++++ escher/include/escher/input_view_controller.h | 2 +- escher/include/escher/layout_field.h | 4 ++-- .../include/escher/nested_menu_controller.h | 7 ++++--- escher/include/escher/responder.h | 5 +---- escher/include/escher/text_area.h | 4 +++- escher/include/escher/text_field.h | 5 +++-- escher/include/escher/text_input.h | 1 - escher/include/escher/text_input_delegate.h | 3 ++- escher/src/expression_field.cpp | 8 ++++++++ escher/src/input_event_handler.cpp | 13 +++++++++++++ escher/src/input_view_controller.cpp | 2 +- escher/src/layout_field.cpp | 12 ++++++------ escher/src/responder.cpp | 10 ---------- escher/src/text_area.cpp | 12 +++++++++--- escher/src/text_field.cpp | 19 +++++++++++++------ escher/src/text_input.cpp | 7 ------- 36 files changed, 123 insertions(+), 85 deletions(-) rename escher/include/escher/{field.h => editable_field.h} (63%) create mode 100644 escher/include/escher/input_event_handler.h create mode 100644 escher/src/input_event_handler.cpp diff --git a/apps/code/app.cpp b/apps/code/app.cpp index 960deadba..78b4855fc 100644 --- a/apps/code/app.cpp +++ b/apps/code/app.cpp @@ -109,14 +109,14 @@ bool App::handleEvent(Ion::Events::Event event) { return false; } -bool App::textInputDidReceiveEvent(TextInput * textInput, Ion::Events::Event event) { +bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) { const char * pythonText = Helpers::PythonTextForEvent(event); if (pythonText != nullptr) { textInput->handleEventWithText(pythonText); return true; } if (event == Ion::Events::Var) { - m_variableBoxController.setTextInputCaller(textInput); + m_variableBoxController.setSender(textInput); displayModalViewController(&m_variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } diff --git a/apps/code/app.h b/apps/code/app.h index f9de1d626..2f60448bd 100644 --- a/apps/code/app.h +++ b/apps/code/app.h @@ -41,7 +41,7 @@ public: ConsoleController * consoleController() { return &m_consoleController; } PythonToolbox * pythonToolbox() { return &m_toolbox; } bool handleEvent(Ion::Events::Event event) override; - bool textInputDidReceiveEvent(TextInput * textInput, Ion::Events::Event event); + bool textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event); // Python delegate bool pythonIsInited() { return m_pythonUser != nullptr; } bool isPythonUser(const void * pythonUser) { return m_pythonUser == pythonUser; } diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 294d51d96..2217acb4c 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -291,7 +291,7 @@ bool ConsoleController::textFieldDidAbortEditing(TextField * textField) { return true; } -Toolbox * ConsoleController::toolboxForTextInput(TextInput * textInput) { +Toolbox * ConsoleController::toolboxForTextInput(InputEventHandler * textInput) { Code::App * codeApp = static_cast(app()); return codeApp->pythonToolbox(); } diff --git a/apps/code/console_controller.h b/apps/code/console_controller.h index 0502d6476..54283cd11 100644 --- a/apps/code/console_controller.h +++ b/apps/code/console_controller.h @@ -60,7 +60,7 @@ public: bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(TextField * textField) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; // MicroPython::ExecutionEnvironment void displaySandbox() override; diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index 15232e79a..fb944d93c 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -127,7 +127,7 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events: return false; } -Toolbox * EditorController::toolboxForTextInput(TextInput * textInput) { +Toolbox * EditorController::toolboxForTextInput(InputEventHandler * textInput) { Code::App * codeApp = static_cast(app()); return codeApp->pythonToolbox(); } diff --git a/apps/code/editor_controller.h b/apps/code/editor_controller.h index 8161b7f3a..989e3c46c 100644 --- a/apps/code/editor_controller.h +++ b/apps/code/editor_controller.h @@ -25,7 +25,7 @@ public: /* TextAreaDelegate */ bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; private: static constexpr int k_indentationSpacesNumber = 2; diff --git a/apps/code/menu_controller.h b/apps/code/menu_controller.h index 2720732cc..0d86c2888 100644 --- a/apps/code/menu_controller.h +++ b/apps/code/menu_controller.h @@ -54,7 +54,7 @@ public: bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(TextField * textField) override; bool textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textHasChanged) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override { return nullptr; } + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override { return nullptr; } /* ButtonRowDelegate */ int numberOfButtons(ButtonRowController::Position position) const override { return 1; } diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index 128cccdbd..dd217aa71 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -26,8 +26,8 @@ VariableBoxController::ContentViewController::ContentViewController(Responder * } } -void VariableBoxController::ContentViewController::setTextInputCaller(TextInput * textInput) { - m_textInputCaller = textInput; +void VariableBoxController::ContentViewController::setSender(InputEventHandler * textInput) { + m_sender = textInput; } void VariableBoxController::ContentViewController::reloadData() { @@ -147,7 +147,7 @@ void VariableBoxController::ContentViewController::insertTextInCaller(const char char commandBuffer[k_maxScriptObjectNameSize]; assert(commandBufferMaxSize <= k_maxScriptObjectNameSize); Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer, commandBufferMaxSize, true); - m_textInputCaller->handleEventWithText(commandBuffer); + m_sender->handleEventWithText(commandBuffer); } VariableBoxController::VariableBoxController(App * pythonDelegate, ScriptStore * scriptStore) : @@ -160,8 +160,8 @@ void VariableBoxController::didBecomeFirstResponder() { app()->setFirstResponder(&m_contentViewController); } -void VariableBoxController::setTextInputCaller(TextInput * textInput) { - m_contentViewController.setTextInputCaller(textInput); +void VariableBoxController::setSender(InputEventHandler * sender) { + m_contentViewController.setSender(sender); } void VariableBoxController::viewWillAppear() { diff --git a/apps/code/variable_box_controller.h b/apps/code/variable_box_controller.h index a850a9473..9a803fd71 100644 --- a/apps/code/variable_box_controller.h +++ b/apps/code/variable_box_controller.h @@ -13,14 +13,14 @@ class VariableBoxController : public StackViewController { public: VariableBoxController(App * pythonDelegate, ScriptStore * scriptStore); void didBecomeFirstResponder() override; - void setTextInputCaller(TextInput * textInput); + void setSender(InputEventHandler * sender); void viewWillAppear() override; void viewDidDisappear() override; private: class ContentViewController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { public: ContentViewController(Responder * parentResponder, App * pythonDelegate, ScriptStore * scriptStore); - void setTextInputCaller(TextInput * textInput); + void setSender(InputEventHandler * sender); void reloadData(); void addFunctionAtIndex(const char * functionName, int scriptIndex); @@ -52,7 +52,7 @@ private: ScriptNode m_scriptNodes[k_maxScriptNodesCount]; App * m_pythonDelegate; ScriptStore * m_scriptStore; - TextInput * m_textInputCaller; + InputEventHandler * m_sender; ScriptNodeCell m_leafCells[k_maxNumberOfDisplayedRows]; SelectableTableView m_selectableTableView; }; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index a446f826f..490915519 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -28,7 +28,7 @@ const char * ListController::title() { return I18n::translate(I18n::Message::SequenceTab); } -Toolbox * ListController::toolboxForTextInput(TextInput * textInput) { +Toolbox * ListController::toolboxForTextInput(InputEventHandler * textInput) { return toolboxForSender(textInput); } @@ -88,7 +88,7 @@ void ListController::selectPreviousNewSequenceCell() { } } -Toolbox * ListController::toolboxForSender(Responder * sender) { +Toolbox * ListController::toolboxForSender(InputEventHandler * sender) { // Set extra cells int recurrenceDepth = -1; int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 3857a0723..8476f4172 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -21,13 +21,13 @@ public: int numberOfExpressionRows() override; KDCoordinate expressionRowHeight(int j) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; Toolbox * toolboxForLayoutField(LayoutField * layoutField) override; void selectPreviousNewSequenceCell(); void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event); private: static constexpr KDCoordinate k_expressionCellVerticalMargin = 3; - Toolbox * toolboxForSender(Responder * sender); + Toolbox * toolboxForSender(InputEventHandler * sender); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; ListParameterController * parameterController() override; diff --git a/apps/shared/text_field_delegate.cpp b/apps/shared/text_field_delegate.cpp index 2f1cb3828..ded8d6565 100644 --- a/apps/shared/text_field_delegate.cpp +++ b/apps/shared/text_field_delegate.cpp @@ -12,7 +12,7 @@ bool TextFieldDelegate::textFieldDidReceiveEvent(::TextField * textField, Ion::E return textFieldDelegateApp()->textFieldDidReceiveEvent(textField, event); } -Toolbox * TextFieldDelegate::toolboxForTextInput(TextInput * textInput) { +Toolbox * TextFieldDelegate::toolboxForTextInput(InputEventHandler * textInput) { return textFieldDelegateApp()->toolboxForTextInput(textInput); } diff --git a/apps/shared/text_field_delegate.h b/apps/shared/text_field_delegate.h index 5d52df9ee..4e9a696be 100644 --- a/apps/shared/text_field_delegate.h +++ b/apps/shared/text_field_delegate.h @@ -10,7 +10,7 @@ class TextFieldDelegate : public ::TextFieldDelegate { public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; private: virtual TextFieldDelegateApp * textFieldDelegateApp() = 0; }; diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index 10c52aa03..5e130593b 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -41,7 +41,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion:: return false; } -Toolbox * TextFieldDelegateApp::toolboxForTextInput(TextInput * textInput) { +Toolbox * TextFieldDelegateApp::toolboxForTextInput(InputEventHandler * textInput) { Toolbox * toolbox = container()->mathToolbox(); toolbox->setSender(textInput); return toolbox; @@ -49,12 +49,12 @@ Toolbox * TextFieldDelegateApp::toolboxForTextInput(TextInput * textInput) { /* Protected */ -bool TextFieldDelegateApp::fieldDidReceiveEvent(Field * field, Responder * responder, Ion::Events::Event event) { +bool TextFieldDelegateApp::fieldDidReceiveEvent(EditableField * field, Responder * responder, Ion::Events::Event event) { if (event == Ion::Events::Var) { forceEdition(field); AppsContainer * appsContainer = (AppsContainer *)responder->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setSender(responder); + variableBoxController->setSender(field); responder->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; @@ -62,12 +62,12 @@ bool TextFieldDelegateApp::fieldDidReceiveEvent(Field * field, Responder * respo if (event == Ion::Events::XNT) { forceEdition(field); const char xnt[2] = {field->XNTChar(XNT()), 0}; - return responder->handleEventWithText(xnt); + return field->handleEventWithText(xnt); } return false; } -void TextFieldDelegateApp::forceEdition(Field * field) { +void TextFieldDelegateApp::forceEdition(EditableField * field) { if (!field->isEditing()) { field->setEditing(true); } diff --git a/apps/shared/text_field_delegate_app.h b/apps/shared/text_field_delegate_app.h index a2a9f507f..ceee6feb4 100644 --- a/apps/shared/text_field_delegate_app.h +++ b/apps/shared/text_field_delegate_app.h @@ -17,12 +17,12 @@ public: virtual char XNT(); bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; protected: TextFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); protected: - bool fieldDidReceiveEvent(Field * field, Responder * responder, Ion::Events::Event event); - void forceEdition(Field * field); + bool fieldDidReceiveEvent(EditableField * field, Responder * responder, Ion::Events::Event event); + void forceEdition(EditableField * field); bool isFinishingEvent(Ion::Events::Event event); bool unparsableText(const char * text, Responder * responder); }; diff --git a/escher/Makefile b/escher/Makefile index ce8d4bb07..3c96dcd46 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -26,6 +26,7 @@ objs += $(addprefix escher/src/,\ highlight_cell.o\ gauge_view.o\ image_view.o\ + input_event_handler.o\ invocation.o\ input_view_controller.o\ key_view.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 982717aba..38445ad20 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/escher/include/escher/field.h b/escher/include/escher/editable_field.h similarity index 63% rename from escher/include/escher/field.h rename to escher/include/escher/editable_field.h index ed8e9bf7e..bb47217a2 100644 --- a/escher/include/escher/field.h +++ b/escher/include/escher/editable_field.h @@ -1,9 +1,10 @@ -#ifndef ESCHER_FIELD_H -#define ESCHER_FIELD_H +#ifndef ESCHER_EDITABLE_FIELD_H +#define ESCHER_EDITABLE_FIELD_H #include +#include -class Field { +class EditableField : public InputEventHandler { public: virtual bool isEditing() const = 0; virtual void setEditing(bool isEditing, bool reinitDraftBuffer = true) = 0; diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index f7c039a5f..6d382f79d 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -7,12 +7,14 @@ #include #include -class ExpressionField : public Responder, public View { +class ExpressionField : public Responder, public View, public EditableField { public: ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate); - void setEditing(bool isEditing, bool reinitDraftBuffer = true); - bool isEditing() const; + void setEditing(bool isEditing, bool reinitDraftBuffer = true) override; + bool isEditing() const override; + char XNTChar(char defaultXNTChar) override; + bool shouldFinishEditing(Ion::Events::Event event) override; /* Warning: this function is VERY dangerous! Indeed: sometimes the * m_layoutField might overflow the m_textBuffer once serialized * and still have been accepted before because the model can hold a longer diff --git a/escher/include/escher/input_event_handler.h b/escher/include/escher/input_event_handler.h new file mode 100644 index 000000000..a248592c7 --- /dev/null +++ b/escher/include/escher/input_event_handler.h @@ -0,0 +1,15 @@ +#ifndef ESCHER_INPUT_EVENT_HANDLER_H +#define ESCHER_INPUT_EVENT_HANDLER_H + +class Toolbox; +class App; + +class InputEventHandler { +public: + virtual bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) { return false; } + virtual Toolbox * toolbox() { return nullptr; } +protected: + bool handleToolboxEvent(App * app); +}; + +#endif diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 089c8170e..1d0a9291f 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -24,7 +24,7 @@ public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(TextField * textField) override; - Toolbox * toolboxForTextInput(TextInput * textInput) override; + Toolbox * toolboxForTextInput(InputEventHandler * textInput) override; /* LayoutFieldDelegate */ bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override; diff --git a/escher/include/escher/layout_field.h b/escher/include/escher/layout_field.h index cb6489a28..8f416bddb 100644 --- a/escher/include/escher/layout_field.h +++ b/escher/include/escher/layout_field.h @@ -1,7 +1,7 @@ #ifndef ESCHER_LAYOUT_FIELD_H #define ESCHER_LAYOUT_FIELD_H -#include +#include #include #include #include @@ -11,7 +11,7 @@ #include #include -class LayoutField : public ScrollableView, public ScrollViewDataSource, public Field { +class LayoutField : public ScrollableView, public ScrollViewDataSource, public EditableField { public: LayoutField(Responder * parentResponder, LayoutFieldDelegate * delegate = nullptr) : ScrollableView(parentResponder, &m_contentView, this), diff --git a/escher/include/escher/nested_menu_controller.h b/escher/include/escher/nested_menu_controller.h index acb027ad0..d886f4212 100644 --- a/escher/include/escher/nested_menu_controller.h +++ b/escher/include/escher/nested_menu_controller.h @@ -1,6 +1,7 @@ #ifndef ESCHER_NESTED_MENU_CONTROLLER_H #define ESCHER_NESTED_MENU_CONTROLLER_H +#include #include #include #include @@ -9,7 +10,7 @@ class NestedMenuController : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource { public: NestedMenuController(Responder * parentResponder, I18n::Message title = (I18n::Message)0); - void setSender(Responder * sender) { m_sender = sender; } + void setSender(InputEventHandler * sender) { m_sender = sender; } // StackViewController bool handleEvent(Ion::Events::Event event) override; @@ -63,14 +64,14 @@ protected: virtual bool selectSubMenu(int selectedRow); virtual bool returnToPreviousMenu(); virtual bool selectLeaf(int selectedRow) = 0; - Responder * sender() { return m_sender; } + InputEventHandler * sender() { return m_sender; } virtual HighlightCell * leafCellAtIndex(int index) = 0; virtual HighlightCell * nodeCellAtIndex(int index) = 0; SelectableTableView m_selectableTableView; Stack m_stack; ListController m_listController; private: - Responder * m_sender; + InputEventHandler * m_sender; }; #endif diff --git a/escher/include/escher/responder.h b/escher/include/escher/responder.h index ac3f06e51..45b425f4f 100644 --- a/escher/include/escher/responder.h +++ b/escher/include/escher/responder.h @@ -4,13 +4,11 @@ #include class App; -class Toolbox; class Responder { public: Responder(Responder * parentResponder); - virtual bool handleEvent(Ion::Events::Event event); // Default implementation does nothing - virtual bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) { return false; } + virtual bool handleEvent(Ion::Events::Event event) { return false; }; // Default implementation does nothing virtual void didBecomeFirstResponder(); virtual void willResignFirstResponder(); virtual void didEnterResponderChain(Responder * previousFirstResponder); @@ -19,7 +17,6 @@ public: Responder * commonAncestorWith(Responder * responder); void setParentResponder(Responder * responder); App * app() const; - virtual Toolbox * toolbox() { return nullptr; } private: Responder * m_parentResponder; }; diff --git a/escher/include/escher/text_area.h b/escher/include/escher/text_area.h index 8c11b2856..cfc16224e 100644 --- a/escher/include/escher/text_area.h +++ b/escher/include/escher/text_area.h @@ -2,16 +2,18 @@ #define ESCHER_TEXT_AREA_H #include +#include #include #include #include -class TextArea : public TextInput { +class TextArea : public TextInput, public InputEventHandler { public: TextArea(Responder * parentResponder, View * contentView, const KDFont * font = KDFont::LargeFont); void setDelegate(TextAreaDelegate * delegate) { m_delegate = delegate; } bool handleEvent(Ion::Events::Event event) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; + Toolbox * toolbox() override; void setText(char * textBuffer, size_t textBufferSize); protected: diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index a668b41cc..15fb348dc 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -1,12 +1,12 @@ #ifndef ESCHER_TEXT_FIELD_H #define ESCHER_TEXT_FIELD_H -#include +#include #include #include #include -class TextField : public TextInput, public Field { +class TextField : public TextInput, public EditableField { public: TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize, TextFieldDelegate * delegate = nullptr, bool hasTwoBuffers = true, const KDFont * font = KDFont::LargeFont, @@ -24,6 +24,7 @@ public: char XNTChar(char defaultXNTChar) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; bool handleEvent(Ion::Events::Event event) override; + Toolbox * toolbox() override; constexpr static int maxBufferSize() { return ContentView::k_maxBufferSize; } diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 66ba8a36c..aa2cc4950 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -11,7 +11,6 @@ class TextInput : public ScrollableView, public ScrollViewDataSource { public: TextInput(Responder * parentResponder, View * contentView); void setFont(const KDFont * font) { contentView()->setFont(font); } - Toolbox * toolbox() override; const char * text() const { return nonEditableContentView()->text(); } bool removeChar(); size_t cursorLocation() const { return nonEditableContentView()->cursorLocation(); } diff --git a/escher/include/escher/text_input_delegate.h b/escher/include/escher/text_input_delegate.h index 2e2b84605..932376f49 100644 --- a/escher/include/escher/text_input_delegate.h +++ b/escher/include/escher/text_input_delegate.h @@ -1,11 +1,12 @@ #ifndef ESCHER_TEXT_INPUT_DELEGATE_H #define ESCHER_TEXT_INPUT_DELEGATE_H +#include class TextInput; class TextInputDelegate { public: - virtual Toolbox * toolboxForTextInput(TextInput * textInput) = 0; + virtual Toolbox * toolboxForTextInput(InputEventHandler * textInput) = 0; }; #endif diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index e4a1055d9..33ba38291 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -35,6 +35,14 @@ bool ExpressionField::isEditing() const { return editionIsInTextField() ? m_textField.isEditing() : m_layoutField.isEditing(); } +char ExpressionField::XNTChar(char defaultXNTChar) { + return editionIsInTextField() ? m_textField.XNTChar(defaultXNTChar) : m_layoutField.XNTChar(defaultXNTChar); +} + +bool ExpressionField::shouldFinishEditing(Ion::Events::Event event) { + return editionIsInTextField() ? m_textField.shouldFinishEditing(event) : m_layoutField.shouldFinishEditing(event); +} + const char * ExpressionField::text() { if (!editionIsInTextField()) { m_layoutField.serialize(m_textBuffer, m_textBufferLength); diff --git a/escher/src/input_event_handler.cpp b/escher/src/input_event_handler.cpp new file mode 100644 index 000000000..fa6052b42 --- /dev/null +++ b/escher/src/input_event_handler.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +bool InputEventHandler::handleToolboxEvent(App * app) { + if (toolbox() != nullptr) { + toolbox()->setSender(this); + app->displayModalViewController(toolbox(), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + return true; + } + return false; +} diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 41aba11c9..fea8d16bc 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -64,7 +64,7 @@ bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::E return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event); } -Toolbox * InputViewController::toolboxForTextInput(TextInput * input) { +Toolbox * InputViewController::toolboxForTextInput(InputEventHandler * input) { return m_textFieldDelegate->toolboxForTextInput(input); } diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 51ade0327..e4ed9e906 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -185,13 +185,13 @@ bool LayoutField::privateHandleEvent(Ion::Events::Event event) { if (m_delegate && m_delegate->layoutFieldDidReceiveEvent(this, event)) { return true; } - if (Responder::handleEvent(event)) { - /* The only event Responder handles is 'Toolbox' displaying. In that case, - * the LayoutField is forced into editing mode. */ - if (!isEditing()) { - setEditing(true); + if (event == Ion::Events::Toolbox) { + if (handleToolboxEvent(app())) { + if (!isEditing()) { + setEditing(true); + } + return true; } - return true; } if (isEditing() && m_delegate->layoutFieldShouldFinishEditing(this, event)) { //TODO use class method? setEditing(false); diff --git a/escher/src/responder.cpp b/escher/src/responder.cpp index 0969c47c2..919b6d99d 100644 --- a/escher/src/responder.cpp +++ b/escher/src/responder.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -17,15 +16,6 @@ void Responder::setParentResponder(Responder * responder) { m_parentResponder = 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, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); - return true; - } - return false; -} - void Responder::didBecomeFirstResponder() { } diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index 9a5c17b7a..ad7abeec8 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -18,6 +18,13 @@ TextArea::TextArea(Responder * parentResponder, View * contentView, const KDFont { } +Toolbox * TextArea::toolbox() { + if (delegate()) { + return delegate()->toolboxForTextInput(this); + } + return nullptr; +} + bool TextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { int nextCursorLocation = cursorLocation(); @@ -50,9 +57,8 @@ bool TextArea::handleEventWithText(const char * text, bool indentation, bool for bool TextArea::handleEvent(Ion::Events::Event event) { if (m_delegate != nullptr && m_delegate->textAreaDidReceiveEvent(this, event)) { return true; - } else if (Responder::handleEvent(event)) { - // The only event Responder handles is 'Toolbox' displaying. - return true; + } else if (event == Ion::Events::Toolbox) { + return handleToolboxEvent(app()); } else if (event == Ion::Events::Left) { return setCursorLocation(cursorLocation()-1); } else if (event == Ion::Events::Right) { diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index 355a765e7..7a6e0fad0 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -228,13 +228,13 @@ void TextField::setEditing(bool isEditing, bool reinitDrafBuffer) { } bool TextField::privateHandleEvent(Ion::Events::Event event) { - if (Responder::handleEvent(event)) { - /* The only event Responder handles is 'Toolbox' displaying. In that case, - * the text field is forced into editing mode. */ - if (!isEditing()) { - setEditing(true); + if (event == Ion::Events::Toolbox) { + if (handleToolboxEvent(app())) { + if (!isEditing()) { + setEditing(true); + } + return true; } - return true; } if (event == Ion::Events::Left && isEditing() && cursorLocation() > 0) { return setCursorLocation(cursorLocation()-1); @@ -358,6 +358,13 @@ char TextField::XNTChar(char defaultXNTChar) { return defaultXNTChar; } +Toolbox * TextField::toolbox() { + if (delegate()) { + return delegate()->toolboxForTextInput(this); + } + return nullptr; +} + bool TextField::handleEvent(Ion::Events::Event event) { assert(m_delegate != nullptr); if (m_delegate->textFieldDidReceiveEvent(this, event)) { diff --git a/escher/src/text_input.cpp b/escher/src/text_input.cpp index c4c237885..837dec996 100644 --- a/escher/src/text_input.cpp +++ b/escher/src/text_input.cpp @@ -59,13 +59,6 @@ TextInput::TextInput(Responder * parentResponder, View * contentView) : { } -Toolbox * TextInput::toolbox() { - if (delegate()) { - return delegate()->toolboxForTextInput(this); - } - return nullptr; -} - bool TextInput::removeChar() { contentView()->removeChar(); scrollToCursor();