From 8ab23f66b5d7237467665da36791955405f72db2 Mon Sep 17 00:00:00 2001 From: Gabriel Ozouf Date: Thu, 11 Jun 2020 11:40:42 +0200 Subject: [PATCH] [escher/expression_field] Methods on layout Added some methods to manipulate the layout of a LayoutField from an ExpressionField, like storing into and restoring from a buffer. Change-Id: I7b7b5b53626f19237a5215bd196e897a518e9577 --- escher/include/escher/expression_field.h | 2 ++ escher/include/escher/layout_field.h | 1 + escher/src/expression_field.cpp | 43 ++++++++++++++++++++++++ escher/src/layout_field.cpp | 8 +++++ 4 files changed, 54 insertions(+) diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index a79da0bdb..e89c1dc98 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -26,6 +26,8 @@ public: bool inputViewHeightDidChange(); bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false); void setLayoutInsertionCursorEvent(Ion::Events::Event event) { m_layoutField.setInsertionCursorEvent(event); } + size_t dumpLayout(char * buffer, size_t bufferSize) const; + void restoreLayout(const char * buffer, size_t size); /* View */ int numberOfSubviews() const override { return 1; } diff --git a/escher/include/escher/layout_field.h b/escher/include/escher/layout_field.h index b2ebf927c..a39e585ba 100644 --- a/escher/include/escher/layout_field.h +++ b/escher/include/escher/layout_field.h @@ -35,6 +35,7 @@ public: CodePoint XNTCodePoint(CodePoint defaultXNTCodePoint) override; void putCursorRightOfLayout(); void setInsertionCursorEvent(Ion::Events::Event event) { m_insertionCursorEvent = event; } + void setLayout(Poincare::Layout newLayout); // ScrollableView void setBackgroundColor(KDColor c) override { diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 300f1d039..599f69b7f 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -121,3 +121,46 @@ KDCoordinate ExpressionField::inputViewHeight() const { std::min(k_maximalHeight, std::max(k_minimalHeight, m_layoutField.minimalSizeForOptimalDisplay().height()))); } + +size_t ExpressionField::dumpLayout(char * buffer, size_t bufferSize) const { + size_t size; + size_t returnValue; + char * currentLayout; + if (editionIsInTextField()) { + size = strlen(m_textField.draftTextBuffer()) + 1; + currentLayout = m_textField.draftTextBuffer(); + /* We take advantage of the fact that draftTextBuffer is null terminated to + * use a size of 0 as a shorthand for "The buffer contains raw text instead + * of layouts", since the size of a layout is at least 32 (the size of an + * empty horizontal layout). This way, we can detect when the edition mode + * has changed and invalidate the data.*/ + returnValue = 0; + } else { + size = m_layoutField.layout().size(); + currentLayout = reinterpret_cast(m_layoutField.layout().node()); + returnValue = size; + } + if (size > bufferSize - 1) { + buffer[0] = 0; + return 0; + } + memcpy(buffer, currentLayout, size); + return returnValue; +} + +void ExpressionField::restoreLayout(const char * buffer, size_t size) { + if (editionIsInTextField()) { + if (size != 0 || buffer[0] == 0) { + /* A size other than 0 means the buffer contains Layout information + * (instead of raw text) that we don't want to restore. This is most + * likely because the edition mode has been changed between use. */ + return; + } + setText(buffer); + return; + } + if (size == 0) { + return; + } + m_layoutField.setLayout(Poincare::Layout::LayoutFromAddress(buffer, size)); +} diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 86fd6aa1e..ff6b493dd 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -314,6 +314,14 @@ void LayoutField::clearLayout() { reloadScroll(); // Put the scroll to offset 0 } +void LayoutField::setLayout(Poincare::Layout newLayout) { + m_contentView.clearLayout(); + KDSize previousSize = minimalSizeForOptimalDisplay(); + const_cast(m_contentView.expressionView())->setLayout(newLayout); + putCursorRightOfLayout(); + reload(previousSize); +} + Context * LayoutField::context() const { return (m_delegate != nullptr) ? m_delegate->context() : nullptr; }