Files
Upsilon/escher/src/input_view_controller.cpp
Ruben Dashyan 7fce83d1dd [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.
2020-02-12 15:13:16 +01:00

122 lines
4.8 KiB
C++

#include <escher/input_view_controller.h>
#include <escher/container.h>
#include <escher/palette.h>
#include <assert.h>
InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
ViewController(parentResponder),
m_expressionField(this, inputEventHandlerDelegate, textFieldDelegate, layoutFieldDelegate)
{
}
void InputViewController::ExpressionFieldController::didBecomeFirstResponder() {
Container::activeApp()->setFirstResponder(&m_expressionField);
}
InputViewController::InputViewController(Responder * parentResponder, ViewController * child, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
ModalViewController(parentResponder, child),
m_expressionFieldController(this, this, this, this),
m_successAction(Invocation(nullptr, nullptr)),
m_failureAction(Invocation(nullptr, nullptr)),
m_inputEventHandlerDelegate(inputEventHandlerDelegate),
m_textFieldDelegate(textFieldDelegate),
m_layoutFieldDelegate(layoutFieldDelegate)
{
}
void InputViewController::edit(Responder * caller, Ion::Events::Event event, void * context, Invocation::Action successAction, Invocation::Action failureAction) {
m_successAction = Invocation(successAction, context);
m_failureAction = Invocation(failureAction, context);
displayModalViewController(&m_expressionFieldController, 1.0f, 1.0f);
m_expressionFieldController.expressionField()->handleEvent(event);
}
bool InputViewController::isEditing() {
return m_expressionFieldController.expressionField()->isEditing();
}
void InputViewController::abortEditionAndDismiss() {
m_expressionFieldController.expressionField()->setEditing(false);
dismissModalViewController();
}
bool InputViewController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
return event == Ion::Events::OK || event == Ion::Events::EXE;
}
bool InputViewController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
if (inputViewDidFinishEditing()) {
m_textFieldDelegate->textFieldDidFinishEditing(textField, text, event);
return true;
}
return false;
}
bool InputViewController::textFieldDidAbortEditing(TextField * textField) {
inputViewDidAbortEditing();
m_textFieldDelegate->textFieldDidAbortEditing(textField);
return true;
}
bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event);
}
bool InputViewController::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) {
return event == Ion::Events::OK || event == Ion::Events::EXE;
}
bool InputViewController::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) {
return m_layoutFieldDelegate->layoutFieldDidReceiveEvent(layoutField, event);
}
bool InputViewController::layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) {
if (inputViewDidFinishEditing()) {
m_layoutFieldDelegate->layoutFieldDidFinishEditing(layoutField, layoutR, event);
return true;
}
return false;
}
bool InputViewController::layoutFieldDidAbortEditing(LayoutField * layoutField) {
inputViewDidAbortEditing();
m_layoutFieldDelegate->layoutFieldDidAbortEditing(layoutField);
return true;
}
void InputViewController::layoutFieldDidChangeSize(LayoutField * layoutField) {
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
* the view underneath, but the view inside the input view might still need
* to be relayouted.
* We force the relayout because the frame stays the same but we need to
* propagate a relayout to the content of the field scroll view. */
m_expressionFieldController.expressionField()->layoutSubviews(true);
}
}
Toolbox * InputViewController::toolboxForInputEventHandler(InputEventHandler * handler) {
return m_inputEventHandlerDelegate->toolboxForInputEventHandler(handler);
}
NestedMenuController * InputViewController::variableBoxForInputEventHandler(InputEventHandler * handler) {
return m_inputEventHandlerDelegate->variableBoxForInputEventHandler(handler);
}
bool InputViewController::inputViewDidFinishEditing() {
if (m_successAction.perform(this)) {
dismissModalViewController();
return true;
}
return false;
}
void InputViewController::inputViewDidAbortEditing() {
m_failureAction.perform(this);
dismissModalViewController();
}