From 7fce83d1dd954d504ac223bef3988095ab333fbc Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 10 Oct 2019 16:42:25 +0200 Subject: [PATCH] [escher/expression_field] Detect whether view's height did change by memoizing the height Such changes used to be detected only when the height was equal to the maximal allowed value, by detecting whether the height shifted from or to that maximal value. For that purpose, a boolean was memoized in InputViewController and in Calculation::EditExpressionController. --- apps/calculation/edit_expression_controller.cpp | 11 ++++------- apps/calculation/edit_expression_controller.h | 1 - escher/include/escher/expression_field.h | 4 +++- escher/include/escher/input_view_controller.h | 1 - escher/src/expression_field.cpp | 12 ++++++++++-- escher/src/input_view_controller.cpp | 11 ++++------- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 41a63a854..df76015ab 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -42,8 +42,7 @@ EditExpressionController::EditExpressionController(Responder * parentResponder, ViewController(parentResponder), m_historyController(historyController), m_calculationStore(calculationStore), - m_contentView(this, (TableView *)m_historyController->view(), inputEventHandlerDelegate, this, this), - m_inputViewHeightIsMaximal(false) + m_contentView(this, (TableView *)m_historyController->view(), inputEventHandlerDelegate, this, this) { m_cacheBuffer[0] = 0; } @@ -90,11 +89,9 @@ bool EditExpressionController::layoutFieldDidAbortEditing(::LayoutField * layout } void EditExpressionController::layoutFieldDidChangeSize(::LayoutField * layoutField) { - /* Reload the view only if the ExpressionField height actually changes, i.e. - * not if the height is already maximal and stays maximal. */ - bool newInputViewHeightIsMaximal = m_contentView.expressionField()->heightIsMaximal(); - if (!m_inputViewHeightIsMaximal || !newInputViewHeightIsMaximal) { - m_inputViewHeightIsMaximal = newInputViewHeightIsMaximal; + if (m_contentView.expressionField()->inputViewHeightDidChange()) { + /* Reload the whole view only if the ExpressionField's height did actually + * change. */ reloadView(); } else { /* The input view is already at maximal size so we do not need to relayout diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 42c949323..0259f8795 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -53,7 +53,6 @@ private: HistoryController * m_historyController; CalculationStore * m_calculationStore; ContentView m_contentView; - bool m_inputViewHeightIsMaximal; }; } diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index 6e3faf5b2..bdbec1afa 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -23,7 +23,7 @@ public: void setText(const char * text); bool editionIsInTextField() const; bool isEmpty() const; - bool heightIsMaximal() const; + bool inputViewHeightDidChange(); bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false); /* View */ @@ -35,6 +35,7 @@ public: /* Responder */ bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; private: static constexpr int k_textFieldBufferSize = TextField::maxBufferSize(); @@ -44,6 +45,7 @@ private: static constexpr KDCoordinate k_verticalMargin = 5; constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness; KDCoordinate inputViewHeight() const; + KDCoordinate m_inputViewMemoizedHeight; TextField m_textField; LayoutField m_layoutField; }; diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 2867c6959..5d0bd9197 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -64,7 +64,6 @@ private: InputEventHandlerDelegate * m_inputEventHandlerDelegate; TextFieldDelegate * m_textFieldDelegate; LayoutFieldDelegate * m_layoutFieldDelegate; - bool m_inputViewHeightIsMaximal; }; #endif diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index fb8fcf7df..9c7dbab8a 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -8,6 +8,7 @@ static inline KDCoordinate maxCoordinate(KDCoordinate x, KDCoordinate y) { retur ExpressionField::ExpressionField(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : Responder(parentResponder), View(), + m_inputViewMemoizedHeight(0), m_textField(parentResponder, nullptr, k_textFieldBufferSize, k_textFieldBufferSize, inputEventHandlerDelegate, textFieldDelegate, KDFont::LargeFont, 0.0f, 0.5f, KDColorBlack, KDColorWhite), m_layoutField(parentResponder, inputEventHandlerDelegate, layoutFieldDelegate) { @@ -82,6 +83,10 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) { return editionIsInTextField() ? m_textField.handleEvent(event) : m_layoutField.handleEvent(event); } +void ExpressionField::didBecomeFirstResponder() { + m_inputViewMemoizedHeight = inputViewHeight(); +} + KDSize ExpressionField::minimalSizeForOptimalDisplay() const { return KDSize(0, inputViewHeight()); } @@ -94,8 +99,11 @@ bool ExpressionField::isEmpty() const { return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_layoutField.hasText(); } -bool ExpressionField::heightIsMaximal() const { - return inputViewHeight() == k_separatorThickness + k_maximalHeight; +bool ExpressionField::inputViewHeightDidChange() { + KDCoordinate newHeight = inputViewHeight(); + bool didChange = m_inputViewMemoizedHeight != newHeight; + m_inputViewMemoizedHeight = newHeight; + return didChange; } bool ExpressionField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 669c7e60c..2947054a7 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -20,8 +20,7 @@ InputViewController::InputViewController(Responder * parentResponder, ViewContro m_failureAction(Invocation(nullptr, nullptr)), m_inputEventHandlerDelegate(inputEventHandlerDelegate), m_textFieldDelegate(textFieldDelegate), - m_layoutFieldDelegate(layoutFieldDelegate), - m_inputViewHeightIsMaximal(false) + m_layoutFieldDelegate(layoutFieldDelegate) { } @@ -86,11 +85,9 @@ bool InputViewController::layoutFieldDidAbortEditing(LayoutField * layoutField) } void InputViewController::layoutFieldDidChangeSize(LayoutField * layoutField) { - /* Reload the view only if the ExpressionField height actually changes, i.e. - * not if the height is already maximal and stays maximal. */ - bool newInputViewHeightIsMaximal = m_expressionFieldController.expressionField()->heightIsMaximal(); - if (!m_inputViewHeightIsMaximal || !newInputViewHeightIsMaximal) { - m_inputViewHeightIsMaximal = newInputViewHeightIsMaximal; + if (m_expressionFieldController.expressionField()->inputViewHeightDidChange()) { + /* Reload the whole view only if the ExpressionField's height did actually + * change. */ reloadModalViewController(); } else { /* The input view is already at maximal size so we do not need to relayout