[poincare] Layout::serialize is serializeForParsing or ParsedExpression

serializeForParsing serializes the layout once,
serializeParsedExpression serializes the layout, parses it and
serializes it again.
This commit is contained in:
Léa Saviot
2018-11-21 14:49:20 +01:00
committed by Émilie Feral
parent 2bdce9dd82
commit 94603b2b7d
11 changed files with 55 additions and 17 deletions

View File

@@ -157,7 +157,7 @@ bool EditExpressionController::inputViewDidFinishEditing(const char * text, Layo
assert(text);
strlcpy(m_cacheBuffer, text, k_cacheBufferSize);
} else {
layoutR.serialize(m_cacheBuffer, k_cacheBufferSize);
layoutR.serializeParsedExpression(m_cacheBuffer, k_cacheBufferSize);
}
m_calculationStore->push(m_cacheBuffer, calculationApp->localContext());
m_historyController->reload();

View File

@@ -97,7 +97,7 @@ void SequenceToolbox::buildExtraCellsLayouts(const char * sequenceName, int recu
bool SequenceToolbox::selectAddedCell(int selectedRow){
constexpr int bufferSize = 10;
char buffer[bufferSize];
m_addedCellLayout[selectedRow].serialize(buffer, bufferSize);
m_addedCellLayout[selectedRow].serializeParsedExpression(buffer, bufferSize);
sender()->handleEventWithText(buffer);
app()->dismissModalViewController();
return true;

View File

@@ -25,7 +25,7 @@ bool ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(LayoutField * layout
}
char buffer[TextField::maxBufferSize()];
int bufferSize = TextField::maxBufferSize();
int length = layoutField->serialize(buffer, bufferSize);
int length = layoutField->layout().serializeForParsing(buffer, bufferSize);
if (length >= bufferSize-1) {
/* If the buffer is totally full, it is VERY likely that writeTextInBuffer
* escaped before printing utterly the expression. */

View File

@@ -176,8 +176,8 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
/* Check for identity between exact and approximate layouts */
char exactBuffer[Shared::ExpressionModel::k_expressionBufferSize];
char approximateBuffer[Shared::ExpressionModel::k_expressionBufferSize];
m_exactSolutionExactLayouts[i].serialize(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionApproximateLayouts[i].serialize(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionExactLayouts[i].serializeForParsing(exactBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionApproximateLayouts[i].serializeForParsing(approximateBuffer, Shared::ExpressionModel::k_expressionBufferSize);
m_exactSolutionIdentity[i] = strcmp(exactBuffer, approximateBuffer) == 0;
/* Check for equality between exact and approximate layouts */
if (!m_exactSolutionIdentity[i]) {

View File

@@ -1,5 +1,6 @@
#include "list_controller.h"
#include "app.h"
#include <poincare/char_layout.h>
#include <assert.h>
using namespace Shared;
@@ -120,6 +121,12 @@ bool textRepresentsAnEquality(const char * text) {
return false;
}
bool layoutRepresentsAnEquality(Poincare::Layout l) {
return l.recursivelyMatches(
[](Poincare::Layout layout) {
return layout.isChar() && static_cast<Poincare::CharLayout &>(layout).character() == '"'; });
}
bool ListController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
if (textField->isEditing() && textField->shouldFinishEditing(event)) {
if (!textRepresentsAnEquality(textField->text())) {
@@ -139,13 +146,10 @@ bool ListController::textFieldDidReceiveEvent(TextField * textField, Ion::Events
bool ListController::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) {
if (layoutField->isEditing() && layoutField->shouldFinishEditing(event)) {
char buffer[TextField::maxBufferSize()];
layoutField->serialize(buffer, TextField::maxBufferSize());
if (!textRepresentsAnEquality(buffer)) {
if (!layoutRepresentsAnEquality(layoutField->layout())) {
layoutField->handleEvent(Ion::Events::ShiftRight);
layoutField->handleEventWithText("=0");
layoutField->serialize(buffer, TextField::maxBufferSize());
if (!textRepresentsAnEquality(buffer)) {
if (!layoutRepresentsAnEquality(layoutField->layout())) {
app()->displayWarning(I18n::Message::RequireEquation);
return true;
}

View File

@@ -41,7 +41,7 @@ void assert_equation_system_exact_solve_to(const char * equations[], EquationSto
}
int n = type == EquationStore::Type::PolynomialMonovariable ? numberOfSolutions+1 : numberOfSolutions; // Check Delta for PolynomialMonovariable
for (int i = 0; i < n; i++) {
equationStore.exactSolutionLayoutAtIndex(i, true).serialize(buffer, 200);
equationStore.exactSolutionLayoutAtIndex(i, true).serializeParsedExpression(buffer, 200);
translate_in_ASCII_chars(buffer);
quiz_assert(strcmp(buffer, solutions[i]) == 0);
}

View File

@@ -27,7 +27,6 @@ public:
scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline());
}
bool hasText() const { return layout().hasText(); }
int serialize(char * buffer, int bufferLength) { return layout().serialize(buffer, bufferLength); }
Poincare::Layout layout() const { return m_contentView.expressionView()->layout(); }
char XNTChar(char defaultXNTChar) override;

View File

@@ -11,7 +11,7 @@ void Clipboard::store(const char * storedText) {
}
void Clipboard::store(Poincare::Layout layoutR) {
layoutR.serialize(m_textBuffer, TextField::maxBufferSize());
layoutR.serializeParsedExpression(m_textBuffer, TextField::maxBufferSize());
}
const char * Clipboard::storedText() {

View File

@@ -37,7 +37,7 @@ bool ExpressionField::isEditing() const {
const char * ExpressionField::text() {
if (!editionIsInTextField()) {
m_layoutField.serialize(m_textBuffer, m_textBufferLength);
m_layoutField.layout().serializeParsedExpression(m_textBuffer, m_textBufferLength);
}
return m_textBuffer;
}

View File

@@ -36,9 +36,12 @@ public:
void invalidAllSizesPositionsAndBaselines() { return node()->invalidAllSizesPositionsAndBaselines(); }
// Serialization
int serialize(char * buffer, int bufferSize) const { return node()->serialize(buffer, bufferSize); }
int serializeForParsing(char * buffer, int bufferSize) const { return node()->serialize(buffer, bufferSize); }
int serializeParsedExpression(char * buffer, int bufferSize) const;
// Layout properties
typedef bool (*LayoutTest)(const Layout l);
bool recursivelyMatches(LayoutTest test) const;
bool mustHaveLeftSibling() const { return const_cast<Layout *>(this)->node()->mustHaveLeftSibling(); }
bool isEmpty() const { return const_cast<Layout *>(this)->node()->isEmpty(); }
bool isHorizontal() const { return const_cast<Layout *>(this)->node()->isHorizontal(); }
@@ -63,7 +66,7 @@ public:
LayoutCursor equivalentCursor(LayoutCursor * cursor);
// Tree
Layout childAtIndex(int i);
Layout childAtIndex(int i) const;
Layout root() const {
assert(!isUninitialized());
return Layout(node()->root());

View File

@@ -2,6 +2,7 @@
#include <poincare/bracket_pair_layout.h>
#include <poincare/char_layout.h>
#include <poincare/empty_layout.h>
#include <poincare/expression.h>
#include <poincare/horizontal_layout.h>
#include <poincare/layout_cursor.h>
@@ -16,6 +17,37 @@ Layout Layout::clone() const {
return cast;
}
int Layout::serializeParsedExpression(char * buffer, int bufferSize) const {
/* This method fixes the following problem:
* Some layouts have a special serialization so they can be parsed afterwards,
* such has logBase3(2) that serializes as log_{3}(2). When handling the
* layout text, we want to use log(2,3) because we might paste the text in a
* LinearEdition textfield, so what we really want is the parsed expression's
* serialization. */
if (bufferSize <= 0) {
return 0;
}
serializeForParsing(buffer, bufferSize);
Poincare::Expression e = Poincare::Expression::parse(buffer);
if (e.isUninitialized()) {
buffer[0] = 0;
return 0;
}
return e.serialize(buffer, bufferSize, Poincare::Preferences::sharedPreferences()->displayMode());
}
bool Layout::recursivelyMatches(LayoutTest test) const {
if (test(*this)) {
return true;
}
for (int i = 0; i < numberOfChildren(); i++) {
if (childAtIndex(i).recursivelyMatches(test)) {
return true;
}
}
return false;
}
// Cursor
LayoutCursor Layout::cursor() const {
assert(!isUninitialized());
@@ -27,7 +59,7 @@ LayoutCursor Layout::equivalentCursor(LayoutCursor * cursor) {
return node()->equivalentCursor(cursor);
}
Layout Layout::childAtIndex(int i) {
Layout Layout::childAtIndex(int i) const {
TreeHandle c = TreeHandle::childAtIndex(i);
return static_cast<Layout &>(c);
}