From 7a4ee746b2a49a090cf920cfe53935ccdea7d607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 30 Jul 2019 11:27:42 +0200 Subject: [PATCH] [escher] TextField: call reinitDraftBuffer after edition is complete to avoid erasing text that is required later. Fix bug: OK handling on function list in linear mode did not copy the function expression into the textfield before editing --- apps/code/console_edit_cell.cpp | 4 +- apps/code/console_edit_cell.h | 2 +- apps/code/menu_controller.cpp | 4 +- apps/graph/list/list_controller.cpp | 4 +- .../list/text_field_function_title_cell.cpp | 2 +- .../buffer_text_view_with_text_field.cpp | 2 +- escher/include/escher/editable_field.h | 2 +- escher/include/escher/layout_field.h | 2 +- escher/include/escher/text_field.h | 5 +- escher/src/expression_field.cpp | 6 ++- escher/src/text_field.cpp | 50 ++++++++----------- 11 files changed, 40 insertions(+), 43 deletions(-) diff --git a/apps/code/console_edit_cell.cpp b/apps/code/console_edit_cell.cpp index 8e1938aa8..e1c078ca4 100644 --- a/apps/code/console_edit_cell.cpp +++ b/apps/code/console_edit_cell.cpp @@ -38,8 +38,8 @@ void ConsoleEditCell::didBecomeFirstResponder() { Container::activeApp()->setFirstResponder(&m_textField); } -void ConsoleEditCell::setEditing(bool isEditing, bool reinitDraftBuffer) { - m_textField.setEditing(isEditing, reinitDraftBuffer); +void ConsoleEditCell::setEditing(bool isEditing) { + m_textField.setEditing(isEditing); } void ConsoleEditCell::setText(const char * text) { diff --git a/apps/code/console_edit_cell.h b/apps/code/console_edit_cell.h index 8a6b2d9b3..f97c2653d 100644 --- a/apps/code/console_edit_cell.h +++ b/apps/code/console_edit_cell.h @@ -27,7 +27,7 @@ public: } // Edit cell - void setEditing(bool isEditing, bool reinitDraftBuffer = false); + void setEditing(bool isEditing); const char * text() const override { return m_textField.text(); } void setText(const char * text); bool insertText(const char * text); diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 381d13e23..c9b163e1d 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -49,7 +49,7 @@ void MenuController::willExitResponderChain(Responder * nextFirstResponder) { if (selectedRow >= 0 && selectedRow < m_scriptStore->numberOfScripts() && selectedColumn == 0) { TextField * tf = static_cast(m_selectableTableView.selectedCell())->textField(); if (tf->isEditing()) { - tf->setEditing(false, false); + tf->setEditing(false); privateTextFieldDidAbortEditing(tf, false); } } @@ -126,7 +126,7 @@ void MenuController::renameSelectedScript() { ScriptNameCell * myCell = static_cast(m_selectableTableView.selectedCell()); Container::activeApp()->setFirstResponder(myCell); myCell->setHighlighted(false); - myCell->textField()->setEditing(true, false); + myCell->textField()->setEditing(true); myCell->textField()->setCursorLocation(myCell->textField()->text() + strlen(myCell->textField()->text())); } diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index ed17fd5d5..9174738a5 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -73,7 +73,7 @@ bool ListController::textFieldDidFinishEditing(TextField * textField, const char // Handle any error if (error == Ion::Storage::Record::ErrorStatus::None) { bool selectTab = false; - textField->setEditing(false, false); + textField->setEditing(false); computeTitlesColumnWidth(); int currentRow = m_selectableTableView.selectedRow(); if (event == Ion::Events::Down && currentRow < numberOfRows() - 1) { @@ -109,7 +109,7 @@ bool ListController::textFieldDidFinishEditing(TextField * textField, const char assert(error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable); Container::activeApp()->displayWarning(I18n::Message::NameTooLong); } - textField->setEditing(true, false); + textField->setEditing(true); return false; } diff --git a/apps/graph/list/text_field_function_title_cell.cpp b/apps/graph/list/text_field_function_title_cell.cpp index 16ef037c3..4953d4621 100644 --- a/apps/graph/list/text_field_function_title_cell.cpp +++ b/apps/graph/list/text_field_function_title_cell.cpp @@ -26,7 +26,7 @@ Responder * TextFieldFunctionTitleCell::responder() { void TextFieldFunctionTitleCell::setEditing(bool editing) { Container::activeApp()->setFirstResponder(&m_textField); const char * previousText = m_textField.text(); - m_textField.setEditing(true, false); + m_textField.setEditing(true); m_textField.setText(previousText); } diff --git a/apps/shared/buffer_text_view_with_text_field.cpp b/apps/shared/buffer_text_view_with_text_field.cpp index ca71591a1..15b149913 100644 --- a/apps/shared/buffer_text_view_with_text_field.cpp +++ b/apps/shared/buffer_text_view_with_text_field.cpp @@ -41,7 +41,7 @@ void BufferTextViewWithTextField::drawRect(KDContext * ctx, KDRect rect) const { void BufferTextViewWithTextField::didBecomeFirstResponder() { Container::activeApp()->setFirstResponder(&m_textField); - m_textField.setEditing(true, false); + m_textField.setEditing(true); markRectAsDirty(bounds()); } diff --git a/escher/include/escher/editable_field.h b/escher/include/escher/editable_field.h index 3e7beeb98..bdee14acc 100644 --- a/escher/include/escher/editable_field.h +++ b/escher/include/escher/editable_field.h @@ -9,7 +9,7 @@ class EditableField : public InputEventHandler { public: using InputEventHandler::InputEventHandler; virtual bool isEditing() const = 0; - virtual void setEditing(bool isEditing, bool reinitDraftBuffer = true) = 0; + virtual void setEditing(bool isEditing) = 0; virtual CodePoint XNTCodePoint(CodePoint defaultXNTCodePoint) = 0; virtual bool shouldFinishEditing(Ion::Events::Event event) = 0; }; diff --git a/escher/include/escher/layout_field.h b/escher/include/escher/layout_field.h index 3994e89d4..ef19f271a 100644 --- a/escher/include/escher/layout_field.h +++ b/escher/include/escher/layout_field.h @@ -21,7 +21,7 @@ public: {} void setDelegates(InputEventHandlerDelegate * inputEventHandlerDelegate, LayoutFieldDelegate * delegate) { m_inputEventHandlerDelegate = inputEventHandlerDelegate; m_delegate = delegate; } bool isEditing() const override { return m_contentView.isEditing(); } - void setEditing(bool isEditing, bool reinitDraftBuffer = false) override { m_contentView.setEditing(isEditing); } + void setEditing(bool isEditing) override { m_contentView.setEditing(isEditing); } void clearLayout() { m_contentView.clearLayout(); } void scrollToCursor() { scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline()); diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index f1e7d1392..b78cd3ce5 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -14,13 +14,14 @@ public: void setBackgroundColor(KDColor backgroundColor) override; void setTextColor(KDColor textColor); void setDelegates(InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * delegate) { m_inputEventHandlerDelegate = inputEventHandlerDelegate; m_delegate = delegate; } + void reinitDraftTextBuffer() { m_contentView.reinitDraftTextBuffer(); } void setDraftTextBuffer(char * draftTextBuffer); bool isEditing() const override; const char * draftTextBuffer() const { return const_cast(this)->m_contentView.draftTextBuffer(); } size_t draftTextLength() const; //TODO keep ? void setText(const char * text); void setAlignment(float horizontalAlignment, float verticalAlignment); - virtual void setEditing(bool isEditing, bool reinitDraftBuffer = true) override; + void setEditing(bool isEditing) override { m_contentView.setEditing(isEditing); } CodePoint XNTCodePoint(CodePoint defaultXNTCodePoint) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; bool handleEvent(Ion::Events::Event event) override; @@ -48,7 +49,7 @@ protected: int bufferSize() { return k_maxBufferSize; } void setText(const char * text); void setAlignment(float horizontalAlignment, float verticalAlignment); - void setEditing(bool isEditing, bool reinitDraftBuffer); + void setEditing(bool isEditing); void reinitDraftTextBuffer(); /* If the text to be appended is too long to be added without overflowing the * buffer, nothing is done (not even adding few letters from the text to reach diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 043a80de4..649d073d4 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -23,7 +23,10 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { if (editionIsInTextField()) { - m_textField.setEditing(isEditing, reinitDraftBuffer); + if (reinitDraftBuffer) { + m_textField.reinitDraftTextBuffer(); + } + m_textField.setEditing(isEditing); } else { if (reinitDraftBuffer) { m_layoutField.clearLayout(); @@ -45,6 +48,7 @@ const char * ExpressionField::text() { void ExpressionField::setText(const char * text) { if (editionIsInTextField()) { + m_textField.reinitDraftTextBuffer(); m_textField.setText(text); } else { m_layoutField.clearLayout(); diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index d85ce90de..13232f5a4 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -22,7 +22,9 @@ TextField::ContentView::ContentView(char * textBuffer, char * draftTextBuffer, s m_backgroundColor(backgroundColor) { assert(m_textBufferSize <= k_maxBufferSize); - m_cursorLocation = draftTextBuffer; + if (m_draftTextBuffer) { + reinitDraftTextBuffer(); + } } void TextField::ContentView::setBackgroundColor(KDColor backgroundColor) { @@ -70,14 +72,11 @@ void TextField::ContentView::setAlignment(float horizontalAlignment, float verti markRectAsDirty(bounds()); } -void TextField::ContentView::setEditing(bool isEditing, bool reinitDrafBuffer) { - if (m_isEditing == isEditing && !reinitDrafBuffer) { +void TextField::ContentView::setEditing(bool isEditing) { + if (m_isEditing == isEditing) { return; } m_isEditing = isEditing; - if (reinitDrafBuffer) { - reinitDraftTextBuffer(); - } m_currentDraftTextLength = strlen(m_draftTextBuffer); if (m_cursorLocation < m_draftTextBuffer || m_cursorLocation > m_draftTextBuffer + m_currentDraftTextLength) @@ -245,6 +244,7 @@ void TextField::setTextColor(KDColor textColor) { void TextField::setDraftTextBuffer(char * draftTextBuffer) { m_contentView.setDraftTextBuffer(draftTextBuffer); + reinitDraftTextBuffer(); } bool TextField::isEditing() const { @@ -268,13 +268,6 @@ void TextField::setAlignment(float horizontalAlignment, float verticalAlignment) m_contentView.setAlignment(horizontalAlignment, verticalAlignment); } -void TextField::setEditing(bool isEditing, bool reinitDrafBuffer) { - m_contentView.setEditing(isEditing, reinitDrafBuffer); - if (reinitDrafBuffer) { - reloadScroll(); - } -} - bool TextField::privateHandleEvent(Ion::Events::Event event) { // Handle Toolbox or Var event if (handleBoxEvent(event)) { @@ -284,10 +277,7 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { return true; } if (isEditing() && shouldFinishEditing(event)) { - char bufferText[ContentView::k_maxBufferSize]; - const char * cursorLoc = cursorLocation(); if (m_hasTwoBuffers) { - strlcpy(bufferText, m_contentView.textBuffer(), ContentView::k_maxBufferSize); strlcpy(m_contentView.textBuffer(), m_contentView.draftTextBuffer(), m_contentView.bufferSize()); } /* If textFieldDidFinishEditing displays a pop-up (because of an unvalid @@ -296,21 +286,18 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { * which we do not want, as we are not really aborting edition, just * displaying a pop-up before returning to edition. * We thus set editing to false. */ - setEditing(false, m_hasTwoBuffers); + setEditing(false); if (m_delegate->textFieldDidFinishEditing(this, text(), event)) { + // Clean draft text for next use + if (m_hasTwoBuffers) { + reinitDraftTextBuffer(); + } /* We allow overscroll to avoid calling layoutSubviews twice because the * content might have changed. */ reloadScroll(true); return true; } - setEditing(true, false); - if (m_hasTwoBuffers) { - /* If the text was refused (textInputDidFinishEditing returned false, we - * reset the textfield in the same state as before */ - setText(m_contentView.textBuffer()); - strlcpy(m_contentView.textBuffer(), bufferText, ContentView::k_maxBufferSize); - setCursorLocation(cursorLoc); - } + setEditing(true); return true; } /* If a move event was not caught before, we handle it here to avoid bubbling @@ -327,7 +314,8 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { return removePreviousGlyph(); } if (event == Ion::Events::Back && isEditing()) { - setEditing(false, m_hasTwoBuffers); + reinitDraftTextBuffer(); + setEditing(false); m_delegate->textFieldDidAbortEditing(this); reloadScroll(true); return true; @@ -344,7 +332,7 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { } if (event == Ion::Events::Cut && !isEditing()) { Clipboard::sharedClipboard()->store(text()); - setEditing(true, true); + setEditing(true); return true; } return false; @@ -416,7 +404,9 @@ bool TextField::handleEvent(Ion::Events::Event event) { } else if (event == Ion::Events::Paste) { return handleEventWithText(Clipboard::sharedClipboard()->storedText()); } else if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { - return handleEventWithText(m_contentView.textBuffer()); + setEditing(true); + setText(m_contentView.textBuffer()); + didHandleEvent = true; } if (!didHandleEvent) { didHandleEvent = privateHandleEvent(event); @@ -489,5 +479,7 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation, bo } void TextField::removeWholeText() { - setEditing(true, true); + reinitDraftTextBuffer(); + setEditing(true); + reloadScroll(); }