diff --git a/apps/Makefile b/apps/Makefile index 2a34edc13..815800ced 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -7,6 +7,7 @@ include apps/calculation/Makefile app_objs += $(addprefix apps/,\ apps_container.o\ constant.o\ + expression_text_field_delegate.o\ main.o\ ) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 4c2867583..25ccffc53 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -8,7 +8,7 @@ App::App(Context * context) : m_globalContext(context), m_calculationStore(CalculationStore()), m_historyController(HistoryController(&m_editExpressionController, &m_calculationStore)), - m_editExpressionController(EditExpressionController(&m_modalViewController, &m_historyController, &m_calculationStore)) + m_editExpressionController(EditExpressionController(&m_modalViewController, &m_historyController, &m_calculationStore, this)) { } diff --git a/apps/calculation/app.h b/apps/calculation/app.h index 35553e85f..863fcfd8c 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -3,11 +3,12 @@ #include "edit_expression_controller.h" #include "history_controller.h" +#include "../expression_text_field_delegate.h" #include namespace Calculation { -class App : public ::App { +class App : public ::App, public ExpressionTextFieldDelegate { public: App(Context * context); Context * globalContext(); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 9fc3c7b8b..45864ec15 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -4,10 +4,10 @@ namespace Calculation { -EditExpressionController::ContentView::ContentView(TableView * subview) : +EditExpressionController::ContentView::ContentView(TableView * subview, TextFieldDelegate * textFieldDelegate) : View(), m_mainView(subview), - m_textField(nullptr, m_textBody, 255) + m_textField(nullptr, m_textBody, 255, textFieldDelegate) { m_textBody[0] = 0; } @@ -43,9 +43,9 @@ TableView * EditExpressionController::ContentView::mainView() { return m_mainView; } -EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) : +EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore, TextFieldDelegate * textFieldDelegate) : ViewController(parentResponder), - m_contentView((TableView *)historyController->view()), + m_contentView((TableView *)historyController->view(), textFieldDelegate), m_historyController(historyController), m_calculationStore(calculationStore) { diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index a47f8112f..533a68993 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -10,7 +10,7 @@ class HistoryController; class EditExpressionController : public ViewController { public: - EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore); + EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore, TextFieldDelegate * textFieldDelegate); View * view() override; const char * title() const override; void didBecomeFirstResponder() override; @@ -21,7 +21,7 @@ public: private: class ContentView : public View { public: - ContentView(TableView * subview); + ContentView(TableView * subview, TextFieldDelegate * textFieldDelegate); int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; diff --git a/apps/expression_text_field_delegate.cpp b/apps/expression_text_field_delegate.cpp new file mode 100644 index 000000000..a591baa2a --- /dev/null +++ b/apps/expression_text_field_delegate.cpp @@ -0,0 +1,13 @@ +#include "expression_text_field_delegate.h" +#include + +bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) { + if (event == Ion::Events::Event::ENTER && Expression::parse(textField->textBuffer()) == nullptr) { + if (textField->bufferLength() == 0) { + return true; + } + textField->app()->displayWarning("Attention a la syntaxe jeune padawan"); + return true; + } + return false; +} diff --git a/apps/expression_text_field_delegate.h b/apps/expression_text_field_delegate.h new file mode 100644 index 000000000..c21aa3f5d --- /dev/null +++ b/apps/expression_text_field_delegate.h @@ -0,0 +1,11 @@ +#ifndef APPS_EXPRESSION_TEXT_FIELD_DELEGATE_H +#define APPS_EXPRESSION_TEXT_FIELD_DELEGATE_H + +#include + +class ExpressionTextFieldDelegate : public TextFieldDelegate { +public: + bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; +}; + +#endif diff --git a/apps/graph/app.cpp b/apps/graph/app.cpp index aea5a71d4..3611dd320 100644 --- a/apps/graph/app.cpp +++ b/apps/graph/app.cpp @@ -14,7 +14,7 @@ App::App(::Context * context) : m_valuesController(nullptr, &m_functionStore, &m_evaluateContext), m_valuesStackViewController(StackViewController(&m_tabViewController, &m_valuesController)), m_tabViewController(&m_inputViewController, &m_listStackViewController, &m_graphController, &m_valuesStackViewController), - m_inputViewController(&m_modalViewController, &m_tabViewController) + m_inputViewController(&m_modalViewController, &m_tabViewController, this) { } diff --git a/apps/graph/app.h b/apps/graph/app.h index dd7894eac..a0b4b462e 100644 --- a/apps/graph/app.h +++ b/apps/graph/app.h @@ -7,10 +7,11 @@ #include "graph/graph_controller.h" #include "list/list_controller.h" #include "values/values_controller.h" +#include "../expression_text_field_delegate.h" namespace Graph { -class App : public ::App { +class App : public ::App, public ExpressionTextFieldDelegate { public: App(::Context * context); InputViewController * inputViewController(); diff --git a/escher/include/escher.h b/escher/include/escher.h index 36b671309..16daa2425 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 22c1dbdfe..27ccbf3bd 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -4,10 +4,11 @@ #include #include #include +#include class InputViewController : public ViewController { public: - InputViewController(Responder * parentResponder, ViewController * child); + InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate = nullptr); View * view() override; const char * title() const override; @@ -17,7 +18,7 @@ public: private: class ContentView : public View { public: - ContentView(); + ContentView(TextFieldDelegate * textFieldDelegate); void setMainView(View * subview); int numberOfSubviews() const override; View * subviewAtIndex(int index) override; diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index 23aef242a..26b7e682d 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -3,17 +3,19 @@ #include #include +#include #include class TextField : public View, public Responder { public: - TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize); + TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate = nullptr); // View void drawRect(KDContext * ctx, KDRect rect) const override; // Responder bool handleEvent(Ion::Events::Event event) override; const char * textBuffer() const; + int bufferLength() const; void setTextBuffer(const char * text); protected: #if ESCHER_VIEW_LOGGING @@ -23,6 +25,7 @@ private: char * m_textBuffer; size_t m_textBufferSize; size_t m_currentTextLength; + TextFieldDelegate * m_delegate; }; #endif diff --git a/escher/include/escher/text_field_delegate.h b/escher/include/escher/text_field_delegate.h new file mode 100644 index 000000000..8630e61c7 --- /dev/null +++ b/escher/include/escher/text_field_delegate.h @@ -0,0 +1,11 @@ +#ifndef ESCHER_TEXT_FIELD_DELEGATE_H +#define ESCHER_TEXT_FIELD_DELEGATE_H + +class TextField; + +class TextFieldDelegate { +public: + virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) = 0; +}; + +#endif diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index b09b9712d..5e817f657 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -2,10 +2,10 @@ #include #include -InputViewController::ContentView::ContentView() : +InputViewController::ContentView::ContentView(TextFieldDelegate * textFieldDelegate) : View(), m_mainView(nullptr), - m_textField(nullptr, m_textBody, 255), + m_textField(nullptr, m_textBody, 255, textFieldDelegate), m_visibleInput(false) { m_textBody[0] = 0; @@ -61,9 +61,9 @@ TextField * InputViewController::ContentView::textField() { return &m_textField; } -InputViewController::InputViewController(Responder * parentResponder, ViewController * child) : +InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate) : ViewController(parentResponder), - m_contentView(), + m_contentView(textFieldDelegate), m_previousResponder(nullptr), m_regularViewController(child), m_successAction(Invocation(nullptr, nullptr)), diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index b3987ff1f..cd9c72981 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -1,11 +1,12 @@ #include -TextField::TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize) : +TextField::TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate) : View(), Responder(parentResponder), m_textBuffer(textBuffer), m_textBufferSize(textBufferSize), - m_currentTextLength(0) + m_currentTextLength(0), + m_delegate(delegate) { } @@ -25,27 +26,36 @@ const char * TextField::className() const { /* Responder */ bool TextField::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::Event::DELETE && m_currentTextLength > 0) { - KDSize sizePreviousText = KDText::stringSize(m_textBuffer); - m_currentTextLength--; - m_textBuffer[m_currentTextLength] = 0; - KDSize sizeText = KDText::stringSize(m_textBuffer); - KDRect dirtyZone(sizeText.width(), 0, sizePreviousText.width()-sizeText.width(), sizeText.height()); - markRectAsDirty(dirtyZone); - return true; + if (m_delegate) { + if (m_delegate->textFieldDidReceiveEvent(this, event)) { + return true; + } } - if ((int)event >= 0x100) { - return false; + switch (event) { + case Ion::Events::Event::DELETE: + if (m_currentTextLength > 0) { + KDSize sizePreviousText = KDText::stringSize(m_textBuffer); + m_currentTextLength--; + m_textBuffer[m_currentTextLength] = 0; + KDSize sizeText = KDText::stringSize(m_textBuffer); + KDRect dirtyZone(sizeText.width(), 0, sizePreviousText.width()-sizeText.width(), sizeText.height()); + markRectAsDirty(dirtyZone); + } + return true; + default: + if ((int)event >= 0x100) { + return false; + } + if (m_currentTextLength == 0 || m_currentTextLength-1 < m_textBufferSize) { + KDSize sizePreviousText = KDText::stringSize(m_textBuffer); + m_textBuffer[m_currentTextLength++] = (int)event; + m_textBuffer[m_currentTextLength] = 0; + KDSize sizeText = KDText::stringSize(m_textBuffer); + KDRect dirtyZone(sizePreviousText.width(), 0, sizeText.width()-sizePreviousText.width(), sizeText.height()); + markRectAsDirty(dirtyZone); + } + return true; } - if (m_currentTextLength == 0 || m_currentTextLength-1 < m_textBufferSize) { - KDSize sizePreviousText = KDText::stringSize(m_textBuffer); - m_textBuffer[m_currentTextLength++] = (int)event; - m_textBuffer[m_currentTextLength] = 0; - KDSize sizeText = KDText::stringSize(m_textBuffer); - KDRect dirtyZone(sizePreviousText.width(), 0, sizeText.width()-sizePreviousText.width(), sizeText.height()); - markRectAsDirty(dirtyZone); - } - return true; } const char * TextField::textBuffer () const { @@ -53,6 +63,10 @@ const char * TextField::textBuffer () const { return textBuffer; } +int TextField::bufferLength () const { + return m_currentTextLength; +} + void TextField::setTextBuffer(const char * text) { strlcpy(m_textBuffer, text, m_textBufferSize); m_currentTextLength = strlen(text);