From be9cde8ca47259aa67ece9d469595dfd4f61a11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Dec 2017 15:32:25 +0100 Subject: [PATCH 001/459] [expression_editor] Base app for development, to remove later. Change-Id: I1d5b59f67fd146d2e2917546a7d8b9419a0a7036 --- apps/Makefile | 2 +- apps/expression_editor/Makefile | 18 +++++++ apps/expression_editor/app.cpp | 29 +++++++++++ apps/expression_editor/app.h | 35 +++++++++++++ apps/expression_editor/base.universal.i18n | 2 + apps/expression_editor/controller.cpp | 34 +++++++++++++ apps/expression_editor/controller.h | 39 ++++++++++++++ .../expression_and_layout.cpp | 51 +++++++++++++++++++ .../expression_editor/expression_and_layout.h | 26 ++++++++++ apps/expression_editor/test/dummy_test.cpp | 6 +++ 10 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 apps/expression_editor/Makefile create mode 100644 apps/expression_editor/app.cpp create mode 100644 apps/expression_editor/app.h create mode 100644 apps/expression_editor/base.universal.i18n create mode 100644 apps/expression_editor/controller.cpp create mode 100644 apps/expression_editor/controller.h create mode 100644 apps/expression_editor/expression_and_layout.cpp create mode 100644 apps/expression_editor/expression_and_layout.h create mode 100644 apps/expression_editor/test/dummy_test.cpp diff --git a/apps/Makefile b/apps/Makefile index 7e5d367ab..9c3ecf405 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= calculation graph sequence settings statistics probability regression code +EPSILON_APPS ?= expression_editor include apps/shared/Makefile include apps/home/Makefile diff --git a/apps/expression_editor/Makefile b/apps/expression_editor/Makefile new file mode 100644 index 000000000..4fa2fd2f5 --- /dev/null +++ b/apps/expression_editor/Makefile @@ -0,0 +1,18 @@ +snapshots += ExpressionEditor::App::Snapshot +snapshot_headers += apps/expression_editor/app.h + +app_objs += $(addprefix apps/expression_editor/,\ + app.o\ + controller.o\ + expression_and_layout.o\ +) + +i18n_files += $(addprefix apps/expression_editor/,\ + base.universal.i18n\ +) + +tests += $(addprefix apps/expression_editor/test/,\ + dummy_test.cpp\ +) + +test_objs += $(addprefix apps/expression_editor/, controller.o) diff --git a/apps/expression_editor/app.cpp b/apps/expression_editor/app.cpp new file mode 100644 index 000000000..9c7111f02 --- /dev/null +++ b/apps/expression_editor/app.cpp @@ -0,0 +1,29 @@ +#include "app.h" +#include "../i18n.h" + +namespace ExpressionEditor { + +I18n::Message App::Descriptor::name() { + return I18n::Message::ExpressionEditorApp; +} + +I18n::Message App::Descriptor::upperName() { + return I18n::Message::ExpressionEditorAppCapital; +} + +App * App::Snapshot::unpack(Container * container) { + return new App(container, this); +} + +App::Descriptor * App::Snapshot::descriptor() { + static Descriptor descriptor; + return &descriptor; +} + +App::App(Container * container, Snapshot * snapshot) : + ::App(container, snapshot, &m_controller), + m_controller(&m_modalViewController, snapshot->expressionAndLayout()) +{ +} + +} diff --git a/apps/expression_editor/app.h b/apps/expression_editor/app.h new file mode 100644 index 000000000..f90805121 --- /dev/null +++ b/apps/expression_editor/app.h @@ -0,0 +1,35 @@ +#ifndef EXPRESSION_EDITOR_APP_H +#define EXPRESSION_EDITOR_APP_H + +#include +#include "controller.h" +#include "expression_and_layout.h" + +namespace ExpressionEditor { + +/* TODO This app is used for creating ExpressionLayout edition. It should be + * removed when the development is finished. */ + +class App : public ::App { +public: + class Descriptor : public ::App::Descriptor { + public: + I18n::Message name() override; + I18n::Message upperName() override; + }; + class Snapshot : public ::App::Snapshot, public SelectableTableViewDataSource { + public: + App * unpack(Container * container) override; + Descriptor * descriptor() override; + ExpressionAndLayout * expressionAndLayout() { return &m_expressionAndLayout; } + private: + ExpressionAndLayout m_expressionAndLayout; + }; +private: + App(Container * container, Snapshot * snapshot); + Controller m_controller; +}; + +} + +#endif diff --git a/apps/expression_editor/base.universal.i18n b/apps/expression_editor/base.universal.i18n new file mode 100644 index 000000000..01a156f37 --- /dev/null +++ b/apps/expression_editor/base.universal.i18n @@ -0,0 +1,2 @@ +ExpressionEditorApp = "ExpressionEdit" +ExpressionEditorAppCapital = "EXPRESSION EDITOR" diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp new file mode 100644 index 000000000..8c51c5d4d --- /dev/null +++ b/apps/expression_editor/controller.cpp @@ -0,0 +1,34 @@ +#include "controller.h" + +namespace ExpressionEditor { + +Controller::ContentView::ContentView(ExpressionAndLayout * expressionAndLayout) : + SolidColorView(KDColorWhite), + m_expressionView() +{ + m_expressionView.setExpression(expressionAndLayout->expressionLayout()); +} + +void Controller::ContentView::layoutSubviews() { + m_expressionView.setFrame(KDRect( + k_margin, + k_margin, + bounds().width() - 2 * k_margin, + bounds().height() - 2 * k_margin)); +} + +KDSize Controller::ContentView::minimalSizeForOptimalDisplay() const { + return m_expressionView.minimalSizeForOptimalDisplay(); +} + +Controller::Controller(Responder * parentResponder, ExpressionAndLayout * expressionAndLayout) : + ViewController(parentResponder), + m_view(expressionAndLayout) +{ +} + +bool Controller::handleEvent(Ion::Events::Event event) { + return false; +} + +} diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h new file mode 100644 index 000000000..c74e0d076 --- /dev/null +++ b/apps/expression_editor/controller.h @@ -0,0 +1,39 @@ +#ifndef EXPRESSION_EDITOR_CONTROLLER_H +#define EXPRESSION_EDITOR_CONTROLLER_H + +#include +#include +#include "expression_and_layout.h" +extern "C" { +#include +} + +namespace ExpressionEditor { + +class Controller : public ViewController { +public: + Controller(Responder * parentResponder, ExpressionAndLayout * expressionAndLayout); + View * view() override { return &m_view; } + bool handleEvent(Ion::Events::Event event) override; + +private: + class ContentView : public SolidColorView { + public: + ContentView(ExpressionAndLayout * expressionAndLayout); + int numberOfSubviews() const override { return 1; } + View * subviewAtIndex(int index) override { + assert(index == 0); + return &m_expressionView; + } + void layoutSubviews() override; + KDSize minimalSizeForOptimalDisplay() const override; + private: + constexpr static KDCoordinate k_margin = 10; + ExpressionView m_expressionView; + }; + ContentView m_view; +}; + +} + +#endif diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp new file mode 100644 index 000000000..89a0f310e --- /dev/null +++ b/apps/expression_editor/expression_and_layout.cpp @@ -0,0 +1,51 @@ +#include "expression_and_layout.h" + +namespace ExpressionEditor { + +ExpressionAndLayout::ExpressionAndLayout() { + //const char * expression = "2/3"; + //const char * expression = "1+2/(3+4)"; + //const char * expression = "1+2/3+5+8"; + //const char * expression = "[[1+5,2,3][4,5,6]]"; + //const char * expression = "1+2/(7+5/3/467777777)/3+8"; + //const char * expression = "1+2/7467777777"; + //const char * expression = "2385658/(7+5/46)"; + //const char * expression = "1+conj(100)+2"; + //const char * expression = "1+abs(100)+2"; + //const char * expression = "1+root(100,41)+2"; + //const char * expression = "ln(36)"; + //const char * expression = "1+floor(36)+2"; + //const char * expression = "ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988)"; + //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+(1111111)/(2/3+4/5)"; + //const char * expression = "2385658/(int(5/46*7/8,3,45))"; + //const char * expression = "1+binomial(6,88)+1"; + //const char * expression = "[[1+5,2,3][4,5,int(5/46+1,3,4)]]"; + //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; + //const char * expression = "1/2+[[1,2,3][4,5,6]]+1"; + //const char * expression = "1+(3+4)+1"; + //const char * expression = "1+product(23,46,123)+[[2,3][5,6]]+1/4"; + //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; + //const char * expression = "7/78+int(5/46*7/8,3,45)+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; + //const char * expression = "1+conj(39)+abs(3)+root(6000,23)"; + //const char * expression = "1.5+3.4"; + //const char * expression = "abs(5)+int(5/46*7/8,3,4544444)+conj(4)+int(333,4,5)"; + //const char * expression = "conj(int(5/46*7/8,3,45))+conj(4)"; + //const char * expression = "abs(1+conj(conj(4))+(23)+conj(42))+abs(1+2)"; + const char * expression = "13+(23)"; + //const char * expression = "1+sum(12,3,4)+product(12,3,4)+2"; + + m_expression = Poincare::Expression::parse(expression); + m_expressionLayout = m_expression->createLayout(); +} +ExpressionAndLayout::~ExpressionAndLayout() { + if (m_expressionLayout) { + delete m_expressionLayout; + m_expressionLayout = nullptr; + } + if (m_expression) { + delete m_expression; + m_expression = nullptr; + } +} + +} diff --git a/apps/expression_editor/expression_and_layout.h b/apps/expression_editor/expression_and_layout.h new file mode 100644 index 000000000..a1ef237fc --- /dev/null +++ b/apps/expression_editor/expression_and_layout.h @@ -0,0 +1,26 @@ +#ifndef EXPRESSION_EDITOR_EXPRESSION_AND_LAYOUT_H +#define EXPRESSION_EDITOR_EXPRESSION_AND_LAYOUT_H + +#include + +namespace ExpressionEditor { + +class ExpressionAndLayout { +public: + ExpressionAndLayout(); + ~ExpressionAndLayout(); + ExpressionAndLayout(const ExpressionAndLayout& other) = delete; + ExpressionAndLayout(ExpressionAndLayout&& other) = delete; + ExpressionAndLayout operator=(const ExpressionAndLayout& other) = delete; + ExpressionAndLayout& operator=(ExpressionAndLayout&& other) = delete; + + Poincare::Expression * expression() { return m_expression; } + Poincare::ExpressionLayout * expressionLayout() { return m_expressionLayout; } +private: + Poincare::Expression * m_expression; + Poincare::ExpressionLayout * m_expressionLayout; +}; + +} + +#endif diff --git a/apps/expression_editor/test/dummy_test.cpp b/apps/expression_editor/test/dummy_test.cpp new file mode 100644 index 000000000..18e40f6c0 --- /dev/null +++ b/apps/expression_editor/test/dummy_test.cpp @@ -0,0 +1,6 @@ +#include +#include + +QUIZ_CASE() { + assert(true); +} From 4ad3adaab2ac8d75a27e2bb720a46affef2db667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 5 Dec 2017 17:45:54 +0100 Subject: [PATCH 002/459] [apps/escher] Changed setExpression to setExpressionLayout. Change-Id: I095a12868fd7eaf8d4eb2408617941a86f43e1ee --- apps/calculation/history_view_cell.cpp | 2 +- apps/calculation/output_expressions_view.cpp | 4 ++-- apps/calculation/scrollable_expression_view.cpp | 4 ++-- apps/calculation/scrollable_expression_view.h | 2 +- apps/expression_editor/controller.cpp | 2 +- apps/graph/list/list_controller.cpp | 2 +- apps/regression/calculation_controller.cpp | 2 +- apps/regression/store_controller.cpp | 2 +- apps/sequence/graph/term_sum_controller.cpp | 6 +++--- apps/sequence/list/list_controller.cpp | 12 ++++++------ apps/sequence/list/list_parameter_controller.cpp | 2 +- apps/sequence/list/sequence_toolbox.cpp | 2 +- apps/sequence/list/type_parameter_controller.cpp | 2 +- apps/sequence/sequence_title_cell.cpp | 4 ++-- apps/sequence/sequence_title_cell.h | 2 +- apps/sequence/values/values_controller.cpp | 2 +- apps/settings/main_controller.cpp | 2 +- apps/settings/sub_controller.cpp | 2 +- apps/shared/function_expression_cell.cpp | 4 ++-- apps/shared/function_expression_cell.h | 2 +- apps/variable_box_leaf_cell.cpp | 2 +- escher/include/escher/even_odd_expression_cell.h | 2 +- escher/include/escher/expression_table_cell.h | 2 +- escher/include/escher/expression_view.h | 2 +- .../message_table_cell_with_chevron_and_expression.h | 2 +- escher/src/even_odd_expression_cell.cpp | 4 ++-- escher/src/expression_table_cell.cpp | 4 ++-- escher/src/expression_view.cpp | 2 +- ...essage_table_cell_with_chevron_and_expression.cpp | 4 ++-- 29 files changed, 43 insertions(+), 43 deletions(-) diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 02c1ec198..5518bcdca 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -83,7 +83,7 @@ void HistoryViewCell::layoutSubviews() { } void HistoryViewCell::setCalculation(Calculation * calculation) { - m_inputView.setExpression(calculation->inputLayout()); + m_inputView.setExpressionLayout(calculation->inputLayout()); App * calculationApp = (App *)app(); /* Both output expressions have to be updated at the same time. The * outputView points to deleted layouts and a call to diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index 43caefc23..7deeddb64 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -16,8 +16,8 @@ OutputExpressionsView::OutputExpressionsView(Responder * parentResponder) : } void OutputExpressionsView::setExpressions(ExpressionLayout ** expressionsLayout) { - m_approximateExpressionView.setExpression(expressionsLayout[0]); - m_exactExpressionView.setExpression(expressionsLayout[1]); + m_approximateExpressionView.setExpressionLayout(expressionsLayout[0]); + m_exactExpressionView.setExpressionLayout(expressionsLayout[1]); layoutSubviews(); } diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index def347a0f..4fd7572df 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -10,8 +10,8 @@ ScrollableExpressionView::ScrollableExpressionView(Responder * parentResponder) { } -void ScrollableExpressionView::setExpression(ExpressionLayout * expressionLayout) { - m_expressionView.setExpression(expressionLayout); +void ScrollableExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) { + m_expressionView.setExpressionLayout(expressionLayout); layoutSubviews(); } diff --git a/apps/calculation/scrollable_expression_view.h b/apps/calculation/scrollable_expression_view.h index a613600f1..fb156fbc9 100644 --- a/apps/calculation/scrollable_expression_view.h +++ b/apps/calculation/scrollable_expression_view.h @@ -8,7 +8,7 @@ namespace Calculation { class ScrollableExpressionView : public ScrollableView, public ScrollViewDataSource { public: ScrollableExpressionView(Responder * parentResponder); - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void setBackgroundColor(KDColor backgroundColor); KDSize minimalSizeForOptimalDisplay() const override; private: diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 8c51c5d4d..a62313cdc 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -6,7 +6,7 @@ Controller::ContentView::ContentView(ExpressionAndLayout * expressionAndLayout) SolidColorView(KDColorWhite), m_expressionView() { - m_expressionView.setExpression(expressionAndLayout->expressionLayout()); + m_expressionView.setExpressionLayout(expressionAndLayout->expressionLayout()); } void Controller::ContentView::layoutSubviews() { diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index 1eb2f4a0d..9c84175d6 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -90,7 +90,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; Function * f = m_functionStore->functionAtIndex(j); - myCell->setExpression(f->layout()); + myCell->setExpressionLayout(f->layout()); bool active = f->isActive(); KDColor textColor = active ? KDColorBlack : Palette::GreyDark; myCell->setTextColor(textColor); diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 4b231acc6..1a937c6ea 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -129,7 +129,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int if (i == 0) { if (j == numberOfRows()-1) { EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell; - myCell->setExpression(m_r2Layout); + myCell->setExpressionLayout(m_r2Layout); return; } EvenOddMessageTextCell * myCell = (EvenOddMessageTextCell *)cell; diff --git a/apps/regression/store_controller.cpp b/apps/regression/store_controller.cpp index 62e2e4400..59617a330 100644 --- a/apps/regression/store_controller.cpp +++ b/apps/regression/store_controller.cpp @@ -34,7 +34,7 @@ void StoreController::willDisplayCellAtLocation(HighlightCell * cell, int i, int return; } EvenOddExpressionCell * mytitleCell = (EvenOddExpressionCell *)cell; - mytitleCell->setExpression(m_titleLayout[i]); + mytitleCell->setExpressionLayout(m_titleLayout[i]); } HighlightCell * StoreController::titleCells(int index) { diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index a22e729e0..cc136bd87 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -201,7 +201,7 @@ void TermSumController::LegendView::setSumSubscript(float start) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; Complex::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); - m_sum.setExpression(m_sumLayout); + m_sum.setExpressionLayout(m_sumLayout); m_sum.setAlignment(0.0f, 0.5f); } @@ -216,7 +216,7 @@ void TermSumController::LegendView::setSumSuperscript(float start, float end) { char bufferEnd[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; Complex::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), new StringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), new StringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small)); - m_sum.setExpression(m_sumLayout); + m_sum.setExpressionLayout(m_sumLayout); m_sum.setAlignment(0.0f, 0.5f); } @@ -229,7 +229,7 @@ void TermSumController::LegendView::setSumResult(const char * sequenceName, doub childrenLayouts[1] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); childrenLayouts[0] = m_sumLayout; m_sumLayout = new HorizontalLayout(childrenLayouts, 3); - m_sum.setExpression(m_sumLayout); + m_sum.setExpressionLayout(m_sumLayout); m_sum.setAlignment(0.5f, 0.5f); } diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 29eefaf32..c3a8e6031 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -169,13 +169,13 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { SequenceTitleCell * myCell = (SequenceTitleCell *)cell; Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { - myCell->setExpression(sequence->definitionName()); + myCell->setExpressionLayout(sequence->definitionName()); } if (sequenceDefinitionForRow(j) == 1) { - myCell->setExpression(sequence->firstInitialConditionName()); + myCell->setExpressionLayout(sequence->firstInitialConditionName()); } if (sequenceDefinitionForRow(j) == 2) { - myCell->setExpression(sequence->secondInitialConditionName()); + myCell->setExpressionLayout(sequence->secondInitialConditionName()); } KDColor nameColor = sequence->isActive() ? sequence->color() : Palette::GreyDark; myCell->setColor(nameColor); @@ -185,13 +185,13 @@ void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { - myCell->setExpression(sequence->layout()); + myCell->setExpressionLayout(sequence->layout()); } if (sequenceDefinitionForRow(j) == 1) { - myCell->setExpression(sequence->firstInitialConditionLayout()); + myCell->setExpressionLayout(sequence->firstInitialConditionLayout()); } if (sequenceDefinitionForRow(j) == 2) { - myCell->setExpression(sequence->secondInitialConditionLayout()); + myCell->setExpressionLayout(sequence->secondInitialConditionLayout()); } bool active = sequence->isActive(); KDColor textColor = active ? KDColorBlack : Palette::GreyDark; diff --git a/apps/sequence/list/list_parameter_controller.cpp b/apps/sequence/list/list_parameter_controller.cpp index 075d96581..d466fa330 100644 --- a/apps/sequence/list/list_parameter_controller.cpp +++ b/apps/sequence/list/list_parameter_controller.cpp @@ -103,7 +103,7 @@ void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int cell->setHighlighted(index == selectedRow()); // See FIXME in SelectableTableView::reloadData() Shared::ListParameterController::willDisplayCellForIndex(cell, index); if (cell == &m_typeCell && m_sequence != nullptr) { - m_typeCell.setExpression(m_sequence->definitionName()); + m_typeCell.setExpressionLayout(m_sequence->definitionName()); } if (cell == &m_initialRankCell && m_sequence != nullptr) { MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *) cell; diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index 708e670d6..ed5a3f49b 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -54,7 +54,7 @@ HighlightCell * SequenceToolbox::reusableCell(int index, int type) { void SequenceToolbox::willDisplayCellForIndex(HighlightCell * cell, int index) { if (typeAtLocation(0, index) == 2) { ExpressionTableCell * myCell = (ExpressionTableCell *)cell; - myCell->setExpression(m_addedCellLayout[index]); + myCell->setExpressionLayout(m_addedCellLayout[index]); return; } else { MathToolbox::willDisplayCellForIndex(cell, mathToolboxIndex(index)); diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index 29e3ec3d6..037aaa98f 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -122,7 +122,7 @@ void TypeParameterController::willDisplayCellAtLocation(HighlightCell * cell, in } m_expressionLayouts[j] = new BaselineRelativeLayout(new StringLayout(nextName, 1, size), new StringLayout(subscripts[j], strlen(subscripts[j]), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); ExpressionTableCellWithPointer * myCell = (ExpressionTableCellWithPointer *)cell; - myCell->setExpression(m_expressionLayouts[j]); + myCell->setExpressionLayout(m_expressionLayouts[j]); } void TypeParameterController::setSequence(Sequence * sequence) { diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 3f86911d0..7138d103f 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -12,8 +12,8 @@ SequenceTitleCell::SequenceTitleCell(Orientation orientation) : { } -void SequenceTitleCell::setExpression(Poincare::ExpressionLayout * expressionLayout) { - m_titleTextView.setExpression(expressionLayout); +void SequenceTitleCell::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) { + m_titleTextView.setExpressionLayout(expressionLayout); } void SequenceTitleCell::setHighlighted(bool highlight) { diff --git a/apps/sequence/sequence_title_cell.h b/apps/sequence/sequence_title_cell.h index 253c43902..1fe659c07 100644 --- a/apps/sequence/sequence_title_cell.h +++ b/apps/sequence/sequence_title_cell.h @@ -8,7 +8,7 @@ namespace Sequence { class SequenceTitleCell : public Shared::FunctionTitleCell { public: SequenceTitleCell(Orientation orientation); - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void setEven(bool even) override; void setHighlighted(bool highlight) override; void setColor(KDColor color) override; diff --git a/apps/sequence/values/values_controller.cpp b/apps/sequence/values/values_controller.cpp index 184685a91..0a1bc8f94 100644 --- a/apps/sequence/values/values_controller.cpp +++ b/apps/sequence/values/values_controller.cpp @@ -30,7 +30,7 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in if (j == 0 && i > 0) { SequenceTitleCell * myCell = (SequenceTitleCell *)cell; Sequence * sequence = m_sequenceStore->activeFunctionAtIndex(i-1); - myCell->setExpression(sequence->nameLayout()); + myCell->setExpressionLayout(sequence->nameLayout()); myCell->setColor(sequence->color()); } } diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 4b7dc6768..32a0f7c80 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -183,7 +183,7 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { m_complexFormatLayout = new BaselineRelativeLayout(new StringLayout(base, sizeof(base), KDText::FontSize::Small), new StringLayout(superscript, sizeof(superscript), KDText::FontSize::Small), BaselineRelativeLayout::Type::Superscript); } MessageTableCellWithChevronAndExpression * myExpCell = (MessageTableCellWithChevronAndExpression *)cell; - myExpCell->setExpression(m_complexFormatLayout); + myExpCell->setExpressionLayout(m_complexFormatLayout); return; } if (index == 3) { diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp index 9ea464dfb..6d5b8ec4e 100644 --- a/apps/settings/sub_controller.cpp +++ b/apps/settings/sub_controller.cpp @@ -28,7 +28,7 @@ SubController::SubController(Responder * parentResponder) : const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '}; m_complexFormatLayout[1] = new BaselineRelativeLayout(new StringLayout(base, sizeof(base)), new StringLayout(superscript, sizeof(superscript)), BaselineRelativeLayout::Type::Superscript); for (int i = 0; i < 2; i++) { - m_complexFormatCells[i].setExpression(m_complexFormatLayout[i]); + m_complexFormatCells[i].setExpressionLayout(m_complexFormatLayout[i]); } m_editableCell.setMessage(I18n::Message::SignificantFigures); m_editableCell.setMessageFontSize(KDText::FontSize::Large); diff --git a/apps/shared/function_expression_cell.cpp b/apps/shared/function_expression_cell.cpp index fee970761..c9345ee71 100644 --- a/apps/shared/function_expression_cell.cpp +++ b/apps/shared/function_expression_cell.cpp @@ -11,8 +11,8 @@ FunctionExpressionCell::FunctionExpressionCell() : { } -void FunctionExpressionCell::setExpression(ExpressionLayout * expressionLayout) { - m_expressionView.setExpression(expressionLayout); +void FunctionExpressionCell::setExpressionLayout(ExpressionLayout * expressionLayout) { + m_expressionView.setExpressionLayout(expressionLayout); } void FunctionExpressionCell::setTextColor(KDColor textColor) { diff --git a/apps/shared/function_expression_cell.h b/apps/shared/function_expression_cell.h index 0b2288f56..351bbe360 100644 --- a/apps/shared/function_expression_cell.h +++ b/apps/shared/function_expression_cell.h @@ -9,7 +9,7 @@ namespace Shared { class FunctionExpressionCell : public EvenOddCell { public: FunctionExpressionCell(); - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void setTextColor(KDColor color); void setEven(bool even) override; void setHighlighted(bool highlight) override; diff --git a/apps/variable_box_leaf_cell.cpp b/apps/variable_box_leaf_cell.cpp index 6806d64fc..cc7a60983 100644 --- a/apps/variable_box_leaf_cell.cpp +++ b/apps/variable_box_leaf_cell.cpp @@ -91,7 +91,7 @@ void VariableBoxLeafCell::setExpression(const Expression * expression) { if (expression) { m_expressionLayout = expression->createLayout(); } - m_expressionView.setExpression(m_expressionLayout); + m_expressionView.setExpressionLayout(m_expressionLayout); } void VariableBoxLeafCell::drawRect(KDContext * ctx, KDRect rect) const { diff --git a/escher/include/escher/even_odd_expression_cell.h b/escher/include/escher/even_odd_expression_cell.h index 05daf3818..157981777 100644 --- a/escher/include/escher/even_odd_expression_cell.h +++ b/escher/include/escher/even_odd_expression_cell.h @@ -10,7 +10,7 @@ public: KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); void setEven(bool even) override; void setHighlighted(bool highlight) override; - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void setBackgroundColor(KDColor backgroundColor); void setTextColor(KDColor textColor); KDSize minimalSizeForOptimalDisplay() const override; diff --git a/escher/include/escher/expression_table_cell.h b/escher/include/escher/expression_table_cell.h index 0bd233a33..4318dc603 100644 --- a/escher/include/escher/expression_table_cell.h +++ b/escher/include/escher/expression_table_cell.h @@ -9,7 +9,7 @@ public: ExpressionTableCell(Layout layout = Layout::Horizontal); View * labelView() const override; void setHighlighted(bool highlight) override; - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); private: ExpressionView m_labelExpressionView; }; diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index f5632a453..0b3888d9e 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -16,7 +16,7 @@ public: ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); Poincare::ExpressionLayout * expressionLayout() const; - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void drawRect(KDContext * ctx, KDRect rect) const override; void setBackgroundColor(KDColor backgroundColor); void setTextColor(KDColor textColor); diff --git a/escher/include/escher/message_table_cell_with_chevron_and_expression.h b/escher/include/escher/message_table_cell_with_chevron_and_expression.h index e1423629a..ae8b45c7d 100644 --- a/escher/include/escher/message_table_cell_with_chevron_and_expression.h +++ b/escher/include/escher/message_table_cell_with_chevron_and_expression.h @@ -9,7 +9,7 @@ public: MessageTableCellWithChevronAndExpression(I18n::Message message = (I18n::Message)0, KDText::FontSize size = KDText::FontSize::Small); View * subAccessoryView() const override; void setHighlighted(bool highlight) override; - void setExpression(Poincare::ExpressionLayout * expressionLayout); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); private: ExpressionView m_subtitleView; }; diff --git a/escher/src/even_odd_expression_cell.cpp b/escher/src/even_odd_expression_cell.cpp index 75e076768..4fb2e8739 100644 --- a/escher/src/even_odd_expression_cell.cpp +++ b/escher/src/even_odd_expression_cell.cpp @@ -19,8 +19,8 @@ void EvenOddExpressionCell::setEven(bool even) { m_expressionView.setBackgroundColor(backgroundColor()); } -void EvenOddExpressionCell::setExpression(ExpressionLayout * expressionLayout) { - m_expressionView.setExpression(expressionLayout); +void EvenOddExpressionCell::setExpressionLayout(ExpressionLayout * expressionLayout) { + m_expressionView.setExpressionLayout(expressionLayout); } void EvenOddExpressionCell::setBackgroundColor(KDColor backgroundColor) { diff --git a/escher/src/expression_table_cell.cpp b/escher/src/expression_table_cell.cpp index 136fddb41..2d27687ec 100644 --- a/escher/src/expression_table_cell.cpp +++ b/escher/src/expression_table_cell.cpp @@ -18,7 +18,7 @@ void ExpressionTableCell::setHighlighted(bool highlight) { m_labelExpressionView.setBackgroundColor(backgroundColor); } -void ExpressionTableCell::setExpression(Poincare::ExpressionLayout * expressionLayout) { - m_labelExpressionView.setExpression(expressionLayout); +void ExpressionTableCell::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) { + m_labelExpressionView.setExpressionLayout(expressionLayout); layoutSubviews(); } diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index cc5c27a3a..2686d7688 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -15,7 +15,7 @@ ExpressionLayout * ExpressionView::expressionLayout() const { return m_expressionLayout; } -void ExpressionView::setExpression(ExpressionLayout * expressionLayout) { +void ExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) { m_expressionLayout = expressionLayout; markRectAsDirty(bounds()); } diff --git a/escher/src/message_table_cell_with_chevron_and_expression.cpp b/escher/src/message_table_cell_with_chevron_and_expression.cpp index d3e46ee75..9d8dc1cb0 100644 --- a/escher/src/message_table_cell_with_chevron_and_expression.cpp +++ b/escher/src/message_table_cell_with_chevron_and_expression.cpp @@ -17,8 +17,8 @@ void MessageTableCellWithChevronAndExpression::setHighlighted(bool highlight) { m_subtitleView.setBackgroundColor(backgroundColor); } -void MessageTableCellWithChevronAndExpression::setExpression(Poincare::ExpressionLayout * expressionLayout) { - m_subtitleView.setExpression(expressionLayout); +void MessageTableCellWithChevronAndExpression::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) { + m_subtitleView.setExpressionLayout(expressionLayout); reloadCell(); layoutSubviews(); } From 73810bbd9a84f7e0a3bd13e5addaf5637597f4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 12:08:42 +0100 Subject: [PATCH 003/459] [poincare] ExpressionLayout cursor. Change-Id: I2367d20754189608a7925f0d8e8dfe361fed0fd0 --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + .../poincare/expression_layout_cursor.h | 44 +++++++++++++++++++ poincare/src/expression_layout_cursor.cpp | 22 ++++++++++ 4 files changed, 68 insertions(+) create mode 100644 poincare/include/poincare/expression_layout_cursor.h create mode 100644 poincare/src/expression_layout_cursor.cpp diff --git a/poincare/Makefile b/poincare/Makefile index b681b27aa..08473fef5 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -26,6 +26,7 @@ objs += $(addprefix poincare/src/,\ division_remainder.o\ division.o\ dynamic_hierarchy.o\ + expression_layout_cursor.o\ expression_lexer.o\ expression_parser.o\ expression.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 2a0a4a801..3bd0a9a9b 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h new file mode 100644 index 000000000..b1b14c180 --- /dev/null +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -0,0 +1,44 @@ +#ifndef POINCARE_EXPRESSION_LAYOUT_CURSOR_H +#define POINCARE_EXPRESSION_LAYOUT_CURSOR_H + +#include + +namespace Poincare { + +class ExpressionLayoutCursor { +public: + enum class Position { + Left, + Inside, + Right + }; + + ExpressionLayoutCursor() : + m_pointedExpressionLayout(nullptr), + m_position(Position::Left), + m_positionInside(0) + {}; + + /* Getters and setters */ + ExpressionLayout * pointedExpressionLayout() { return m_pointedExpressionLayout; } + void setPointedExpressionLayout(ExpressionLayout * expressionLayout) { m_pointedExpressionLayout = expressionLayout; } + Position position() const { return m_position; } + void setPosition(Position position) { m_position = position; } + int positionInside() const { return m_positionInside; } + void setPositionInside(int positionInside) { m_positionInside = positionInside; } + + /* Move */ + bool moveLeft(); + bool moveRight(); + bool moveUp(); + bool moveDown(); + +private: + ExpressionLayout * m_pointedExpressionLayout; + Position m_position; + int m_positionInside; +}; + +} + +#endif diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp new file mode 100644 index 000000000..14ea1aae1 --- /dev/null +++ b/poincare/src/expression_layout_cursor.cpp @@ -0,0 +1,22 @@ +#include + +namespace Poincare { + +bool ExpressionLayoutCursor::moveLeft() { + return false; //TODO +} + +bool ExpressionLayoutCursor::moveRight() { + return false; //TODO +} + +bool ExpressionLayoutCursor::moveUp() { + return false; //TODO +} + +bool ExpressionLayoutCursor::moveDown() { + return false; //TODO +} + +} + From 62c8db97997d44752da15a505031e1aab8852fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 12:09:42 +0100 Subject: [PATCH 004/459] [expression_editor] The controller has a ExpressionLayoutCursor. Change-Id: I8a7e35670eeecca5b633bd784b84df7de1e64626 --- apps/expression_editor/controller.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index c74e0d076..56b268c99 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -2,7 +2,7 @@ #define EXPRESSION_EDITOR_CONTROLLER_H #include -#include +#include #include "expression_and_layout.h" extern "C" { #include @@ -32,6 +32,7 @@ private: ExpressionView m_expressionView; }; ContentView m_view; + Poincare::ExpressionLayoutCursor m_cursor; }; } From 53e7f6ea4477b1ccb83d3eb08b15d8186d8ca1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 13:38:07 +0100 Subject: [PATCH 005/459] [escher] Get a View's frame. Change-Id: I9fbcf2fb8db5f735df5c852762dc8645c0358683 --- escher/include/escher/view.h | 1 + escher/src/view.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/escher/include/escher/view.h b/escher/include/escher/view.h index c1f6bdde8..80d2d3714 100644 --- a/escher/include/escher/view.h +++ b/escher/include/escher/view.h @@ -41,6 +41,7 @@ public: KDPoint pointFromPointInView(View * view, KDPoint point); KDRect bounds() const; + KDRect frame() const; View * subview(int index); virtual KDSize minimalSizeForOptimalDisplay() const; diff --git a/escher/src/view.cpp b/escher/src/view.cpp index 46d3d9212..a2092490a 100644 --- a/escher/src/view.cpp +++ b/escher/src/view.cpp @@ -158,6 +158,10 @@ KDRect View::bounds() const { return m_frame.movedTo(KDPointZero); } +KDRect View::frame() const { + return KDRect(m_frame); +} + KDPoint View::absoluteOrigin() const { if (m_superview == nullptr) { assert(this == (View *)window()); From 589926284c81fd4c7549f61e986a8dfb81b1cceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 13:41:00 +0100 Subject: [PATCH 006/459] [poincare] absoluteOrigin() is public in ExpressionLayout. Change-Id: I7e381887e3c62c36c72536ed7ef280bcc637ead4 --- poincare/include/poincare/expression_layout.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 3d0e65d37..7e27b892a 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -12,6 +12,7 @@ public: void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); KDPoint origin(); + KDPoint absoluteOrigin(); KDSize size(); KDCoordinate baseline(); void setParent(ExpressionLayout* parent); @@ -22,9 +23,7 @@ protected: virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; KDCoordinate m_baseline; private: - KDPoint absoluteOrigin(); - //void computeLayout();//ExpressionLayout * parent, uint16_t childIndex); - ExpressionLayout* m_parent; + ExpressionLayout * m_parent; bool m_sized, m_positioned; KDRect m_frame; }; From 8828eaf79fd7d2bc532181b0bb3d4f8c28455bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 13:51:40 +0100 Subject: [PATCH 007/459] [escher] ExpressionView drawingOrigin(). Change-Id: I737f17f857edb6e9971feeeb196f2698cc92ad9e --- escher/include/escher/expression_view.h | 1 + escher/src/expression_view.cpp | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index 0b3888d9e..25861e61f 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -22,6 +22,7 @@ public: void setTextColor(KDColor textColor); void setAlignment(float horizontalAlignment, float verticalAlignment); KDSize minimalSizeForOptimalDisplay() const override; + KDPoint drawingOrigin() const; private: /* Warning: we do not need to delete the previous expression layout when * deleting object or setting a new expression layout. Indeed, the expression diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 2686d7688..0fa196d63 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -47,13 +47,15 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const { return m_expressionLayout->size(); } +KDPoint ExpressionView::drawingOrigin() const { + KDSize expressionSize = m_expressionLayout->size(); + return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), + 0.5f*(m_frame.height() - expressionSize.height())); +} + void ExpressionView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, m_backgroundColor); if (m_expressionLayout != nullptr) { - //Position the origin of expression - KDSize expressionSize = m_expressionLayout->size(); - KDPoint origin(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), - 0.5f*(m_frame.height() - expressionSize.height())); - m_expressionLayout->draw(ctx, origin, m_textColor, m_backgroundColor); + m_expressionLayout->draw(ctx, drawingOrigin(), m_textColor, m_backgroundColor); } } From 1c6d18afd98988de4f6a10d94692e3f46c72f9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 12:25:51 +0100 Subject: [PATCH 008/459] [expression_editor] Scrollable ExpressionView with cursor. Change-Id: I8f75bcb0be78d8c8901cdad0e85e8463c2ea717c --- apps/expression_editor/Makefile | 3 ++ .../expression_editor_view.cpp | 31 ++++++++++++ .../expression_editor_view.h | 29 +++++++++++ .../expression_view_with_cursor.cpp | 50 +++++++++++++++++++ .../expression_view_with_cursor.h | 36 +++++++++++++ ...scrollable_expression_view_with_cursor.cpp | 21 ++++++++ .../scrollable_expression_view_with_cursor.h | 25 ++++++++++ 7 files changed, 195 insertions(+) create mode 100644 apps/expression_editor/expression_editor_view.cpp create mode 100644 apps/expression_editor/expression_editor_view.h create mode 100644 apps/expression_editor/expression_view_with_cursor.cpp create mode 100644 apps/expression_editor/expression_view_with_cursor.h create mode 100644 apps/expression_editor/scrollable_expression_view_with_cursor.cpp create mode 100644 apps/expression_editor/scrollable_expression_view_with_cursor.h diff --git a/apps/expression_editor/Makefile b/apps/expression_editor/Makefile index 4fa2fd2f5..bdee10973 100644 --- a/apps/expression_editor/Makefile +++ b/apps/expression_editor/Makefile @@ -5,6 +5,9 @@ app_objs += $(addprefix apps/expression_editor/,\ app.o\ controller.o\ expression_and_layout.o\ + expression_editor_view.o\ + expression_view_with_cursor.o\ + scrollable_expression_view_with_cursor.o\ ) i18n_files += $(addprefix apps/expression_editor/,\ diff --git a/apps/expression_editor/expression_editor_view.cpp b/apps/expression_editor/expression_editor_view.cpp new file mode 100644 index 000000000..fc13a7f78 --- /dev/null +++ b/apps/expression_editor/expression_editor_view.cpp @@ -0,0 +1,31 @@ +#include "expression_editor_view.h" +#include + +namespace ExpressionEditor { + +ExpressionEditorView::ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor) : + SolidColorView(KDColorWhite), + m_scrollableExpressionViewWithCursor(parentResponder, expressionLayout, cursor) +{ +} + +void ExpressionEditorView::cursorPositionChanged() { + m_scrollableExpressionViewWithCursor.expressionViewWithCursor()->cursorPositionChanged(); + m_scrollableExpressionViewWithCursor.scrollToCursor(); +} + +void ExpressionEditorView::layoutSubviews() { + m_scrollableExpressionViewWithCursor.setFrame(KDRect( + k_margin, + k_margin, + bounds().width() - 2 * k_margin, + bounds().height() - 2 * k_margin)); +} + +KDSize ExpressionEditorView::minimalSizeForOptimalDisplay() const { + return m_scrollableExpressionViewWithCursor.minimalSizeForOptimalDisplay(); +} + + +} + diff --git a/apps/expression_editor/expression_editor_view.h b/apps/expression_editor/expression_editor_view.h new file mode 100644 index 000000000..49116463e --- /dev/null +++ b/apps/expression_editor/expression_editor_view.h @@ -0,0 +1,29 @@ +#ifndef EXPRESSION_EDITOR_EXPRESSION_EDITOR_VIEW_H +#define EXPRESSION_EDITOR_EXPRESSION_EDITOR_VIEW_H + +#include +#include "expression_and_layout.h" +#include "scrollable_expression_view_with_cursor.h" + +namespace ExpressionEditor { + +class ExpressionEditorView : public SolidColorView { +public: + ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); + void cursorPositionChanged(); + int numberOfSubviews() const override { return 1; } + ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } + View * subviewAtIndex(int index) override { + assert(index == 0); + return &m_scrollableExpressionViewWithCursor; + } + void layoutSubviews() override; + KDSize minimalSizeForOptimalDisplay() const override; +private: + constexpr static KDCoordinate k_margin = 10; + ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; +}; + +} + +#endif diff --git a/apps/expression_editor/expression_view_with_cursor.cpp b/apps/expression_editor/expression_view_with_cursor.cpp new file mode 100644 index 000000000..66f1b8d6e --- /dev/null +++ b/apps/expression_editor/expression_view_with_cursor.cpp @@ -0,0 +1,50 @@ +#include "expression_view_with_cursor.h" +#include + +using namespace Poincare; + +namespace ExpressionEditor { + +ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expressionLayout, ExpressionLayoutCursor * cursor) : + m_cursor(cursor) +{ + m_expressionView.setExpressionLayout(expressionLayout); +} + +void ExpressionViewWithCursor::cursorPositionChanged() { + layoutCursorSubview(); +} + +KDRect ExpressionViewWithCursor::cursorRect() { + return m_cursorView.frame(); +} + +KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { + return m_expressionView.minimalSizeForOptimalDisplay(); +} + +View * ExpressionViewWithCursor::subviewAtIndex(int index) { + assert(index >= 0 && index < 2); + View * m_views[] = {&m_expressionView, &m_cursorView}; + return m_views[index]; +} + +void ExpressionViewWithCursor::layoutSubviews() { + m_expressionView.setFrame(bounds()); + layoutCursorSubview(); +} + +void ExpressionViewWithCursor::layoutCursorSubview() { + KDPoint expressionViewOrigin = m_expressionView.drawingOrigin(); + KDPoint cursoredExpressionViewOrigin = m_cursor->pointedExpressionLayout()->absoluteOrigin(); + KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); + if (m_cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursorX += m_cursor->pointedExpressionLayout()->size().width(); + } else if (m_cursor->position() == ExpressionLayoutCursor::Position::Inside) { + cursorX += m_cursor->positionInside() * KDText::charSize().width(); + } + KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor->pointedExpressionLayout()->baseline()-k_cursorHeight/2); + m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, k_cursorHeight)); +} + +} diff --git a/apps/expression_editor/expression_view_with_cursor.h b/apps/expression_editor/expression_view_with_cursor.h new file mode 100644 index 000000000..991bc4ba1 --- /dev/null +++ b/apps/expression_editor/expression_view_with_cursor.h @@ -0,0 +1,36 @@ +#ifndef EXPRESSION_EDITOR_EXPRESSION_VIEW_WITH_CURSOR_H +#define EXPRESSION_EDITOR_EXPRESSION_VIEW_WITH_CURSOR_H + +#include +#include +#include +#include + +namespace ExpressionEditor { + +class ExpressionViewWithCursor : public View { +public: + ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); + void cursorPositionChanged(); + KDRect cursorRect(); + const ExpressionView * expressionView() const { return &m_expressionView; } + /* View */ + KDSize minimalSizeForOptimalDisplay() const override; +private: + enum class Position { + Top, + Bottom + }; + constexpr static KDCoordinate k_cursorHeight = 18; + int numberOfSubviews() const override { return 2; } + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + void layoutCursorSubview(); + Poincare::ExpressionLayoutCursor * m_cursor; + ExpressionView m_expressionView; + TextCursorView m_cursorView; +}; + +} + +#endif diff --git a/apps/expression_editor/scrollable_expression_view_with_cursor.cpp b/apps/expression_editor/scrollable_expression_view_with_cursor.cpp new file mode 100644 index 000000000..b7beb0baf --- /dev/null +++ b/apps/expression_editor/scrollable_expression_view_with_cursor.cpp @@ -0,0 +1,21 @@ +#include "scrollable_expression_view_with_cursor.h" +#include + +namespace ExpressionEditor { + +ScrollableExpressionViewWithCursor::ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor) : + ScrollableView(parentResponder, &m_expressionViewWithCursor, this), + m_expressionViewWithCursor(expressionLayout, cursor) +{ +} + +KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { + return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); +} + +void ScrollableExpressionViewWithCursor::scrollToCursor() { + scrollToContentRect(m_expressionViewWithCursor.cursorRect()); +} + +} + diff --git a/apps/expression_editor/scrollable_expression_view_with_cursor.h b/apps/expression_editor/scrollable_expression_view_with_cursor.h new file mode 100644 index 000000000..7083f1153 --- /dev/null +++ b/apps/expression_editor/scrollable_expression_view_with_cursor.h @@ -0,0 +1,25 @@ +#ifndef EXPRESSION_EDITOR_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H +#define EXPRESSION_EDITOR_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H + +#include +#include +#include +#include "expression_view_with_cursor.h" + +namespace ExpressionEditor { + +class ScrollableExpressionViewWithCursor : public ScrollableView, public ScrollViewDataSource { +public: + ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); + KDSize minimalSizeForOptimalDisplay() const override; + ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } + void scrollToCursor(); + /* ScrollableView */ + bool handleEvent(Ion::Events::Event event) override { return false; } +private: + ExpressionViewWithCursor m_expressionViewWithCursor; +}; + +} + +#endif From 23d49f768f742cabd49f2fd2a25f22cea1a23d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 15:23:21 +0100 Subject: [PATCH 009/459] [expression_editor] Use ExpressionEditorView. Change-Id: Ib4080fd76f7040be6ad8ebfda10d2e2070c7381c --- apps/expression_editor/Makefile | 7 +++- apps/expression_editor/app.cpp | 2 +- apps/expression_editor/controller.cpp | 39 +++++++++---------- apps/expression_editor/controller.h | 21 ++-------- .../expression_view_with_cursor.cpp | 3 +- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/apps/expression_editor/Makefile b/apps/expression_editor/Makefile index bdee10973..7edd46555 100644 --- a/apps/expression_editor/Makefile +++ b/apps/expression_editor/Makefile @@ -18,4 +18,9 @@ tests += $(addprefix apps/expression_editor/test/,\ dummy_test.cpp\ ) -test_objs += $(addprefix apps/expression_editor/, controller.o) +test_objs += $(addprefix apps/expression_editor/,\ + controller.o\ + expression_editor_view.o\ + expression_view_with_cursor.o\ + scrollable_expression_view_with_cursor.o\ +) diff --git a/apps/expression_editor/app.cpp b/apps/expression_editor/app.cpp index 9c7111f02..5ef392b9c 100644 --- a/apps/expression_editor/app.cpp +++ b/apps/expression_editor/app.cpp @@ -22,7 +22,7 @@ App::Descriptor * App::Snapshot::descriptor() { App::App(Container * container, Snapshot * snapshot) : ::App(container, snapshot, &m_controller), - m_controller(&m_modalViewController, snapshot->expressionAndLayout()) + m_controller(&m_modalViewController, snapshot->expressionAndLayout()->expressionLayout()) { } diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index a62313cdc..bbf0ee478 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -2,29 +2,26 @@ namespace ExpressionEditor { -Controller::ContentView::ContentView(ExpressionAndLayout * expressionAndLayout) : - SolidColorView(KDColorWhite), - m_expressionView() -{ - m_expressionView.setExpressionLayout(expressionAndLayout->expressionLayout()); -} - -void Controller::ContentView::layoutSubviews() { - m_expressionView.setFrame(KDRect( - k_margin, - k_margin, - bounds().width() - 2 * k_margin, - bounds().height() - 2 * k_margin)); -} - -KDSize Controller::ContentView::minimalSizeForOptimalDisplay() const { - return m_expressionView.minimalSizeForOptimalDisplay(); -} - -Controller::Controller(Responder * parentResponder, ExpressionAndLayout * expressionAndLayout) : +Controller::Controller(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout) : ViewController(parentResponder), - m_view(expressionAndLayout) + m_view(parentResponder, expressionLayout, &m_cursor) { + m_cursor.setPointedExpressionLayout(expressionLayout); +} + +void Controller::didBecomeFirstResponder() { + m_view.layoutSubviews(); + /* TODO We need the layout to be done in order to scroll to the cursor. We + * thus made ExpressionViewWithCursor's layoutSubviews() public, which is the + * solution used in ModalViewController for instance. A cleaner solution would + * be to split viewWillAppear into loadViewIfNeeded() and viewWillAppear(), in + * order to change App::didBecomeActive to: + * m_modalViewController.loadViewIfNeeded(); + * window->setContentView(view); + * m_modalViewController.viewWillAppear(); + * The scrolling could then be done in viewWillAppear(), without calling + * layoutSubviews() manually. */ + m_view.scrollableExpressionViewWithCursor()->scrollToCursor(); } bool Controller::handleEvent(Ion::Events::Event event) { diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index 56b268c99..f09630034 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -4,6 +4,7 @@ #include #include #include "expression_and_layout.h" +#include "expression_editor_view.h" extern "C" { #include } @@ -12,26 +13,12 @@ namespace ExpressionEditor { class Controller : public ViewController { public: - Controller(Responder * parentResponder, ExpressionAndLayout * expressionAndLayout); + Controller(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout); View * view() override { return &m_view; } + void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; - private: - class ContentView : public SolidColorView { - public: - ContentView(ExpressionAndLayout * expressionAndLayout); - int numberOfSubviews() const override { return 1; } - View * subviewAtIndex(int index) override { - assert(index == 0); - return &m_expressionView; - } - void layoutSubviews() override; - KDSize minimalSizeForOptimalDisplay() const override; - private: - constexpr static KDCoordinate k_margin = 10; - ExpressionView m_expressionView; - }; - ContentView m_view; + ExpressionEditorView m_view; Poincare::ExpressionLayoutCursor m_cursor; }; diff --git a/apps/expression_editor/expression_view_with_cursor.cpp b/apps/expression_editor/expression_view_with_cursor.cpp index 66f1b8d6e..0c83c41ce 100644 --- a/apps/expression_editor/expression_view_with_cursor.cpp +++ b/apps/expression_editor/expression_view_with_cursor.cpp @@ -20,7 +20,8 @@ KDRect ExpressionViewWithCursor::cursorRect() { } KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { - return m_expressionView.minimalSizeForOptimalDisplay(); + KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); + return KDSize(expressionViewSize.width()+1, m_expressionView.minimalSizeForOptimalDisplay().height()); // +1 for the cursor } View * ExpressionViewWithCursor::subviewAtIndex(int index) { From 8f6a27bee8e97be2b8c037b2b5f731fe9ac2caca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 15:23:53 +0100 Subject: [PATCH 010/459] [TO REMOVE] Bigger test case. Change-Id: I72c0474000aab5eec5ebada2e09c0f7f555c8e2b --- apps/expression_editor/expression_and_layout.cpp | 3 ++- poincare/include/poincare/expression_layout_cursor.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp index 89a0f310e..1f36461be 100644 --- a/apps/expression_editor/expression_and_layout.cpp +++ b/apps/expression_editor/expression_and_layout.cpp @@ -31,8 +31,9 @@ ExpressionAndLayout::ExpressionAndLayout() { //const char * expression = "abs(5)+int(5/46*7/8,3,4544444)+conj(4)+int(333,4,5)"; //const char * expression = "conj(int(5/46*7/8,3,45))+conj(4)"; //const char * expression = "abs(1+conj(conj(4))+(23)+conj(42))+abs(1+2)"; - const char * expression = "13+(23)"; + //const char * expression = "13+(23)"; //const char * expression = "1+sum(12,3,4)+product(12,3,4)+2"; + const char * expression = "(1+2^3)-385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]/123+ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988+2)+abs(conj(345))+conj(conj(conj(3)))+floor(48)+binomial(6,88)+product(23,46,123)"; m_expression = Poincare::Expression::parse(expression); m_expressionLayout = m_expression->createLayout(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index b1b14c180..89b2a0462 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -15,7 +15,7 @@ public: ExpressionLayoutCursor() : m_pointedExpressionLayout(nullptr), - m_position(Position::Left), + m_position(Position::Right), m_positionInside(0) {}; From 5aa1946796e6e559e28e8d915a20fc3aa84eb325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 15:28:35 +0100 Subject: [PATCH 011/459] [expression_editor] Handle navigation events in the controller. Change-Id: I7f8f2846f7b7ac141e854215edd30e0c078a992c --- apps/expression_editor/controller.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index bbf0ee478..632310443 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -25,7 +25,16 @@ void Controller::didBecomeFirstResponder() { } bool Controller::handleEvent(Ion::Events::Event event) { - return false; + bool returnValue = false; + if ((event == Ion::Events::Left && m_cursor.moveLeft()) + || (event == Ion::Events::Right && m_cursor.moveRight()) + || (event == Ion::Events::Up && m_cursor.moveUp()) + || (event == Ion::Events::Down && m_cursor.moveDown())) + { + returnValue = true; + } + m_view.cursorPositionChanged(); + return returnValue; } } From 78c02e68712c8750395daace86656c365b77503c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 14 Dec 2017 18:12:06 +0100 Subject: [PATCH 012/459] [expression_editor/poincare] Move Left in an ExpressionLayout. Change-Id: Id69def65e0976bfb045c1da6e8786a2f5797120c --- poincare/include/poincare/expression_layout.h | 12 +++- poincare/src/expression_layout_cursor.cpp | 2 +- .../src/layout/baseline_relative_layout.cpp | 42 +++++++++++ .../src/layout/baseline_relative_layout.h | 1 + poincare/src/layout/bracket_layout.cpp | 28 ++++++++ poincare/src/layout/bracket_layout.h | 1 + poincare/src/layout/condensed_sum_layout.cpp | 39 +++++++++++ poincare/src/layout/condensed_sum_layout.h | 1 + poincare/src/layout/conjugate_layout.cpp | 31 ++++++++ poincare/src/layout/conjugate_layout.h | 1 + poincare/src/layout/fraction_layout.cpp | 30 +++++++- poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 52 +++++++++++++- poincare/src/layout/grid_layout.h | 4 ++ poincare/src/layout/horizontal_layout.cpp | 70 ++++++++++++++++--- poincare/src/layout/horizontal_layout.h | 2 + poincare/src/layout/integral_layout.cpp | 41 +++++++++++ poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 44 +++++++++++- poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/parenthesis_layout.cpp | 28 ++++++++ poincare/src/layout/parenthesis_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 42 +++++++++++ poincare/src/layout/sequence_layout.h | 1 + poincare/src/layout/string_layout.cpp | 45 +++++++++++- poincare/src/layout/string_layout.h | 1 + 26 files changed, 506 insertions(+), 16 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 7e27b892a..9bafc81ac 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -5,25 +5,33 @@ namespace Poincare { +class ExpressionLayoutCursor; + class ExpressionLayout { public: ExpressionLayout(); virtual ~ExpressionLayout() = default; + /* Rendering */ void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); KDPoint origin(); KDPoint absoluteOrigin(); KDSize size(); KDCoordinate baseline(); + + /* Hierarchy */ void setParent(ExpressionLayout* parent); + virtual ExpressionLayout * child(uint16_t index) = 0; + + /* Tree navigation */ + virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; - virtual ExpressionLayout * child(uint16_t index) = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; KDCoordinate m_baseline; -private: ExpressionLayout * m_parent; +private: bool m_sized, m_positioned; KDRect m_frame; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 14ea1aae1..ce5468741 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -3,7 +3,7 @@ namespace Poincare { bool ExpressionLayoutCursor::moveLeft() { - return false; //TODO + return m_pointedExpressionLayout->moveLeft(this); } bool ExpressionLayoutCursor::moveRight() { diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index da55937a9..11cc237ee 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -1,4 +1,5 @@ #include "baseline_relative_layout.h" +#include #include #include @@ -29,6 +30,47 @@ ExpressionLayout * BaselineRelativeLayout::indiceLayout() { return m_indiceLayout; } +bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the indice. + // Go from the indice to the base. + if (m_indiceLayout + && cursor->pointedExpressionLayout() == m_indiceLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_baseLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Left of the base. + // Ask the parent. + if (m_baseLayout + && cursor->pointedExpressionLayout() == m_baseLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the indice. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + return true; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void BaselineRelativeLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // There is nothing to draw for a subscript/superscript, only the position of the children matters } diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index f313d9212..029ed653f 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -20,6 +20,7 @@ public: BaselineRelativeLayout& operator=(BaselineRelativeLayout&& other) = delete; ExpressionLayout * baseLayout(); ExpressionLayout * indiceLayout(); + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index dddd78aa9..32cdb10b0 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -1,4 +1,5 @@ #include "bracket_layout.h" +#include extern "C" { #include #include @@ -18,6 +19,33 @@ BracketLayout::~BracketLayout() { delete m_operandLayout; } +bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the operand. + // Go Left of the brackets. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right of the brackets. + // Go Right of the operand. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left of the brackets. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize operandSize = m_operandLayout->size(); ctx->fillRect(KDRect(p.x(), p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 4fca30e92..9016cb803 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -14,6 +14,7 @@ public: BracketLayout(BracketLayout&& other) = delete; BracketLayout& operator=(const BracketLayout& other) = delete; BracketLayout& operator=(BracketLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: virtual KDCoordinate widthMargin() const { return 5; } virtual bool renderTopBar() const { return true; } diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index e2c20e853..0a74eece4 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -1,4 +1,5 @@ #include "condensed_sum_layout.h" +#include #include #include @@ -27,6 +28,44 @@ CondensedSumLayout::~CondensedSumLayout() { } } +bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the bounds. + // Go Left of the sum. + if (((m_subscriptLayout && cursor->pointedExpressionLayout() == m_subscriptLayout) + || (m_superscriptLayout && cursor->pointedExpressionLayout() == m_superscriptLayout)) + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Left of the base. + // Go Right of the lower bound. + if (m_baseLayout + && cursor->pointedExpressionLayout() == m_baseLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(m_subscriptLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the base and move Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_baseLayout); + cursor->setPointedExpressionLayout(m_baseLayout); + return m_baseLayout->moveLeft(cursor); + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Nothing to draw } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index dc52f4e5f..fce1333c3 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -14,6 +14,7 @@ public: CondensedSumLayout(CondensedSumLayout&& other) = delete; CondensedSumLayout& operator=(const CondensedSumLayout& other) = delete; CondensedSumLayout& operator=(CondensedSumLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index ca0aa4cef..fc83bc45b 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -1,4 +1,5 @@ #include "conjugate_layout.h" +#include extern "C" { #include #include @@ -18,6 +19,36 @@ ConjugateLayout::~ConjugateLayout() { delete m_operandLayout; } +bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the operand. + // Ask the parent. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the operand and move Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return m_operandLayout->moveLeft(cursor); + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x(), p.y(), m_operandLayout->size().width(), k_overlineWidth), expressionColor); } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 29ebdfaa3..4d6eacf8c 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -14,6 +14,7 @@ public: ConjugateLayout(ConjugateLayout&& other) = delete; ConjugateLayout& operator=(const ConjugateLayout& other) = delete; ConjugateLayout& operator=(ConjugateLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index e71a263db..01ce02e87 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -1,6 +1,7 @@ +#include "fraction_layout.h" +#include #include #include -#include "fraction_layout.h" namespace Poincare { @@ -17,6 +18,33 @@ FractionLayout::~FractionLayout() { delete m_numerator_layout; } +bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the numerator or the denominator. + // Go Left of the fraction. + if (((m_numerator_layout && cursor->pointedExpressionLayout() == m_numerator_layout) + || (m_denominator_layout && cursor->pointedExpressionLayout() == m_denominator_layout)) + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the denominator. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_denominator_layout != nullptr); + cursor->setPointedExpressionLayout(m_denominator_layout); + return true; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + m_numerator_layout->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 4a01a60ae..355f5c44b 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -14,6 +14,7 @@ public: FractionLayout(FractionLayout&& other) = delete; FractionLayout& operator=(const FractionLayout& other) = delete; FractionLayout& operator=(FractionLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 92dae7a72..79e91f4e9 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -1,4 +1,5 @@ #include "grid_layout.h" +#include extern "C" { #include #include @@ -26,6 +27,42 @@ GridLayout::~GridLayout() { delete[] m_entryLayouts; } +bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Right. + // Go to the last entry. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + ExpressionLayout * lastChild = m_entryLayouts[m_numberOfColumns*m_numberOfRows-1]; + assert(lastChild != nullptr); + cursor->setPointedExpressionLayout(lastChild); + return true; + } + // Case: The cursor points to a grid's child. + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (childIsLeftOfGrid(childIndex)) { + // Case: Left of a child on the left of the grid. + // Go Left of the grid + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Left of another child. + // Go Right of its brother on the left. + cursor->setPointedExpressionLayout(m_entryLayouts[childIndex-1]); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { @@ -34,7 +71,6 @@ KDCoordinate GridLayout::rowBaseline(int i) { return rowBaseline; } - KDCoordinate GridLayout::rowHeight(int i) { KDCoordinate rowHeight = 0; KDCoordinate baseline = rowBaseline(i); @@ -110,4 +146,18 @@ KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } +int GridLayout::indexOfChild(ExpressionLayout * eL) const { + for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { + if (eL == m_entryLayouts[i]) { + return i; + } + } + return -1; +} + +bool GridLayout::childIsLeftOfGrid(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == 0; +} + } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index f252f28df..7e5de435e 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class GridLayout : public ExpressionLayout { + //TODO Split it in MatrixLayout and BinomialCoefficientayout. public: GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns); ~GridLayout(); @@ -14,6 +15,7 @@ public: GridLayout(GridLayout&& other) = delete; GridLayout& operator=(const GridLayout& other) = delete; GridLayout& operator=(GridLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -26,6 +28,8 @@ private: KDCoordinate height(); KDCoordinate columnWidth(int j); KDCoordinate width(); + int indexOfChild(ExpressionLayout * eL) const; + bool childIsLeftOfGrid(int index) const; ExpressionLayout ** m_entryLayouts; int m_numberOfRows; int m_numberOfColumns; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 804ef7bd6..63d1e1a9e 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,10 +1,12 @@ +#include "horizontal_layout.h" +#include "string_layout.h" +#include + extern "C" { #include #include #include } -#include "horizontal_layout.h" -#include "string_layout.h" namespace Poincare { @@ -28,6 +30,53 @@ HorizontalLayout::~HorizontalLayout() { delete[] m_children_layouts; } +bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left. + // Ask the parent. + if (cursor->pointedExpressionLayout() == this) { + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Go to the last child if there is one, and move Left. + // Else go Left and ask the parent. + if (m_number_of_children < 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + ExpressionLayout * lastChild = m_children_layouts[m_number_of_children-1]; + assert(lastChild != nullptr); + cursor->setPointedExpressionLayout(lastChild); + return lastChild->moveLeft(cursor); + } + + // Case: The cursor is Left of a child. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + assert(childIndex >= 0); + if (childIndex == 0) { + // Case: the child is the leftmost. + // Ask the parent. + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + // Case: the child is not the leftmost. + // Go to its left brother and move Left. + cursor->setPointedExpressionLayout(m_children_layouts[childIndex-1]); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return m_children_layouts[childIndex-1]->moveLeft(cursor); +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } @@ -61,13 +110,7 @@ ExpressionLayout * HorizontalLayout::child(uint16_t index) { KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - uint16_t index = 0; - for (int i=0;i 0) { ExpressionLayout * previousChild = m_children_layouts[index-1]; assert(previousChild != nullptr); @@ -77,4 +120,13 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } +int HorizontalLayout::indexOfChild(ExpressionLayout * eL) const { + for (int i = 0; i < m_number_of_children; i++) { + if (m_children_layouts[i] == eL) { + return i; + } + } + return -1; +} + } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 1770eee1f..55f8dd279 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -14,12 +14,14 @@ public: HorizontalLayout(HorizontalLayout&& other) = delete; HorizontalLayout& operator=(const HorizontalLayout& other) = delete; HorizontalLayout& operator=(HorizontalLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: + int indexOfChild(ExpressionLayout * eL) const; int m_number_of_children; ExpressionLayout ** m_children_layouts; }; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 6b91dc738..23470cd74 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -1,4 +1,5 @@ #include "integral_layout.h" +#include #include #include @@ -36,6 +37,46 @@ IntegralLayout::~IntegralLayout() { delete m_integrandLayout; } +bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left the upper or lower bound. + // Go Left of the integral. + if (((m_upperBoundLayout + && cursor->pointedExpressionLayout() == m_upperBoundLayout) + || (m_lowerBoundLayout + && cursor->pointedExpressionLayout() == m_lowerBoundLayout)) + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Left the integrand. + // Go Right of the lower bound. + if (m_integrandLayout + && cursor->pointedExpressionLayout() == m_integrandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_lowerBoundLayout != nullptr); + cursor->setPointedExpressionLayout(m_lowerBoundLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right of the integral. + // Go Right of the integrand, Left of "dx". + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_integrandLayout != nullptr); + cursor->setPointedExpressionLayout(m_integrandLayout->child(0)); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left of the brackets. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = m_integrandLayout->size(); KDSize upperBoundSize = m_upperBoundLayout->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 2e7059acd..abf47ff33 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -16,6 +16,7 @@ public: IntegralLayout& operator=(IntegralLayout&& other) = delete; constexpr static KDCoordinate k_symbolHeight = 4; constexpr static KDCoordinate k_symbolWidth = 4; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index c9b75fbae..9fda611b8 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -1,6 +1,7 @@ +#include "nth_root_layout.h" +#include #include #include -#include "nth_root_layout.h" namespace Poincare { @@ -37,6 +38,47 @@ NthRootLayout::~NthRootLayout() { } } +bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the radicand. + // Go the index if there is one, else go Left of the root. + if (m_radicandLayout + && cursor->pointedExpressionLayout() == m_radicandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + if (m_indexLayout) { + cursor->setPointedExpressionLayout(m_indexLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Left of the index. + // Go Left of the root. + if (m_indexLayout + && cursor->pointedExpressionLayout() == m_indexLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go Right of the radicand. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_radicandLayout != nullptr); + cursor->setPointedExpressionLayout(m_radicandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = m_radicandLayout->size(); KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index b75cebdb0..ade120681 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -16,6 +16,7 @@ public: NthRootLayout& operator=(NthRootLayout&& other) = delete; constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index 133e6c3af..d71ef1e22 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -1,4 +1,5 @@ #include "parenthesis_layout.h" +#include extern "C" { #include #include @@ -61,6 +62,33 @@ ParenthesisLayout::~ParenthesisLayout() { delete m_operandLayout; } +bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the operand. + // Go Left of the brackets. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right of the parentheses. + // Go Right of the operand. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left of the parentheses. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + KDColor s_parenthesisWorkingBuffer[ParenthesisLayout::k_parenthesisCurveHeight*ParenthesisLayout::k_parenthesisCurveWidth]; void ParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 7ed17ca4a..92f4892ed 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -16,6 +16,7 @@ public: ParenthesisLayout& operator=(ParenthesisLayout&& other) = delete; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 52ed5dc95..1bf01e536 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -1,4 +1,6 @@ #include "sequence_layout.h" +#include "string_layout.h" +#include #include #include @@ -22,6 +24,46 @@ SequenceLayout::~SequenceLayout() { delete m_argumentLayout; } +bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the bounds. + // Go Left of the sequence. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && ((m_lowerBoundLayout + && cursor->pointedExpressionLayout() == m_lowerBoundLayout) + || (m_upperBoundLayout + && cursor->pointedExpressionLayout() == m_upperBoundLayout))) + { + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Left of the argument. + // Go Right of the lower bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && m_argumentLayout + && cursor->pointedExpressionLayout() == m_argumentLayout) + { + assert(m_lowerBoundLayout != nullptr); + cursor->setPointedExpressionLayout(m_lowerBoundLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the argument and move Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_argumentLayout != nullptr); + cursor->setPointedExpressionLayout(m_argumentLayout); + return m_argumentLayout->moveLeft(cursor); + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + KDSize SequenceLayout::computeSize() { KDSize argumentSize = m_argumentLayout->size(); KDSize lowerBoundSize = m_lowerBoundLayout->size(); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 41f3b17bb..03e289454 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -16,6 +16,7 @@ public: SequenceLayout& operator=(SequenceLayout&& other) = delete; constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; ExpressionLayout * m_lowerBoundLayout; diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index 62bbbb68c..ab0b2818d 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -1,6 +1,7 @@ +#include "string_layout.h" +#include #include #include -#include "string_layout.h" namespace Poincare { @@ -23,6 +24,48 @@ char * StringLayout::text() { return m_string; } +bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go before the last char. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + size_t stringLength = strlen(m_string); + if (stringLength > 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Inside); + cursor->setPositionInside(stringLength - 1); + return true; + } + if (stringLength == 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(stringLength == 0); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + // Case: Inside. + // Go one char left. + if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { + int cursorIndex = cursor->positionInside(); + assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); + if (cursorIndex == 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + cursor->setPositionInside(cursorIndex - 1); + return true; + } + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + ExpressionLayout * StringLayout::child(uint16_t index) { return nullptr; } diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 4aa4b584e..bb86c4dc6 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -18,6 +18,7 @@ public: StringLayout& operator=(const StringLayout& other) = delete; StringLayout& operator=(StringLayout&& other) = delete; char * text(); + bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; From 3af2f88da72943fbb38e5d80d6f6af04ca94cd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 7 Dec 2017 16:01:41 +0100 Subject: [PATCH 013/459] [poincare] Added extern margins on BracketLayout to see the cursor. Change-Id: I32f6d54c2121b4de1d7ae2552239a1e8ac557913 --- poincare/src/layout/bracket_layout.cpp | 22 ++++++++++++++-------- poincare/src/layout/bracket_layout.h | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 32cdb10b0..c185fff75 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -47,22 +47,26 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { } void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + const KDCoordinate k_widthMargin = widthMargin(); + const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = m_operandLayout->size(); - ctx->fillRect(KDRect(p.x(), p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); - ctx->fillRect(KDRect(p.x()+operandSize.width()+2*widthMargin()+k_lineThickness, p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); if (renderTopBar()) { - ctx->fillRect(KDRect(p.x(), p.y(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+2*k_lineThickness+operandSize.width()+2*widthMargin()-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); } if (renderBottomBar()) { - ctx->fillRect(KDRect(p.x(), p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+2*k_lineThickness+operandSize.width()+2*widthMargin()-k_bracketWidth, p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); } } KDSize BracketLayout::computeSize() { + const KDCoordinate k_widthMargin = widthMargin(); + const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = m_operandLayout->size(); - return KDSize(operandSize.width() + 2*widthMargin() + 2*k_lineThickness, operandSize.height()); + return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height()); } ExpressionLayout * BracketLayout::child(uint16_t index) { @@ -73,7 +77,9 @@ ExpressionLayout * BracketLayout::child(uint16_t index) { } KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { - return KDPoint(widthMargin()+k_lineThickness, 0); + const KDCoordinate k_widthMargin = widthMargin(); + const KDCoordinate k_externWidthMargin = externWidthMargin(); + return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, 0); } } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 9016cb803..f110789aa 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -16,6 +16,7 @@ public: BracketLayout& operator=(BracketLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: + KDCoordinate externWidthMargin() const { return 2; } virtual KDCoordinate widthMargin() const { return 5; } virtual bool renderTopBar() const { return true; } virtual bool renderBottomBar() const { return true; } From 074f8c533797f190beb543be1682d84e93cefc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 7 Dec 2017 16:03:59 +0100 Subject: [PATCH 014/459] [TO REMOVE] Colored the cursor in Red for visibility. Change-Id: Ia93ebbac1f4b7e15e7de7a3d8546a19797929d72 --- escher/src/text_cursor_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/text_cursor_view.cpp b/escher/src/text_cursor_view.cpp index 6ef9a6ebe..fd2ea48f1 100644 --- a/escher/src/text_cursor_view.cpp +++ b/escher/src/text_cursor_view.cpp @@ -2,7 +2,7 @@ void TextCursorView::drawRect(KDContext * ctx, KDRect rect) const { KDCoordinate height = bounds().height(); - ctx->fillRect(KDRect(0, 0, 1, height), KDColorBlack); + ctx->fillRect(KDRect(0, 0, 1, height), KDColorRed); } KDSize TextCursorView::minimalSizeForOptimalDisplay() const { From d5316e06f7a6b77df074f59d7b49a143cabd8a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 10:26:59 +0100 Subject: [PATCH 015/459] [poincare] EditableStringLayout. Change-Id: Ie985874c216881a722d9c6807c007bc17b25d4f0 --- poincare/Makefile | 1 + .../src/layout/editable_string_layout.cpp | 50 +++++++++++++++++++ poincare/src/layout/editable_string_layout.h | 17 +++++++ poincare/src/layout/string_layout.cpp | 30 ++--------- poincare/src/layout/string_layout.h | 2 +- 5 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 poincare/src/layout/editable_string_layout.cpp create mode 100644 poincare/src/layout/editable_string_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index 08473fef5..a33606ae2 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -87,6 +87,7 @@ objs += $(addprefix poincare/src/layout/,\ bracket_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ + editable_string_layout.o\ expression_layout.o\ fraction_layout.o\ grid_layout.o\ diff --git a/poincare/src/layout/editable_string_layout.cpp b/poincare/src/layout/editable_string_layout.cpp new file mode 100644 index 000000000..e06ab544a --- /dev/null +++ b/poincare/src/layout/editable_string_layout.cpp @@ -0,0 +1,50 @@ +#include "editable_string_layout.h" +#include +#include +#include + +namespace Poincare { + +bool EditableStringLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go before the last char. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + size_t stringLength = strlen(m_string); + if (stringLength > 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Inside); + cursor->setPositionInside(stringLength - 1); + return true; + } + if (stringLength == 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(stringLength == 0); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + // Case: Inside. + // Go one char left. + if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { + int cursorIndex = cursor->positionInside(); + assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); + if (cursorIndex == 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + cursor->setPositionInside(cursorIndex - 1); + return true; + } + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +} diff --git a/poincare/src/layout/editable_string_layout.h b/poincare/src/layout/editable_string_layout.h new file mode 100644 index 000000000..23e92bc65 --- /dev/null +++ b/poincare/src/layout/editable_string_layout.h @@ -0,0 +1,17 @@ +#ifndef POINCARE_EDITABLE_STRING_LAYOUT_H +#define POINCARE_EDITABLE_STRING_LAYOUT_H + +#include "string_layout.h" +#include + +namespace Poincare { + +class EditableStringLayout : public StringLayout { +public: + using StringLayout::StringLayout; + bool moveLeft(ExpressionLayoutCursor * cursor) override; +}; + +} + +#endif diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index ab0b2818d..84a8a35fe 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -25,37 +25,13 @@ char * StringLayout::text() { } bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // A StringLayout is not editable, and the cursor cannot go inside it. assert(cursor->pointedExpressionLayout() == this); // Case: Right. - // Go before the last char. + // Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - size_t stringLength = strlen(m_string); - if (stringLength > 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Inside); - cursor->setPositionInside(stringLength - 1); - return true; - } - if (stringLength == 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - assert(stringLength == 0); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } - // Case: Inside. - // Go one char left. - if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { - int cursorIndex = cursor->positionInside(); - assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); - if (cursorIndex == 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - cursor->setPositionInside(cursorIndex - 1); return true; } // Case: Left. diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index bb86c4dc6..236bfaa8b 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -24,8 +24,8 @@ protected: KDSize computeSize() override; ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; -private: char * m_string; +private: KDText::FontSize m_fontSize; }; From ee77ab972318e3aa7287bd6942ba84a6d2ade229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 10:27:56 +0100 Subject: [PATCH 016/459] [poincare] EditableBaselineRelativeLayout. Change-Id: I8fa6ed2b255d20eb815055987871881b3b5bbf09 --- poincare/Makefile | 1 + .../src/layout/baseline_relative_layout.cpp | 28 +---------- .../src/layout/baseline_relative_layout.h | 4 +- .../editable_baseline_relative_layout.cpp | 50 +++++++++++++++++++ .../editable_baseline_relative_layout.h | 16 ++++++ 5 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 poincare/src/layout/editable_baseline_relative_layout.cpp create mode 100644 poincare/src/layout/editable_baseline_relative_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index a33606ae2..747065f8a 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -87,6 +87,7 @@ objs += $(addprefix poincare/src/layout/,\ bracket_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ + editable_baseline_relative_layout.o\ editable_string_layout.o\ expression_layout.o\ fraction_layout.o\ diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 11cc237ee..80cf27596 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -31,35 +31,11 @@ ExpressionLayout * BaselineRelativeLayout::indiceLayout() { } bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // Case: Left of the indice. - // Go from the indice to the base. - if (m_indiceLayout - && cursor->pointedExpressionLayout() == m_indiceLayout - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - assert(m_baseLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - // Case: Left of the base. - // Ask the parent. - if (m_baseLayout - && cursor->pointedExpressionLayout() == m_baseLayout - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } assert(cursor->pointedExpressionLayout() == this); // Case: Right. - // Go to the indice. + // Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Left. diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index 029ed653f..ac3146b86 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -26,10 +26,10 @@ protected: KDSize computeSize() override; ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; -private: - constexpr static KDCoordinate k_indiceHeight = 5; ExpressionLayout * m_baseLayout; ExpressionLayout * m_indiceLayout; +private: + constexpr static KDCoordinate k_indiceHeight = 5; Type m_type; }; diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp new file mode 100644 index 000000000..27c3988da --- /dev/null +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -0,0 +1,50 @@ +#include "editable_baseline_relative_layout.h" +#include +#include +#include + +namespace Poincare { + +bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the indice. + // Go from the indice to the base. + if (m_indiceLayout + && cursor->pointedExpressionLayout() == m_indiceLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_baseLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Left of the base. + // Ask the parent. + if (m_baseLayout + && cursor->pointedExpressionLayout() == m_baseLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the indice. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + return true; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +} + diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h new file mode 100644 index 000000000..f390e1c77 --- /dev/null +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_EDITABLE_BASELINE_RELATIVE_LAYOUT_H +#define POINCARE_EDITABLE_BASELINE_RELATIVE_LAYOUT_H + +#include "baseline_relative_layout.h" + +namespace Poincare { + +class EditableBaselineRelativeLayout : public BaselineRelativeLayout { +public: + using BaselineRelativeLayout::BaselineRelativeLayout; + bool moveLeft(ExpressionLayoutCursor * cursor) override; +}; + +} + +#endif From f49168d77910f4c3317c81efcd50613b0759c49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 10:28:50 +0100 Subject: [PATCH 017/459] [poincare] Use editable String and BaselineRelative layouts. Change-Id: I978c4aa43772b294251b948fc20bb0d8b8b05a08 --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/complex.cpp | 12 ++++++------ poincare/src/decimal.cpp | 4 ++-- poincare/src/factorial.cpp | 4 ++-- poincare/src/integer.cpp | 4 ++-- poincare/src/layout/integral_layout.cpp | 4 ++-- poincare/src/layout_engine.cpp | 8 ++++---- poincare/src/logarithm.cpp | 6 +++--- poincare/src/opposite.cpp | 4 ++-- poincare/src/power.cpp | 4 ++-- poincare/src/store.cpp | 4 ++-- poincare/src/symbol.cpp | 7 ++++--- poincare/src/undefined.cpp | 4 ++-- 13 files changed, 34 insertions(+), 33 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 9bafc81ac..d2df7e271 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -21,13 +21,13 @@ public: /* Hierarchy */ void setParent(ExpressionLayout* parent); - virtual ExpressionLayout * child(uint16_t index) = 0; /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; + virtual ExpressionLayout * child(uint16_t index) = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; KDCoordinate m_baseline; ExpressionLayout * m_parent; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index b11787250..af44cb656 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -6,8 +6,8 @@ extern "C" { #include } #include -#include "layout/string_layout.h" -#include "layout/baseline_relative_layout.h" +#include "layout/editable_string_layout.h" +#include "layout/editable_baseline_relative_layout.h" #include namespace Poincare { @@ -443,7 +443,7 @@ ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode fl if (std::isnan(r()) || (std::isnan(th()) && r() != 0)) { numberOfCharInBase = convertFloatToText(NAN, bufferBase, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode); - return new StringLayout(bufferBase, numberOfCharInBase); + return new EditableStringLayout(bufferBase, numberOfCharInBase); } if (r() != 1 || th() == 0) { numberOfCharInBase = convertFloatToText(r(), bufferBase, PrintFloat::k_maxFloatBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode); @@ -463,16 +463,16 @@ ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode fl bufferSuperscript[numberOfCharInSuperscript] = 0; } if (numberOfCharInSuperscript == 0) { - return new StringLayout(bufferBase, numberOfCharInBase); + return new EditableStringLayout(bufferBase, numberOfCharInBase); } - return new BaselineRelativeLayout(new StringLayout(bufferBase, numberOfCharInBase), new StringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript); + return new EditableBaselineRelativeLayout(new EditableStringLayout(bufferBase, numberOfCharInBase), new EditableStringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript); } template ExpressionLayout * Complex::createCartesianLayout(Expression::FloatDisplayMode floatDisplayMode) const { char buffer[PrintFloat::k_maxComplexBufferLength]; int numberOfChars = convertComplexToText(buffer, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode, Expression::ComplexFormat::Cartesian, Ion::Charset::MiddleDot); - return new StringLayout(buffer, numberOfChars); + return new EditableStringLayout(buffer, numberOfChars); } template class Complex; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index d502e1d4e..400866c16 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -9,7 +9,7 @@ extern "C" { #include } -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" namespace Poincare { @@ -204,7 +204,7 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); - return new StringLayout(buffer, numberOfChars); + return new EditableStringLayout(buffer, numberOfChars); } Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 097802b33..3f57bf154 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -1,5 +1,5 @@ #include -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" #include "layout/horizontal_layout.h" #include #include @@ -78,7 +78,7 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = new StringLayout("!", 1); + childrenLayouts[1] = new EditableStringLayout("!", 1); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index c8f713516..cb27eb6ef 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -6,7 +6,7 @@ extern "C" { } #include #include -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" #include namespace Poincare { @@ -618,7 +618,7 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { ExpressionLayout * Integer::createLayout() const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); - return new StringLayout(buffer, numberOfChars); + return new EditableStringLayout(buffer, numberOfChars); } template float Poincare::Integer::approximate() const; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 23470cd74..f4a594e85 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -65,8 +65,8 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Right of the integrand, Left of "dx". if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(m_integrandLayout != nullptr); - cursor->setPointedExpressionLayout(m_integrandLayout->child(0)); - return true; + cursor->setPointedExpressionLayout(m_integrandLayout); + return m_integrandLayout->moveLeft(cursor); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index f5d6896b8..d35d010dc 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -1,5 +1,5 @@ #include -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" #include "layout/parenthesis_layout.h" #include "layout/horizontal_layout.h" extern "C" { @@ -16,7 +16,7 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression ExpressionLayout** children_layouts = new ExpressionLayout * [2*numberOfOperands-1]; children_layouts[0] = expression->operand(0)->createLayout(); for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat)) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); } /* HorizontalLayout holds the children layouts so they do not need to be @@ -34,7 +34,7 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio int layoutIndex = 0; grandChildrenLayouts[layoutIndex++] = expression->operand(0)->createLayout(floatDisplayMode, complexFormat); for (int i = 1; i < numberOfOperands; i++) { - grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); + grandChildrenLayouts[layoutIndex++] = new EditableStringLayout(",", 1); grandChildrenLayouts[layoutIndex++] = expression->operand(i)->createLayout(floatDisplayMode, complexFormat); } /* HorizontalLayout holds the grand children layouts so they do not need to @@ -42,7 +42,7 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); delete [] grandChildrenLayouts; ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout(operatorName, strlen(operatorName)); + childrenLayouts[0] = new EditableStringLayout(operatorName, strlen(operatorName)); childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); /* Same comment as above */ return new HorizontalLayout(childrenLayouts, 2); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 5e6a19549..2b20d2e33 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -16,10 +16,10 @@ extern "C" { #include #include } -#include "layout/baseline_relative_layout.h" +#include "layout/editable_baseline_relative_layout.h" +#include "layout/editable_string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" -#include "layout/string_layout.h" namespace Poincare { @@ -237,7 +237,7 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); + childrenLayouts[0] = new EditableBaselineRelativeLayout(new EditableStringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index aad66e0cf..08956ca2e 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -10,7 +10,7 @@ extern "C" { #include #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" namespace Poincare { @@ -50,7 +50,7 @@ ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMo assert(complexFormat != ComplexFormat::Default); ExpressionLayout * children_layouts[2]; char string[2] = {'-', '\0'}; - children_layouts[0] = new StringLayout(string, 1); + children_layouts[0] = new EditableStringLayout(string, 1); children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)) : operand(0)->createLayout(floatDisplayMode, complexFormat); return new HorizontalLayout(children_layouts, 2); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 64b029aec..be426900f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -21,7 +21,7 @@ extern "C" { #include #include #include -#include "layout/baseline_relative_layout.h" +#include "layout/editable_baseline_relative_layout.h" namespace Poincare { @@ -121,7 +121,7 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = m_operands[1]->operand(0); } - return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); + return new EditableBaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 34296a405..a3598228c 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -8,7 +8,7 @@ extern "C" { #include #include #include "layout/horizontal_layout.h" -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" namespace Poincare { @@ -31,7 +31,7 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ExpressionLayout * childrenLayouts[3]; childrenLayouts[0] = value()->createLayout(floatDisplayMode, complexFormat); const char stoSymbol[2] = {Ion::Charset::Sto, 0}; - childrenLayouts[1] = new StringLayout(stoSymbol, 1); + childrenLayouts[1] = new EditableStringLayout(stoSymbol, 1); childrenLayouts[2] = symbol()->createLayout(floatDisplayMode, complexFormat); return new HorizontalLayout(childrenLayouts, 3); } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 5d091721b..b3dc142cd 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -3,6 +3,7 @@ #include #include "layout/baseline_relative_layout.h" #include "layout/string_layout.h" +#include "layout/editable_string_layout.h" #include extern "C" { #include @@ -131,7 +132,7 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); if (m_name == SpecialSymbols::Ans) { - return new StringLayout("ans", 3); + return new EditableStringLayout("ans", 3); } if (m_name == SpecialSymbols::un) { return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); @@ -147,9 +148,9 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode } if (isMatrixSymbol()) { const char mi[] = { 'M', (char)(m_name-(char)SpecialSymbols::M0+'0') }; - return new StringLayout(mi, sizeof(mi)); + return new EditableStringLayout(mi, sizeof(mi)); } - return new StringLayout(&m_name, 1); + return new EditableStringLayout(&m_name, 1); } int Symbol::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 1fc6f27ad..36b55ff15 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -2,7 +2,7 @@ extern "C" { #include } -#include "layout/string_layout.h" +#include "layout/editable_string_layout.h" namespace Poincare { @@ -21,7 +21,7 @@ template Complex * Undefined::templatedApproximate(Context& conte ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { char buffer[16]; int numberOfChars = Complex::convertFloatToText(NAN, buffer, 16, 1, floatDisplayMode); - return new StringLayout(buffer, numberOfChars); + return new EditableStringLayout(buffer, numberOfChars); } int Undefined::writeTextInBuffer(char * buffer, int bufferSize) const { From 8237bab64ff68a9899241853f31017f4e1efef23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 7 Dec 2017 11:50:19 +0100 Subject: [PATCH 018/459] [poincare] ParenthesisLeft and Right layouts. Change-Id: I13cdb59c8b0d7ec1cf773688edff37babb15f893 --- poincare/Makefile | 3 + poincare/src/layout/parenthesis_layout.cpp | 117 ++++++++---------- poincare/src/layout/parenthesis_layout.h | 5 +- .../src/layout/parenthesis_left_layout.cpp | 52 ++++++++ poincare/src/layout/parenthesis_left_layout.h | 19 +++ .../layout/parenthesis_left_right_layout.cpp | 43 +++++++ .../layout/parenthesis_left_right_layout.h | 33 +++++ .../src/layout/parenthesis_right_layout.cpp | 59 +++++++++ .../src/layout/parenthesis_right_layout.h | 19 +++ 9 files changed, 283 insertions(+), 67 deletions(-) create mode 100644 poincare/src/layout/parenthesis_left_layout.cpp create mode 100644 poincare/src/layout/parenthesis_left_layout.h create mode 100644 poincare/src/layout/parenthesis_left_right_layout.cpp create mode 100644 poincare/src/layout/parenthesis_left_right_layout.h create mode 100644 poincare/src/layout/parenthesis_right_layout.cpp create mode 100644 poincare/src/layout/parenthesis_right_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index 747065f8a..a5a5f5548 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -96,6 +96,9 @@ objs += $(addprefix poincare/src/layout/,\ integral_layout.o\ nth_root_layout.o\ parenthesis_layout.o\ + parenthesis_left_layout.o\ + parenthesis_left_right_layout.o\ + parenthesis_right_layout.o\ product_layout.o\ sequence_layout.o\ string_layout.o\ diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index d71ef1e22..ecd6d7cdd 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -1,5 +1,7 @@ #include "parenthesis_layout.h" #include +#include "parenthesis_left_layout.h" +#include "parenthesis_right_layout.h" extern "C" { #include #include @@ -7,64 +9,38 @@ extern "C" { namespace Poincare { -const uint8_t topLeftCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { - {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, - {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, - {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, - {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, - {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, - {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, - {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, - -}; - -const uint8_t bottomLeftCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { - {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, - {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, - {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, - {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, - {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, - {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, - {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, - -}; - -const uint8_t topRightCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { - {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, - {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, - {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, - {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, - {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, - {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, - {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, -}; - -const uint8_t bottomRightCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { - {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, - {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, - {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, - {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, - {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, - {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, - {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, - -}; - ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operandLayout) : ExpressionLayout(), m_operandLayout(operandLayout) { + m_leftParenthesisLayout = new ParenthesisLeftLayout(); + m_rightParenthesisLayout = new ParenthesisRightLayout(); m_operandLayout->setParent(this); + m_leftParenthesisLayout->setParent(this); + m_rightParenthesisLayout->setParent(this); m_baseline = m_operandLayout->baseline(); } ParenthesisLayout::~ParenthesisLayout() { delete m_operandLayout; + delete m_rightParenthesisLayout; + delete m_leftParenthesisLayout; } bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the Right parenthesis. + // Go to the operand and move left. + if (m_rightParenthesisLayout + && cursor->pointedExpressionLayout() == m_rightParenthesisLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } // Case: Left of the operand. - // Go Left of the brackets. + // Go Left. if (m_operandLayout && cursor->pointedExpressionLayout() == m_operandLayout && cursor->position() == ExpressionLayoutCursor::Position::Left) @@ -72,6 +48,19 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); return true; } + // Case: Left of the Left parenthesis. + // Aske the parent. + if (m_leftParenthesisLayout + && cursor->pointedExpressionLayout() == m_leftParenthesisLayout + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } assert(cursor->pointedExpressionLayout() == this); // Case: Right of the parentheses. // Go Right of the operand. @@ -89,40 +78,36 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } -KDColor s_parenthesisWorkingBuffer[ParenthesisLayout::k_parenthesisCurveHeight*ParenthesisLayout::k_parenthesisCurveWidth]; - -void ParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDSize operandSize = m_operandLayout->size(); - KDRect frame(p.x()+k_externWidthMargin, p.y()+k_externHeightMargin, k_parenthesisCurveWidth, k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)s_parenthesisWorkingBuffer); - frame = KDRect(p.x()+k_externWidthMargin, p.y() + operandSize.height() - k_parenthesisCurveHeight - k_externHeightMargin, - k_parenthesisCurveWidth, k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomLeftCurve, (KDColor *)s_parenthesisWorkingBuffer); - frame = KDRect(p.x()+k_externWidthMargin + operandSize.width() + 2*k_widthMargin + 2*k_lineThickness - k_parenthesisCurveWidth, p.y() + k_externHeightMargin, - k_parenthesisCurveWidth, k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)s_parenthesisWorkingBuffer); - frame = KDRect(p.x() +k_externWidthMargin + operandSize.width() + 2*k_widthMargin + 2*k_lineThickness - k_parenthesisCurveWidth, p.y() + operandSize.height() - k_parenthesisCurveHeight - k_externHeightMargin, - k_parenthesisCurveWidth, k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomRightCurve, (KDColor *)s_parenthesisWorkingBuffer); - - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+k_parenthesisCurveHeight+k_externHeightMargin, k_lineThickness, m_operandLayout->size().height() - 2*(k_parenthesisCurveHeight+k_externHeightMargin)), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y()+k_parenthesisCurveHeight+2, k_lineThickness, m_operandLayout->size().height()- 2*(k_parenthesisCurveHeight+k_externHeightMargin)), expressionColor); -} - KDSize ParenthesisLayout::computeSize() { KDSize operandSize = m_operandLayout->size(); - return KDSize(operandSize.width() + 2*k_widthMargin + 2*k_lineThickness+2*k_externWidthMargin, operandSize.height()); + return KDSize(operandSize.width() + 2*m_leftParenthesisLayout->size().width(), operandSize.height()); } ExpressionLayout * ParenthesisLayout::child(uint16_t index) { if (index == 0) { + return m_leftParenthesisLayout; + } + if (index == 1) { return m_operandLayout; } + if (index == 2) { + return m_rightParenthesisLayout; + } return nullptr; } KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { - return KDPoint(k_widthMargin+k_lineThickness+k_externWidthMargin, 0); + if (child == m_leftParenthesisLayout) { + return KDPoint(0, 0); + } + if (child == m_operandLayout) { + return KDPoint(m_leftParenthesisLayout->size().width(), 0); + } + if (child == m_rightParenthesisLayout) { + return KDPoint(m_operandLayout->origin().x() + m_operandLayout->size().width(), 0); + } + assert(false); + return KDPointZero; } } diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 92f4892ed..e6fcab76a 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -18,7 +18,8 @@ public: constexpr static KDCoordinate k_parenthesisCurveHeight = 7; bool moveLeft(ExpressionLayoutCursor * cursor) override; protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { + }; KDSize computeSize() override; ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; @@ -28,6 +29,8 @@ private: constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_lineThickness = 1; ExpressionLayout * m_operandLayout; + ExpressionLayout * m_leftParenthesisLayout; + ExpressionLayout * m_rightParenthesisLayout; }; } diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp new file mode 100644 index 000000000..807927588 --- /dev/null +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -0,0 +1,52 @@ +#include "parenthesis_left_layout.h" +extern "C" { +#include +#include +} + +namespace Poincare { + +const uint8_t topLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { + {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, + {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, + {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, + {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, + {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, + {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, + {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, +}; + +const uint8_t bottomLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { + {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, + {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, + {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, + {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, + {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, + {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, +}; + +void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + //TODO Make sure m_operandHeight is up-to-date. + KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, + p.y()+ParenthesisLeftRightLayout::k_externHeightMargin, + ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + + frame = KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, + p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + + ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, + p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin, + ParenthesisLeftRightLayout::k_lineThickness, + m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + expressionColor); +} + +} diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h new file mode 100644 index 000000000..32796d8c3 --- /dev/null +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -0,0 +1,19 @@ +#ifndef POINCARE_PARENTHESIS_LEFT_LAYOUT_H +#define POINCARE_PARENTHESIS_LEFT_LAYOUT_H + +#include +#include +#include + +namespace Poincare { + +class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { +public: + using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +} + +#endif diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp new file mode 100644 index 000000000..7b7ae1e88 --- /dev/null +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -0,0 +1,43 @@ +#include "parenthesis_left_right_layout.h" +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : + ExpressionLayout(), + m_operandHeight(36) //TODO +{ +} + +bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +KDSize ParenthesisLeftRightLayout::computeSize() { + //TODO: compute the operandHeight according to the brothers + return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, m_operandHeight); +} + +KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { + assert(false); + return KDPointZero; +} + +} diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h new file mode 100644 index 000000000..a2496e22c --- /dev/null +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H +#define POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H + +#include +#include + +namespace Poincare { + +class ParenthesisLeftRightLayout : public ExpressionLayout { +public: + ParenthesisLeftRightLayout(); + ~ParenthesisLeftRightLayout() {} + ParenthesisLeftRightLayout(const ParenthesisLeftRightLayout& other) = delete; + ParenthesisLeftRightLayout(ParenthesisLeftRightLayout&& other) = delete; + ParenthesisLeftRightLayout& operator=(const ParenthesisLeftRightLayout& other) = delete; + ParenthesisLeftRightLayout& operator=(ParenthesisLeftRightLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + constexpr static KDCoordinate k_parenthesisCurveWidth = 5; + constexpr static KDCoordinate k_parenthesisCurveHeight = 7; + constexpr static KDCoordinate k_externWidthMargin = 1; + constexpr static KDCoordinate k_externHeightMargin = 2; + constexpr static KDCoordinate k_widthMargin = 5; + constexpr static KDCoordinate k_lineThickness = 1; +protected: + KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; + KDSize computeSize() override; + ExpressionLayout * child(uint16_t index) override { return nullptr; } + KDPoint positionOfChild(ExpressionLayout * child) override; + uint16_t m_operandHeight; +}; +} + +#endif diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp new file mode 100644 index 000000000..0a9a3af60 --- /dev/null +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -0,0 +1,59 @@ +#include "parenthesis_right_layout.h" +extern "C" { +#include +#include +} + +namespace Poincare { + +const uint8_t topRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { + {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, + {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, + {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, + {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, + {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, + {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, +}; + +const uint8_t bottomRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { + {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, + {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, + {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, + {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, + {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, + {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, + {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, +}; + +void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + //TODO Make sure m_operandHeight is up-to-date. + KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + p.y() + ParenthesisLeftRightLayout::k_externHeightMargin, + ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + + frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + ParenthesisLeftRightLayout::k_parenthesisCurveWidth, + ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + + ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_widthMargin, + p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+2, + ParenthesisLeftRightLayout::k_lineThickness, + m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + expressionColor); +} + +} + + + + + + + diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h new file mode 100644 index 000000000..efb98763b --- /dev/null +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -0,0 +1,19 @@ +#ifndef POINCARE_PARENTHESIS_RIGHT_LAYOUT_H +#define POINCARE_PARENTHESIS_RIGHT_LAYOUT_H + +#include +#include +#include + +namespace Poincare { + +class ParenthesisRightLayout : public ParenthesisLeftRightLayout { +public: + using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +} + +#endif From ab81f74bbf12da53d1e36620f9affaa3d2a88a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 12:04:19 +0100 Subject: [PATCH 019/459] [poincare] Bracket Left and Right layouts. Change-Id: I05987e837324628b5141b31d01f59c88ae5ff3ce --- poincare/Makefile | 3 ++ poincare/src/layout/bracket_left_layout.cpp | 12 ++++++ poincare/src/layout/bracket_left_layout.h | 17 ++++++++ .../src/layout/bracket_left_right_layout.cpp | 43 +++++++++++++++++++ .../src/layout/bracket_left_right_layout.h | 30 +++++++++++++ poincare/src/layout/bracket_right_layout.cpp | 19 ++++++++ poincare/src/layout/bracket_right_layout.h | 17 ++++++++ 7 files changed, 141 insertions(+) create mode 100644 poincare/src/layout/bracket_left_layout.cpp create mode 100644 poincare/src/layout/bracket_left_layout.h create mode 100644 poincare/src/layout/bracket_left_right_layout.cpp create mode 100644 poincare/src/layout/bracket_left_right_layout.h create mode 100644 poincare/src/layout/bracket_right_layout.cpp create mode 100644 poincare/src/layout/bracket_right_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index a5a5f5548..c778125ba 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -85,6 +85,9 @@ objs += $(addprefix poincare/src/,\ objs += $(addprefix poincare/src/layout/,\ baseline_relative_layout.o\ bracket_layout.o\ + bracket_left_layout.o\ + bracket_left_right_layout.o\ + bracket_right_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ editable_baseline_relative_layout.o\ diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/bracket_left_layout.cpp new file mode 100644 index 000000000..f9024923e --- /dev/null +++ b/poincare/src/layout/bracket_left_layout.cpp @@ -0,0 +1,12 @@ +#include "bracket_left_layout.h" + +namespace Poincare { + +void BracketLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + //TODO Make sure m_operandHeight is up-to-date. + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); +} + +} diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h new file mode 100644 index 000000000..ce025ec99 --- /dev/null +++ b/poincare/src/layout/bracket_left_layout.h @@ -0,0 +1,17 @@ +#ifndef POINCARE_BRACKET_LEFT_LAYOUT_H +#define POINCARE_BRACKET_LEFT_LAYOUT_H + +#include + +namespace Poincare { + +class BracketLeftLayout : public BracketLeftRightLayout { +public: + using BracketLeftRightLayout::BracketLeftRightLayout; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +} + +#endif diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp new file mode 100644 index 000000000..44c6eaa79 --- /dev/null +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -0,0 +1,43 @@ +#include "bracket_left_right_layout.h" +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +BracketLeftRightLayout::BracketLeftRightLayout() : + ExpressionLayout(), + m_operandHeight(36) //TODO +{ +} + +bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +KDSize BracketLeftRightLayout::computeSize() { + //TODO: compute the operandHeight according to the brothers + return KDSize(k_externWidthMargin + k_lineThickness + k_bracketWidth + k_widthMargin, m_operandHeight); +} + +KDPoint BracketLeftRightLayout::positionOfChild(ExpressionLayout * child) { + assert(false); + return KDPointZero; +} + +} diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h new file mode 100644 index 000000000..e65a4d446 --- /dev/null +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -0,0 +1,30 @@ +#ifndef POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H +#define POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H + +#include +#include + +namespace Poincare { + +class BracketLeftRightLayout : public ExpressionLayout { +public: + BracketLeftRightLayout(); + ~BracketLeftRightLayout() {} + BracketLeftRightLayout(const BracketLeftRightLayout& other) = delete; + BracketLeftRightLayout(BracketLeftRightLayout&& other) = delete; + BracketLeftRightLayout& operator=(const BracketLeftRightLayout& other) = delete; + BracketLeftRightLayout& operator=(BracketLeftRightLayout&& other) = delete; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + constexpr static KDCoordinate k_bracketWidth = 5; + constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_widthMargin = 5; + constexpr static KDCoordinate k_externWidthMargin = 2; +protected: + KDSize computeSize() override; + ExpressionLayout * child(uint16_t index) override { return nullptr; } + KDPoint positionOfChild(ExpressionLayout * child) override; + uint16_t m_operandHeight; +}; +} + +#endif diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp new file mode 100644 index 000000000..3eac6ba5e --- /dev/null +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -0,0 +1,19 @@ +#include "bracket_right_layout.h" + +namespace Poincare { + +void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + //TODO Make sure m_operandHeight is up-to-date. + ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); +} + +} + + + + + + + diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h new file mode 100644 index 000000000..a9d9c7c79 --- /dev/null +++ b/poincare/src/layout/bracket_right_layout.h @@ -0,0 +1,17 @@ +#ifndef POINCARE_BRACKET_RIGHT_LAYOUT_H +#define POINCARE_BRACKET_RIGHT_LAYOUT_H + +#include + +namespace Poincare { + +class BracketRightLayout : public BracketLeftRightLayout { +public: + using BracketLeftRightLayout::BracketLeftRightLayout; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +} + +#endif From 29e549d475abef85cac9b3f9991f34a4616e3234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 14:49:37 +0100 Subject: [PATCH 020/459] [expression_editor/poincare] Move Right in an ExpressionLayout. Change-Id: Ib5f018666350d6bb061272ae7b04b6f721d50e84 --- poincare/include/poincare/expression_layout.h | 1 + poincare/src/expression_layout_cursor.cpp | 2 +- .../src/layout/baseline_relative_layout.cpp | 17 +++++++ .../src/layout/baseline_relative_layout.h | 1 + poincare/src/layout/bracket_layout.cpp | 28 ++++++++++ poincare/src/layout/bracket_layout.h | 1 + .../src/layout/bracket_left_right_layout.cpp | 18 +++++++ .../src/layout/bracket_left_right_layout.h | 1 + poincare/src/layout/condensed_sum_layout.cpp | 42 +++++++++++++++ poincare/src/layout/condensed_sum_layout.h | 1 + poincare/src/layout/conjugate_layout.cpp | 30 +++++++++++ poincare/src/layout/conjugate_layout.h | 1 + .../editable_baseline_relative_layout.cpp | 40 +++++++++++++++ .../editable_baseline_relative_layout.h | 1 + .../src/layout/editable_string_layout.cpp | 42 +++++++++++++++ poincare/src/layout/editable_string_layout.h | 1 + poincare/src/layout/fraction_layout.cpp | 27 ++++++++++ poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 42 +++++++++++++++ poincare/src/layout/grid_layout.h | 2 + poincare/src/layout/horizontal_layout.cpp | 47 +++++++++++++++++ poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/integral_layout.cpp | 40 +++++++++++++++ poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 42 +++++++++++++++ poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/parenthesis_layout.cpp | 51 +++++++++++++++++++ poincare/src/layout/parenthesis_layout.h | 1 + .../layout/parenthesis_left_right_layout.cpp | 17 +++++++ .../layout/parenthesis_left_right_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 43 ++++++++++++++++ poincare/src/layout/sequence_layout.h | 1 + poincare/src/layout/string_layout.cpp | 17 +++++++ poincare/src/layout/string_layout.h | 1 + 34 files changed, 562 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index d2df7e271..2f49c2b8e 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -24,6 +24,7 @@ public: /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? + virtual bool moveRight(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index ce5468741..17c38ae12 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -7,7 +7,7 @@ bool ExpressionLayoutCursor::moveLeft() { } bool ExpressionLayoutCursor::moveRight() { - return false; //TODO + return m_pointedExpressionLayout->moveRight(this); } bool ExpressionLayoutCursor::moveUp() { diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 80cf27596..4b553d116 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -47,6 +47,23 @@ bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool BaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void BaselineRelativeLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // There is nothing to draw for a subscript/superscript, only the position of the children matters } diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index ac3146b86..d88e26708 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -21,6 +21,7 @@ public: ExpressionLayout * baseLayout(); ExpressionLayout * indiceLayout(); bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index c185fff75..1b369ec5a 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -46,6 +46,34 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the operand. + // Go Right of the brackets. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left of the brackets. + // Go Left of the operand. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right of the brackets. + // Ask the parent. + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index f110789aa..e2f6c926b 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -15,6 +15,7 @@ public: BracketLayout& operator=(const BracketLayout& other) = delete; BracketLayout& operator=(BracketLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: KDCoordinate externWidthMargin() const { return 2; } virtual KDCoordinate widthMargin() const { return 5; } diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index 44c6eaa79..95c26bade 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -30,6 +30,24 @@ bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + + KDSize BracketLeftRightLayout::computeSize() { //TODO: compute the operandHeight according to the brothers return KDSize(k_externWidthMargin + k_lineThickness + k_bracketWidth + k_widthMargin, m_operandHeight); diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index e65a4d446..6cc309184 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -15,6 +15,7 @@ public: BracketLeftRightLayout& operator=(const BracketLeftRightLayout& other) = delete; BracketLeftRightLayout& operator=(BracketLeftRightLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; constexpr static KDCoordinate k_widthMargin = 5; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 0a74eece4..401c684af 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -66,6 +66,48 @@ bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the bounds. + // Go Left of the operand. + if (((m_subscriptLayout && cursor->pointedExpressionLayout() == m_subscriptLayout) + || (m_superscriptLayout && cursor->pointedExpressionLayout() == m_superscriptLayout)) + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(m_baseLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right of the base. + // Ask the parent. + if (m_baseLayout + && cursor->pointedExpressionLayout() == m_baseLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the upper bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_superscriptLayout); + cursor->setPointedExpressionLayout(m_superscriptLayout); + return true; + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Nothing to draw } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index fce1333c3..6e9ae9dd2 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -15,6 +15,7 @@ public: CondensedSumLayout& operator=(const CondensedSumLayout& other) = delete; CondensedSumLayout& operator=(CondensedSumLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index fc83bc45b..18844c96f 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -49,6 +49,36 @@ bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the operand. + // Ask the parent. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the operand and move Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return m_operandLayout->moveRight(cursor); + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x(), p.y(), m_operandLayout->size().width(), k_overlineWidth), expressionColor); } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 4d6eacf8c..6e1030c88 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -15,6 +15,7 @@ public: ConjugateLayout& operator=(const ConjugateLayout& other) = delete; ConjugateLayout& operator=(ConjugateLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp index 27c3988da..f217e8a33 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -46,5 +46,45 @@ bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool EditableBaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the base. + // Go from the base to the indice. + if (m_baseLayout + && cursor->pointedExpressionLayout() == m_baseLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right of the indice. + // Go Right. + if (m_indiceLayout + && cursor->pointedExpressionLayout() == m_indiceLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the base and move Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_baseLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + return m_baseLayout->moveRight(cursor); + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + + } diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h index f390e1c77..9839e8628 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -9,6 +9,7 @@ class EditableBaselineRelativeLayout : public BaselineRelativeLayout { public: using BaselineRelativeLayout::BaselineRelativeLayout; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; }; } diff --git a/poincare/src/layout/editable_string_layout.cpp b/poincare/src/layout/editable_string_layout.cpp index e06ab544a..98f085fff 100644 --- a/poincare/src/layout/editable_string_layout.cpp +++ b/poincare/src/layout/editable_string_layout.cpp @@ -47,4 +47,46 @@ bool EditableStringLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool EditableStringLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go after the first char. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + size_t stringLength = strlen(m_string); + if (stringLength > 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Inside); + cursor->setPositionInside(1); + return true; + } + if (stringLength == 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(stringLength == 0); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + // Case: Inside. + // Go one char right. + if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { + int cursorIndex = cursor->positionInside(); + assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); + if (cursorIndex == strlen(m_string)-1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + cursor->setPositionInside(cursorIndex + 1); + return true; + } + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + } diff --git a/poincare/src/layout/editable_string_layout.h b/poincare/src/layout/editable_string_layout.h index 23e92bc65..92e0e9730 100644 --- a/poincare/src/layout/editable_string_layout.h +++ b/poincare/src/layout/editable_string_layout.h @@ -10,6 +10,7 @@ class EditableStringLayout : public StringLayout { public: using StringLayout::StringLayout; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; }; } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 01ce02e87..5f7a0043a 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -45,6 +45,33 @@ bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the numerator or the denominator. + // Go Right of the fraction. + if (((m_numerator_layout && cursor->pointedExpressionLayout() == m_numerator_layout) + || (m_denominator_layout && cursor->pointedExpressionLayout() == m_denominator_layout)) + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the numerator. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_numerator_layout != nullptr); + cursor->setPointedExpressionLayout(m_numerator_layout); + return true; + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + m_numerator_layout->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 355f5c44b..8f777040e 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -15,6 +15,7 @@ public: FractionLayout& operator=(const FractionLayout& other) = delete; FractionLayout& operator=(FractionLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 79e91f4e9..6df7a62b3 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -63,6 +63,43 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Left. + // Go to the first entry. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_numberOfColumns*m_numberOfRows >= 1); + ExpressionLayout * firstChild = m_entryLayouts[0]; + assert(firstChild != nullptr); + cursor->setPointedExpressionLayout(firstChild); + return true; + } + // Case: The cursor points to a grid's child. + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (childIsRightOfGrid(childIndex)) { + // Case: Right of a child on the right of the grid. + // Go Right of the grid. + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Right of another child. + // Go Left of its brother on the right. + cursor->setPointedExpressionLayout(m_entryLayouts[childIndex+1]); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { @@ -159,5 +196,10 @@ bool GridLayout::childIsLeftOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == 0; } +bool GridLayout::childIsRightOfGrid(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == m_numberOfColumns - 1; +} + } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 7e5de435e..0cab38840 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -16,6 +16,7 @@ public: GridLayout& operator=(const GridLayout& other) = delete; GridLayout& operator=(GridLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -30,6 +31,7 @@ private: KDCoordinate width(); int indexOfChild(ExpressionLayout * eL) const; bool childIsLeftOfGrid(int index) const; + bool childIsRightOfGrid(int index) const; ExpressionLayout ** m_entryLayouts; int m_numberOfRows; int m_numberOfColumns; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 63d1e1a9e..429931df8 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -77,6 +77,53 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { return m_children_layouts[childIndex-1]->moveLeft(cursor); } +bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right. + // Ask the parent. + if (cursor->pointedExpressionLayout() == this) { + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Go to the first child if there is one, and move Right. + // Else go Right and ask the parent. + if (m_number_of_children < 1) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + ExpressionLayout * firstChild = m_children_layouts[0]; + assert(firstChild != nullptr); + cursor->setPointedExpressionLayout(firstChild); + return firstChild->moveRight(cursor); + } + + // Case: The cursor is Right of a child. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + assert(childIndex >= 0); + if (childIndex == m_number_of_children - 1) { + // Case: the child is the rightmost. + // Ask the parent. + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + // Case: the child is not the rightmost. + // Go to its right brother and move Right. + cursor->setPointedExpressionLayout(m_children_layouts[childIndex+1]); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return m_children_layouts[childIndex+1]->moveRight(cursor); +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 55f8dd279..c081589fb 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -15,6 +15,7 @@ public: HorizontalLayout& operator=(const HorizontalLayout& other) = delete; HorizontalLayout& operator=(HorizontalLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index f4a594e85..1ce316836 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -77,6 +77,46 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right the upper or lower bound. + // Go Left of the integrand. + if (((m_upperBoundLayout + && cursor->pointedExpressionLayout() == m_upperBoundLayout) + || (m_lowerBoundLayout + && cursor->pointedExpressionLayout() == m_lowerBoundLayout)) + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(m_integrandLayout != nullptr); + cursor->setPointedExpressionLayout(m_integrandLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right the integrand. + // Go Right and move Right. + if (m_integrandLayout + && cursor->pointedExpressionLayout() == m_integrandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return m_parent->moveRight(cursor); + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left of the integral. + // Go ti the upper bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_upperBoundLayout != nullptr); + cursor->setPointedExpressionLayout(m_upperBoundLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = m_integrandLayout->size(); KDSize upperBoundSize = m_upperBoundLayout->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index abf47ff33..0a3ad388d 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -17,6 +17,7 @@ public: constexpr static KDCoordinate k_symbolHeight = 4; constexpr static KDCoordinate k_symbolWidth = 4; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 9fda611b8..0e8727fba 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -79,6 +79,48 @@ bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the radicand. + // Go the Right of the root. + if (m_radicandLayout + && cursor->pointedExpressionLayout() == m_radicandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Right of the index. + // Go Left of the integrand. + if (m_indexLayout + && cursor->pointedExpressionLayout() == m_indexLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(m_radicandLayout != nullptr); + cursor->setPointedExpressionLayout(m_radicandLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go index if there is one, else go to the radicand. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (m_indexLayout) { + cursor->setPointedExpressionLayout(m_indexLayout); + return true; + } + assert(m_radicandLayout != nullptr); + cursor->setPointedExpressionLayout(m_radicandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = m_radicandLayout->size(); KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index ade120681..b4727b531 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -17,6 +17,7 @@ public: constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index ecd6d7cdd..56a50ed51 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -78,6 +78,57 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the Left parenthesis. + // Go to the operand and move Right. + if (m_leftParenthesisLayout + && cursor->pointedExpressionLayout() == m_leftParenthesisLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return m_operandLayout->moveRight(cursor); + } + // Case: Right of the operand. + // Go Right. + if (m_operandLayout + && cursor->pointedExpressionLayout() == m_operandLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Right of the Right parenthesis. + // Ask the parent. + if (m_rightParenthesisLayout + && cursor->pointedExpressionLayout() == m_rightParenthesisLayout + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left of the parentheses. + // Go Left of the operand. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_operandLayout != nullptr); + cursor->setPointedExpressionLayout(m_operandLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right of the parentheses. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + KDSize ParenthesisLayout::computeSize() { KDSize operandSize = m_operandLayout->size(); return KDSize(operandSize.width() + 2*m_leftParenthesisLayout->size().width(), operandSize.height()); diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index e6fcab76a..84c765893 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -17,6 +17,7 @@ public: constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { }; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 7b7ae1e88..bbf204a79 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -30,6 +30,23 @@ bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + KDSize ParenthesisLeftRightLayout::computeSize() { //TODO: compute the operandHeight according to the brothers return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, m_operandHeight); diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index a2496e22c..d032fa1af 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -15,6 +15,7 @@ public: ParenthesisLeftRightLayout& operator=(const ParenthesisLeftRightLayout& other) = delete; ParenthesisLeftRightLayout& operator=(ParenthesisLeftRightLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; constexpr static KDCoordinate k_externWidthMargin = 1; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 1bf01e536..2ec7658c9 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -64,6 +64,49 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the bounds. + // Go Left of the argument. + if (cursor->position() == ExpressionLayoutCursor::Position::Right + && ((m_lowerBoundLayout + && cursor->pointedExpressionLayout() == m_lowerBoundLayout) + || (m_upperBoundLayout + && cursor->pointedExpressionLayout() == m_upperBoundLayout))) + { + assert(m_argumentLayout != nullptr); + cursor->setPointedExpressionLayout(m_argumentLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right of the argument. + // Ask the parent. + if (cursor->position() == ExpressionLayoutCursor::Position::Right + && m_argumentLayout + && cursor->pointedExpressionLayout() == m_argumentLayout) + { + cursor->setPointedExpressionLayout(this); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the upper bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(m_upperBoundLayout != nullptr); + cursor->setPointedExpressionLayout(m_upperBoundLayout); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + KDSize SequenceLayout::computeSize() { KDSize argumentSize = m_argumentLayout->size(); KDSize lowerBoundSize = m_lowerBoundLayout->size(); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 03e289454..bcef26d56 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -17,6 +17,7 @@ public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; ExpressionLayout * m_lowerBoundLayout; diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index 84a8a35fe..c4df91684 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -42,6 +42,23 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { return false; } +bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { + // A StringLayout is not editable, and the cursor cannot go inside it. + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + ExpressionLayout * StringLayout::child(uint16_t index) { return nullptr; } diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 236bfaa8b..60600f022 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -19,6 +19,7 @@ public: StringLayout& operator=(StringLayout&& other) = delete; char * text(); bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; From 96c2f9aebad36a039547139fa6ca7f0987df4681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 14:50:29 +0100 Subject: [PATCH 021/459] [poincare] Fixed some layout moveLeft() problems. Change-Id: Id7b9f9a1cc823589e1abd8a69800331649393126 --- poincare/src/layout/parenthesis_layout.cpp | 4 ++-- poincare/src/layout/string_layout.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index 56a50ed51..6c9fa5ed4 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -37,7 +37,7 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(m_operandLayout != nullptr); cursor->setPointedExpressionLayout(m_operandLayout); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return m_operandLayout->moveLeft(cursor); } // Case: Left of the operand. // Go Left. @@ -49,7 +49,7 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { return true; } // Case: Left of the Left parenthesis. - // Aske the parent. + // Ask the parent. if (m_leftParenthesisLayout && cursor->pointedExpressionLayout() == m_leftParenthesisLayout && cursor->position() == ExpressionLayoutCursor::Position::Left) diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index c4df91684..4a053c80d 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -25,7 +25,6 @@ char * StringLayout::text() { } bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); // A StringLayout is not editable, and the cursor cannot go inside it. assert(cursor->pointedExpressionLayout() == this); // Case: Right. From fc8cd6c06ea579934b29489dec1883bdb3e53cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 15 Dec 2017 18:10:14 +0100 Subject: [PATCH 022/459] [expression_editor/poincare] Move Up in an ExpressionLayout. Change-Id: I75fd91233729afd4eb77d8e9d53c102a632643ea --- .../expression_view_with_cursor.cpp | 4 +- .../expression_view_with_cursor.h | 1 - kandinsky/include/kandinsky/point.h | 1 + kandinsky/include/kandinsky/rect.h | 4 + kandinsky/src/point.cpp | 4 + kandinsky/src/rect.cpp | 8 ++ poincare/include/poincare/expression_layout.h | 15 ++++ .../poincare/expression_layout_cursor.h | 9 +++ poincare/src/expression_layout_cursor.cpp | 26 ++++++- .../src/layout/baseline_relative_layout.h | 2 +- poincare/src/layout/condensed_sum_layout.cpp | 17 +++++ poincare/src/layout/condensed_sum_layout.h | 1 + .../editable_baseline_relative_layout.cpp | 46 ++++++++++++ .../editable_baseline_relative_layout.h | 1 + .../src/layout/editable_string_layout.cpp | 25 +++++++ poincare/src/layout/editable_string_layout.h | 8 ++ poincare/src/layout/expression_layout.cpp | 74 +++++++++++++++++++ poincare/src/layout/fraction_layout.cpp | 14 ++++ poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 15 ++++ poincare/src/layout/grid_layout.h | 2 + poincare/src/layout/horizontal_layout.cpp | 36 +++++++++ poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/integral_layout.cpp | 17 +++++ poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 25 +++++++ poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 17 +++++ poincare/src/layout/sequence_layout.h | 1 + 29 files changed, 372 insertions(+), 5 deletions(-) diff --git a/apps/expression_editor/expression_view_with_cursor.cpp b/apps/expression_editor/expression_view_with_cursor.cpp index 0c83c41ce..3f501434a 100644 --- a/apps/expression_editor/expression_view_with_cursor.cpp +++ b/apps/expression_editor/expression_view_with_cursor.cpp @@ -44,8 +44,8 @@ void ExpressionViewWithCursor::layoutCursorSubview() { } else if (m_cursor->position() == ExpressionLayoutCursor::Position::Inside) { cursorX += m_cursor->positionInside() * KDText::charSize().width(); } - KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor->pointedExpressionLayout()->baseline()-k_cursorHeight/2); - m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, k_cursorHeight)); + KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor->pointedExpressionLayout()->baseline()-m_cursor->cursorHeight()/2); + m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor->cursorHeight())); } } diff --git a/apps/expression_editor/expression_view_with_cursor.h b/apps/expression_editor/expression_view_with_cursor.h index 991bc4ba1..79353173c 100644 --- a/apps/expression_editor/expression_view_with_cursor.h +++ b/apps/expression_editor/expression_view_with_cursor.h @@ -21,7 +21,6 @@ private: Top, Bottom }; - constexpr static KDCoordinate k_cursorHeight = 18; int numberOfSubviews() const override { return 2; } View * subviewAtIndex(int index) override; void layoutSubviews() override; diff --git a/kandinsky/include/kandinsky/point.h b/kandinsky/include/kandinsky/point.h index 67003b8e7..892aa92c7 100644 --- a/kandinsky/include/kandinsky/point.h +++ b/kandinsky/include/kandinsky/point.h @@ -17,6 +17,7 @@ public: bool operator !=(const KDPoint &other) const { return !(operator ==(other)); } + uint16_t squareDistanceTo(KDPoint other) const; private: KDCoordinate m_x; KDCoordinate m_y; diff --git a/kandinsky/include/kandinsky/rect.h b/kandinsky/include/kandinsky/rect.h index b149a35cf..d5c93ae82 100644 --- a/kandinsky/include/kandinsky/rect.h +++ b/kandinsky/include/kandinsky/rect.h @@ -45,6 +45,8 @@ public: KDCoordinate left() const { return m_x; } KDPoint topLeft() const { return KDPoint(left(), top()); } + KDPoint topRight() const { return KDPoint(right(), top()); } + KDPoint bottomLeft() const { return KDPoint(left(), bottom()); } KDPoint bottomRight() const { return KDPoint(right(), bottom()); } bool operator ==(const KDRect &other) const { @@ -61,6 +63,8 @@ public: KDRect intersectedWith(const KDRect & other) const; KDRect unionedWith(const KDRect & other) const; // Returns the smallest rectangle containing r1 and r2 bool contains(KDPoint p) const; + bool isAbove(KDPoint p) const; + bool isUnder(KDPoint p) const; bool isEmpty() const; private: diff --git a/kandinsky/src/point.cpp b/kandinsky/src/point.cpp index 4fe0a7afb..796232558 100644 --- a/kandinsky/src/point.cpp +++ b/kandinsky/src/point.cpp @@ -7,3 +7,7 @@ KDPoint KDPoint::translatedBy(KDPoint other) const { KDPoint KDPoint::opposite() const { return KDPoint(-m_x, -m_y); } + +uint16_t KDPoint::squareDistanceTo(KDPoint other) const { + return (m_x-other.x()) * (m_x-other.x()) + (m_y-other.y()) * (m_y-other.y()); +} diff --git a/kandinsky/src/rect.cpp b/kandinsky/src/rect.cpp index a9702ce45..9cf0df654 100644 --- a/kandinsky/src/rect.cpp +++ b/kandinsky/src/rect.cpp @@ -105,6 +105,14 @@ bool KDRect::contains(KDPoint p) const { return (p.x() >= x() && p.x() <= right() && p.y() >= y() && p.y() <= bottom()); } +bool KDRect::isAbove(KDPoint p) const { + return (p.y() >= y()); +} + +bool KDRect::isUnder(KDPoint p) const { + return (p.y() <= bottom()); +} + KDRect KDRect::translatedBy(KDPoint p) const { return KDRect(x() + p.x(), y() + p.y(), width(), height()); } diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 2f49c2b8e..b54e8d058 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -9,6 +9,11 @@ class ExpressionLayoutCursor; class ExpressionLayout { public: + enum class VerticalDirection { + Up, + Down + }; + ExpressionLayout(); virtual ~ExpressionLayout() = default; @@ -25,6 +30,8 @@ public: /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? virtual bool moveRight(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? + virtual bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); + bool moveUpInside(ExpressionLayoutCursor * cursor); protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; @@ -32,7 +39,15 @@ protected: virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; KDCoordinate m_baseline; ExpressionLayout * m_parent; + virtual void moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultPositionInside, + int * resultScore); private: + bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); bool m_sized, m_positioned; KDRect m_frame; }; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 89b2a0462..0fe1f689e 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -2,6 +2,7 @@ #define POINCARE_EXPRESSION_LAYOUT_CURSOR_H #include +#include namespace Poincare { @@ -26,6 +27,7 @@ public: void setPosition(Position position) { m_position = position; } int positionInside() const { return m_positionInside; } void setPositionInside(int positionInside) { m_positionInside = positionInside; } + KDCoordinate cursorHeight() const { return k_cursorHeight; } /* Move */ bool moveLeft(); @@ -33,7 +35,14 @@ public: bool moveUp(); bool moveDown(); + /* Comparison */ + bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex = 0); + + /* Position */ + KDPoint middleLeftPoint(); + KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position, int positionInside = 0); private: + constexpr static KDCoordinate k_cursorHeight = 18; ExpressionLayout * m_pointedExpressionLayout; Position m_position; int m_positionInside; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 17c38ae12..1b45f7d32 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,4 +1,6 @@ #include +#include +#include namespace Poincare { @@ -11,12 +13,34 @@ bool ExpressionLayoutCursor::moveRight() { } bool ExpressionLayoutCursor::moveUp() { - return false; //TODO + return m_pointedExpressionLayout->moveUp(this); } bool ExpressionLayoutCursor::moveDown() { return false; //TODO } +bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex) { + assert(expressionLayout != nullptr); + return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position, positionIndex); +} + +KDPoint ExpressionLayoutCursor::middleLeftPoint() { + return middleLeftPointOfCursor(m_pointedExpressionLayout, m_position, m_positionInside); +} + +KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position, int positionInside) { + KDPoint layoutOrigin = expressionLayout->absoluteOrigin(); + KDCoordinate y = layoutOrigin.y() + expressionLayout->baseline() - k_cursorHeight/2; + if (position == Position::Left) { + return KDPoint(layoutOrigin.x(), y); + } + if (position == Position::Right) { + return KDPoint(layoutOrigin.x() + expressionLayout->size().width(), y); + } + assert(position == Position::Inside); + return KDPoint(layoutOrigin.x() + positionInside * KDText::charSize().width(), y); +} + } diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index d88e26708..1b75f6822 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -29,9 +29,9 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; ExpressionLayout * m_baseLayout; ExpressionLayout * m_indiceLayout; + Type m_type; private: constexpr static KDCoordinate k_indiceHeight = 5; - Type m_type; }; } diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 401c684af..1a4169024 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -108,6 +108,23 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the subscript layout, move it to the superscript. + if (m_subscriptLayout && previousLayout == m_subscriptLayout) { + assert(m_superscriptLayout != nullptr); + return m_superscriptLayout->moveUpInside(cursor); + } + // If the cursor is Left of the base layout, move it to the superscript. + if (m_baseLayout + && previousLayout == m_baseLayout + && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_superscriptLayout != nullptr); + return m_superscriptLayout->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Nothing to draw } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 6e9ae9dd2..f2aa85bc9 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -16,6 +16,7 @@ public: CondensedSumLayout& operator=(CondensedSumLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp index f217e8a33..7078f9b8f 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -85,6 +85,52 @@ bool EditableBaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) return false; } +bool EditableBaselineRelativeLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the baseline is a superscript: + if (m_type == BaselineRelativeLayout::Type::Superscript) { + // If the cursor is Right of the base layout, move it to the indice. + if (m_baseLayout + && previousLayout == m_baseLayout + && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Right)) + { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Right, move it to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + } + // If the baseline is a subscript: + if (m_type == BaselineRelativeLayout::Type::Subscript + && m_indiceLayout + && previousLayout == m_indiceLayout) + { + // If the cursor is Left of the indice layout, move it to the base. + if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Left)) { + assert(m_baseLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Right of the indice layout, move it Right. + if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Right)) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} } diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h index 9839e8628..e9bddbffd 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -10,6 +10,7 @@ public: using BaselineRelativeLayout::BaselineRelativeLayout; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; }; } diff --git a/poincare/src/layout/editable_string_layout.cpp b/poincare/src/layout/editable_string_layout.cpp index 98f085fff..1dfd613b8 100644 --- a/poincare/src/layout/editable_string_layout.cpp +++ b/poincare/src/layout/editable_string_layout.cpp @@ -89,4 +89,29 @@ bool EditableStringLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +void EditableStringLayout::moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultPositionInside, + int * resultScore) +{ + ExpressionLayout::moveCursorInsideAtDirection(direction, cursor, childResult, resultPosition, resultPositionInside, resultScore); + ExpressionLayoutCursor::Position * castedResultPosition = static_cast(resultPosition); + // Check the distance to Inside cursors. + size_t stringLength = strlen(m_string); + int currentDistance = 0; + KDPoint cursorMiddleLeft = cursor->middleLeftPoint(); + for (int i = 1; i < stringLength; i++) { + currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Inside, i).squareDistanceTo(cursorMiddleLeft); + if (currentDistance < *resultScore) { + *childResult = this; + *castedResultPosition = ExpressionLayoutCursor::Position::Inside; + *resultPositionInside = i; + *resultScore = currentDistance; + } + } +} + } diff --git a/poincare/src/layout/editable_string_layout.h b/poincare/src/layout/editable_string_layout.h index 92e0e9730..75e8b77d9 100644 --- a/poincare/src/layout/editable_string_layout.h +++ b/poincare/src/layout/editable_string_layout.h @@ -11,6 +11,14 @@ public: using StringLayout::StringLayout; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; +private: + void moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultPositionInside, + int * resultScore) override; }; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 560eed6f8..f3f8a4dfb 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,6 +1,8 @@ #include #include #include "string_layout.h" +#include +#include namespace Poincare { @@ -57,4 +59,76 @@ void ExpressionLayout::setParent(ExpressionLayout* parent) { m_parent = parent; } +bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + if (m_parent) { + return m_parent->moveUp(cursor, this, previousLayout); + } + return false; +} + +bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor) { + return moveInside(VerticalDirection::Up, cursor); +} + +bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor) { + ExpressionLayout * chilResult = nullptr; + ExpressionLayout ** childResultPtr = &chilResult; + ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; + int resultPositionInside = 0; + // The distance between the cursor and its next position cannot be greater + // than this initial value of score. + int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; + + moveCursorInsideAtDirection(direction, cursor, childResultPtr, &resultPosition, &resultPositionInside, &resultScore); + + // If there is a valid result + if (*childResultPtr == nullptr) { + return false; + } + cursor->setPointedExpressionLayout(*childResultPtr); + cursor->setPosition(resultPosition); + cursor->setPositionInside(resultPositionInside); + return true; +} + +void ExpressionLayout::moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultPositionInside, + int * resultScore) +{ + ExpressionLayoutCursor::Position * castedResultPosition = static_cast(resultPosition); + KDPoint cursorMiddleLeft = cursor->middleLeftPoint(); + bool layoutIsUnderOrAbove = direction == VerticalDirection::Up ? m_frame.isAbove(cursorMiddleLeft) : m_frame.isUnder(cursorMiddleLeft); + bool layoutContains = m_frame.contains(cursorMiddleLeft); + + if (layoutIsUnderOrAbove) { + // Check the distance to a Left cursor. + int currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Left, 0).squareDistanceTo(cursorMiddleLeft); + if (currentDistance <= *resultScore ){ + *childResult = this; + *castedResultPosition = ExpressionLayoutCursor::Position::Left; + *resultPositionInside = 0; + *resultScore = currentDistance; + } + + // Check the distance to a Right cursor. + currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Right, 0).squareDistanceTo(cursorMiddleLeft); + if (currentDistance < *resultScore) { + *childResult = this; + *castedResultPosition = ExpressionLayoutCursor::Position::Right; + *resultPositionInside = 0; + *resultScore = currentDistance; + } + } + if (layoutIsUnderOrAbove || layoutContains) { + int childIndex = 0; + while (child(childIndex++)) { + child(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultPositionInside, resultScore); + } + } +} + } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 5f7a0043a..48b0e8778 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -72,6 +72,20 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside denominator, move it to the numerator. + if (m_denominator_layout && previousLayout == m_denominator_layout) { + assert(m_numerator_layout != nullptr); + return m_numerator_layout->moveUpInside(cursor); + } + // If the cursor is Left or Right, move it to the numerator. + if (cursor->pointedExpressionLayout() == this){ + assert(m_numerator_layout != nullptr); + return m_numerator_layout->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + m_numerator_layout->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 8f777040e..d5a69c9cd 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -16,6 +16,7 @@ public: FractionLayout& operator=(FractionLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 6df7a62b3..c6110f2ba 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -100,6 +100,16 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is child that is not on the top row, move it inside the upper + // neighbourg. + int childIndex = indexOfChild(previousLayout); + if (childIndex >- 1 && !childIsTopOfGrid(childIndex)) { + return m_entryLayouts[childIndex - m_numberOfColumns]->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { @@ -196,10 +206,15 @@ bool GridLayout::childIsLeftOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == 0; } + bool GridLayout::childIsRightOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == m_numberOfColumns - 1; } +bool GridLayout::childIsTopOfGrid(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return index < m_numberOfColumns; +} } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 0cab38840..e3b6d25f2 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -17,6 +17,7 @@ public: GridLayout& operator=(GridLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -32,6 +33,7 @@ private: int indexOfChild(ExpressionLayout * eL) const; bool childIsLeftOfGrid(int index) const; bool childIsRightOfGrid(int index) const; + bool childIsTopOfGrid(int index) const; ExpressionLayout ** m_entryLayouts; int m_numberOfRows; int m_numberOfColumns; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 429931df8..2635e7648 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -124,6 +124,39 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { return m_children_layouts[childIndex+1]->moveRight(cursor); } +bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Prevent looping fom child to parent + if (previousPreviousLayout == this) { + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + } + // If the cursor Left or Right of a child, try moving it up from its brother. + int previousLayoutIndex = indexOfChild(previousLayout); + if (previousLayoutIndex > -1) { + ExpressionLayout * brother = nullptr; + ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; + if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { + brother = m_children_layouts[previousLayoutIndex - 1]; + newPosition = ExpressionLayoutCursor::Position::Right; + } + if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < m_number_of_children - 1) { + brother = m_children_layouts[previousLayoutIndex + 1]; + newPosition = ExpressionLayoutCursor::Position::Left; + } + if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { + ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); + ExpressionLayoutCursor::Position previousPosition = cursor->position(); + cursor->setPointedExpressionLayout(brother); + cursor->setPosition(newPosition); + if (brother->moveUp(cursor, this, previousLayout)) { + return true; + } + cursor->setPointedExpressionLayout(previousPointedLayout); + cursor->setPosition(previousPosition); + } + } + return ExpressionLayout::moveUp(cursor, previousLayout); +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } @@ -168,6 +201,9 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { } int HorizontalLayout::indexOfChild(ExpressionLayout * eL) const { + if (eL == nullptr) { + return -1; + } for (int i = 0; i < m_number_of_children; i++) { if (m_children_layouts[i] == eL) { return i; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index c081589fb..33f0ba434 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -16,6 +16,7 @@ public: HorizontalLayout& operator=(HorizontalLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 1ce316836..c1e755fc8 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -117,6 +117,23 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the lower bound, move it to the upper bound. + if (m_lowerBoundLayout && previousLayout == m_lowerBoundLayout) { + assert(m_upperBoundLayout != nullptr); + return m_upperBoundLayout->moveUpInside(cursor); + } + // If the cursor is Left of the integrand, move it to the upper bound. + if (m_integrandLayout + && previousLayout == m_integrandLayout + && cursor->positionIsEquivalentTo(m_integrandLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_upperBoundLayout != nullptr); + return m_upperBoundLayout->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = m_integrandLayout->size(); KDSize upperBoundSize = m_upperBoundLayout->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 0a3ad388d..d28d98347 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -18,6 +18,7 @@ public: constexpr static KDCoordinate k_symbolWidth = 4; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 0e8727fba..238f504b6 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -121,6 +121,31 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is Left of the radicand, move it to the index. + if (m_radicandLayout + && previousLayout == m_radicandLayout + && cursor->positionIsEquivalentTo(m_radicandLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_indexLayout != nullptr); + cursor->setPointedExpressionLayout(m_indexLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Left, move it to the index. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(m_indexLayout != nullptr); + cursor->setPointedExpressionLayout(m_indexLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPositionInside(0); + return true; + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = m_radicandLayout->size(); KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index b4727b531..14ed3f2f2 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -18,6 +18,7 @@ public: constexpr static KDCoordinate k_leftRadixWidth = 5; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 2ec7658c9..535182d6e 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -107,6 +107,23 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the lower bound, move it to the upper bound. + if (m_lowerBoundLayout && previousLayout == m_lowerBoundLayout) { + assert(m_upperBoundLayout != nullptr); + return m_upperBoundLayout->moveUpInside(cursor); + } + // If the cursor is Left of the argument, move it to the upper bound. + if (m_argumentLayout + && previousLayout == m_argumentLayout + && cursor->positionIsEquivalentTo(m_argumentLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_upperBoundLayout != nullptr); + return m_upperBoundLayout->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + KDSize SequenceLayout::computeSize() { KDSize argumentSize = m_argumentLayout->size(); KDSize lowerBoundSize = m_lowerBoundLayout->size(); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index bcef26d56..aaf9f9bb2 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -18,6 +18,7 @@ public: constexpr static KDCoordinate k_symbolWidth = 9; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; ExpressionLayout * m_lowerBoundLayout; From a4c014c75e36ae02a0191c549901ef217ea4eafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 18 Dec 2017 11:14:05 +0100 Subject: [PATCH 023/459] [expression_editor/poincare] Move Down in an ExpressionLayout. Change-Id: I87f3394cce5eb4936ab926d5e92fdf44d4473cf7 --- poincare/include/poincare/expression_layout.h | 2 + poincare/src/expression_layout_cursor.cpp | 2 +- poincare/src/layout/condensed_sum_layout.cpp | 17 ++++ poincare/src/layout/condensed_sum_layout.h | 1 + .../editable_baseline_relative_layout.cpp | 48 +++++++++++ .../editable_baseline_relative_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 11 +++ poincare/src/layout/fraction_layout.cpp | 14 ++++ poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 15 ++++ poincare/src/layout/grid_layout.h | 2 + poincare/src/layout/horizontal_layout.cpp | 79 ++++++++++++------- poincare/src/layout/horizontal_layout.h | 2 + poincare/src/layout/integral_layout.cpp | 17 ++++ poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 21 +++++ poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 16 ++++ poincare/src/layout/sequence_layout.h | 1 + 19 files changed, 221 insertions(+), 31 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index b54e8d058..1381aecf5 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -32,6 +32,8 @@ public: virtual bool moveRight(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? virtual bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); bool moveUpInside(ExpressionLayoutCursor * cursor); + virtual bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); + bool moveDownInside(ExpressionLayoutCursor * cursor); protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 1b45f7d32..5fd6c0887 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -17,7 +17,7 @@ bool ExpressionLayoutCursor::moveUp() { } bool ExpressionLayoutCursor::moveDown() { - return false; //TODO + return m_pointedExpressionLayout->moveDown(this); } bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex) { diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 1a4169024..e1a73f1c2 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -125,6 +125,23 @@ bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayou return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the superscript layout, move it to the subscript. + if (m_superscriptLayout && previousLayout == m_superscriptLayout) { + assert(m_subscriptLayout != nullptr); + return m_subscriptLayout->moveUpInside(cursor); + } + // If the cursor is Left of the base layout, move it to the subscript. + if (m_baseLayout + && previousLayout == m_baseLayout + && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_subscriptLayout != nullptr); + return m_subscriptLayout->moveUpInside(cursor); + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Nothing to draw } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index f2aa85bc9..1d15dc1c3 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -17,6 +17,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp index 7078f9b8f..b06e27449 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -132,5 +132,53 @@ bool EditableBaselineRelativeLayout::moveUp(ExpressionLayoutCursor * cursor, Exp return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool EditableBaselineRelativeLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the baseline is a subscript: + if (m_type == BaselineRelativeLayout::Type::Subscript) { + // If the cursor is Right of the base layout, move it to the indice. + if (m_baseLayout + && previousLayout == m_baseLayout + && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Right)) + { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Right, move it to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_indiceLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + } + // If the baseline is a superscript: + if (m_type == BaselineRelativeLayout::Type::Superscript + && m_indiceLayout + && previousLayout == m_indiceLayout) + { + // If the cursor is Left of the indice layout, move it to the base. + if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Left)) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(m_baseLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Right of the indice layout, move it Right. + if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Right)) { + assert(m_indiceLayout != nullptr); + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); + return true; + } + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + } diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h index e9bddbffd..72ef5aa4a 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -11,6 +11,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; }; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index f3f8a4dfb..630b1c61e 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -70,6 +70,17 @@ bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor) { return moveInside(VerticalDirection::Up, cursor); } +bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + if (m_parent) { + return m_parent->moveDown(cursor, this, previousLayout); + } + return false; +} + +bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor) { + return moveInside(VerticalDirection::Down, cursor); +} + bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor) { ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 48b0e8778..4191504ab 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -86,6 +86,20 @@ bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside numerator, move it to the denominator. + if (m_numerator_layout && previousLayout == m_numerator_layout) { + assert(m_denominator_layout != nullptr); + return m_denominator_layout->moveDownInside(cursor); + } + // If the cursor is Left or Right, move it to the denominator. + if (cursor->pointedExpressionLayout() == this){ + assert(m_denominator_layout != nullptr); + return m_denominator_layout->moveDownInside(cursor); + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + m_numerator_layout->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index d5a69c9cd..97dd6043a 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -17,6 +17,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index c6110f2ba..075854b95 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -110,6 +110,16 @@ bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * prev return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is child that is not on the bottom row, move it inside the + // lower neighbourg. + int childIndex = indexOfChild(previousLayout); + if (childIndex >- 1 && !childIsBottomOfGrid(childIndex)) { + return m_entryLayouts[childIndex + m_numberOfColumns]->moveDownInside(cursor); + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { @@ -217,4 +227,9 @@ bool GridLayout::childIsTopOfGrid(int index) const { return index < m_numberOfColumns; } +bool GridLayout::childIsBottomOfGrid(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return index > (m_numberOfRows - 1) * m_numberOfColumns - 1; +} + } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index e3b6d25f2..40cec0ef4 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -18,6 +18,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -34,6 +35,7 @@ private: bool childIsLeftOfGrid(int index) const; bool childIsRightOfGrid(int index) const; bool childIsTopOfGrid(int index) const; + bool childIsBottomOfGrid(int index) const; ExpressionLayout ** m_entryLayouts; int m_numberOfRows; int m_numberOfColumns; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 2635e7648..ddd7b81ea 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -125,36 +125,11 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { } bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - // Prevent looping fom child to parent - if (previousPreviousLayout == this) { - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); - } - // If the cursor Left or Right of a child, try moving it up from its brother. - int previousLayoutIndex = indexOfChild(previousLayout); - if (previousLayoutIndex > -1) { - ExpressionLayout * brother = nullptr; - ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; - if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { - brother = m_children_layouts[previousLayoutIndex - 1]; - newPosition = ExpressionLayoutCursor::Position::Right; - } - if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < m_number_of_children - 1) { - brother = m_children_layouts[previousLayoutIndex + 1]; - newPosition = ExpressionLayoutCursor::Position::Left; - } - if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { - ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); - ExpressionLayoutCursor::Position previousPosition = cursor->position(); - cursor->setPointedExpressionLayout(brother); - cursor->setPosition(newPosition); - if (brother->moveUp(cursor, this, previousLayout)) { - return true; - } - cursor->setPointedExpressionLayout(previousPointedLayout); - cursor->setPosition(previousPosition); - } - } - return ExpressionLayout::moveUp(cursor, previousLayout); + return moveVertically(ExpressionLayout::VerticalDirection::Up, cursor, previousLayout, previousPreviousLayout); +} + +bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, previousLayout, previousPreviousLayout); } void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { @@ -200,6 +175,50 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } +bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Prevent looping fom child to parent + if (previousPreviousLayout == this) { + if (direction == ExpressionLayout::VerticalDirection::Up) { + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + } + assert(direction == ExpressionLayout::VerticalDirection::Down); + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + } + // If the cursor Left or Right of a child, try moving it up from its brother. + int previousLayoutIndex = indexOfChild(previousLayout); + if (previousLayoutIndex > -1) { + ExpressionLayout * brother = nullptr; + ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; + if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { + brother = m_children_layouts[previousLayoutIndex - 1]; + newPosition = ExpressionLayoutCursor::Position::Right; + } + if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < m_number_of_children - 1) { + brother = m_children_layouts[previousLayoutIndex + 1]; + newPosition = ExpressionLayoutCursor::Position::Left; + } + if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { + ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); + ExpressionLayoutCursor::Position previousPosition = cursor->position(); + cursor->setPointedExpressionLayout(brother); + cursor->setPosition(newPosition); + if (direction == ExpressionLayout::VerticalDirection::Up && brother->moveUp(cursor, this, previousLayout)) { + return true; + } + if (direction == ExpressionLayout::VerticalDirection::Down && brother->moveDown(cursor, this, previousLayout)) { + return true; + } + cursor->setPointedExpressionLayout(previousPointedLayout); + cursor->setPosition(previousPosition); + } + } + if (direction == ExpressionLayout::VerticalDirection::Up) { + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + } + assert(direction == ExpressionLayout::VerticalDirection::Down); + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + int HorizontalLayout::indexOfChild(ExpressionLayout * eL) const { if (eL == nullptr) { return -1; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 33f0ba434..8e8eb3750 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -17,12 +17,14 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: + bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); int indexOfChild(ExpressionLayout * eL) const; int m_number_of_children; ExpressionLayout ** m_children_layouts; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index c1e755fc8..82f923ec6 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -134,6 +134,23 @@ bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the upper bound, move it to the lower bound. + if (m_upperBoundLayout && previousLayout == m_upperBoundLayout) { + assert(m_lowerBoundLayout != nullptr); + return m_lowerBoundLayout->moveDownInside(cursor); + } + // If the cursor is Left of the integrand, move it to the lower bound. + if (m_integrandLayout + && previousLayout == m_integrandLayout + && cursor->positionIsEquivalentTo(m_integrandLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_lowerBoundLayout != nullptr); + return m_lowerBoundLayout->moveDownInside(cursor); + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = m_integrandLayout->size(); KDSize upperBoundSize = m_upperBoundLayout->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index d28d98347..f1beceee0 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -19,6 +19,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 238f504b6..47ff1725c 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -146,6 +146,27 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + if (m_indexLayout && previousLayout == m_indexLayout) { + // If the cursor is Right of the index, move it to the radicand. + if (cursor->positionIsEquivalentTo(m_indexLayout, ExpressionLayoutCursor::Position::Right)) { + assert(m_radicandLayout != nullptr); + cursor->setPointedExpressionLayout(m_radicandLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPositionInside(0); + return true; + } + // If the cursor is Left of the index, move it Left . + if (cursor->positionIsEquivalentTo(m_indexLayout, ExpressionLayoutCursor::Position::Left)) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPositionInside(0); + return true; + } + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = m_radicandLayout->size(); KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 14ed3f2f2..7a4432c31 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -19,6 +19,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 535182d6e..8bb66e969 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -123,6 +123,22 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } +bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // If the cursor is inside the upper bound, move it to the lower bound. + if (m_upperBoundLayout && previousLayout == m_upperBoundLayout) { + assert(m_lowerBoundLayout != nullptr); + return m_lowerBoundLayout->moveDownInside(cursor); + } + // If the cursor is Left of the argument, move it to the lower bound. + if (m_argumentLayout + && previousLayout == m_argumentLayout + && cursor->positionIsEquivalentTo(m_argumentLayout, ExpressionLayoutCursor::Position::Left)) + { + assert(m_lowerBoundLayout != nullptr); + return m_lowerBoundLayout->moveDownInside(cursor); + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} KDSize SequenceLayout::computeSize() { KDSize argumentSize = m_argumentLayout->size(); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index aaf9f9bb2..95cf67f5d 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -19,6 +19,7 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; ExpressionLayout * m_lowerBoundLayout; From 0cc1d99a5442569afb686edb94376983eba66a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 12:10:37 +0100 Subject: [PATCH 024/459] [poincare] Static and Dynamic Layout hierarchies. Change-Id: I3b47dbd76552b77db762482932518a74c1996cc0 --- poincare/Makefile | 5 + .../poincare/dynamic_layout_hierarchy.h | 31 ++++ poincare/include/poincare/expression_layout.h | 25 +++- .../poincare/static_layout_hierarchy.h | 31 ++++ poincare/src/absolute_value.cpp | 2 +- poincare/src/binomial_coefficient.cpp | 2 +- poincare/src/ceiling.cpp | 2 +- poincare/src/complex.cpp | 2 +- poincare/src/conjugate.cpp | 2 +- poincare/src/division.cpp | 2 +- poincare/src/factorial.cpp | 2 +- poincare/src/floor.cpp | 2 +- poincare/src/integral.cpp | 2 +- poincare/src/layout/absolute_value_layout.cpp | 10 ++ poincare/src/layout/absolute_value_layout.h | 14 +- .../src/layout/baseline_relative_layout.cpp | 59 +++----- .../src/layout/baseline_relative_layout.h | 20 +-- poincare/src/layout/bracket_layout.cpp | 48 +++--- poincare/src/layout/bracket_layout.h | 16 +- poincare/src/layout/bracket_left_layout.cpp | 5 + poincare/src/layout/bracket_left_layout.h | 1 + .../src/layout/bracket_left_right_layout.cpp | 2 +- .../src/layout/bracket_left_right_layout.h | 11 +- poincare/src/layout/bracket_right_layout.cpp | 5 + poincare/src/layout/bracket_right_layout.h | 1 + poincare/src/layout/ceiling_layout.cpp | 10 ++ poincare/src/layout/ceiling_layout.h | 8 +- poincare/src/layout/condensed_sum_layout.cpp | 130 ++++++++-------- poincare/src/layout/condensed_sum_layout.h | 20 +-- poincare/src/layout/conjugate_layout.cpp | 48 +++--- poincare/src/layout/conjugate_layout.h | 16 +- .../src/layout/dynamic_layout_hierarchy.cpp | 62 ++++++++ .../editable_baseline_relative_layout.cpp | 93 ++++++------ .../editable_baseline_relative_layout.h | 1 + .../src/layout/editable_string_layout.cpp | 5 + poincare/src/layout/editable_string_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 48 +++++- poincare/src/layout/floor_layout.cpp | 10 ++ poincare/src/layout/floor_layout.h | 8 +- poincare/src/layout/fraction_layout.cpp | 88 ++++++----- poincare/src/layout/fraction_layout.h | 18 +-- poincare/src/layout/grid_layout.cpp | 46 ++---- poincare/src/layout/grid_layout.h | 19 +-- poincare/src/layout/horizontal_layout.cpp | 64 ++++---- poincare/src/layout/horizontal_layout.h | 18 +-- poincare/src/layout/integral_layout.cpp | 140 +++++++++--------- poincare/src/layout/integral_layout.h | 20 +-- poincare/src/layout/nth_root_layout.cpp | 130 ++++++++-------- poincare/src/layout/nth_root_layout.h | 18 +-- poincare/src/layout/parenthesis_layout.cpp | 105 +++++++------ poincare/src/layout/parenthesis_layout.h | 20 +-- .../src/layout/parenthesis_left_layout.cpp | 5 + poincare/src/layout/parenthesis_left_layout.h | 3 +- .../layout/parenthesis_left_right_layout.cpp | 2 +- .../layout/parenthesis_left_right_layout.h | 11 +- .../src/layout/parenthesis_right_layout.cpp | 5 + .../src/layout/parenthesis_right_layout.h | 3 +- poincare/src/layout/product_layout.cpp | 15 +- poincare/src/layout/product_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 137 ++++++++--------- poincare/src/layout/sequence_layout.h | 19 +-- .../src/layout/static_layout_hierarchy.cpp | 70 +++++++++ poincare/src/layout/string_layout.cpp | 11 +- poincare/src/layout/string_layout.h | 12 +- poincare/src/layout/sum_layout.cpp | 11 +- poincare/src/layout/sum_layout.h | 1 + poincare/src/layout_engine.cpp | 10 +- poincare/src/logarithm.cpp | 6 +- poincare/src/matrix.cpp | 2 +- poincare/src/nth_root.cpp | 2 +- poincare/src/opposite.cpp | 4 +- poincare/src/parenthesis.cpp | 2 +- poincare/src/power.cpp | 2 +- poincare/src/product.cpp | 2 +- poincare/src/rational.cpp | 2 +- poincare/src/sequence.cpp | 2 +- poincare/src/square_root.cpp | 2 +- poincare/src/store.cpp | 2 +- poincare/src/sum.cpp | 2 +- poincare/src/symbol.cpp | 8 +- 80 files changed, 966 insertions(+), 836 deletions(-) create mode 100644 poincare/include/poincare/dynamic_layout_hierarchy.h create mode 100644 poincare/include/poincare/static_layout_hierarchy.h create mode 100644 poincare/src/layout/absolute_value_layout.cpp create mode 100644 poincare/src/layout/ceiling_layout.cpp create mode 100644 poincare/src/layout/dynamic_layout_hierarchy.cpp create mode 100644 poincare/src/layout/floor_layout.cpp create mode 100644 poincare/src/layout/static_layout_hierarchy.cpp diff --git a/poincare/Makefile b/poincare/Makefile index c778125ba..ba3d233bf 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -83,16 +83,20 @@ objs += $(addprefix poincare/src/,\ ) objs += $(addprefix poincare/src/layout/,\ + absolute_value_layout.o\ baseline_relative_layout.o\ bracket_layout.o\ bracket_left_layout.o\ bracket_left_right_layout.o\ bracket_right_layout.o\ + ceiling_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ + dynamic_layout_hierarchy.o\ editable_baseline_relative_layout.o\ editable_string_layout.o\ expression_layout.o\ + floor_layout.o\ fraction_layout.o\ grid_layout.o\ horizontal_layout.o\ @@ -104,6 +108,7 @@ objs += $(addprefix poincare/src/layout/,\ parenthesis_right_layout.o\ product_layout.o\ sequence_layout.o\ + static_layout_hierarchy.o\ string_layout.o\ sum_layout.o\ ) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h new file mode 100644 index 000000000..ef8053f76 --- /dev/null +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -0,0 +1,31 @@ +#ifndef POINCARE_DYNAMIC_LAYOUT_HIERARCHY_H +#define POINCARE_DYNAMIC_LAYOUT_HIERARCHY_H + +#include + +namespace Poincare { + +class DynamicLayoutHierarchy : public ExpressionLayout { +public: + DynamicLayoutHierarchy(); + DynamicLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); + DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands = true) : + DynamicLayoutHierarchy(ExpressionLayoutArray2(operand1, operand2), 2, cloneOperands) {} + ~DynamicLayoutHierarchy(); + DynamicLayoutHierarchy(const DynamicLayoutHierarchy & other) = delete; + DynamicLayoutHierarchy(DynamicLayoutHierarchy && other) = delete; + DynamicLayoutHierarchy& operator=(const DynamicLayoutHierarchy & other) = delete; + DynamicLayoutHierarchy& operator=(DynamicLayoutHierarchy && other) = delete; + + int numberOfChildren() const override { return m_numberOfChildren; } + const ExpressionLayout * const * children() const override { return m_children; }; + + //bool addChildAtIndex(ExpressionLayout * operand, int index) override; TODO +protected: + const ExpressionLayout ** m_children; + int m_numberOfChildren; +}; + +} + +#endif diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 1381aecf5..141f0f58c 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -13,19 +13,39 @@ public: Up, Down }; + enum class HorizontalDirection { + Left, + Right + }; + /* Constructor & Destructor */ ExpressionLayout(); virtual ~ExpressionLayout() = default; + static const ExpressionLayout * const * ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2); + static const ExpressionLayout * const * ExpressionLayoutArray3(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3); + virtual ExpressionLayout * clone() const = 0; /* Rendering */ void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); KDPoint origin(); KDPoint absoluteOrigin(); KDSize size(); - KDCoordinate baseline(); + KDCoordinate baseline() const { return m_baseline; } /* Hierarchy */ - void setParent(ExpressionLayout* parent); + virtual const ExpressionLayout * const * children() const = 0; + const ExpressionLayout * child(int i) const; + ExpressionLayout * editableChild(int i) { return const_cast(child(i)); } + virtual int numberOfChildren() const = 0; + int indexOfChild(ExpressionLayout * child) const; + + void setParent(ExpressionLayout * parent); + const ExpressionLayout * parent() const { return m_parent; } + ExpressionLayout * editableParent() { return m_parent; } + bool hasAncestor(const ExpressionLayout * e) const; + + /* Dynamic Layout*/ + virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? @@ -37,7 +57,6 @@ public: protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; - virtual ExpressionLayout * child(uint16_t index) = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; KDCoordinate m_baseline; ExpressionLayout * m_parent; diff --git a/poincare/include/poincare/static_layout_hierarchy.h b/poincare/include/poincare/static_layout_hierarchy.h new file mode 100644 index 000000000..daf4bbc2c --- /dev/null +++ b/poincare/include/poincare/static_layout_hierarchy.h @@ -0,0 +1,31 @@ +#ifndef POINCARE_STATIC_LAYOUT_HIERARCHY_H +#define POINCARE_STATIC_LAYOUT_HIERARCHY_H + +#include + +namespace Poincare { + +template +class StaticLayoutHierarchy : public ExpressionLayout { +public: + StaticLayoutHierarchy(); + StaticLayoutHierarchy(const ExpressionLayout * const * operands, bool cloneOperands = true); + StaticLayoutHierarchy(const ExpressionLayout * expression, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<1> + StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> + StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, const ExpressionLayout * expression3, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<3> + ~StaticLayoutHierarchy(); + StaticLayoutHierarchy(const StaticLayoutHierarchy & other) = delete; + StaticLayoutHierarchy(StaticLayoutHierarchy && other) = delete; + StaticLayoutHierarchy& operator=(const StaticLayoutHierarchy & other) = delete; + StaticLayoutHierarchy& operator=(StaticLayoutHierarchy && other) = delete; + + int numberOfChildren() const override { return T; } + const ExpressionLayout * const * children() const override { return m_children; } +protected: + void build(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands); + const ExpressionLayout * m_children[T]; +}; + +} + +#endif diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 62bbe0000..42a523c9c 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -27,7 +27,7 @@ Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUn ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); + return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index dfabebd51..d770e25bf 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -79,7 +79,7 @@ ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode flo ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); - return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); + return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1, false), false); } template diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 3fd5205e4..3e1b551da 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -62,7 +62,7 @@ Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { ExpressionLayout * Ceiling::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new CeilingLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat)); + return new CeilingLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false); } } diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index af44cb656..d4cb71a93 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -465,7 +465,7 @@ ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode fl if (numberOfCharInSuperscript == 0) { return new EditableStringLayout(bufferBase, numberOfCharInBase); } - return new EditableBaselineRelativeLayout(new EditableStringLayout(bufferBase, numberOfCharInBase), new EditableStringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript); + return new EditableBaselineRelativeLayout(new EditableStringLayout(bufferBase, numberOfCharInBase), new EditableStringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript, false); } template diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 0944df809..33f1fe30b 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -22,7 +22,7 @@ Expression * Conjugate::clone() const { ExpressionLayout * Conjugate::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); + return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 032e58feb..d2a4edac4 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -90,7 +90,7 @@ ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMo assert(complexFormat != ComplexFormat::Default); const Expression * numerator = operand(0)->type() == Type::Parenthesis ? operand(0)->operand(0) : operand(0); const Expression * denominator = operand(1)->type() == Type::Parenthesis ? operand(1)->operand(0) : operand(1); - return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat)); + return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat), false); } template Matrix * Division::computeOnComplexAndMatrix(const Complex * c, const Matrix * n) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 3f57bf154..da49dabf0 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -79,7 +79,7 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new EditableStringLayout("!", 1); - return new HorizontalLayout(childrenLayouts, 2); + return new HorizontalLayout(childrenLayouts, 2, false); } int Factorial::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 48892fe5d..987306e77 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -59,7 +59,7 @@ Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { ExpressionLayout * Floor::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new FloorLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat)); + return new FloorLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false); } } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 8fb5ad914..596c838e2 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -62,7 +62,7 @@ ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMo ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("dx", 2); - return new IntegralLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); + return new IntegralLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2, false), false); } template diff --git a/poincare/src/layout/absolute_value_layout.cpp b/poincare/src/layout/absolute_value_layout.cpp new file mode 100644 index 000000000..32fbf72f2 --- /dev/null +++ b/poincare/src/layout/absolute_value_layout.cpp @@ -0,0 +1,10 @@ +#include "absolute_value_layout.h" + +namespace Poincare { + +ExpressionLayout * AbsoluteValueLayout::clone() const { + AbsoluteValueLayout * layout = new AbsoluteValueLayout(const_cast(this)->operandLayout(), true); + return layout; +} + +} diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index 8f31b387c..55691659c 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -7,16 +7,12 @@ namespace Poincare { class AbsoluteValueLayout : public BracketLayout { public: - AbsoluteValueLayout(ExpressionLayout * operandLayout) : BracketLayout(operandLayout) {} - ~AbsoluteValueLayout() {} - AbsoluteValueLayout(const AbsoluteValueLayout& other) = delete; - AbsoluteValueLayout(AbsoluteValueLayout&& other) = delete; - AbsoluteValueLayout& operator=(const AbsoluteValueLayout& other) = delete; - AbsoluteValueLayout& operator=(AbsoluteValueLayout&& other) = delete; + using BracketLayout::BracketLayout; + ExpressionLayout * clone() const override; protected: - KDCoordinate widthMargin() const { return 2; } - bool renderTopBar() const { return false; } - bool renderBottomBar() const { return false; } + KDCoordinate widthMargin() const override { return 2; } + bool renderTopBar() const override { return false; } + bool renderBottomBar() const override { return false; } }; } diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 4b553d116..0e5b23439 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -5,29 +5,17 @@ namespace Poincare { -BaselineRelativeLayout::BaselineRelativeLayout(ExpressionLayout * baseLayout, ExpressionLayout * indiceLayout, Type type) : - ExpressionLayout(), - m_baseLayout(baseLayout), - m_indiceLayout(indiceLayout), +BaselineRelativeLayout::BaselineRelativeLayout(ExpressionLayout * base, ExpressionLayout * indice, Type type, bool cloneOperands) : + StaticLayoutHierarchy(base, indice, cloneOperands), m_type(type) { - m_baseLayout->setParent(this); - m_indiceLayout->setParent(this); - m_baseline = type == Type::Subscript ? m_baseLayout->baseline() : - m_indiceLayout->size().height() + m_baseLayout->baseline() - k_indiceHeight; + m_baseline = type == Type::Subscript ? baseLayout()->baseline() : + indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; } -BaselineRelativeLayout::~BaselineRelativeLayout() { - delete m_baseLayout; - delete m_indiceLayout; -} - -ExpressionLayout * BaselineRelativeLayout::baseLayout() { - return m_baseLayout; -} - -ExpressionLayout * BaselineRelativeLayout::indiceLayout() { - return m_indiceLayout; +ExpressionLayout * BaselineRelativeLayout::clone() const { + BaselineRelativeLayout * layout = new BaselineRelativeLayout(const_cast(this)->baseLayout(), const_cast(this)->indiceLayout(), m_type, true); + return layout; } bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -64,37 +52,34 @@ bool BaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +ExpressionLayout * BaselineRelativeLayout::baseLayout() { + return editableChild(0); +} + +ExpressionLayout * BaselineRelativeLayout::indiceLayout() { + return editableChild(1); +} + void BaselineRelativeLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // There is nothing to draw for a subscript/superscript, only the position of the children matters } KDSize BaselineRelativeLayout::computeSize() { - KDSize baseSize = m_baseLayout->size(); - KDSize indiceSize = m_indiceLayout->size(); + KDSize baseSize = baseLayout()->size(); + KDSize indiceSize = indiceLayout()->size(); return KDSize(baseSize.width() + indiceSize.width(), baseSize.height() + indiceSize.height() - k_indiceHeight); } -ExpressionLayout * BaselineRelativeLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_baseLayout; - case 1: - return m_indiceLayout; - default: - return nullptr; - } -} - KDPoint BaselineRelativeLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - if (child == m_baseLayout && m_type == Type::Superscript) { + if (child == baseLayout() && m_type == Type::Superscript) { x = 0; - y = m_indiceLayout->size().height() - k_indiceHeight; + y = indiceLayout()->size().height() - k_indiceHeight; } - if (child == m_indiceLayout) { - x = m_baseLayout->size().width(); - y = m_type == Type::Superscript ? 0 : m_baseLayout->size().height() - k_indiceHeight; + if (child == indiceLayout()) { + x = baseLayout()->size().width(); + y = m_type == Type::Superscript ? 0 : baseLayout()->size().height() - k_indiceHeight; } return KDPoint(x,y); } diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index 1b75f6822..8ef335015 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -1,34 +1,26 @@ #ifndef POINCARE_BASELINE_RELATIVE_LAYOUT_H #define POINCARE_BASELINE_RELATIVE_LAYOUT_H -#include -#include +#include namespace Poincare { -class BaselineRelativeLayout : public ExpressionLayout { +class BaselineRelativeLayout : public StaticLayoutHierarchy<2> { public: enum class Type { Subscript, Superscript }; - BaselineRelativeLayout(ExpressionLayout * baseLayout, ExpressionLayout * indiceLayout, Type type); - ~BaselineRelativeLayout(); - BaselineRelativeLayout(const BaselineRelativeLayout& other) = delete; - BaselineRelativeLayout(BaselineRelativeLayout&& other) = delete; - BaselineRelativeLayout& operator=(const BaselineRelativeLayout& other) = delete; - BaselineRelativeLayout& operator=(BaselineRelativeLayout&& other) = delete; - ExpressionLayout * baseLayout(); - ExpressionLayout * indiceLayout(); + BaselineRelativeLayout(ExpressionLayout * base, ExpressionLayout * indice, Type type, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: + ExpressionLayout * baseLayout(); + ExpressionLayout * indiceLayout(); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; - ExpressionLayout * m_baseLayout; - ExpressionLayout * m_indiceLayout; Type m_type; private: constexpr static KDCoordinate k_indiceHeight = 5; diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 1b369ec5a..487d1e2b0 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -7,23 +7,22 @@ extern "C" { namespace Poincare { -BracketLayout::BracketLayout(ExpressionLayout * operandLayout) : - ExpressionLayout(), - m_operandLayout(operandLayout) +BracketLayout::BracketLayout(ExpressionLayout * operandLayout, bool cloneOperands) : + StaticLayoutHierarchy<1>(operandLayout, cloneOperands) { - m_operandLayout->setParent(this); - m_baseline = m_operandLayout->baseline(); + m_baseline = operandLayout->baseline(); } -BracketLayout::~BracketLayout() { - delete m_operandLayout; +ExpressionLayout * BracketLayout::clone() const { + BracketLayout * layout = new BracketLayout(const_cast(this)->operandLayout(), true); + return layout; } bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the operand. // Go Left of the brackets. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -33,8 +32,8 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right of the brackets. // Go Right of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); @@ -49,8 +48,8 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the operand. // Go Right of the brackets. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -60,8 +59,8 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left of the brackets. // Go Left of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); @@ -74,12 +73,16 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +ExpressionLayout * BracketLayout::operandLayout() { + return editableChild(0); +} + void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); - KDSize operandSize = m_operandLayout->size(); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, m_operandLayout->size().height()), expressionColor); + KDSize operandSize = operandLayout()->size(); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, operandLayout()->size().height()), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, operandLayout()->size().height()), expressionColor); if (renderTopBar()) { ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); @@ -93,17 +96,10 @@ void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDSize BracketLayout::computeSize() { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); - KDSize operandSize = m_operandLayout->size(); + KDSize operandSize = operandLayout()->size(); return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height()); } -ExpressionLayout * BracketLayout::child(uint16_t index) { - if (index == 0) { - return m_operandLayout; - } - return nullptr; -} - KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index e2f6c926b..977095632 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -1,34 +1,28 @@ #ifndef POINCARE_BRACKET_LAYOUT_H #define POINCARE_BRACKET_LAYOUT_H -#include -#include +#include namespace Poincare { -class BracketLayout : public ExpressionLayout { +class BracketLayout : public StaticLayoutHierarchy<1> { public: - BracketLayout(ExpressionLayout * operandLayout); - ~BracketLayout(); - BracketLayout(const BracketLayout& other) = delete; - BracketLayout(BracketLayout&& other) = delete; - BracketLayout& operator=(const BracketLayout& other) = delete; - BracketLayout& operator=(BracketLayout&& other) = delete; + BracketLayout(ExpressionLayout * operandLayout, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: + ExpressionLayout * operandLayout(); KDCoordinate externWidthMargin() const { return 2; } virtual KDCoordinate widthMargin() const { return 5; } virtual bool renderTopBar() const { return true; } virtual bool renderBottomBar() const { return true; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayout * m_operandLayout; }; } diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/bracket_left_layout.cpp index f9024923e..07d4cb95e 100644 --- a/poincare/src/layout/bracket_left_layout.cpp +++ b/poincare/src/layout/bracket_left_layout.cpp @@ -2,6 +2,11 @@ namespace Poincare { +ExpressionLayout * BracketLeftLayout::clone() const { + BracketLeftLayout * layout = new BracketLeftLayout(); + return layout; +} + void BracketLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { //TODO Make sure m_operandHeight is up-to-date. ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index ce025ec99..8f46d06d9 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class BracketLeftLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; + ExpressionLayout * clone() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index 95c26bade..70701274d 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -8,7 +8,7 @@ extern "C" { namespace Poincare { BracketLeftRightLayout::BracketLeftRightLayout() : - ExpressionLayout(), + StaticLayoutHierarchy<0>(), m_operandHeight(36) //TODO { } diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 6cc309184..1c9527e1b 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -1,19 +1,13 @@ #ifndef POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H #define POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H -#include -#include +#include namespace Poincare { -class BracketLeftRightLayout : public ExpressionLayout { +class BracketLeftRightLayout : public StaticLayoutHierarchy<0> { public: BracketLeftRightLayout(); - ~BracketLeftRightLayout() {} - BracketLeftRightLayout(const BracketLeftRightLayout& other) = delete; - BracketLeftRightLayout(BracketLeftRightLayout&& other) = delete; - BracketLeftRightLayout& operator=(const BracketLeftRightLayout& other) = delete; - BracketLeftRightLayout& operator=(BracketLeftRightLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_bracketWidth = 5; @@ -22,7 +16,6 @@ public: constexpr static KDCoordinate k_externWidthMargin = 2; protected: KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override { return nullptr; } KDPoint positionOfChild(ExpressionLayout * child) override; uint16_t m_operandHeight; }; diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp index 3eac6ba5e..86c43e66f 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -2,6 +2,11 @@ namespace Poincare { +ExpressionLayout * BracketRightLayout::clone() const { + BracketRightLayout * layout = new BracketRightLayout(); + return layout; +} + void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { //TODO Make sure m_operandHeight is up-to-date. ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index a9d9c7c79..f2c25186a 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class BracketRightLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; + ExpressionLayout * clone() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/ceiling_layout.cpp b/poincare/src/layout/ceiling_layout.cpp new file mode 100644 index 000000000..0e04baf2b --- /dev/null +++ b/poincare/src/layout/ceiling_layout.cpp @@ -0,0 +1,10 @@ +#include "ceiling_layout.h" + +namespace Poincare { + +ExpressionLayout * CeilingLayout::clone() const { + CeilingLayout * layout = new CeilingLayout(const_cast(this)->operandLayout(), true); + return layout; +} + +} diff --git a/poincare/src/layout/ceiling_layout.h b/poincare/src/layout/ceiling_layout.h index 6fe8d60a8..1dd170093 100644 --- a/poincare/src/layout/ceiling_layout.h +++ b/poincare/src/layout/ceiling_layout.h @@ -7,12 +7,8 @@ namespace Poincare { class CeilingLayout : public BracketLayout { public: - CeilingLayout(ExpressionLayout * operandLayout) : BracketLayout(operandLayout) {} - ~CeilingLayout() {} - CeilingLayout(const CeilingLayout& other) = delete; - CeilingLayout(CeilingLayout&& other) = delete; - CeilingLayout& operator=(const CeilingLayout& other) = delete; - CeilingLayout& operator=(CeilingLayout&& other) = delete; + using BracketLayout::BracketLayout; + ExpressionLayout * clone() const override; protected: bool renderBottomBar() const override { return false; } }; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index e1a73f1c2..d696cb170 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -5,34 +5,23 @@ namespace Poincare { -CondensedSumLayout::CondensedSumLayout(ExpressionLayout * baseLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) : - ExpressionLayout(), - m_baseLayout(baseLayout), - m_subscriptLayout(subscriptLayout), - m_superscriptLayout(superscriptLayout) +CondensedSumLayout::CondensedSumLayout(ExpressionLayout * base, ExpressionLayout * subscript, ExpressionLayout * superscript, bool cloneOperands) : + StaticLayoutHierarchy<3>(base, subscript, superscript, cloneOperands) { - m_baseLayout->setParent(this); - m_subscriptLayout->setParent(this); - if (m_superscriptLayout) { - m_superscriptLayout->setParent(this); - } - KDSize superscriptSize = m_superscriptLayout == nullptr ? KDSizeZero : m_superscriptLayout->size(); - m_baseline = m_baseLayout->baseline() + max(0, superscriptSize.height() - m_baseLayout->size().height()/2); + KDSize superscriptSize = superscriptLayout() == nullptr ? KDSizeZero : superscriptLayout()->size(); + m_baseline = baseLayout()->baseline() + max(0, superscriptSize.height() - baseLayout()->size().height()/2); } -CondensedSumLayout::~CondensedSumLayout() { - delete m_baseLayout; - delete m_subscriptLayout; - if (m_superscriptLayout) { - delete m_superscriptLayout; - } +ExpressionLayout * CondensedSumLayout::clone() const { + CondensedSumLayout * layout = new CondensedSumLayout(const_cast(this)->baseLayout(), const_cast(this)->subscriptLayout(), const_cast(this)->superscriptLayout(), true); + return layout; } bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the bounds. // Go Left of the sum. - if (((m_subscriptLayout && cursor->pointedExpressionLayout() == m_subscriptLayout) - || (m_superscriptLayout && cursor->pointedExpressionLayout() == m_superscriptLayout)) + if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) + || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -41,11 +30,11 @@ bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: Left of the base. // Go Right of the lower bound. - if (m_baseLayout - && cursor->pointedExpressionLayout() == m_baseLayout + if (baseLayout() + && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(m_subscriptLayout); + cursor->setPointedExpressionLayout(subscriptLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -53,9 +42,9 @@ bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the base and move Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_baseLayout); - cursor->setPointedExpressionLayout(m_baseLayout); - return m_baseLayout->moveLeft(cursor); + assert(baseLayout()); + cursor->setPointedExpressionLayout(baseLayout()); + return baseLayout()->moveLeft(cursor); } // Case: Left. // Ask the parent. @@ -69,19 +58,19 @@ bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the bounds. // Go Left of the operand. - if (((m_subscriptLayout && cursor->pointedExpressionLayout() == m_subscriptLayout) - || (m_superscriptLayout && cursor->pointedExpressionLayout() == m_superscriptLayout)) + if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) + || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_baseLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); + assert(baseLayout() != nullptr); + cursor->setPointedExpressionLayout(baseLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Right of the base. // Ask the parent. - if (m_baseLayout - && cursor->pointedExpressionLayout() == m_baseLayout + if (baseLayout() + && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -95,8 +84,8 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_superscriptLayout); - cursor->setPointedExpressionLayout(m_superscriptLayout); + assert(superscriptLayout()); + cursor->setPointedExpressionLayout(superscriptLayout()); return true; } // Case: Right. @@ -110,34 +99,34 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the subscript layout, move it to the superscript. - if (m_subscriptLayout && previousLayout == m_subscriptLayout) { - assert(m_superscriptLayout != nullptr); - return m_superscriptLayout->moveUpInside(cursor); + if (subscriptLayout() && previousLayout == subscriptLayout()) { + assert(superscriptLayout() != nullptr); + return superscriptLayout()->moveUpInside(cursor); } // If the cursor is Left of the base layout, move it to the superscript. - if (m_baseLayout - && previousLayout == m_baseLayout - && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Left)) + if (baseLayout() + && previousLayout == baseLayout() + && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_superscriptLayout != nullptr); - return m_superscriptLayout->moveUpInside(cursor); + assert(superscriptLayout() != nullptr); + return superscriptLayout()->moveUpInside(cursor); } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the superscript layout, move it to the subscript. - if (m_superscriptLayout && previousLayout == m_superscriptLayout) { - assert(m_subscriptLayout != nullptr); - return m_subscriptLayout->moveUpInside(cursor); + if (superscriptLayout() && previousLayout == superscriptLayout()) { + assert(subscriptLayout() != nullptr); + return subscriptLayout()->moveUpInside(cursor); } // If the cursor is Left of the base layout, move it to the subscript. - if (m_baseLayout - && previousLayout == m_baseLayout - && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Left)) + if (baseLayout() + && previousLayout == baseLayout() + && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_subscriptLayout != nullptr); - return m_subscriptLayout->moveUpInside(cursor); + assert(subscriptLayout() != nullptr); + return subscriptLayout()->moveUpInside(cursor); } return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } @@ -147,42 +136,41 @@ void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCo } KDSize CondensedSumLayout::computeSize() { - KDSize baseSize = m_baseLayout->size(); - KDSize subscriptSize = m_subscriptLayout->size(); - KDSize superscriptSize = m_superscriptLayout == nullptr ? KDSizeZero : m_superscriptLayout->size(); + KDSize baseSize = baseLayout()->size(); + KDSize subscriptSize = subscriptLayout()->size(); + KDSize superscriptSize = superscriptLayout() == nullptr ? KDSizeZero : superscriptLayout()->size(); return KDSize(baseSize.width() + max(subscriptSize.width(), superscriptSize.width()), max(baseSize.height()/2, subscriptSize.height()) + max(baseSize.height()/2, superscriptSize.height())); } -ExpressionLayout * CondensedSumLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_baseLayout; - case 1: - return m_subscriptLayout; - case 2: - return m_superscriptLayout; - default: - return nullptr; - } -} - KDPoint CondensedSumLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - KDSize baseSize = m_baseLayout->size(); - KDSize superscriptSize = m_superscriptLayout == nullptr ? KDSizeZero : m_superscriptLayout->size(); - if (child == m_baseLayout) { + KDSize baseSize = baseLayout()->size(); + KDSize superscriptSize = superscriptLayout() == nullptr ? KDSizeZero : superscriptLayout()->size(); + if (child == baseLayout()) { y = max(0, superscriptSize.height() - baseSize.height()/2); } - if (child == m_subscriptLayout) { + if (child == subscriptLayout()) { x = baseSize.width(); y = max(baseSize.height()/2, superscriptSize.height()); } - if (child == m_superscriptLayout) { + if (child == superscriptLayout()) { x = baseSize.width(); } return KDPoint(x,y); } +ExpressionLayout * CondensedSumLayout::baseLayout() { + return editableChild(0); +} + +ExpressionLayout * CondensedSumLayout::subscriptLayout() { + return editableChild(1); +} + +ExpressionLayout * CondensedSumLayout::superscriptLayout() { + return editableChild(2); +} + } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 1d15dc1c3..16528e6c7 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -1,19 +1,14 @@ #ifndef POINCARE_CONDENSED_SUM_LAYOUT_H #define POINCARE_CONDENSED_SUM_LAYOUT_H -#include -#include +#include namespace Poincare { -class CondensedSumLayout : public ExpressionLayout { +class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: - CondensedSumLayout(ExpressionLayout * baseLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout = nullptr); - ~CondensedSumLayout(); - CondensedSumLayout(const CondensedSumLayout& other) = delete; - CondensedSumLayout(CondensedSumLayout&& other) = delete; - CondensedSumLayout& operator=(const CondensedSumLayout& other) = delete; - CondensedSumLayout& operator=(CondensedSumLayout&& other) = delete; + CondensedSumLayout(ExpressionLayout * base, ExpressionLayout * subscript, ExpressionLayout * superscript, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; @@ -21,12 +16,11 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - ExpressionLayout * m_baseLayout; - ExpressionLayout * m_subscriptLayout; - ExpressionLayout * m_superscriptLayout; + ExpressionLayout * baseLayout(); + ExpressionLayout * subscriptLayout(); + ExpressionLayout * superscriptLayout(); }; } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 18844c96f..db289ce45 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -7,23 +7,22 @@ extern "C" { namespace Poincare { -ConjugateLayout::ConjugateLayout(ExpressionLayout * operandLayout) : - ExpressionLayout(), - m_operandLayout(operandLayout) +ConjugateLayout::ConjugateLayout(ExpressionLayout * operand, bool cloneOperands) : + StaticLayoutHierarchy<1>(operand, cloneOperands) { - m_operandLayout->setParent(this); - m_baseline = m_operandLayout->baseline()+k_overlineWidth+k_overlineMargin; + m_baseline = operandLayout()->baseline()+k_overlineWidth+k_overlineMargin; } -ConjugateLayout::~ConjugateLayout() { - delete m_operandLayout; +ExpressionLayout * ConjugateLayout::clone() const { + ConjugateLayout * layout = new ConjugateLayout(const_cast(this)->operandLayout(), true); + return layout; } bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the operand. // Ask the parent. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -36,9 +35,9 @@ bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the operand and move Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); - return m_operandLayout->moveLeft(cursor); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); + return operandLayout()->moveLeft(cursor); } // Case: Left. // Ask the parent. @@ -52,8 +51,8 @@ bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the operand. // Ask the parent. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -66,9 +65,9 @@ bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go to the operand and move Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); - return m_operandLayout->moveRight(cursor); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); + return operandLayout()->moveRight(cursor); } // Case: Right. // Ask the parent. @@ -80,24 +79,21 @@ bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { } void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - ctx->fillRect(KDRect(p.x(), p.y(), m_operandLayout->size().width(), k_overlineWidth), expressionColor); + ctx->fillRect(KDRect(p.x(), p.y(), operandLayout()->size().width(), k_overlineWidth), expressionColor); } KDSize ConjugateLayout::computeSize() { - KDSize operandSize = m_operandLayout->size(); + KDSize operandSize = operandLayout()->size(); return KDSize(operandSize.width(), operandSize.height()+k_overlineWidth+k_overlineMargin); } -ExpressionLayout * ConjugateLayout::child(uint16_t index) { - if (index == 0) { - return m_operandLayout; - } - return nullptr; -} - KDPoint ConjugateLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(0, k_overlineWidth+k_overlineMargin); } +ExpressionLayout * ConjugateLayout::operandLayout() { + return editableChild(0); +} + } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 6e1030c88..15834cce4 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -1,30 +1,24 @@ #ifndef POINCARE_CONJUGATE_LAYOUT_H #define POINCARE_CONJUGATE_LAYOUT_H -#include -#include +#include namespace Poincare { -class ConjugateLayout : public ExpressionLayout { +class ConjugateLayout : public StaticLayoutHierarchy<1> { public: - ConjugateLayout(ExpressionLayout * operandLayout); - ~ConjugateLayout(); - ConjugateLayout(const ConjugateLayout& other) = delete; - ConjugateLayout(ConjugateLayout&& other) = delete; - ConjugateLayout& operator=(const ConjugateLayout& other) = delete; - ConjugateLayout& operator=(ConjugateLayout&& other) = delete; + ConjugateLayout(ExpressionLayout * operand, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_overlineWidth = 1; constexpr static KDCoordinate k_overlineMargin = 3; - ExpressionLayout * m_operandLayout; + ExpressionLayout * operandLayout(); }; } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp new file mode 100644 index 000000000..09106b617 --- /dev/null +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -0,0 +1,62 @@ +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +DynamicLayoutHierarchy::DynamicLayoutHierarchy() : + ExpressionLayout(), + m_children(nullptr), + m_numberOfChildren(0) +{ +} + +DynamicLayoutHierarchy::DynamicLayoutHierarchy(const ExpressionLayout * const * children, int numberOfChildren, bool cloneChildren) : + ExpressionLayout(), + m_numberOfChildren(numberOfChildren) +{ + assert(children != nullptr); + m_children = new const ExpressionLayout * [numberOfChildren]; + for (int i=0; iclone(); + } else { + m_children[i] = children[i]; + } + const_cast(m_children[i])->setParent(this); + } +} + +DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { + if (m_children != nullptr) { + for (int i = 0; i < m_numberOfChildren; i++) { + if (m_children[i] != nullptr) { + delete m_children[i]; + } + } + } + delete[] m_children; +} + +/*bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index) { + assert(index >= 0 && index <= m_numberOfChildren); + const ExpressionLayout ** newChildren = new const ExpressionLayout * [m_numberOfChildren+1]; + int j = 0; + for (int i=0; i<=m_numberOfChildren; i++) { + if (i == index) { + child->setParent(this); + newChildren[i] = child; + } else { + newChildren[i] = m_children[j++]; + } + } + delete[] m_children; + m_children = newChildren; + m_numberOfChildren += 1; + return true; +}*/ //TODO + +} diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp index b06e27449..e5b0d29c1 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -5,22 +5,27 @@ namespace Poincare { +ExpressionLayout * EditableBaselineRelativeLayout::clone() const { + EditableBaselineRelativeLayout * layout = new EditableBaselineRelativeLayout(const_cast(this)->baseLayout(), const_cast(this)->indiceLayout(), m_type, true); + return layout; +} + bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the indice. // Go from the indice to the base. - if (m_indiceLayout - && cursor->pointedExpressionLayout() == m_indiceLayout + if (indiceLayout() + && cursor->pointedExpressionLayout() == indiceLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_baseLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); + assert(baseLayout() != nullptr); + cursor->setPointedExpressionLayout(baseLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } // Case: Left of the base. // Ask the parent. - if (m_baseLayout - && cursor->pointedExpressionLayout() == m_baseLayout + if (baseLayout() + && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -33,8 +38,8 @@ bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the indice. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); return true; } // Case: Left. @@ -49,19 +54,19 @@ bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool EditableBaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the base. // Go from the base to the indice. - if (m_baseLayout - && cursor->pointedExpressionLayout() == m_baseLayout + if (baseLayout() + && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Right of the indice. // Go Right. - if (m_indiceLayout - && cursor->pointedExpressionLayout() == m_indiceLayout + if (indiceLayout() + && cursor->pointedExpressionLayout() == indiceLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -71,9 +76,9 @@ bool EditableBaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) // Case: Left. // Go to the base and move Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_baseLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); - return m_baseLayout->moveRight(cursor); + assert(baseLayout() != nullptr); + cursor->setPointedExpressionLayout(baseLayout()); + return baseLayout()->moveRight(cursor); } // Case: Right. // Ask the parent. @@ -89,20 +94,20 @@ bool EditableBaselineRelativeLayout::moveUp(ExpressionLayoutCursor * cursor, Exp // If the baseline is a superscript: if (m_type == BaselineRelativeLayout::Type::Superscript) { // If the cursor is Right of the base layout, move it to the indice. - if (m_baseLayout - && previousLayout == m_baseLayout - && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Right)) + if (baseLayout() + && previousLayout == baseLayout() + && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Right)) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); cursor->setPositionInside(0); return true; } // If the cursor is Right, move it to the indice. if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); return true; @@ -110,19 +115,19 @@ bool EditableBaselineRelativeLayout::moveUp(ExpressionLayoutCursor * cursor, Exp } // If the baseline is a subscript: if (m_type == BaselineRelativeLayout::Type::Subscript - && m_indiceLayout - && previousLayout == m_indiceLayout) + && indiceLayout() + && previousLayout == indiceLayout()) { // If the cursor is Left of the indice layout, move it to the base. - if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Left)) { - assert(m_baseLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); + if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left)) { + assert(baseLayout() != nullptr); + cursor->setPointedExpressionLayout(baseLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); return true; } // If the cursor is Right of the indice layout, move it Right. - if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Right)) { + if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right)) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); @@ -136,20 +141,20 @@ bool EditableBaselineRelativeLayout::moveDown(ExpressionLayoutCursor * cursor, E // If the baseline is a subscript: if (m_type == BaselineRelativeLayout::Type::Subscript) { // If the cursor is Right of the base layout, move it to the indice. - if (m_baseLayout - && previousLayout == m_baseLayout - && cursor->positionIsEquivalentTo(m_baseLayout, ExpressionLayoutCursor::Position::Right)) + if (baseLayout() + && previousLayout == baseLayout() + && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Right)) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); cursor->setPositionInside(0); return true; } // If the cursor is Right, move it to the indice. if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_indiceLayout); + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); return true; @@ -157,20 +162,20 @@ bool EditableBaselineRelativeLayout::moveDown(ExpressionLayoutCursor * cursor, E } // If the baseline is a superscript: if (m_type == BaselineRelativeLayout::Type::Superscript - && m_indiceLayout - && previousLayout == m_indiceLayout) + && indiceLayout() + && previousLayout == indiceLayout()) { // If the cursor is Left of the indice layout, move it to the base. - if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Left)) { - assert(m_indiceLayout != nullptr); - cursor->setPointedExpressionLayout(m_baseLayout); + if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left)) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(baseLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); return true; } // If the cursor is Right of the indice layout, move it Right. - if (cursor->positionIsEquivalentTo(m_indiceLayout, ExpressionLayoutCursor::Position::Right)) { - assert(m_indiceLayout != nullptr); + if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right)) { + assert(indiceLayout() != nullptr); cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h index 72ef5aa4a..22c5c968f 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class EditableBaselineRelativeLayout : public BaselineRelativeLayout { public: using BaselineRelativeLayout::BaselineRelativeLayout; + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/editable_string_layout.cpp b/poincare/src/layout/editable_string_layout.cpp index 1dfd613b8..951989192 100644 --- a/poincare/src/layout/editable_string_layout.cpp +++ b/poincare/src/layout/editable_string_layout.cpp @@ -5,6 +5,11 @@ namespace Poincare { +ExpressionLayout * EditableStringLayout::clone() const { + EditableStringLayout * layout = new EditableStringLayout(m_string, strlen(m_string), m_fontSize); + return layout; +} + bool EditableStringLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. diff --git a/poincare/src/layout/editable_string_layout.h b/poincare/src/layout/editable_string_layout.h index 75e8b77d9..147cb1622 100644 --- a/poincare/src/layout/editable_string_layout.h +++ b/poincare/src/layout/editable_string_layout.h @@ -9,6 +9,7 @@ namespace Poincare { class EditableStringLayout : public StringLayout { public: using StringLayout::StringLayout; + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; private: diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 630b1c61e..6defb6e39 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,6 +1,6 @@ #include #include -#include "string_layout.h" +#include #include #include @@ -14,8 +14,19 @@ ExpressionLayout::ExpressionLayout() : m_frame(KDRectZero) { } -KDCoordinate ExpressionLayout::baseline() { - return m_baseline; +const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2) { + static const ExpressionLayout * result[2] = {nullptr, nullptr}; + result[0] = e1; + result[1] = e2; + return result; +} + +const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray3(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3) { + static const ExpressionLayout * result[3] = {nullptr, nullptr, nullptr}; + result[0] = e1; + result[1] = e2; + result[2] = e3; + return result; } KDPoint ExpressionLayout::origin() { @@ -29,7 +40,7 @@ KDPoint ExpressionLayout::origin() { void ExpressionLayout::draw(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { int i = 0; - while (ExpressionLayout * c = child(i++)) { + while (ExpressionLayout * c = editableChild(i++)) { c->draw(ctx, p, expressionColor, backgroundColor); } render(ctx, absoluteOrigin().translatedBy(p), expressionColor, backgroundColor); @@ -55,10 +66,37 @@ KDSize ExpressionLayout::size() { return m_frame.size(); } +const ExpressionLayout * ExpressionLayout::child(int i) const { + assert(i >= 0); + assert(i < numberOfChildren()); + assert(children()[i]->parent() == nullptr || children()[i]->parent() == this); + return children()[i]; +} + +int ExpressionLayout::indexOfChild(ExpressionLayout * child) const { + for (int i = 0; i < numberOfChildren(); i++) { + if (children()[i] == child) { + return i; + } + } + return -1; +} + void ExpressionLayout::setParent(ExpressionLayout* parent) { m_parent = parent; } +bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { + assert(m_parent != this); + if (m_parent == e) { + return true; + } + if (m_parent == nullptr) { + return false; + } + return m_parent->hasAncestor(e); +} + bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (m_parent) { return m_parent->moveUp(cursor, this, previousLayout); @@ -137,7 +175,7 @@ void ExpressionLayout::moveCursorInsideAtDirection ( if (layoutIsUnderOrAbove || layoutContains) { int childIndex = 0; while (child(childIndex++)) { - child(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultPositionInside, resultScore); + editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultPositionInside, resultScore); } } } diff --git a/poincare/src/layout/floor_layout.cpp b/poincare/src/layout/floor_layout.cpp new file mode 100644 index 000000000..598cfea39 --- /dev/null +++ b/poincare/src/layout/floor_layout.cpp @@ -0,0 +1,10 @@ +#include "floor_layout.h" + +namespace Poincare { + +ExpressionLayout * FloorLayout::clone() const { + FloorLayout * layout = new FloorLayout(const_cast(this)->operandLayout(), true); + return layout; +} + +} diff --git a/poincare/src/layout/floor_layout.h b/poincare/src/layout/floor_layout.h index 17c994eb5..1bfb7e8f3 100644 --- a/poincare/src/layout/floor_layout.h +++ b/poincare/src/layout/floor_layout.h @@ -7,12 +7,8 @@ namespace Poincare { class FloorLayout : public BracketLayout { public: - FloorLayout(ExpressionLayout * operandLayout) : BracketLayout(operandLayout) {} - ~FloorLayout() {} - FloorLayout(const FloorLayout& other) = delete; - FloorLayout(FloorLayout&& other) = delete; - FloorLayout& operator=(const FloorLayout& other) = delete; - FloorLayout& operator=(FloorLayout&& other) = delete; + using BracketLayout::BracketLayout; + ExpressionLayout * clone() const override; protected: bool renderTopBar() const override { return false; } }; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 4191504ab..41d4ec315 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -5,24 +5,23 @@ namespace Poincare { -FractionLayout::FractionLayout(ExpressionLayout * numerator_layout, ExpressionLayout * denominator_layout) : -ExpressionLayout(), m_numerator_layout(numerator_layout), m_denominator_layout(denominator_layout) { - m_numerator_layout->setParent(this); - m_denominator_layout->setParent(this); - m_baseline = m_numerator_layout->size().height() +FractionLayout::FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator, bool cloneOperands) : + StaticLayoutHierarchy<2>(numerator, denominator, cloneOperands) +{ + m_baseline = numeratorLayout()->size().height() + k_fractionLineMargin + k_fractionLineHeight; } -FractionLayout::~FractionLayout() { - delete m_denominator_layout; - delete m_numerator_layout; +ExpressionLayout * FractionLayout::clone() const { + FractionLayout * layout = new FractionLayout(const_cast(this)->numeratorLayout(), const_cast(this)->denominatorLayout(), true); + return layout; } bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the numerator or the denominator. // Go Left of the fraction. - if (((m_numerator_layout && cursor->pointedExpressionLayout() == m_numerator_layout) - || (m_denominator_layout && cursor->pointedExpressionLayout() == m_denominator_layout)) + if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) + || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -32,8 +31,8 @@ bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the denominator. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_denominator_layout != nullptr); - cursor->setPointedExpressionLayout(m_denominator_layout); + assert(denominatorLayout() != nullptr); + cursor->setPointedExpressionLayout(denominatorLayout()); return true; } // Case: Left. @@ -48,8 +47,8 @@ bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the numerator or the denominator. // Go Right of the fraction. - if (((m_numerator_layout && cursor->pointedExpressionLayout() == m_numerator_layout) - || (m_denominator_layout && cursor->pointedExpressionLayout() == m_denominator_layout)) + if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) + || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -59,8 +58,8 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go to the numerator. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_numerator_layout != nullptr); - cursor->setPointedExpressionLayout(m_numerator_layout); + assert(numeratorLayout() != nullptr); + cursor->setPointedExpressionLayout(numeratorLayout()); return true; } // Case: Right. @@ -74,69 +73,66 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside denominator, move it to the numerator. - if (m_denominator_layout && previousLayout == m_denominator_layout) { - assert(m_numerator_layout != nullptr); - return m_numerator_layout->moveUpInside(cursor); + if (denominatorLayout() && previousLayout == denominatorLayout()) { + assert(numeratorLayout() != nullptr); + return numeratorLayout()->moveUpInside(cursor); } // If the cursor is Left or Right, move it to the numerator. if (cursor->pointedExpressionLayout() == this){ - assert(m_numerator_layout != nullptr); - return m_numerator_layout->moveUpInside(cursor); + assert(numeratorLayout() != nullptr); + return numeratorLayout()->moveUpInside(cursor); } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside numerator, move it to the denominator. - if (m_numerator_layout && previousLayout == m_numerator_layout) { - assert(m_denominator_layout != nullptr); - return m_denominator_layout->moveDownInside(cursor); + if (numeratorLayout() && previousLayout == numeratorLayout()) { + assert(denominatorLayout() != nullptr); + return denominatorLayout()->moveDownInside(cursor); } // If the cursor is Left or Right, move it to the denominator. if (cursor->pointedExpressionLayout() == this){ - assert(m_denominator_layout != nullptr); - return m_denominator_layout->moveDownInside(cursor); + assert(denominatorLayout() != nullptr); + return denominatorLayout()->moveDownInside(cursor); } return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDCoordinate fractionLineY = p.y() + m_numerator_layout->size().height() + k_fractionLineMargin; + KDCoordinate fractionLineY = p.y() + numeratorLayout()->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); } KDSize FractionLayout::computeSize() { - KDCoordinate width = max(m_numerator_layout->size().width(), m_denominator_layout->size().width()) + KDCoordinate width = max(numeratorLayout()->size().width(), denominatorLayout()->size().width()) + 2*k_fractionBorderLength+2*k_fractionBorderMargin; - KDCoordinate height = m_numerator_layout->size().height() + KDCoordinate height = numeratorLayout()->size().height() + k_fractionLineMargin + k_fractionLineHeight + k_fractionLineMargin - + m_denominator_layout->size().height(); + + denominatorLayout()->size().height(); return KDSize(width, height); } -ExpressionLayout * FractionLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_numerator_layout; - case 1: - return m_denominator_layout; - default: - return nullptr; - } -} - KDPoint FractionLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - if (child == m_numerator_layout) { - x = (KDCoordinate)((size().width() - m_numerator_layout->size().width())/2); - } else if (child == m_denominator_layout) { - x = (KDCoordinate)((size().width() - m_denominator_layout->size().width())/2); - y = (KDCoordinate)(m_numerator_layout->size().height() + 2*k_fractionLineMargin + k_fractionLineHeight); + if (child == numeratorLayout()) { + x = (KDCoordinate)((size().width() - numeratorLayout()->size().width())/2); + } else if (child == denominatorLayout()) { + x = (KDCoordinate)((size().width() - denominatorLayout()->size().width())/2); + y = (KDCoordinate)(numeratorLayout()->size().height() + 2*k_fractionLineMargin + k_fractionLineHeight); } else { assert(false); // Should not happen } return KDPoint(x, y); } +ExpressionLayout * FractionLayout::numeratorLayout() { + return editableChild(0); +} + +ExpressionLayout * FractionLayout::denominatorLayout() { + return editableChild(1); +} + } diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 97dd6043a..13154045b 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -1,19 +1,14 @@ #ifndef POINCARE_FRACTION_LAYOUT_H #define POINCARE_FRACTION_LAYOUT_H -#include -#include +#include namespace Poincare { -class FractionLayout : public ExpressionLayout { +class FractionLayout : public StaticLayoutHierarchy<2> { public: - FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator); - ~FractionLayout(); - FractionLayout(const FractionLayout& other) = delete; - FractionLayout(FractionLayout&& other) = delete; - FractionLayout& operator=(const FractionLayout& other) = delete; - FractionLayout& operator=(FractionLayout&& other) = delete; + FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; @@ -21,15 +16,14 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_fractionBorderLength = 2; constexpr static KDCoordinate k_fractionBorderMargin = 2; constexpr static KDCoordinate k_fractionLineMargin = 2; constexpr static KDCoordinate k_fractionLineHeight = 2; - ExpressionLayout * m_numerator_layout; - ExpressionLayout * m_denominator_layout; + ExpressionLayout * numeratorLayout(); + ExpressionLayout * denominatorLayout(); }; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 075854b95..c379c5883 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -7,24 +7,17 @@ extern "C" { namespace Poincare { -GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns) : - ExpressionLayout(), +GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands) : + DynamicLayoutHierarchy(entryLayouts, numberOfRows*numberOfColumns, cloneOperands), m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { - m_entryLayouts = new ExpressionLayout *[numberOfColumns*numberOfRows]; - for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { - m_entryLayouts[i] = entryLayouts[i]; - m_entryLayouts[i]->setParent(this); - } m_baseline = (height()+1)/2; } -GridLayout::~GridLayout() { - for (int i=0; i(children()), m_numberOfRows, m_numberOfColumns, true); + return layout; } bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -33,7 +26,7 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { - ExpressionLayout * lastChild = m_entryLayouts[m_numberOfColumns*m_numberOfRows-1]; + ExpressionLayout * lastChild = editableChild(m_numberOfColumns*m_numberOfRows-1); assert(lastChild != nullptr); cursor->setPointedExpressionLayout(lastChild); return true; @@ -50,7 +43,7 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: Left of another child. // Go Right of its brother on the left. - cursor->setPointedExpressionLayout(m_entryLayouts[childIndex-1]); + cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -70,7 +63,7 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { && cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(m_numberOfColumns*m_numberOfRows >= 1); - ExpressionLayout * firstChild = m_entryLayouts[0]; + ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); cursor->setPointedExpressionLayout(firstChild); return true; @@ -87,7 +80,7 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { } // Case: Right of another child. // Go Left of its brother on the right. - cursor->setPointedExpressionLayout(m_entryLayouts[childIndex+1]); + cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } @@ -105,7 +98,7 @@ bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * prev // neighbourg. int childIndex = indexOfChild(previousLayout); if (childIndex >- 1 && !childIsTopOfGrid(childIndex)) { - return m_entryLayouts[childIndex - m_numberOfColumns]->moveUpInside(cursor); + return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor); } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } @@ -115,7 +108,7 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * pr // lower neighbourg. int childIndex = indexOfChild(previousLayout); if (childIndex >- 1 && !childIsBottomOfGrid(childIndex)) { - return m_entryLayouts[childIndex + m_numberOfColumns]->moveDownInside(cursor); + return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor); } return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } @@ -123,7 +116,7 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * pr KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { - rowBaseline = max(rowBaseline, m_entryLayouts[i*m_numberOfColumns+j]->baseline()); + rowBaseline = max(rowBaseline, child(i*m_numberOfColumns+j)->baseline()); } return rowBaseline; } @@ -132,7 +125,7 @@ KDCoordinate GridLayout::rowHeight(int i) { KDCoordinate rowHeight = 0; KDCoordinate baseline = rowBaseline(i); for (int j = 0; j < m_numberOfColumns; j++) { - rowHeight = max(rowHeight, m_entryLayouts[i*m_numberOfColumns+j]->size().height() - m_entryLayouts[i*m_numberOfColumns+j]->baseline()); + rowHeight = max(rowHeight, editableChild(i*m_numberOfColumns+j)->size().height() - child(i*m_numberOfColumns+j)->baseline()); } return baseline+rowHeight; } @@ -149,7 +142,7 @@ KDCoordinate GridLayout::height() { KDCoordinate GridLayout::columnWidth(int j) { KDCoordinate columnWidth = 0; for (int i = 0; i < m_numberOfRows; i++) { - columnWidth = max(columnWidth, m_entryLayouts[i*m_numberOfColumns+j]->size().width()); + columnWidth = max(columnWidth, editableChild(i*m_numberOfColumns+j)->size().width()); } return columnWidth; } @@ -171,19 +164,12 @@ KDSize GridLayout::computeSize() { return KDSize(width(), height()); } -ExpressionLayout * GridLayout::child(uint16_t index) { - if (index < m_numberOfColumns*m_numberOfRows) { - return m_entryLayouts[index]; - } - return nullptr; -} - KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { int rowIndex = 0; int columnIndex = 0; for (int i = 0; i < m_numberOfRows; i++) { for (int j = 0; j < m_numberOfColumns; j++) { - if (child == m_entryLayouts[i*m_numberOfColumns+j]) { + if (child == editableChild(i*m_numberOfColumns+j)) { rowIndex = i; columnIndex = j; break; @@ -205,7 +191,7 @@ KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { int GridLayout::indexOfChild(ExpressionLayout * eL) const { for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { - if (eL == m_entryLayouts[i]) { + if (eL == child(i)) { return i; } } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 40cec0ef4..ce48b66e6 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -1,28 +1,24 @@ #ifndef POINCARE_GRID_LAYOUT_H #define POINCARE_GRID_LAYOUT_H -#include -#include +#include namespace Poincare { -class GridLayout : public ExpressionLayout { - //TODO Split it in MatrixLayout and BinomialCoefficientayout. +class GridLayout : public DynamicLayoutHierarchy { public: - GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns); - ~GridLayout(); - GridLayout(const GridLayout& other) = delete; - GridLayout(GridLayout&& other) = delete; - GridLayout& operator=(const GridLayout& other) = delete; - GridLayout& operator=(GridLayout&& other) = delete; + GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); + ExpressionLayout * clone() const override; + + /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_gridEntryMargin = 6; @@ -36,7 +32,6 @@ private: bool childIsRightOfGrid(int index) const; bool childIsTopOfGrid(int index) const; bool childIsBottomOfGrid(int index) const; - ExpressionLayout ** m_entryLayouts; int m_numberOfRows; int m_numberOfColumns; }; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index ddd7b81ea..8f6ac75ba 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -10,24 +10,19 @@ extern "C" { namespace Poincare { -HorizontalLayout::HorizontalLayout(ExpressionLayout ** children_layouts, int number_of_children) : - ExpressionLayout(), m_number_of_children(number_of_children) { - assert(number_of_children > 0); - m_children_layouts = new ExpressionLayout *[number_of_children]; - for (int i=0; isetParent(this); - if (m_children_layouts[i]->baseline() > m_baseline) { - m_baseline = m_children_layouts[i]->baseline(); +HorizontalLayout::HorizontalLayout(ExpressionLayout ** childrenLayouts, int childrenCount, bool cloneOperands) : + DynamicLayoutHierarchy(childrenLayouts, childrenCount, cloneOperands) +{ + for (int i = 0; i < numberOfChildren(); i++) { + if (child(i)->baseline() > m_baseline) { + m_baseline = child(i)->baseline(); } } } -HorizontalLayout::~HorizontalLayout() { - for (int i=0; i(children()), numberOfChildren(), true); + return layout; } bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -44,14 +39,14 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the last child if there is one, and move Left. // Else go Left and ask the parent. - if (m_number_of_children < 1) { + if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->moveLeft(cursor); } return false; } - ExpressionLayout * lastChild = m_children_layouts[m_number_of_children-1]; + ExpressionLayout * lastChild = editableChild(numberOfChildren()-1); assert(lastChild != nullptr); cursor->setPointedExpressionLayout(lastChild); return lastChild->moveLeft(cursor); @@ -72,9 +67,9 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: the child is not the leftmost. // Go to its left brother and move Left. - cursor->setPointedExpressionLayout(m_children_layouts[childIndex-1]); + cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_children_layouts[childIndex-1]->moveLeft(cursor); + return editableChild(childIndex-1)->moveLeft(cursor); } bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { @@ -91,14 +86,14 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go to the first child if there is one, and move Right. // Else go Right and ask the parent. - if (m_number_of_children < 1) { + if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { return m_parent->moveRight(cursor); } return false; } - ExpressionLayout * firstChild = m_children_layouts[0]; + ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); cursor->setPointedExpressionLayout(firstChild); return firstChild->moveRight(cursor); @@ -108,7 +103,7 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { assert(cursor->position() == ExpressionLayoutCursor::Position::Right); int childIndex = indexOfChild(cursor->pointedExpressionLayout()); assert(childIndex >= 0); - if (childIndex == m_number_of_children - 1) { + if (childIndex == numberOfChildren() - 1) { // Case: the child is the rightmost. // Ask the parent. cursor->setPointedExpressionLayout(this); @@ -119,9 +114,9 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { } // Case: the child is not the rightmost. // Go to its right brother and move Right. - cursor->setPointedExpressionLayout(m_children_layouts[childIndex+1]); + cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_children_layouts[childIndex+1]->moveRight(cursor); + return editableChild(childIndex+1)->moveRight(cursor); } bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { @@ -140,7 +135,7 @@ KDSize HorizontalLayout::computeSize() { int i = 0; KDCoordinate max_under_baseline = 0; KDCoordinate max_above_baseline = 0; - while (ExpressionLayout * c = child(i++)) { + while (ExpressionLayout * c = editableChild(i++)) { KDSize childSize = c->size(); totalWidth += childSize.width(); if (childSize.height() - c->baseline() > max_under_baseline) { @@ -153,21 +148,12 @@ KDSize HorizontalLayout::computeSize() { return KDSize(totalWidth, max_under_baseline + max_above_baseline); } -ExpressionLayout * HorizontalLayout::child(uint16_t index) { - assert(index <= (unsigned int) m_number_of_children); - if (index < (unsigned int) m_number_of_children) { - return m_children_layouts[index]; - } else { - return nullptr; - } -} - KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; int index = indexOfChild(child); if (index > 0) { - ExpressionLayout * previousChild = m_children_layouts[index-1]; + ExpressionLayout * previousChild = editableChild(index-1); assert(previousChild != nullptr); x = previousChild->origin().x() + previousChild->size().width(); } @@ -190,11 +176,11 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct ExpressionLayout * brother = nullptr; ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { - brother = m_children_layouts[previousLayoutIndex - 1]; + brother = editableChild(previousLayoutIndex - 1); newPosition = ExpressionLayoutCursor::Position::Right; } - if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < m_number_of_children - 1) { - brother = m_children_layouts[previousLayoutIndex + 1]; + if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < numberOfChildren() - 1) { + brother = editableChild(previousLayoutIndex + 1); newPosition = ExpressionLayoutCursor::Position::Left; } if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { @@ -223,8 +209,8 @@ int HorizontalLayout::indexOfChild(ExpressionLayout * eL) const { if (eL == nullptr) { return -1; } - for (int i = 0; i < m_number_of_children; i++) { - if (m_children_layouts[i] == eL) { + for (int i = 0; i < numberOfChildren(); i++) { + if (child(i) == eL) { return i; } } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 8e8eb3750..561d8a9ea 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -1,19 +1,16 @@ #ifndef POINCARE_HORIZONTAL_LAYOUT_H #define POINCARE_HORIZONTAL_LAYOUT_H -#include -#include +#include namespace Poincare { -class HorizontalLayout : public ExpressionLayout { +class HorizontalLayout : public DynamicLayoutHierarchy { public: - HorizontalLayout(ExpressionLayout ** layouts, int number_of_children); - ~HorizontalLayout(); - HorizontalLayout(const HorizontalLayout& other) = delete; - HorizontalLayout(HorizontalLayout&& other) = delete; - HorizontalLayout& operator=(const HorizontalLayout& other) = delete; - HorizontalLayout& operator=(HorizontalLayout&& other) = delete; + HorizontalLayout(ExpressionLayout ** layouts, int childrenCount, bool cloneOperands); + ExpressionLayout * clone() const override; + + /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; @@ -21,13 +18,10 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); int indexOfChild(ExpressionLayout * eL) const; - int m_number_of_children; - ExpressionLayout ** m_children_layouts; }; } diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 82f923ec6..727e477f0 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -19,31 +19,24 @@ const uint8_t bottomSymbolPixel[IntegralLayout::k_symbolHeight][IntegralLayout:: {0xFF, 0xFF, 0x00, 0x00}, }; -IntegralLayout::IntegralLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * integrandLayout) : - ExpressionLayout(), - m_lowerBoundLayout(lowerBoundLayout), - m_upperBoundLayout(upperBoundLayout), - m_integrandLayout(integrandLayout) +IntegralLayout::IntegralLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * integrand, bool cloneOperands) : + StaticLayoutHierarchy<3>(upperBound, lowerBound, integrand, cloneOperands) { - m_lowerBoundLayout->setParent(this); - m_upperBoundLayout->setParent(this); - m_integrandLayout->setParent(this); - m_baseline = m_upperBoundLayout->size().height() + k_integrandHeigthMargin + m_integrandLayout->baseline(); + m_baseline = upperBoundLayout()->size().height() + k_integrandHeigthMargin + integrandLayout()->baseline(); } -IntegralLayout::~IntegralLayout() { - delete m_lowerBoundLayout; - delete m_upperBoundLayout; - delete m_integrandLayout; +ExpressionLayout * IntegralLayout::clone() const { + IntegralLayout * layout = new IntegralLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->integrandLayout(), true); + return layout; } bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left the upper or lower bound. // Go Left of the integral. - if (((m_upperBoundLayout - && cursor->pointedExpressionLayout() == m_upperBoundLayout) - || (m_lowerBoundLayout - && cursor->pointedExpressionLayout() == m_lowerBoundLayout)) + if (((upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()) + || (lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -51,12 +44,12 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: Left the integrand. // Go Right of the lower bound. - if (m_integrandLayout - && cursor->pointedExpressionLayout() == m_integrandLayout + if (integrandLayout() + && cursor->pointedExpressionLayout() == integrandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_lowerBoundLayout != nullptr); - cursor->setPointedExpressionLayout(m_lowerBoundLayout); + assert(lowerBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(lowerBoundLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -64,9 +57,9 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right of the integral. // Go Right of the integrand, Left of "dx". if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_integrandLayout != nullptr); - cursor->setPointedExpressionLayout(m_integrandLayout); - return m_integrandLayout->moveLeft(cursor); + assert(integrandLayout() != nullptr); + cursor->setPointedExpressionLayout(integrandLayout()); + return integrandLayout()->moveLeft(cursor); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. @@ -80,21 +73,21 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right the upper or lower bound. // Go Left of the integrand. - if (((m_upperBoundLayout - && cursor->pointedExpressionLayout() == m_upperBoundLayout) - || (m_lowerBoundLayout - && cursor->pointedExpressionLayout() == m_lowerBoundLayout)) + if (((upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()) + || (lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_integrandLayout != nullptr); - cursor->setPointedExpressionLayout(m_integrandLayout); + assert(integrandLayout() != nullptr); + cursor->setPointedExpressionLayout(integrandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Right the integrand. // Go Right and move Right. - if (m_integrandLayout - && cursor->pointedExpressionLayout() == m_integrandLayout + if (integrandLayout() + && cursor->pointedExpressionLayout() == integrandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -104,8 +97,8 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left of the integral. // Go ti the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_upperBoundLayout != nullptr); - cursor->setPointedExpressionLayout(m_upperBoundLayout); + assert(upperBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(upperBoundLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); @@ -119,41 +112,41 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (m_lowerBoundLayout && previousLayout == m_lowerBoundLayout) { - assert(m_upperBoundLayout != nullptr); - return m_upperBoundLayout->moveUpInside(cursor); + if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { + assert(upperBoundLayout() != nullptr); + return upperBoundLayout()->moveUpInside(cursor); } // If the cursor is Left of the integrand, move it to the upper bound. - if (m_integrandLayout - && previousLayout == m_integrandLayout - && cursor->positionIsEquivalentTo(m_integrandLayout, ExpressionLayoutCursor::Position::Left)) + if (integrandLayout() + && previousLayout == integrandLayout() + && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_upperBoundLayout != nullptr); - return m_upperBoundLayout->moveUpInside(cursor); + assert(upperBoundLayout() != nullptr); + return upperBoundLayout()->moveUpInside(cursor); } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (m_upperBoundLayout && previousLayout == m_upperBoundLayout) { - assert(m_lowerBoundLayout != nullptr); - return m_lowerBoundLayout->moveDownInside(cursor); + if (upperBoundLayout() && previousLayout == upperBoundLayout()) { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout()->moveDownInside(cursor); } // If the cursor is Left of the integrand, move it to the lower bound. - if (m_integrandLayout - && previousLayout == m_integrandLayout - && cursor->positionIsEquivalentTo(m_integrandLayout, ExpressionLayoutCursor::Position::Left)) + if (integrandLayout() + && previousLayout == integrandLayout() + && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_lowerBoundLayout != nullptr); - return m_lowerBoundLayout->moveDownInside(cursor); + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout()->moveDownInside(cursor); } return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDSize integrandSize = m_integrandLayout->size(); - KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize integrandSize = integrandLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; KDRect topSymbolFrame(p.x() + k_symbolWidth + k_lineThickness, p.y() + upperBoundSize.height() - k_boundHeightMargin, k_symbolWidth, k_symbolHeight); @@ -167,40 +160,27 @@ void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, } KDSize IntegralLayout::computeSize() { - KDSize integrandSize = m_integrandLayout->size(); - KDSize lowerBoundSize = m_lowerBoundLayout->size(); - KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize integrandSize = integrandLayout()->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( k_symbolWidth+k_lineThickness+k_boundWidthMargin+max(lowerBoundSize.width(), upperBoundSize.width())+k_integrandWidthMargin+integrandSize.width(), upperBoundSize.height()+ 2*k_integrandHeigthMargin+integrandSize.height()+lowerBoundSize.height()); } -ExpressionLayout * IntegralLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_upperBoundLayout; - case 1: - return m_lowerBoundLayout; - case 2: - return m_integrandLayout; - default: - return nullptr; - } -} - KDPoint IntegralLayout::positionOfChild(ExpressionLayout * child) { - KDSize integrandSize = m_integrandLayout->size(); - KDSize lowerBoundSize = m_lowerBoundLayout->size(); - KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize integrandSize = integrandLayout()->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); KDCoordinate x = 0; KDCoordinate y = 0; - if (child == m_lowerBoundLayout) { + if (child == lowerBoundLayout()) { x = k_symbolWidth+k_lineThickness+k_boundWidthMargin; y = upperBoundSize.height()+2*k_integrandHeigthMargin+integrandSize.height(); - } else if (child == m_upperBoundLayout) { + } else if (child == upperBoundLayout()) { x = k_symbolWidth+k_lineThickness+k_boundWidthMargin;; y = 0; - } else if (child == m_integrandLayout) { + } else if (child == integrandLayout()) { x = k_symbolWidth +k_lineThickness+ k_boundWidthMargin+max(lowerBoundSize.width(), upperBoundSize.width())+k_integrandWidthMargin; y = upperBoundSize.height()+k_integrandHeigthMargin; } else { @@ -209,4 +189,16 @@ KDPoint IntegralLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x,y); } +ExpressionLayout * IntegralLayout::upperBoundLayout() { + return editableChild(0); +} + +ExpressionLayout * IntegralLayout::lowerBoundLayout() { + return editableChild(1); +} + +ExpressionLayout * IntegralLayout::integrandLayout() { + return editableChild(2); +} + } diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index f1beceee0..067cc7cea 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -1,21 +1,16 @@ #ifndef POINCARE_INTEGRAL_LAYOUT_H #define POINCARE_INTEGRAL_LAYOUT_H -#include -#include +#include namespace Poincare { -class IntegralLayout : public ExpressionLayout { +class IntegralLayout : public StaticLayoutHierarchy<3> { public: - IntegralLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * integrandLayout); - ~IntegralLayout(); - IntegralLayout(const IntegralLayout& other) = delete; - IntegralLayout(IntegralLayout&& other) = delete; - IntegralLayout& operator=(const IntegralLayout& other) = delete; - IntegralLayout& operator=(IntegralLayout&& other) = delete; constexpr static KDCoordinate k_symbolHeight = 4; constexpr static KDCoordinate k_symbolWidth = 4; + IntegralLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * integrand, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; @@ -23,7 +18,6 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_boundHeightMargin = 8; @@ -31,9 +25,9 @@ private: constexpr static KDCoordinate k_integrandWidthMargin = 2; constexpr static KDCoordinate k_integrandHeigthMargin = 2; constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayout * m_lowerBoundLayout; - ExpressionLayout * m_upperBoundLayout; - ExpressionLayout * m_integrandLayout; + ExpressionLayout * lowerBoundLayout(); + ExpressionLayout * upperBoundLayout(); + ExpressionLayout * integrandLayout(); }; } diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 47ff1725c..89a3c59a4 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -16,37 +16,31 @@ const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_left {0xFF, 0xFF, 0xFF, 0xFF, 0x00}, }; -NthRootLayout::NthRootLayout(ExpressionLayout * radicandLayout, ExpressionLayout * indexLayout) : - ExpressionLayout(), - m_radicandLayout(radicandLayout), - m_indexLayout(indexLayout) +NthRootLayout::NthRootLayout(ExpressionLayout * radicand, ExpressionLayout * index, bool cloneOperands) : + StaticLayoutHierarchy<2>(radicand, index, cloneOperands) { - m_radicandLayout->setParent(this); - if (m_indexLayout != nullptr) { - m_indexLayout->setParent(this); - m_baseline = max(m_radicandLayout->baseline() + k_radixLineThickness + k_heightMargin, - m_indexLayout->size().height() + k_indexHeight); + if (indexLayout() != nullptr) { + m_baseline = max(radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin, + indexLayout()->size().height() + k_indexHeight); } else { - m_baseline = m_radicandLayout->baseline() + k_radixLineThickness + k_heightMargin; + m_baseline = radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin; } } -NthRootLayout::~NthRootLayout() { - delete m_radicandLayout; - if (m_indexLayout != nullptr) { - delete m_indexLayout; - } +ExpressionLayout * NthRootLayout::clone() const { + NthRootLayout * layout = new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); + return layout; } bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the radicand. // Go the index if there is one, else go Left of the root. - if (m_radicandLayout - && cursor->pointedExpressionLayout() == m_radicandLayout + if (radicandLayout() + && cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - if (m_indexLayout) { - cursor->setPointedExpressionLayout(m_indexLayout); + if (indexLayout()) { + cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -55,8 +49,8 @@ bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: Left of the index. // Go Left of the root. - if (m_indexLayout - && cursor->pointedExpressionLayout() == m_indexLayout + if (indexLayout() + && cursor->pointedExpressionLayout() == indexLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -66,8 +60,8 @@ bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go Right of the radicand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_radicandLayout != nullptr); - cursor->setPointedExpressionLayout(m_radicandLayout); + assert(radicandLayout() != nullptr); + cursor->setPointedExpressionLayout(radicandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); @@ -82,8 +76,8 @@ bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the radicand. // Go the Right of the root. - if (m_radicandLayout - && cursor->pointedExpressionLayout() == m_radicandLayout + if (radicandLayout() + && cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -91,12 +85,12 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { } // Case: Right of the index. // Go Left of the integrand. - if (m_indexLayout - && cursor->pointedExpressionLayout() == m_indexLayout + if (indexLayout() + && cursor->pointedExpressionLayout() == indexLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_radicandLayout != nullptr); - cursor->setPointedExpressionLayout(m_radicandLayout); + assert(radicandLayout() != nullptr); + cursor->setPointedExpressionLayout(radicandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } @@ -104,12 +98,12 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go index if there is one, else go to the radicand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - if (m_indexLayout) { - cursor->setPointedExpressionLayout(m_indexLayout); + if (indexLayout()) { + cursor->setPointedExpressionLayout(indexLayout()); return true; } - assert(m_radicandLayout != nullptr); - cursor->setPointedExpressionLayout(m_radicandLayout); + assert(radicandLayout() != nullptr); + cursor->setPointedExpressionLayout(radicandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); @@ -123,12 +117,12 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is Left of the radicand, move it to the index. - if (m_radicandLayout - && previousLayout == m_radicandLayout - && cursor->positionIsEquivalentTo(m_radicandLayout, ExpressionLayoutCursor::Position::Left)) + if (radicandLayout() + && previousLayout == radicandLayout() + && cursor->positionIsEquivalentTo(radicandLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_indexLayout != nullptr); - cursor->setPointedExpressionLayout(m_indexLayout); + assert(indexLayout() != nullptr); + cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); cursor->setPositionInside(0); return true; @@ -137,8 +131,8 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_indexLayout != nullptr); - cursor->setPointedExpressionLayout(m_indexLayout); + assert(indexLayout() != nullptr); + cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); cursor->setPositionInside(0); return true; @@ -147,17 +141,17 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p } bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - if (m_indexLayout && previousLayout == m_indexLayout) { + if (indexLayout() && previousLayout == indexLayout()) { // If the cursor is Right of the index, move it to the radicand. - if (cursor->positionIsEquivalentTo(m_indexLayout, ExpressionLayoutCursor::Position::Right)) { - assert(m_radicandLayout != nullptr); - cursor->setPointedExpressionLayout(m_radicandLayout); + if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { + assert(radicandLayout() != nullptr); + cursor->setPointedExpressionLayout(radicandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); cursor->setPositionInside(0); return true; } // If the cursor is Left of the index, move it Left . - if (cursor->positionIsEquivalentTo(m_indexLayout, ExpressionLayoutCursor::Position::Left)) { + if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Left)) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); cursor->setPositionInside(0); @@ -168,24 +162,24 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * } void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDSize radicandSize = m_radicandLayout->size(); - KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); + KDSize radicandSize = radicandLayout()->size(); + KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); KDColor workingBuffer[k_leftRadixWidth*k_leftRadixHeight]; KDRect leftRadixFrame(p.x() + indexSize.width() + k_widthMargin - k_leftRadixWidth, - p.y() + m_baseline + radicandSize.height() - m_radicandLayout->baseline() + k_heightMargin - k_leftRadixHeight, + p.y() + m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, k_leftRadixWidth, k_leftRadixHeight); ctx->blendRectWithMask(leftRadixFrame, expressionColor, (const uint8_t *)radixPixel, (KDColor *)workingBuffer); - if (indexSize.height() + k_indexHeight > m_radicandLayout->baseline() + k_radixLineThickness + k_heightMargin) { + if (indexSize.height() + k_indexHeight > radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin) { ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, - p.y() + indexSize.height() + k_indexHeight - m_radicandLayout->baseline() - k_radixLineThickness - k_heightMargin, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, k_radixLineThickness, radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, - p.y() + indexSize.height() + k_indexHeight - m_radicandLayout->baseline() - k_radixLineThickness - k_heightMargin, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, radicandSize.width() + 2*k_widthMargin, k_radixLineThickness), expressionColor); ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin, - p.y() + indexSize.height() + k_indexHeight - m_radicandLayout->baseline() - k_radixLineThickness - k_heightMargin, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, k_radixLineThickness, k_rightRadixHeight + k_radixLineThickness), expressionColor); } else { @@ -206,40 +200,36 @@ void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, } KDSize NthRootLayout::computeSize() { - KDSize radicandSize = m_radicandLayout->size(); - KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); + KDSize radicandSize = radicandLayout()->size(); + KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); return KDSize( indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width(), - m_baseline + radicandSize.height() - m_radicandLayout->baseline() + k_heightMargin + m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin ); } -ExpressionLayout * NthRootLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_radicandLayout; - case 1: - return m_indexLayout; - default: - return nullptr; - } -} - KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - KDSize indexSize = m_indexLayout != nullptr ? m_indexLayout->size() : KDSize(k_leftRadixWidth,0); - if (child == m_indexLayout) { + KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); + if (child == indexLayout()) { x = 0; y = m_baseline - indexSize.height() - k_indexHeight; - } else if (child == m_radicandLayout) { + } else if (child == radicandLayout()) { x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; - y = m_baseline - m_radicandLayout->baseline(); + y = m_baseline - radicandLayout()->baseline(); } else { assert(false); } return KDPoint(x,y); } +ExpressionLayout * NthRootLayout::radicandLayout() { + return editableChild(0); } +ExpressionLayout * NthRootLayout::indexLayout() { + return editableChild(1); +} + +} diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 7a4432c31..d942b3863 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -1,21 +1,16 @@ #ifndef POINCARE_NTH_ROOT_LAYOUT_H #define POINCARE_NTH_ROOT_LAYOUT_H -#include -#include +#include namespace Poincare { -class NthRootLayout : public ExpressionLayout { +class NthRootLayout : public StaticLayoutHierarchy<2> { public: - NthRootLayout(ExpressionLayout * radicandLayout, ExpressionLayout * indexLayout); - ~NthRootLayout(); - NthRootLayout(const NthRootLayout& other) = delete; - NthRootLayout(NthRootLayout&& other) = delete; - NthRootLayout& operator=(const NthRootLayout& other) = delete; - NthRootLayout& operator=(NthRootLayout&& other) = delete; constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; + NthRootLayout(ExpressionLayout * radicand, ExpressionLayout * index, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; @@ -23,7 +18,6 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_rightRadixHeight = 2; @@ -31,8 +25,8 @@ private: constexpr static KDCoordinate k_heightMargin = 2; constexpr static KDCoordinate k_widthMargin = 1; constexpr static KDCoordinate k_radixLineThickness = 1; - ExpressionLayout * m_radicandLayout; - ExpressionLayout * m_indexLayout; + ExpressionLayout * radicandLayout(); + ExpressionLayout * indexLayout(); }; } diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index 6c9fa5ed4..eccab7030 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -9,40 +9,36 @@ extern "C" { namespace Poincare { -ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operandLayout) : - ExpressionLayout(), - m_operandLayout(operandLayout) +ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operand, bool cloneOperands) : + StaticLayoutHierarchy<3>() { - m_leftParenthesisLayout = new ParenthesisLeftLayout(); - m_rightParenthesisLayout = new ParenthesisRightLayout(); - m_operandLayout->setParent(this); - m_leftParenthesisLayout->setParent(this); - m_rightParenthesisLayout->setParent(this); - m_baseline = m_operandLayout->baseline(); + ExpressionLayout * leftParenthesis = new ParenthesisLeftLayout(); + ExpressionLayout * rightParenthesis = new ParenthesisRightLayout(); + build(ExpressionLayout::ExpressionLayoutArray3(leftParenthesis, operand, rightParenthesis), 3, cloneOperands); + m_baseline = operandLayout()->baseline(); } -ParenthesisLayout::~ParenthesisLayout() { - delete m_operandLayout; - delete m_rightParenthesisLayout; - delete m_leftParenthesisLayout; +ExpressionLayout * ParenthesisLayout::clone() const { + ParenthesisLayout * layout = new ParenthesisLayout(const_cast(this)->operandLayout(), true); + return layout; } bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the Right parenthesis. // Go to the operand and move left. - if (m_rightParenthesisLayout - && cursor->pointedExpressionLayout() == m_rightParenthesisLayout + if (rightParenthesisLayout() + && cursor->pointedExpressionLayout() == rightParenthesisLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_operandLayout->moveLeft(cursor); + return operandLayout()->moveLeft(cursor); } // Case: Left of the operand. // Go Left. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -50,8 +46,8 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { } // Case: Left of the Left parenthesis. // Ask the parent. - if (m_leftParenthesisLayout - && cursor->pointedExpressionLayout() == m_leftParenthesisLayout + if (leftParenthesisLayout() + && cursor->pointedExpressionLayout() == leftParenthesisLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); @@ -65,8 +61,8 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right of the parentheses. // Go Right of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); @@ -81,19 +77,19 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the Left parenthesis. // Go to the operand and move Right. - if (m_leftParenthesisLayout - && cursor->pointedExpressionLayout() == m_leftParenthesisLayout + if (leftParenthesisLayout() + && cursor->pointedExpressionLayout() == leftParenthesisLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_operandLayout->moveRight(cursor); + return operandLayout()->moveRight(cursor); } // Case: Right of the operand. // Go Right. - if (m_operandLayout - && cursor->pointedExpressionLayout() == m_operandLayout + if (operandLayout() + && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -101,8 +97,8 @@ bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { } // Case: Right of the Right parenthesis. // Ask the parent. - if (m_rightParenthesisLayout - && cursor->pointedExpressionLayout() == m_rightParenthesisLayout + if (rightParenthesisLayout() + && cursor->pointedExpressionLayout() == rightParenthesisLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); @@ -116,8 +112,8 @@ bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left of the parentheses. // Go Left of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_operandLayout != nullptr); - cursor->setPointedExpressionLayout(m_operandLayout); + assert(operandLayout() != nullptr); + cursor->setPointedExpressionLayout(operandLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); @@ -130,35 +126,34 @@ bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { } KDSize ParenthesisLayout::computeSize() { - KDSize operandSize = m_operandLayout->size(); - return KDSize(operandSize.width() + 2*m_leftParenthesisLayout->size().width(), operandSize.height()); -} - -ExpressionLayout * ParenthesisLayout::child(uint16_t index) { - if (index == 0) { - return m_leftParenthesisLayout; - } - if (index == 1) { - return m_operandLayout; - } - if (index == 2) { - return m_rightParenthesisLayout; - } - return nullptr; + KDSize operandSize = operandLayout()->size(); + return KDSize(operandSize.width() + 2*leftParenthesisLayout()->size().width(), operandSize.height()); } KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { - if (child == m_leftParenthesisLayout) { + if (child == leftParenthesisLayout()) { return KDPoint(0, 0); } - if (child == m_operandLayout) { - return KDPoint(m_leftParenthesisLayout->size().width(), 0); + if (child == operandLayout()) { + return KDPoint(leftParenthesisLayout()->size().width(), 0); } - if (child == m_rightParenthesisLayout) { - return KDPoint(m_operandLayout->origin().x() + m_operandLayout->size().width(), 0); + if (child == rightParenthesisLayout()) { + return KDPoint(operandLayout()->origin().x() + operandLayout()->size().width(), 0); } assert(false); return KDPointZero; } +ExpressionLayout * ParenthesisLayout::operandLayout() { + return editableChild(1); +} + +ExpressionLayout * ParenthesisLayout::leftParenthesisLayout() { + return editableChild(0); +} + +ExpressionLayout * ParenthesisLayout::rightParenthesisLayout() { + return editableChild(2); +} + } diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 84c765893..594d81a34 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -1,37 +1,31 @@ #ifndef POINCARE_PARENTHESIS_LAYOUT_H #define POINCARE_PARENTHESIS_LAYOUT_H -#include -#include +#include namespace Poincare { -class ParenthesisLayout : public ExpressionLayout { +class ParenthesisLayout : public StaticLayoutHierarchy<3> { public: - ParenthesisLayout(ExpressionLayout * operandLayout); - ~ParenthesisLayout(); - ParenthesisLayout(const ParenthesisLayout& other) = delete; - ParenthesisLayout(ParenthesisLayout&& other) = delete; - ParenthesisLayout& operator=(const ParenthesisLayout& other) = delete; - ParenthesisLayout& operator=(ParenthesisLayout&& other) = delete; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; + ParenthesisLayout(ExpressionLayout * operand, bool cloneOperands); + ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { }; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_externWidthMargin = 1; constexpr static KDCoordinate k_externHeightMargin = 2; constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayout * m_operandLayout; - ExpressionLayout * m_leftParenthesisLayout; - ExpressionLayout * m_rightParenthesisLayout; + ExpressionLayout * operandLayout(); + ExpressionLayout * leftParenthesisLayout(); + ExpressionLayout * rightParenthesisLayout(); }; } diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 807927588..43e3939db 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -26,6 +26,11 @@ const uint8_t bottomLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeig {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, }; +ExpressionLayout * ParenthesisLeftLayout::clone() const { + ParenthesisLeftLayout * layout = new ParenthesisLeftLayout(); + return layout; +} + void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { //TODO Make sure m_operandHeight is up-to-date. KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 32796d8c3..ad0b60906 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -1,8 +1,6 @@ #ifndef POINCARE_PARENTHESIS_LEFT_LAYOUT_H #define POINCARE_PARENTHESIS_LEFT_LAYOUT_H -#include -#include #include namespace Poincare { @@ -10,6 +8,7 @@ namespace Poincare { class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; + ExpressionLayout * clone() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index bbf204a79..4f7e51e89 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -8,7 +8,7 @@ extern "C" { namespace Poincare { ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : - ExpressionLayout(), + StaticLayoutHierarchy<0>(), m_operandHeight(36) //TODO { } diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index d032fa1af..92d63ef3c 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -1,19 +1,13 @@ #ifndef POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H #define POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H -#include -#include +#include namespace Poincare { -class ParenthesisLeftRightLayout : public ExpressionLayout { +class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLeftRightLayout(); - ~ParenthesisLeftRightLayout() {} - ParenthesisLeftRightLayout(const ParenthesisLeftRightLayout& other) = delete; - ParenthesisLeftRightLayout(ParenthesisLeftRightLayout&& other) = delete; - ParenthesisLeftRightLayout& operator=(const ParenthesisLeftRightLayout& other) = delete; - ParenthesisLeftRightLayout& operator=(ParenthesisLeftRightLayout&& other) = delete; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; @@ -25,7 +19,6 @@ public: protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override { return nullptr; } KDPoint positionOfChild(ExpressionLayout * child) override; uint16_t m_operandHeight; }; diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 0a9a3af60..d9a8d4c6c 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -26,6 +26,11 @@ const uint8_t bottomRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHei {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, }; +ExpressionLayout * ParenthesisRightLayout::clone() const { + ParenthesisRightLayout * layout = new ParenthesisRightLayout(); + return layout; +} + void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { //TODO Make sure m_operandHeight is up-to-date. KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index efb98763b..7daba2368 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -1,8 +1,6 @@ #ifndef POINCARE_PARENTHESIS_RIGHT_LAYOUT_H #define POINCARE_PARENTHESIS_RIGHT_LAYOUT_H -#include -#include #include namespace Poincare { @@ -10,6 +8,7 @@ namespace Poincare { class ParenthesisRightLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; + ExpressionLayout * clone() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index cb573cf4b..b344736dd 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -4,17 +4,22 @@ namespace Poincare { +ExpressionLayout * ProductLayout::clone() const { + ProductLayout * layout = new ProductLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); + return layout; +} + void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDSize upperBoundSize = m_upperBoundLayout->size(); - KDSize lowerBoundSize = m_lowerBoundLayout->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-(k_symbolHeight+1)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_lineThickness, k_symbolHeight), expressionColor); ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-(k_symbolHeight+1)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_symbolWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2)+k_symbolWidth, - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-(k_symbolHeight+1)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_lineThickness, k_symbolHeight), expressionColor); } diff --git a/poincare/src/layout/product_layout.h b/poincare/src/layout/product_layout.h index 4aca54737..ae68723be 100644 --- a/poincare/src/layout/product_layout.h +++ b/poincare/src/layout/product_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class ProductLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; + ExpressionLayout * clone() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; private: diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 8bb66e969..c810a91b6 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -6,32 +6,20 @@ namespace Poincare { -SequenceLayout::SequenceLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * argumentLayout) : - ExpressionLayout(), - m_lowerBoundLayout(lowerBoundLayout), - m_upperBoundLayout(upperBoundLayout), - m_argumentLayout(argumentLayout) +SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : + StaticLayoutHierarchy<3>(upperBound, lowerBound, argument, cloneOperands) { - m_lowerBoundLayout->setParent(this); - m_upperBoundLayout->setParent(this); - m_argumentLayout->setParent(this); - m_baseline = max(m_upperBoundLayout->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, m_argumentLayout->baseline()); -} - -SequenceLayout::~SequenceLayout() { - delete m_lowerBoundLayout; - delete m_upperBoundLayout; - delete m_argumentLayout; + m_baseline = max(upperBoundLayout()->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); } bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the bounds. // Go Left of the sequence. if (cursor->position() == ExpressionLayoutCursor::Position::Left - && ((m_lowerBoundLayout - && cursor->pointedExpressionLayout() == m_lowerBoundLayout) - || (m_upperBoundLayout - && cursor->pointedExpressionLayout() == m_upperBoundLayout))) + && ((lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || (upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()))) { cursor->setPointedExpressionLayout(this); return true; @@ -39,11 +27,11 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the argument. // Go Right of the lower bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left - && m_argumentLayout - && cursor->pointedExpressionLayout() == m_argumentLayout) + && argumentLayout() + && cursor->pointedExpressionLayout() == argumentLayout()) { - assert(m_lowerBoundLayout != nullptr); - cursor->setPointedExpressionLayout(m_lowerBoundLayout); + assert(lowerBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(lowerBoundLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -51,9 +39,9 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the argument and move Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(m_argumentLayout != nullptr); - cursor->setPointedExpressionLayout(m_argumentLayout); - return m_argumentLayout->moveLeft(cursor); + assert(argumentLayout() != nullptr); + cursor->setPointedExpressionLayout(argumentLayout()); + return argumentLayout()->moveLeft(cursor); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left. @@ -68,21 +56,21 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the bounds. // Go Left of the argument. if (cursor->position() == ExpressionLayoutCursor::Position::Right - && ((m_lowerBoundLayout - && cursor->pointedExpressionLayout() == m_lowerBoundLayout) - || (m_upperBoundLayout - && cursor->pointedExpressionLayout() == m_upperBoundLayout))) + && ((lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || (upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()))) { - assert(m_argumentLayout != nullptr); - cursor->setPointedExpressionLayout(m_argumentLayout); + assert(argumentLayout() != nullptr); + cursor->setPointedExpressionLayout(argumentLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Right of the argument. // Ask the parent. if (cursor->position() == ExpressionLayoutCursor::Position::Right - && m_argumentLayout - && cursor->pointedExpressionLayout() == m_argumentLayout) + && argumentLayout() + && cursor->pointedExpressionLayout() == argumentLayout()) { cursor->setPointedExpressionLayout(this); if (m_parent) { @@ -94,8 +82,8 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Left. // Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(m_upperBoundLayout != nullptr); - cursor->setPointedExpressionLayout(m_upperBoundLayout); + assert(upperBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(upperBoundLayout()); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); @@ -109,74 +97,73 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (m_lowerBoundLayout && previousLayout == m_lowerBoundLayout) { - assert(m_upperBoundLayout != nullptr); - return m_upperBoundLayout->moveUpInside(cursor); + if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { + assert(upperBoundLayout() != nullptr); + return upperBoundLayout()->moveUpInside(cursor); } // If the cursor is Left of the argument, move it to the upper bound. - if (m_argumentLayout - && previousLayout == m_argumentLayout - && cursor->positionIsEquivalentTo(m_argumentLayout, ExpressionLayoutCursor::Position::Left)) + if (argumentLayout() + && previousLayout == argumentLayout() + && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_upperBoundLayout != nullptr); - return m_upperBoundLayout->moveUpInside(cursor); + assert(upperBoundLayout() != nullptr); + return upperBoundLayout()->moveUpInside(cursor); } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); } bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (m_upperBoundLayout && previousLayout == m_upperBoundLayout) { - assert(m_lowerBoundLayout != nullptr); - return m_lowerBoundLayout->moveDownInside(cursor); + if (upperBoundLayout() && previousLayout == upperBoundLayout()) { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout()->moveDownInside(cursor); } // If the cursor is Left of the argument, move it to the lower bound. - if (m_argumentLayout - && previousLayout == m_argumentLayout - && cursor->positionIsEquivalentTo(m_argumentLayout, ExpressionLayoutCursor::Position::Left)) + if (argumentLayout() + && previousLayout == argumentLayout() + && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(m_lowerBoundLayout != nullptr); - return m_lowerBoundLayout->moveDownInside(cursor); + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout()->moveDownInside(cursor); } return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +ExpressionLayout * SequenceLayout::upperBoundLayout() { + return editableChild(0); +} + +ExpressionLayout * SequenceLayout::lowerBoundLayout() { + return editableChild(1); +} + +ExpressionLayout * SequenceLayout::argumentLayout() { + return editableChild(2); +} + KDSize SequenceLayout::computeSize() { - KDSize argumentSize = m_argumentLayout->size(); - KDSize lowerBoundSize = m_lowerBoundLayout->size(); - KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize argumentSize = argumentLayout()->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), - m_baseline + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - m_argumentLayout->baseline()) + m_baseline + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) ); } -ExpressionLayout * SequenceLayout::child(uint16_t index) { - switch (index) { - case 0: - return m_upperBoundLayout; - case 1: - return m_lowerBoundLayout; - case 2: - return m_argumentLayout; - default: - return nullptr; - } -} - KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { - KDSize lowerBoundSize = m_lowerBoundLayout->size(); - KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); KDCoordinate x = 0; KDCoordinate y = 0; - if (child == m_lowerBoundLayout) { + if (child == lowerBoundLayout()) { x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); y = m_baseline + k_symbolHeight/2 + k_boundHeightMargin; - } else if (child == m_upperBoundLayout) { + } else if (child == upperBoundLayout()) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); y = m_baseline - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (child == m_argumentLayout) { + } else if (child == argumentLayout()) { x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; - y = m_baseline - m_argumentLayout->baseline(); + y = m_baseline - argumentLayout()->baseline(); } else { assert(false); } diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 95cf67f5d..b9e4735d3 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -1,33 +1,26 @@ #ifndef POINCARE_SEQUENCE_LAYOUT_H #define POINCARE_SEQUENCE_LAYOUT_H -#include -#include +#include namespace Poincare { -class SequenceLayout : public ExpressionLayout { +class SequenceLayout : public StaticLayoutHierarchy<3> { public: - SequenceLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * argumentLayout); - ~SequenceLayout(); - SequenceLayout(const SequenceLayout& other) = delete; - SequenceLayout(SequenceLayout&& other) = delete; - SequenceLayout& operator=(const SequenceLayout& other) = delete; - SequenceLayout& operator=(SequenceLayout&& other) = delete; constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; + SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; - ExpressionLayout * m_lowerBoundLayout; - ExpressionLayout * m_upperBoundLayout; - ExpressionLayout * m_argumentLayout; + ExpressionLayout * lowerBoundLayout(); + ExpressionLayout * upperBoundLayout(); + ExpressionLayout * argumentLayout(); private: KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; constexpr static KDCoordinate k_argumentWidthMargin = 2; }; diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp new file mode 100644 index 000000000..27d6c68bb --- /dev/null +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -0,0 +1,70 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +template +StaticLayoutHierarchy::StaticLayoutHierarchy() : + ExpressionLayout(), + m_children{} +{ +} + +template +StaticLayoutHierarchy::StaticLayoutHierarchy(const ExpressionLayout * const * children, bool cloneChildren) : + ExpressionLayout() +{ + build(children, T, cloneChildren); +} + +template<> +StaticLayoutHierarchy<1>::StaticLayoutHierarchy(const ExpressionLayout * e, bool cloneChildren) : + StaticLayoutHierarchy((ExpressionLayout **)&e, cloneChildren) +{ +} + +template<> +StaticLayoutHierarchy<2>::StaticLayoutHierarchy(const ExpressionLayout * e1, const ExpressionLayout * e2, bool cloneChildren) : + StaticLayoutHierarchy(ExpressionLayoutArray2(e1, e2), cloneChildren) +{ +} + +template<> +StaticLayoutHierarchy<3>::StaticLayoutHierarchy(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3, bool cloneChildren) : + StaticLayoutHierarchy(ExpressionLayoutArray3(e1, e2, e3), cloneChildren) +{ +} + +template +StaticLayoutHierarchy::~StaticLayoutHierarchy() { + for (int i = 0; i < T; i++) { + if (m_children[i] != nullptr) { + delete m_children[i]; + } + } +} + +template +void StaticLayoutHierarchy::build(const ExpressionLayout * const * children, int numberOfChildren, bool cloneChildren) { + assert(children != nullptr); + assert(numberOfChildren <= T); + for (int i=0; i < numberOfChildren; i++) { + assert(children[i] != nullptr); + if (cloneChildren) { + m_children[i] = children[i]->clone(); + } else { + m_children[i] = children[i]; + } + const_cast(m_children[i])->setParent(this); + } +} + +template class Poincare::StaticLayoutHierarchy<0>; +template class Poincare::StaticLayoutHierarchy<1>; +template class Poincare::StaticLayoutHierarchy<2>; +template class Poincare::StaticLayoutHierarchy<3>; + +} + diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index 4a053c80d..e9e93970d 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -6,7 +6,7 @@ namespace Poincare { StringLayout::StringLayout(const char * string, size_t length, KDText::FontSize fontSize) : - ExpressionLayout(), + StaticLayoutHierarchy<0>(), m_fontSize(fontSize) { m_string = new char[length+1]; @@ -20,8 +20,9 @@ StringLayout::~StringLayout() { delete[] m_string; } -char * StringLayout::text() { - return m_string; +ExpressionLayout * StringLayout::clone() const { + StringLayout * layout = new StringLayout(m_string, strlen(m_string), m_fontSize); + return layout; } bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -58,10 +59,6 @@ bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } -ExpressionLayout * StringLayout::child(uint16_t index) { - return nullptr; -} - void StringLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->drawString(m_string, p, m_fontSize, expressionColor, backgroundColor); } diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 60600f022..5a70b44fd 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -1,12 +1,12 @@ #ifndef POINCARE_STRING_LAYOUT_H #define POINCARE_STRING_LAYOUT_H -#include +#include #include namespace Poincare { -class StringLayout : public ExpressionLayout { +class StringLayout : public StaticLayoutHierarchy<0> { public: // Here the inverse is a uint8_t instead of a bool, because the size of a bool is // not standardized, thus since we call a foreign C function with this value we want to be @@ -17,16 +17,16 @@ public: StringLayout(StringLayout&& other) = delete; StringLayout& operator=(const StringLayout& other) = delete; StringLayout& operator=(StringLayout&& other) = delete; - char * text(); + ExpressionLayout * clone() const override; + + char * text() { return m_string; } bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDSize computeSize() override; - ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; + KDSize computeSize() override; char * m_string; -private: KDText::FontSize m_fontSize; }; diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 95c376bee..4515eedef 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -22,12 +22,17 @@ const uint8_t symbolPixel[SumLayout::k_symbolHeight][SumLayout::k_symbolWidth] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; +ExpressionLayout * SumLayout::clone() const { + SumLayout * layout = new SumLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); + return layout; +} + void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDSize upperBoundSize = m_upperBoundLayout->size(); - KDSize lowerBoundSize = m_lowerBoundLayout->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-(k_symbolHeight+1)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); } diff --git a/poincare/src/layout/sum_layout.h b/poincare/src/layout/sum_layout.h index e09e447cf..7218e866f 100644 --- a/poincare/src/layout/sum_layout.h +++ b/poincare/src/layout/sum_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class SumLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; + ExpressionLayout * clone() const override; private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index d35d010dc..2690be522 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -17,11 +17,11 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression children_layouts[0] = expression->operand(0)->createLayout(); for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat)) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + children_layouts[2*i] = expression->operand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); } /* HorizontalLayout holds the children layouts so they do not need to be * deleted here. */ - ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1); + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1, false); delete[] children_layouts; return layout; } @@ -39,13 +39,13 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio } /* HorizontalLayout holds the grand children layouts so they do not need to * be deleted */ - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); + ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1, false); delete [] grandChildrenLayouts; ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new EditableStringLayout(operatorName, strlen(operatorName)); - childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); + childrenLayouts[1] = new ParenthesisLayout(argumentLayouts, false); /* Same comment as above */ - return new HorizontalLayout(childrenLayouts, 2); + return new HorizontalLayout(childrenLayouts, 2, false); } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 2b20d2e33..e55a830c5 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -237,9 +237,9 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new EditableBaselineRelativeLayout(new EditableStringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); - childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); - return new HorizontalLayout(childrenLayouts, 2); + childrenLayouts[0] = new EditableBaselineRelativeLayout(new EditableStringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript, false); + childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); + return new HorizontalLayout(childrenLayouts, 2, false); } } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 10bd0d6a1..09bcb7908 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -102,7 +102,7 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode for (int i = 0; i < numberOfOperands(); i++) { childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); } - ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); + ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns(), false), false); delete [] childrenLayouts; return layout; } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index e648818c0..b9a5d6480 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -41,7 +41,7 @@ Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), false); } template diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 08956ca2e..cda885309 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -51,8 +51,8 @@ ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMo ExpressionLayout * children_layouts[2]; char string[2] = {'-', '\0'}; children_layouts[0] = new EditableStringLayout(string, 1); - children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)) : operand(0)->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(children_layouts, 2); + children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false) : operand(0)->createLayout(floatDisplayMode, complexFormat); + return new HorizontalLayout(children_layouts, 2, false); } int Opposite::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index e8a7985b6..214f7ba08 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -20,7 +20,7 @@ Expression * Parenthesis::clone() const { ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); + return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index be426900f..3ae0c3b42 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -121,7 +121,7 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = m_operands[1]->operand(0); } - return new EditableBaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); + return new EditableBaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript, false); } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index d202cd807..ee896bd98 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -27,7 +27,7 @@ int Product::emptySequenceValue() const { } ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { - return new ProductLayout(subscriptLayout, superscriptLayout, argumentLayout); + return new ProductLayout(subscriptLayout, superscriptLayout, argumentLayout, false); } template diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 58fbf8d77..0929172f5 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -150,7 +150,7 @@ ExpressionLayout * Rational::privateCreateLayout(FloatDisplayMode floatDisplayMo return numeratorLayout; } ExpressionLayout * denominatorLayout = m_denominator.createLayout(); - return new FractionLayout(numeratorLayout, denominatorLayout); + return new FractionLayout(numeratorLayout, denominatorLayout, false); } int Rational::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 87386e816..2aa201dad 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -19,7 +19,7 @@ ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMo ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout("n=", 2); childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); - return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); + return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2, false), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); } template diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 5d67ad83a..ccb695d2d 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -52,7 +52,7 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat),nullptr); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), nullptr, false); } } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index a3598228c..03d1c90bb 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -33,7 +33,7 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, const char stoSymbol[2] = {Ion::Charset::Sto, 0}; childrenLayouts[1] = new EditableStringLayout(stoSymbol, 1); childrenLayouts[2] = symbol()->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(childrenLayouts, 3); + return new HorizontalLayout(childrenLayouts, 3, false); } template diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 70a5168b7..0578083e9 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -27,7 +27,7 @@ int Sum::emptySequenceValue() const { } ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { - return new SumLayout(subscriptLayout, superscriptLayout, argumentLayout); + return new SumLayout(subscriptLayout, superscriptLayout, argumentLayout, false); } template diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index b3dc142cd..5b55e8ffa 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -135,16 +135,16 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode return new EditableStringLayout("ans", 3); } if (m_name == SpecialSymbols::un) { - return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); } if (m_name == SpecialSymbols::un1) { - return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); } if (m_name == SpecialSymbols::vn) { - return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); } if (m_name == SpecialSymbols::vn1) { - return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); } if (isMatrixSymbol()) { const char mi[] = { 'M', (char)(m_name-(char)SpecialSymbols::M0+'0') }; From d72de7c484c26f4b6efc64483909da5cadfea561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 14:48:54 +0100 Subject: [PATCH 025/459] [poincare] ExpressionLayout edition. Change-Id: I505320c32fcc3ffb516f345091a89afad90ebf56 --- .../poincare/dynamic_layout_hierarchy.h | 2 +- poincare/include/poincare/expression_layout.h | 20 +++- .../src/layout/dynamic_layout_hierarchy.cpp | 5 +- poincare/src/layout/expression_layout.cpp | 98 ++++++++++++++++++- poincare/src/layout/horizontal_layout.cpp | 5 + poincare/src/layout/horizontal_layout.h | 1 + 6 files changed, 121 insertions(+), 10 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index ef8053f76..54da3dfa9 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -20,7 +20,7 @@ public: int numberOfChildren() const override { return m_numberOfChildren; } const ExpressionLayout * const * children() const override { return m_children; }; - //bool addChildAtIndex(ExpressionLayout * operand, int index) override; TODO + bool addChildAtIndex(ExpressionLayout * operand, int index) override; protected: const ExpressionLayout ** m_children; int m_numberOfChildren; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 141f0f58c..91a04f8cc 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -31,6 +31,7 @@ public: KDPoint absoluteOrigin(); KDSize size(); KDCoordinate baseline() const { return m_baseline; } + void invalidAllSizesAndPositions(); /* Hierarchy */ virtual const ExpressionLayout * const * children() const = 0; @@ -44,6 +45,14 @@ public: ExpressionLayout * editableParent() { return m_parent; } bool hasAncestor(const ExpressionLayout * e) const; + bool insertLayoutForTextAtCursor(const char * text, ExpressionLayoutCursor * cursor); + + void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); + ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); + void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); + void detachChild(const ExpressionLayout * e); // Removes a child WITHOUT deleting it + /* Dynamic Layout*/ virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } @@ -58,18 +67,21 @@ protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; - KDCoordinate m_baseline; - ExpressionLayout * m_parent; - virtual void moveCursorInsideAtDirection ( + void detachChildAtIndex(int i); + virtual void moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout ** childResult, void * resultPosition, int * resultPositionInside, int * resultScore); + KDCoordinate m_baseline; + ExpressionLayout * m_parent; + bool m_sized; private: bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); - bool m_sized, m_positioned; + void replaceWithJuxtapositionOf(ExpressionLayout * firstLayout, ExpressionLayout * secondLayout); + bool m_positioned; KDRect m_frame; }; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 09106b617..667347d46 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -41,7 +41,7 @@ DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { delete[] m_children; } -/*bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index) { +bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index) { assert(index >= 0 && index <= m_numberOfChildren); const ExpressionLayout ** newChildren = new const ExpressionLayout * [m_numberOfChildren+1]; int j = 0; @@ -56,7 +56,8 @@ DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { delete[] m_children; m_children = newChildren; m_numberOfChildren += 1; + m_sized = false; return true; -}*/ //TODO +} } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 6defb6e39..438726b2f 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -66,11 +67,21 @@ KDSize ExpressionLayout::size() { return m_frame.size(); } +void ExpressionLayout::invalidAllSizesAndPositions() { + m_sized = false; + m_positioned = false; + for (int i = 0; i < numberOfChildren(); i++) { + editableChild(i)->invalidAllSizesAndPositions(); + } +} + const ExpressionLayout * ExpressionLayout::child(int i) const { assert(i >= 0); - assert(i < numberOfChildren()); - assert(children()[i]->parent() == nullptr || children()[i]->parent() == this); - return children()[i]; + if (i < numberOfChildren()) { + assert(children()[i]->parent() == nullptr || children()[i]->parent() == this); + return children()[i]; + } + return nullptr; } int ExpressionLayout::indexOfChild(ExpressionLayout * child) const { @@ -97,6 +108,87 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { return m_parent->hasAncestor(e); } +void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { + if (m_parent) { + int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; + if (m_parent->addChildAtIndex(brother, brotherIndex)) { + return; + } + } + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + replaceWithJuxtapositionOf(brother, this, false); + return; + } + replaceWithJuxtapositionOf(this, brother, false); + //TODO Inside position +} + +bool ExpressionLayout::insertLayoutForTextAtCursor(const char * text, ExpressionLayoutCursor * cursor) { + EditableStringLayout * newChild = new EditableStringLayout(text, strlen(text)); + cursor->pointedExpressionLayout()->addBrother(cursor, newChild); + return true; +} + +ExpressionLayout * ExpressionLayout::replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace) { + assert(m_parent != nullptr); + m_parent->replaceChild(this, newChild, deleteAfterReplace); + return newChild; +} + +ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace) { + assert(m_parent != nullptr); + /* One of the children to juxtapose might be "this", so we first have to + * replace "this" with an horizontal layout, then add "this" to the layout. */ + ExpressionLayout * layout = new HorizontalLayout(); + m_parent->replaceChild(this, layout, deleteAfterReplace); + layout->addChildAtIndex(leftChild, 0); + layout->addChildAtIndex(rightChild, 1); + return layout; +} + +void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { + assert(newChild != nullptr); + // Caution: handle the case where we replace an operand with a descendant of ours. + if (newChild->hasAncestor(this)) { + newChild->editableParent()->detachChild(newChild); + } + ExpressionLayout ** op = const_cast(children()); + for (int i = 0; i < numberOfChildren(); i++) { + if (op[i] == oldChild) { + if (oldChild != nullptr && oldChild->parent() == this) { + const_cast(oldChild)->setParent(nullptr); + } + if (deleteOldChild) { + delete oldChild; + } + if (newChild != nullptr) { + const_cast(newChild)->setParent(this); + } + op[i] = newChild; + break; + } + } + m_sized = false; +} + +void ExpressionLayout::detachChild(const ExpressionLayout * e) { + ExpressionLayout ** op = const_cast(children()); + for (int i = 0; i < numberOfChildren(); i++) { + if (op[i] == e) { + detachChildAtIndex(i); + } + } +} + +void ExpressionLayout::detachChildAtIndex(int i) { + ExpressionLayout ** op = const_cast(children()); + if (op[i] != nullptr && op[i]->parent() == this) { + const_cast(op[i])->setParent(nullptr); + } + op[i] = nullptr; + m_sized = false; +} + bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (m_parent) { return m_parent->moveUp(cursor, this, previousLayout); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 8f6ac75ba..4df2322aa 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -10,6 +10,11 @@ extern "C" { namespace Poincare { +HorizontalLayout::HorizontalLayout() : + DynamicLayoutHierarchy() +{ +} + HorizontalLayout::HorizontalLayout(ExpressionLayout ** childrenLayouts, int childrenCount, bool cloneOperands) : DynamicLayoutHierarchy(childrenLayouts, childrenCount, cloneOperands) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 561d8a9ea..dfcd71a63 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { public: + HorizontalLayout(); HorizontalLayout(ExpressionLayout ** layouts, int childrenCount, bool cloneOperands); ExpressionLayout * clone() const override; From 7a5547e3085d53d9726c6d7a11833ecad308feea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 14:46:52 +0100 Subject: [PATCH 026/459] [expression_editor] Changed example. TO REMOVE? Change-Id: Ibf1eb52eeeb9e4386c8c608115ac1ea88fbd715a --- apps/expression_editor/controller.cpp | 2 +- apps/expression_editor/expression_and_layout.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 632310443..5337e432c 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -6,7 +6,7 @@ Controller::Controller(Responder * parentResponder, Poincare::ExpressionLayout * ViewController(parentResponder), m_view(parentResponder, expressionLayout, &m_cursor) { - m_cursor.setPointedExpressionLayout(expressionLayout); + m_cursor.setPointedExpressionLayout(expressionLayout->editableChild(0)); } void Controller::didBecomeFirstResponder() { diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp index 1f36461be..0f777e586 100644 --- a/apps/expression_editor/expression_and_layout.cpp +++ b/apps/expression_editor/expression_and_layout.cpp @@ -1,9 +1,11 @@ #include "expression_and_layout.h" +#include +#include namespace ExpressionEditor { ExpressionAndLayout::ExpressionAndLayout() { - //const char * expression = "2/3"; + const char * expression = "1"; //const char * expression = "1+2/(3+4)"; //const char * expression = "1+2/3+5+8"; //const char * expression = "[[1+5,2,3][4,5,6]]"; @@ -33,10 +35,11 @@ ExpressionAndLayout::ExpressionAndLayout() { //const char * expression = "abs(1+conj(conj(4))+(23)+conj(42))+abs(1+2)"; //const char * expression = "13+(23)"; //const char * expression = "1+sum(12,3,4)+product(12,3,4)+2"; - const char * expression = "(1+2^3)-385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]/123+ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988+2)+abs(conj(345))+conj(conj(conj(3)))+floor(48)+binomial(6,88)+product(23,46,123)"; + //const char * expression = "(1+2^3)-385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]/123+ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988+2)+abs(conj(345))+conj(conj(conj(3)))+floor(48)+binomial(6,88)+product(23,46,123)+log(10,565)-0.03"; m_expression = Poincare::Expression::parse(expression); - m_expressionLayout = m_expression->createLayout(); + m_expressionLayout = new Poincare::HorizontalLayout(); + m_expressionLayout->addChildAtIndex(new Poincare::EditableStringLayout("1", 1), 0); } ExpressionAndLayout::~ExpressionAndLayout() { if (m_expressionLayout) { From c78efeeb5913fa7ed44abaf36982c4f97f487d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 14:49:17 +0100 Subject: [PATCH 027/459] [expression_editor] The user can input text. Change-Id: I6456ee23e3caf3a42899d0734e1bef1f53f68b8d --- apps/expression_editor/controller.cpp | 8 +++++++- apps/expression_editor/controller.h | 1 + apps/expression_editor/expression_editor_view.cpp | 1 + .../scrollable_expression_view_with_cursor.cpp | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 5337e432c..4053ad77c 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -4,7 +4,8 @@ namespace ExpressionEditor { Controller::Controller(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout) : ViewController(parentResponder), - m_view(parentResponder, expressionLayout, &m_cursor) + m_view(parentResponder, expressionLayout, &m_cursor), + m_expressionLayout(expressionLayout) { m_cursor.setPointedExpressionLayout(expressionLayout->editableChild(0)); } @@ -33,6 +34,11 @@ bool Controller::handleEvent(Ion::Events::Event event) { { returnValue = true; } + else if (event.hasText() && m_expressionLayout->insertLayoutForTextAtCursor(event.text(), &m_cursor)) { + returnValue = true; + m_expressionLayout->invalidAllSizesAndPositions(); + m_view.layoutSubviews(); + } m_view.cursorPositionChanged(); return returnValue; } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index f09630034..d827c35d0 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -19,6 +19,7 @@ public: bool handleEvent(Ion::Events::Event event) override; private: ExpressionEditorView m_view; + Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; }; diff --git a/apps/expression_editor/expression_editor_view.cpp b/apps/expression_editor/expression_editor_view.cpp index fc13a7f78..5d1047e53 100644 --- a/apps/expression_editor/expression_editor_view.cpp +++ b/apps/expression_editor/expression_editor_view.cpp @@ -20,6 +20,7 @@ void ExpressionEditorView::layoutSubviews() { k_margin, bounds().width() - 2 * k_margin, bounds().height() - 2 * k_margin)); + markRectAsDirty(bounds()); } KDSize ExpressionEditorView::minimalSizeForOptimalDisplay() const { diff --git a/apps/expression_editor/scrollable_expression_view_with_cursor.cpp b/apps/expression_editor/scrollable_expression_view_with_cursor.cpp index b7beb0baf..60b5c1733 100644 --- a/apps/expression_editor/scrollable_expression_view_with_cursor.cpp +++ b/apps/expression_editor/scrollable_expression_view_with_cursor.cpp @@ -14,7 +14,7 @@ KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const } void ScrollableExpressionViewWithCursor::scrollToCursor() { - scrollToContentRect(m_expressionViewWithCursor.cursorRect()); + scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); } } From 001c174a914ec5d9635374061d9fbfecfb86bed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 14:58:55 +0100 Subject: [PATCH 028/459] [poincare] Fixed problem when the cursor is on a layout extremum. Before, if the cursor pointed at the main Horizontal layout, the user could not add text because this layout has no parent. Now the cursor cannot go to the main HorizontalLayout extrema. Change-Id: I360e5da8b250b73945888e88bc1adcdf67ce1ae3 --- poincare/src/layout/horizontal_layout.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 4df2322aa..d025e9f8a 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -64,8 +64,11 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (childIndex == 0) { // Case: the child is the leftmost. // Ask the parent. - cursor->setPointedExpressionLayout(this); if (m_parent) { + // Only move the cursor if the layout has a parent: If not, the cursor + // would go on the extrema of the main HorizontalLayout, which prevents + // the user from adding more text. + cursor->setPointedExpressionLayout(this); return m_parent->moveLeft(cursor); } return false; @@ -111,8 +114,11 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { if (childIndex == numberOfChildren() - 1) { // Case: the child is the rightmost. // Ask the parent. - cursor->setPointedExpressionLayout(this); if (m_parent) { + // Only move the cursor if the layout has a parent: If not, the cursor + // would go on the extrema of the main HorizontalLayout, which prevents + // the user from adding more text. + cursor->setPointedExpressionLayout(this); return m_parent->moveRight(cursor); } return false; From aa8621f7622b756a4d1f6f87663f0a9b46790f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 15:09:00 +0100 Subject: [PATCH 029/459] [expression_editor] Move the cursor right of the text input. Change-Id: I4c78280a880a9d96e629b26c3d0ad77a1392eb2d --- poincare/src/layout/expression_layout.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 438726b2f..5868bce26 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -126,6 +126,9 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay bool ExpressionLayout::insertLayoutForTextAtCursor(const char * text, ExpressionLayoutCursor * cursor) { EditableStringLayout * newChild = new EditableStringLayout(text, strlen(text)); cursor->pointedExpressionLayout()->addBrother(cursor, newChild); + cursor->setPointedExpressionLayout(newChild); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPositionInside(0); return true; } From 1c54da21c4038deebd9f58e0381a20ed207baa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 15:23:22 +0100 Subject: [PATCH 030/459] [poincare] Char layout. Change-Id: I1fc7180b724b7a9faee0bc0e6e7762a1e883f925 --- poincare/Makefile | 1 + poincare/src/layout/char_layout.cpp | 68 +++++++++++++++++++++++++++++ poincare/src/layout/char_layout.h | 27 ++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 poincare/src/layout/char_layout.cpp create mode 100644 poincare/src/layout/char_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index ba3d233bf..e14e404b0 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -90,6 +90,7 @@ objs += $(addprefix poincare/src/layout/,\ bracket_left_right_layout.o\ bracket_right_layout.o\ ceiling_layout.o\ + char_layout.o\ condensed_sum_layout.o\ conjugate_layout.o\ dynamic_layout_hierarchy.o\ diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp new file mode 100644 index 000000000..b81762916 --- /dev/null +++ b/poincare/src/layout/char_layout.cpp @@ -0,0 +1,68 @@ +#include "char_layout.h" +#include +#include +#include + +namespace Poincare { + +CharLayout::CharLayout(char c, KDText::FontSize fontSize) : + StaticLayoutHierarchy<0>(), + m_char(c), + m_fontSize(fontSize) +{ + // Half height of the font. + m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; +} + +ExpressionLayout * CharLayout::clone() const { + CharLayout * layout = new CharLayout(m_char, m_fontSize); + return layout; +} + +bool CharLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool CharLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +void CharLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + char string[2] = {m_char, 0}; + ctx->drawString(string, p, m_fontSize, expressionColor, backgroundColor); +} + +KDPoint CharLayout::positionOfChild(ExpressionLayout * child) { + assert(false); + return KDPointZero; +} + +KDSize CharLayout::computeSize() { + return KDText::charSize(m_fontSize); +} + +} diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h new file mode 100644 index 000000000..37cedfb90 --- /dev/null +++ b/poincare/src/layout/char_layout.h @@ -0,0 +1,27 @@ +#ifndef POINCARE_CHAR_LAYOUT_H +#define POINCARE_CHAR_LAYOUT_H + +#include +#include + +namespace Poincare { + +class CharLayout : public StaticLayoutHierarchy<0> { +public: + CharLayout(char c, KDText::FontSize fontSize = KDText::FontSize::Large); + ExpressionLayout * clone() const override; + + char character() { return m_char; } + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDPoint positionOfChild(ExpressionLayout * child) override; + KDSize computeSize() override; + char m_char; + KDText::FontSize m_fontSize; +}; + +} + +#endif From b3598e17134df04f3d21f16676c6bf55ed19f5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 15:36:47 +0100 Subject: [PATCH 031/459] [expression_editor] Insert text char by char, using CharLayout. Change-Id: Id5b146bf875c1cf1d9ac949258d43a5ed415a334 --- apps/expression_editor/controller.cpp | 20 ++++++++++++++++++- apps/expression_editor/controller.h | 1 + poincare/include/poincare/expression_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 7 +------ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 4053ad77c..f82229f4e 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,4 +1,5 @@ #include "controller.h" +#include //TODO move from there. namespace ExpressionEditor { @@ -34,7 +35,8 @@ bool Controller::handleEvent(Ion::Events::Event event) { { returnValue = true; } - else if (event.hasText() && m_expressionLayout->insertLayoutForTextAtCursor(event.text(), &m_cursor)) { + else if (event.hasText()) { + insertTextAtCursor(event.text()); returnValue = true; m_expressionLayout->invalidAllSizesAndPositions(); m_view.layoutSubviews(); @@ -43,4 +45,20 @@ bool Controller::handleEvent(Ion::Events::Event event) { return returnValue; } +void Controller::insertTextAtCursor(const char * text) { + int textLength = strlen(text); + if (textLength <= 0) { + return; + } + Poincare::CharLayout * newChild = nullptr; + for (int i = 0; i < textLength; i++) { + newChild = new Poincare::CharLayout(text[i]); + m_cursor.pointedExpressionLayout()->addBrother(&m_cursor, newChild); + } + assert(newChild != nullptr); + m_cursor.setPointedExpressionLayout(newChild); + m_cursor.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_cursor.setPositionInside(0); +} + } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index d827c35d0..f95e5513b 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -18,6 +18,7 @@ public: void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; private: + void insertTextAtCursor(const char * text); ExpressionEditorView m_view; Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 91a04f8cc..a9c824f1d 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -45,7 +45,7 @@ public: ExpressionLayout * editableParent() { return m_parent; } bool hasAncestor(const ExpressionLayout * e) const; - bool insertLayoutForTextAtCursor(const char * text, ExpressionLayoutCursor * cursor); + bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 5868bce26..f7b52bcf9 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -120,15 +120,10 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay return; } replaceWithJuxtapositionOf(this, brother, false); - //TODO Inside position } -bool ExpressionLayout::insertLayoutForTextAtCursor(const char * text, ExpressionLayoutCursor * cursor) { - EditableStringLayout * newChild = new EditableStringLayout(text, strlen(text)); +bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor) { cursor->pointedExpressionLayout()->addBrother(cursor, newChild); - cursor->setPointedExpressionLayout(newChild); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); return true; } From ed7614c925ef7194fe71e928358a76ab7ae1c5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 15:40:02 +0100 Subject: [PATCH 032/459] [poincare] Removed outdated comment. Change-Id: I80cbfa3a3f643e18ca263ed772c2f4da95ca68a5 --- poincare/src/layout/string_layout.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 5a70b44fd..60060efb3 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -8,9 +8,6 @@ namespace Poincare { class StringLayout : public StaticLayoutHierarchy<0> { public: - // Here the inverse is a uint8_t instead of a bool, because the size of a bool is - // not standardized, thus since we call a foreign C function with this value we want to be - // sure about compatibility. StringLayout(const char * string, size_t length, KDText::FontSize fontSize = KDText::FontSize::Large); ~StringLayout(); StringLayout(const StringLayout& other) = delete; From 82469ca96eb32903be07cbb5937093c6116f6bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 16:31:15 +0100 Subject: [PATCH 033/459] [poincare] Added margins to ConjugateLayout. Change-Id: I27b3788c87d36390fcea63c6a70b89aa36a2e9f3 --- escher/include/escher/metric.h | 2 ++ poincare/src/layout/conjugate_layout.cpp | 9 +++++---- poincare/src/layout/conjugate_layout.h | 2 +- poincare/src/layout/fraction_layout.cpp | 5 +++-- poincare/src/layout/fraction_layout.h | 2 -- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/escher/include/escher/metric.h b/escher/include/escher/metric.h index cb62d2724..06c060a1c 100644 --- a/escher/include/escher/metric.h +++ b/escher/include/escher/metric.h @@ -25,6 +25,8 @@ public: constexpr static KDCoordinate ExamPopUpBottomMargin = 55; constexpr static KDCoordinate StoreRowHeight = 50; constexpr static KDCoordinate ToolboxRowHeight = 40; + constexpr static KDCoordinate FractionAndConjugateHorizontalOverflow = 2; + constexpr static KDCoordinate FractionAndConjugateHorizontalMargin = 2; }; #endif diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index db289ce45..45b9f7991 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -1,4 +1,5 @@ #include "conjugate_layout.h" +#include #include extern "C" { #include @@ -10,7 +11,7 @@ namespace Poincare { ConjugateLayout::ConjugateLayout(ExpressionLayout * operand, bool cloneOperands) : StaticLayoutHierarchy<1>(operand, cloneOperands) { - m_baseline = operandLayout()->baseline()+k_overlineWidth+k_overlineMargin; + m_baseline = operandLayout()->baseline()+k_overlineWidth+k_overlineVerticalMargin; } ExpressionLayout * ConjugateLayout::clone() const { @@ -79,16 +80,16 @@ bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { } void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - ctx->fillRect(KDRect(p.x(), p.y(), operandLayout()->size().width(), k_overlineWidth), expressionColor); + ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, p.y(), operandLayout()->size().width()+2*Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth), expressionColor); } KDSize ConjugateLayout::computeSize() { KDSize operandSize = operandLayout()->size(); - return KDSize(operandSize.width(), operandSize.height()+k_overlineWidth+k_overlineMargin); + return KDSize(Metric::FractionAndConjugateHorizontalMargin+Metric::FractionAndConjugateHorizontalOverflow+operandSize.width()+Metric::FractionAndConjugateHorizontalOverflow+Metric::FractionAndConjugateHorizontalMargin, operandSize.height()+k_overlineWidth+k_overlineVerticalMargin); } KDPoint ConjugateLayout::positionOfChild(ExpressionLayout * child) { - return KDPoint(0, k_overlineWidth+k_overlineMargin); + return KDPoint(Metric::FractionAndConjugateHorizontalMargin+Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth+k_overlineVerticalMargin); } ExpressionLayout * ConjugateLayout::operandLayout() { diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 15834cce4..5bb16be5b 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -17,7 +17,7 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_overlineWidth = 1; - constexpr static KDCoordinate k_overlineMargin = 3; + constexpr static KDCoordinate k_overlineVerticalMargin = 1; ExpressionLayout * operandLayout(); }; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 41d4ec315..5d183530e 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -1,4 +1,5 @@ #include "fraction_layout.h" +#include #include #include #include @@ -101,12 +102,12 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + numeratorLayout()->size().height() + k_fractionLineMargin; - ctx->fillRect(KDRect(p.x()+k_fractionBorderMargin, fractionLineY, size().width()-2*k_fractionBorderMargin, 1), expressionColor); + ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, size().width()-2*Metric::FractionAndConjugateHorizontalMargin, 1), expressionColor); } KDSize FractionLayout::computeSize() { KDCoordinate width = max(numeratorLayout()->size().width(), denominatorLayout()->size().width()) - + 2*k_fractionBorderLength+2*k_fractionBorderMargin; + + 2*Metric::FractionAndConjugateHorizontalOverflow+2*Metric::FractionAndConjugateHorizontalMargin; KDCoordinate height = numeratorLayout()->size().height() + k_fractionLineMargin + k_fractionLineHeight + k_fractionLineMargin + denominatorLayout()->size().height(); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 13154045b..c2c93d275 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -18,8 +18,6 @@ protected: KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - constexpr static KDCoordinate k_fractionBorderLength = 2; - constexpr static KDCoordinate k_fractionBorderMargin = 2; constexpr static KDCoordinate k_fractionLineMargin = 2; constexpr static KDCoordinate k_fractionLineHeight = 2; ExpressionLayout * numeratorLayout(); From 04323e82843097a132caa81cd5c9138c2e096658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 19 Dec 2017 16:35:20 +0100 Subject: [PATCH 034/459] [poincare] Changed the navigation in ConjugateLayout. The cursor can now be Right of the conjugate and Right of the operand, not just Right of the operand. Change-Id: I409ca5595c8e19ad29995bbdcc4309a99bf21c73 --- poincare/src/layout/conjugate_layout.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 45b9f7991..cfe653ab0 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -21,24 +21,21 @@ ExpressionLayout * ConjugateLayout::clone() const { bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the operand. - // Ask the parent. + // Move Left. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; + return true; } assert(cursor->pointedExpressionLayout() == this); // Case: Right. - // Go to the operand and move Left. + // Go to the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); cursor->setPointedExpressionLayout(operandLayout()); - return operandLayout()->moveLeft(cursor); + return true; } // Case: Left. // Ask the parent. @@ -51,24 +48,21 @@ bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right of the operand. - // Ask the parent. + // Move Right. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; + return true; } assert(cursor->pointedExpressionLayout() == this); // Case: Left. - // Go to the operand and move Right. + // Go to the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); cursor->setPointedExpressionLayout(operandLayout()); - return operandLayout()->moveRight(cursor); + return true; } // Case: Right. // Ask the parent. From 62322da1ee3ed25e3e3d061c6258ebec81afacbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 09:55:37 +0100 Subject: [PATCH 035/459] [poincare] Empty and EmptyVisible layouts. Change-Id: Id3234f406e1bfe7addb704c873bde357546ddf67 --- poincare/Makefile | 2 + poincare/src/layout/empty_layout.cpp | 38 +++++++++++++ poincare/src/layout/empty_layout.h | 26 +++++++++ poincare/src/layout/empty_visible_layout.cpp | 60 ++++++++++++++++++++ poincare/src/layout/empty_visible_layout.h | 30 ++++++++++ 5 files changed, 156 insertions(+) create mode 100644 poincare/src/layout/empty_layout.cpp create mode 100644 poincare/src/layout/empty_layout.h create mode 100644 poincare/src/layout/empty_visible_layout.cpp create mode 100644 poincare/src/layout/empty_visible_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index e14e404b0..d5e88b035 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -96,6 +96,8 @@ objs += $(addprefix poincare/src/layout/,\ dynamic_layout_hierarchy.o\ editable_baseline_relative_layout.o\ editable_string_layout.o\ + empty_layout.o\ + empty_visible_layout.o\ expression_layout.o\ floor_layout.o\ fraction_layout.o\ diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp new file mode 100644 index 000000000..3823553e5 --- /dev/null +++ b/poincare/src/layout/empty_layout.cpp @@ -0,0 +1,38 @@ +#include "empty_layout.h" +#include +#include + +namespace Poincare { + +EmptyLayout::EmptyLayout() : + StaticLayoutHierarchy<0>() +{ + m_baseline = 0; +} + +ExpressionLayout * EmptyLayout::clone() const { + EmptyLayout * layout = new EmptyLayout(); + return layout; +} + +bool EmptyLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool EmptyLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +} diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h new file mode 100644 index 000000000..9f1a61da7 --- /dev/null +++ b/poincare/src/layout/empty_layout.h @@ -0,0 +1,26 @@ +#ifndef POINCARE_EMPTY_LAYOUT_H +#define POINCARE_EMPTY_LAYOUT_H + +#include +#include + +namespace Poincare { + +class EmptyLayout : public StaticLayoutHierarchy<0> { +public: + EmptyLayout(); + ExpressionLayout * clone() const override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; +protected: + virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { return; } + virtual KDSize computeSize() override { return KDSizeZero; } + KDPoint positionOfChild(ExpressionLayout * child) override { + assert(false); + return KDPointZero; + } +}; + +} + +#endif diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp new file mode 100644 index 000000000..3d8910572 --- /dev/null +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -0,0 +1,60 @@ +#include "empty_visible_layout.h" +#include +#include + +namespace Poincare { + +EmptyVisibleLayout::EmptyVisibleLayout() : + EmptyLayout(), + m_fillRectColor(KDColor::RGB24(0xffd370)) //TODO make static or in Palette? +{ + m_baseline = k_height + 2*k_marginHeight; +} + +ExpressionLayout * EmptyVisibleLayout::clone() const { + EmptyVisibleLayout * layout = new EmptyVisibleLayout(); + return layout; +} + +bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); +} + +KDSize EmptyVisibleLayout::computeSize() { + return KDSize(k_width + 2*k_marginWidth, k_height + 2*k_marginHeight); +} + +} diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h new file mode 100644 index 000000000..c595e9b02 --- /dev/null +++ b/poincare/src/layout/empty_visible_layout.h @@ -0,0 +1,30 @@ +#ifndef POINCARE_EMPTY_VISIBLE_LAYOUT_H +#define POINCARE_EMPTY_VISIBLE_LAYOUT_H + +#include "empty_layout.h" +#include + +namespace Poincare { + +class EmptyVisibleLayout : public EmptyLayout { +public: + EmptyVisibleLayout(); + ExpressionLayout * clone() const override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; +protected: + virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + virtual KDSize computeSize() override; +private: + constexpr static KDCoordinate k_width = 7; + constexpr static KDCoordinate k_height = 13; + constexpr static KDCoordinate k_marginWidth = 1; + constexpr static KDCoordinate k_marginHeight = 3; + constexpr static KDCoordinate k_lineThickness = 1; + + KDColor m_fillRectColor; +}; + +} + +#endif From 241d37afa59bb0af3f3a7505dc0a78c2922e22a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 10:27:14 +0100 Subject: [PATCH 036/459] [poincare] Recompute baselines when needed. Change-Id: I4ec717402a4dfd287aa95f45189e1734e4f5e3ed --- apps/expression_editor/controller.cpp | 2 +- poincare/include/poincare/expression_layout.h | 6 ++++-- .../src/layout/baseline_relative_layout.cpp | 9 +++++++-- poincare/src/layout/baseline_relative_layout.h | 1 + poincare/src/layout/bracket_layout.cpp | 7 ++++++- poincare/src/layout/bracket_layout.h | 1 + .../src/layout/bracket_left_right_layout.cpp | 6 ++++++ .../src/layout/bracket_left_right_layout.h | 1 + poincare/src/layout/char_layout.cpp | 9 +++++++-- poincare/src/layout/char_layout.h | 1 + poincare/src/layout/condensed_sum_layout.cpp | 9 +++++++-- poincare/src/layout/condensed_sum_layout.h | 1 + poincare/src/layout/conjugate_layout.cpp | 7 ++++++- poincare/src/layout/conjugate_layout.h | 1 + poincare/src/layout/empty_layout.cpp | 5 +++++ poincare/src/layout/empty_layout.h | 1 + poincare/src/layout/empty_visible_layout.cpp | 7 ++++++- poincare/src/layout/empty_visible_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 15 +++++++++++++-- poincare/src/layout/fraction_layout.cpp | 9 +++++++-- poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 11 ++++++++--- poincare/src/layout/grid_layout.h | 1 + poincare/src/layout/horizontal_layout.cpp | 18 ++++++++++++------ poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/integral_layout.cpp | 7 ++++++- poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 17 +++++++++++------ poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/parenthesis_layout.cpp | 7 ++++++- poincare/src/layout/parenthesis_layout.h | 1 + .../layout/parenthesis_left_right_layout.cpp | 6 ++++++ .../src/layout/parenthesis_left_right_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 7 ++++++- poincare/src/layout/sequence_layout.h | 1 + poincare/src/layout/string_layout.cpp | 8 ++++++-- poincare/src/layout/string_layout.h | 1 + 37 files changed, 153 insertions(+), 36 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index f82229f4e..0a83b28c7 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -38,7 +38,7 @@ bool Controller::handleEvent(Ion::Events::Event event) { else if (event.hasText()) { insertTextAtCursor(event.text()); returnValue = true; - m_expressionLayout->invalidAllSizesAndPositions(); + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.layoutSubviews(); } m_view.cursorPositionChanged(); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index a9c824f1d..1e48236df 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -30,8 +30,8 @@ public: KDPoint origin(); KDPoint absoluteOrigin(); KDSize size(); - KDCoordinate baseline() const { return m_baseline; } - void invalidAllSizesAndPositions(); + KDCoordinate baseline(); + void invalidAllSizesPositionsAndBaselines(); /* Hierarchy */ virtual const ExpressionLayout * const * children() const = 0; @@ -66,6 +66,7 @@ public: protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; + virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; void detachChildAtIndex(int i); virtual void moveCursorInsideAtDirection ( @@ -78,6 +79,7 @@ protected: KDCoordinate m_baseline; ExpressionLayout * m_parent; bool m_sized; + bool m_baselined; private: bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); void replaceWithJuxtapositionOf(ExpressionLayout * firstLayout, ExpressionLayout * secondLayout); diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 0e5b23439..39b0bac48 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -9,8 +9,7 @@ BaselineRelativeLayout::BaselineRelativeLayout(ExpressionLayout * base, Expressi StaticLayoutHierarchy(base, indice, cloneOperands), m_type(type) { - m_baseline = type == Type::Subscript ? baseLayout()->baseline() : - indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; + computeBaseline(); } ExpressionLayout * BaselineRelativeLayout::clone() const { @@ -70,6 +69,12 @@ KDSize BaselineRelativeLayout::computeSize() { return KDSize(baseSize.width() + indiceSize.width(), baseSize.height() + indiceSize.height() - k_indiceHeight); } +void BaselineRelativeLayout::computeBaseline() { + m_baseline = m_type == Type::Subscript ? baseLayout()->baseline() : + indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; + m_baselined = true; +} + KDPoint BaselineRelativeLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index 8ef335015..1e72783a8 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -20,6 +20,7 @@ protected: ExpressionLayout * indiceLayout(); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; Type m_type; private: diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 487d1e2b0..1ad946b87 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -10,7 +10,7 @@ namespace Poincare { BracketLayout::BracketLayout(ExpressionLayout * operandLayout, bool cloneOperands) : StaticLayoutHierarchy<1>(operandLayout, cloneOperands) { - m_baseline = operandLayout->baseline(); + computeBaseline(); } ExpressionLayout * BracketLayout::clone() const { @@ -100,6 +100,11 @@ KDSize BracketLayout::computeSize() { return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height()); } +void BracketLayout::computeBaseline() { + m_baseline = operandLayout()->baseline(); + m_baselined = true; +} + KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 977095632..b9beeb4c7 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -19,6 +19,7 @@ protected: virtual bool renderBottomBar() const { return true; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_bracketWidth = 5; diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index 70701274d..98d01121e 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -53,6 +53,12 @@ KDSize BracketLeftRightLayout::computeSize() { return KDSize(k_externWidthMargin + k_lineThickness + k_bracketWidth + k_widthMargin, m_operandHeight); } +void BracketLeftRightLayout::computeBaseline() { + //TODO: compute the operandHeight according to the brothers + m_baseline = m_operandHeight; + m_baselined = true; +} + KDPoint BracketLeftRightLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 1c9527e1b..838b9e00e 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -16,6 +16,7 @@ public: constexpr static KDCoordinate k_externWidthMargin = 2; protected: KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; uint16_t m_operandHeight; }; diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index b81762916..22357ddfc 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -10,8 +10,7 @@ CharLayout::CharLayout(char c, KDText::FontSize fontSize) : m_char(c), m_fontSize(fontSize) { - // Half height of the font. - m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; + computeBaseline(); } ExpressionLayout * CharLayout::clone() const { @@ -65,4 +64,10 @@ KDSize CharLayout::computeSize() { return KDText::charSize(m_fontSize); } +void CharLayout::computeBaseline() { + // Half height of the font. + m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; + m_baselined = true; +} + } diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 37cedfb90..d00625c09 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -18,6 +18,7 @@ protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDPoint positionOfChild(ExpressionLayout * child) override; KDSize computeSize() override; + void computeBaseline() override; char m_char; KDText::FontSize m_fontSize; }; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index d696cb170..04babee19 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -8,8 +8,7 @@ namespace Poincare { CondensedSumLayout::CondensedSumLayout(ExpressionLayout * base, ExpressionLayout * subscript, ExpressionLayout * superscript, bool cloneOperands) : StaticLayoutHierarchy<3>(base, subscript, superscript, cloneOperands) { - KDSize superscriptSize = superscriptLayout() == nullptr ? KDSizeZero : superscriptLayout()->size(); - m_baseline = baseLayout()->baseline() + max(0, superscriptSize.height() - baseLayout()->size().height()/2); + computeBaseline(); } ExpressionLayout * CondensedSumLayout::clone() const { @@ -142,6 +141,12 @@ KDSize CondensedSumLayout::computeSize() { return KDSize(baseSize.width() + max(subscriptSize.width(), superscriptSize.width()), max(baseSize.height()/2, subscriptSize.height()) + max(baseSize.height()/2, superscriptSize.height())); } +void CondensedSumLayout::computeBaseline() { + KDSize superscriptSize = superscriptLayout() == nullptr ? KDSizeZero : superscriptLayout()->size(); + m_baseline = baseLayout()->baseline() + max(0, superscriptSize.height() - baseLayout()->size().height()/2); + m_baselined = true; +} + KDPoint CondensedSumLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 16528e6c7..fa9179acd 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -16,6 +16,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: ExpressionLayout * baseLayout(); diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index cfe653ab0..97317f5dc 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -11,7 +11,7 @@ namespace Poincare { ConjugateLayout::ConjugateLayout(ExpressionLayout * operand, bool cloneOperands) : StaticLayoutHierarchy<1>(operand, cloneOperands) { - m_baseline = operandLayout()->baseline()+k_overlineWidth+k_overlineVerticalMargin; + computeBaseline(); } ExpressionLayout * ConjugateLayout::clone() const { @@ -82,6 +82,11 @@ KDSize ConjugateLayout::computeSize() { return KDSize(Metric::FractionAndConjugateHorizontalMargin+Metric::FractionAndConjugateHorizontalOverflow+operandSize.width()+Metric::FractionAndConjugateHorizontalOverflow+Metric::FractionAndConjugateHorizontalMargin, operandSize.height()+k_overlineWidth+k_overlineVerticalMargin); } +void ConjugateLayout::computeBaseline() { + m_baseline = operandLayout()->baseline()+k_overlineWidth+k_overlineVerticalMargin; + m_baselined = true; +} + KDPoint ConjugateLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(Metric::FractionAndConjugateHorizontalMargin+Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth+k_overlineVerticalMargin); } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 5bb16be5b..732e89e49 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -14,6 +14,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_overlineWidth = 1; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 3823553e5..fe9a28222 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -35,4 +35,9 @@ bool EmptyLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +void EmptyLayout::computeBaseline() { + m_baseline = 0; + m_baselined = true; +} + } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 9f1a61da7..5573b0207 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -15,6 +15,7 @@ public: protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { return; } virtual KDSize computeSize() override { return KDSizeZero; } + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override { assert(false); return KDPointZero; diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index 3d8910572..f6cdaf7b4 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -8,7 +8,7 @@ EmptyVisibleLayout::EmptyVisibleLayout() : EmptyLayout(), m_fillRectColor(KDColor::RGB24(0xffd370)) //TODO make static or in Palette? { - m_baseline = k_height + 2*k_marginHeight; + computeBaseline(); } ExpressionLayout * EmptyVisibleLayout::clone() const { @@ -57,4 +57,9 @@ KDSize EmptyVisibleLayout::computeSize() { return KDSize(k_width + 2*k_marginWidth, k_height + 2*k_marginHeight); } +void EmptyVisibleLayout::computeBaseline() { + m_baseline = k_marginHeight + k_height/2; + m_baselined = true; +} + } diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index c595e9b02..7a88565b9 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -15,6 +15,7 @@ public: protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; virtual KDSize computeSize() override; + void computeBaseline() override; private: constexpr static KDCoordinate k_width = 7; constexpr static KDCoordinate k_height = 13; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index f7b52bcf9..3a92820d7 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -11,6 +11,7 @@ ExpressionLayout::ExpressionLayout() : m_baseline(0), m_parent(nullptr), m_sized(false), + m_baselined(false), m_positioned(false), m_frame(KDRectZero) { } @@ -67,11 +68,21 @@ KDSize ExpressionLayout::size() { return m_frame.size(); } -void ExpressionLayout::invalidAllSizesAndPositions() { +KDCoordinate ExpressionLayout::baseline() { + if (!m_baselined) { + computeBaseline(); + m_baselined = true; + } + return m_baseline; +} + + +void ExpressionLayout::invalidAllSizesPositionsAndBaselines() { m_sized = false; m_positioned = false; + m_baselined = false; for (int i = 0; i < numberOfChildren(); i++) { - editableChild(i)->invalidAllSizesAndPositions(); + editableChild(i)->invalidAllSizesPositionsAndBaselines(); } } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 5d183530e..6fd6651b3 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -9,8 +9,7 @@ namespace Poincare { FractionLayout::FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator, bool cloneOperands) : StaticLayoutHierarchy<2>(numerator, denominator, cloneOperands) { - m_baseline = numeratorLayout()->size().height() - + k_fractionLineMargin + k_fractionLineHeight; + computeBaseline(); } ExpressionLayout * FractionLayout::clone() const { @@ -114,6 +113,12 @@ KDSize FractionLayout::computeSize() { return KDSize(width, height); } +void FractionLayout::computeBaseline() { + m_baseline = numeratorLayout()->size().height() + + k_fractionLineMargin + k_fractionLineHeight; + m_baselined = true; +} + KDPoint FractionLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index c2c93d275..670718879 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -16,6 +16,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_fractionLineMargin = 2; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index c379c5883..504a9c65d 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -12,7 +12,7 @@ GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int n m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { - m_baseline = (height()+1)/2; + computeBaseline(); } ExpressionLayout * GridLayout::clone() const { @@ -116,7 +116,7 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * pr KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { - rowBaseline = max(rowBaseline, child(i*m_numberOfColumns+j)->baseline()); + rowBaseline = max(rowBaseline, editableChild(i*m_numberOfColumns+j)->baseline()); } return rowBaseline; } @@ -125,7 +125,7 @@ KDCoordinate GridLayout::rowHeight(int i) { KDCoordinate rowHeight = 0; KDCoordinate baseline = rowBaseline(i); for (int j = 0; j < m_numberOfColumns; j++) { - rowHeight = max(rowHeight, editableChild(i*m_numberOfColumns+j)->size().height() - child(i*m_numberOfColumns+j)->baseline()); + rowHeight = max(rowHeight, editableChild(i*m_numberOfColumns+j)->size().height() - editableChild(i*m_numberOfColumns+j)->baseline()); } return baseline+rowHeight; } @@ -164,6 +164,11 @@ KDSize GridLayout::computeSize() { return KDSize(width(), height()); } +void GridLayout::computeBaseline() { + m_baseline = (height()+1)/2; + m_baselined = true; +} + KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { int rowIndex = 0; int columnIndex = 0; diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index ce48b66e6..379fd642f 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -19,6 +19,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_gridEntryMargin = 6; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index d025e9f8a..dc627bee9 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -18,11 +18,7 @@ HorizontalLayout::HorizontalLayout() : HorizontalLayout::HorizontalLayout(ExpressionLayout ** childrenLayouts, int childrenCount, bool cloneOperands) : DynamicLayoutHierarchy(childrenLayouts, childrenCount, cloneOperands) { - for (int i = 0; i < numberOfChildren(); i++) { - if (child(i)->baseline() > m_baseline) { - m_baseline = child(i)->baseline(); - } - } + computeBaseline(); } ExpressionLayout * HorizontalLayout::clone() const { @@ -159,6 +155,16 @@ KDSize HorizontalLayout::computeSize() { return KDSize(totalWidth, max_under_baseline + max_above_baseline); } +void HorizontalLayout::computeBaseline() { + m_baseline = 0; + for (int i = 0; i < numberOfChildren(); i++) { + if (editableChild(i)->baseline() > m_baseline) { + m_baseline = editableChild(i)->baseline(); + } + } + m_baselined = true; +} + KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; @@ -168,7 +174,7 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { assert(previousChild != nullptr); x = previousChild->origin().x() + previousChild->size().width(); } - y = m_baseline - child->baseline(); + y = baseline() - child->baseline(); return KDPoint(x, y); } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index dfcd71a63..d6f8bba01 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -19,6 +19,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 727e477f0..4e912dd91 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -22,7 +22,7 @@ const uint8_t bottomSymbolPixel[IntegralLayout::k_symbolHeight][IntegralLayout:: IntegralLayout::IntegralLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * integrand, bool cloneOperands) : StaticLayoutHierarchy<3>(upperBound, lowerBound, integrand, cloneOperands) { - m_baseline = upperBoundLayout()->size().height() + k_integrandHeigthMargin + integrandLayout()->baseline(); + computeBaseline(); } ExpressionLayout * IntegralLayout::clone() const { @@ -168,6 +168,11 @@ KDSize IntegralLayout::computeSize() { upperBoundSize.height()+ 2*k_integrandHeigthMargin+integrandSize.height()+lowerBoundSize.height()); } +void IntegralLayout::computeBaseline() { + m_baseline = upperBoundLayout()->size().height() + k_integrandHeigthMargin + integrandLayout()->baseline(); + m_baselined = true; +} + KDPoint IntegralLayout::positionOfChild(ExpressionLayout * child) { KDSize integrandSize = integrandLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 067cc7cea..7390f644a 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -18,6 +18,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_boundHeightMargin = 8; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 89a3c59a4..a52194a0f 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -19,12 +19,7 @@ const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_left NthRootLayout::NthRootLayout(ExpressionLayout * radicand, ExpressionLayout * index, bool cloneOperands) : StaticLayoutHierarchy<2>(radicand, index, cloneOperands) { - if (indexLayout() != nullptr) { - m_baseline = max(radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin, - indexLayout()->size().height() + k_indexHeight); - } else { - m_baseline = radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin; - } + computeBaseline(); } ExpressionLayout * NthRootLayout::clone() const { @@ -208,6 +203,16 @@ KDSize NthRootLayout::computeSize() { ); } +void NthRootLayout::computeBaseline() { + if (indexLayout() != nullptr) { + m_baseline = max(radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin, + indexLayout()->size().height() + k_indexHeight); + } else { + m_baseline = radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin; + } + m_baselined = true; +} + KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index d942b3863..aa7d81814 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -18,6 +18,7 @@ public: protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_rightRadixHeight = 2; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index eccab7030..b5b48641f 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -15,7 +15,7 @@ ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operand, bool cloneOpera ExpressionLayout * leftParenthesis = new ParenthesisLeftLayout(); ExpressionLayout * rightParenthesis = new ParenthesisRightLayout(); build(ExpressionLayout::ExpressionLayoutArray3(leftParenthesis, operand, rightParenthesis), 3, cloneOperands); - m_baseline = operandLayout()->baseline(); + computeBaseline(); } ExpressionLayout * ParenthesisLayout::clone() const { @@ -130,6 +130,11 @@ KDSize ParenthesisLayout::computeSize() { return KDSize(operandSize.width() + 2*leftParenthesisLayout()->size().width(), operandSize.height()); } +void ParenthesisLayout::computeBaseline() { + m_baseline = operandLayout()->baseline(); + m_baselined = true; +} + KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { if (child == leftParenthesisLayout()) { return KDPoint(0, 0); diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 594d81a34..0757c6f5f 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -17,6 +17,7 @@ protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { }; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_externWidthMargin = 1; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 4f7e51e89..1baceff6b 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -11,6 +11,7 @@ ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : StaticLayoutHierarchy<0>(), m_operandHeight(36) //TODO { + computeBaseline(); } bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -52,6 +53,11 @@ KDSize ParenthesisLeftRightLayout::computeSize() { return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, m_operandHeight); } +void ParenthesisLeftRightLayout::computeBaseline() { + m_baseline = m_operandHeight/2; //TODO + m_baselined = true; +} + KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 92d63ef3c..67381f10a 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -19,6 +19,7 @@ public: protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; uint16_t m_operandHeight; }; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index c810a91b6..3955f77b3 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -9,7 +9,7 @@ namespace Poincare { SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : StaticLayoutHierarchy<3>(upperBound, lowerBound, argument, cloneOperands) { - m_baseline = max(upperBoundLayout()->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); + computeBaseline(); } bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -150,6 +150,11 @@ KDSize SequenceLayout::computeSize() { ); } +void SequenceLayout::computeBaseline() { + m_baseline = max(upperBoundLayout()->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); + m_baselined = true; +} + KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { KDSize lowerBoundSize = lowerBoundLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index b9e4735d3..6e186982d 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -21,6 +21,7 @@ protected: ExpressionLayout * argumentLayout(); private: KDSize computeSize() override; + void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; constexpr static KDCoordinate k_argumentWidthMargin = 2; }; diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index e9e93970d..43996cd7d 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -12,8 +12,6 @@ StringLayout::StringLayout(const char * string, size_t length, KDText::FontSize m_string = new char[length+1]; memcpy(m_string, string, length); m_string[length] = 0; - // Half height of the font. - m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; } StringLayout::~StringLayout() { @@ -72,4 +70,10 @@ KDSize StringLayout::computeSize() { return KDText::stringSize(m_string, m_fontSize); } +void StringLayout::computeBaseline() { + // Half height of the font. + m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; + m_baselined = true; +} + } diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 60060efb3..0a3763811 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -23,6 +23,7 @@ protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDPoint positionOfChild(ExpressionLayout * child) override; KDSize computeSize() override; + void computeBaseline() override; char * m_string; KDText::FontSize m_fontSize; }; From 3c45358296218ab93dbb43d07fb7b47f137bbdc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 10:37:40 +0100 Subject: [PATCH 037/459] [expression_editor] Add fraction layouts (simple version). Pressing the divide button adds an empty fraction layout without "absorbing" the neighbouring layouts. Change-Id: I46bdeadfcd80ec3c51c676ae62747e0823718645 --- apps/expression_editor/controller.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 0a83b28c7..4a4c2f842 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,9 +1,13 @@ #include "controller.h" #include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. + +using namespace Poincare; namespace ExpressionEditor { -Controller::Controller(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout) : +Controller::Controller(Responder * parentResponder, ExpressionLayout * expressionLayout) : ViewController(parentResponder), m_view(parentResponder, expressionLayout, &m_cursor), m_expressionLayout(expressionLayout) @@ -34,8 +38,19 @@ bool Controller::handleEvent(Ion::Events::Event event) { || (event == Ion::Events::Down && m_cursor.moveDown())) { returnValue = true; - } - else if (event.hasText()) { + } else if (event == Ion::Events::Division) { + EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + + FractionLayout * newChild = new FractionLayout(child1, child2, false); + m_cursor.pointedExpressionLayout()->addBrother(&m_cursor, newChild); + m_cursor.setPointedExpressionLayout(newChild); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); + m_cursor.setPositionInside(0); + returnValue = true; + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); + m_view.layoutSubviews(); + } else if (event.hasText()) { insertTextAtCursor(event.text()); returnValue = true; m_expressionLayout->invalidAllSizesPositionsAndBaselines(); @@ -50,14 +65,14 @@ void Controller::insertTextAtCursor(const char * text) { if (textLength <= 0) { return; } - Poincare::CharLayout * newChild = nullptr; + CharLayout * newChild = nullptr; for (int i = 0; i < textLength; i++) { - newChild = new Poincare::CharLayout(text[i]); + newChild = new CharLayout(text[i]); m_cursor.pointedExpressionLayout()->addBrother(&m_cursor, newChild); } assert(newChild != nullptr); m_cursor.setPointedExpressionLayout(newChild); - m_cursor.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); m_cursor.setPositionInside(0); } From 4d94764c36e3918e31c760fdb355ee72249f5a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 11:23:58 +0100 Subject: [PATCH 038/459] [expression_editor] Controller code cleaning. Change-Id: Ifb31ad712ce9c59e21fc3d670d05f60a15669d60 --- apps/expression_editor/controller.cpp | 73 ++++++++++--------- apps/expression_editor/controller.h | 4 +- .../poincare/expression_layout_cursor.h | 17 +++-- poincare/src/expression_layout_cursor.cpp | 57 +++++++++++---- 4 files changed, 92 insertions(+), 59 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 4a4c2f842..7e747e03d 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,7 +1,4 @@ #include "controller.h" -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. using namespace Poincare; @@ -31,49 +28,53 @@ void Controller::didBecomeFirstResponder() { } bool Controller::handleEvent(Ion::Events::Event event) { - bool returnValue = false; - if ((event == Ion::Events::Left && m_cursor.moveLeft()) - || (event == Ion::Events::Right && m_cursor.moveRight()) - || (event == Ion::Events::Up && m_cursor.moveUp()) - || (event == Ion::Events::Down && m_cursor.moveDown())) - { - returnValue = true; - } else if (event == Ion::Events::Division) { - EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + if (privateHandleEvent(event)) { + m_view.cursorPositionChanged(); + return true; + } + return false; +} - FractionLayout * newChild = new FractionLayout(child1, child2, false); - m_cursor.pointedExpressionLayout()->addBrother(&m_cursor, newChild); - m_cursor.setPointedExpressionLayout(newChild); +bool Controller::privateHandleEvent(Ion::Events::Event event) { + if (handleMoveEvent(event)) { + return true; + } + ExpressionLayout * newPointedLayout = handleAddEvent(event); + if (newPointedLayout != nullptr) { + m_cursor.setPointedExpressionLayout(newPointedLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); m_cursor.setPositionInside(0); - returnValue = true; - m_expressionLayout->invalidAllSizesPositionsAndBaselines(); - m_view.layoutSubviews(); - } else if (event.hasText()) { - insertTextAtCursor(event.text()); - returnValue = true; m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.layoutSubviews(); + return true; } - m_view.cursorPositionChanged(); - return returnValue; + return false; } -void Controller::insertTextAtCursor(const char * text) { - int textLength = strlen(text); - if (textLength <= 0) { - return; +bool Controller::handleMoveEvent(Ion::Events::Event event) { + if (event == Ion::Events::Left) { + return m_cursor.moveLeft(); } - CharLayout * newChild = nullptr; - for (int i = 0; i < textLength; i++) { - newChild = new CharLayout(text[i]); - m_cursor.pointedExpressionLayout()->addBrother(&m_cursor, newChild); + if (event == Ion::Events::Right) { + return m_cursor.moveRight(); } - assert(newChild != nullptr); - m_cursor.setPointedExpressionLayout(newChild); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - m_cursor.setPositionInside(0); + if (event == Ion::Events::Up) { + return m_cursor.moveUp(); + } + if (event == Ion::Events::Down) { + return m_cursor.moveDown(); + } + return false; +} + +ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { + if (event == Ion::Events::Division) { + return m_cursor.addEmptyFractionLayout(); + } + if (event.hasText()) { + return m_cursor.insertText(event.text()); + } + return nullptr; } } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index f95e5513b..e285ff8a8 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -18,7 +18,9 @@ public: void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; private: - void insertTextAtCursor(const char * text); + bool privateHandleEvent(Ion::Events::Event event); + bool handleMoveEvent(Ion::Events::Event event); + Poincare::ExpressionLayout * handleAddEvent(Ion::Events::Event event); ExpressionEditorView m_view; Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 0fe1f689e..88b29d81f 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -29,18 +29,23 @@ public: void setPositionInside(int positionInside) { m_positionInside = positionInside; } KDCoordinate cursorHeight() const { return k_cursorHeight; } - /* Move */ - bool moveLeft(); - bool moveRight(); - bool moveUp(); - bool moveDown(); - /* Comparison */ bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex = 0); /* Position */ KDPoint middleLeftPoint(); KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position, int positionInside = 0); + + /* Move */ + bool moveLeft(); + bool moveRight(); + bool moveUp(); + bool moveDown(); + + /* Edition */ + ExpressionLayout * addEmptyFractionLayout(); + ExpressionLayout * insertText(const char * text); + private: constexpr static KDCoordinate k_cursorHeight = 18; ExpressionLayout * m_pointedExpressionLayout; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 5fd6c0887..1fc9935bc 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,25 +1,12 @@ #include #include +#include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. #include namespace Poincare { -bool ExpressionLayoutCursor::moveLeft() { - return m_pointedExpressionLayout->moveLeft(this); -} - -bool ExpressionLayoutCursor::moveRight() { - return m_pointedExpressionLayout->moveRight(this); -} - -bool ExpressionLayoutCursor::moveUp() { - return m_pointedExpressionLayout->moveUp(this); -} - -bool ExpressionLayoutCursor::moveDown() { - return m_pointedExpressionLayout->moveDown(this); -} - bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex) { assert(expressionLayout != nullptr); return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position, positionIndex); @@ -42,5 +29,43 @@ KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expre return KDPoint(layoutOrigin.x() + positionInside * KDText::charSize().width(), y); } +bool ExpressionLayoutCursor::moveLeft() { + return m_pointedExpressionLayout->moveLeft(this); +} + +bool ExpressionLayoutCursor::moveRight() { + return m_pointedExpressionLayout->moveRight(this); +} + +bool ExpressionLayoutCursor::moveUp() { + return m_pointedExpressionLayout->moveUp(this); +} + +bool ExpressionLayoutCursor::moveDown() { + return m_pointedExpressionLayout->moveDown(this); +} + +ExpressionLayout * ExpressionLayoutCursor::addEmptyFractionLayout() { + EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + FractionLayout * newChild = new FractionLayout(child1, child2, false); + pointedExpressionLayout()->addBrother(this, newChild); + return child1; +} + +ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { + int textLength = strlen(text); + if (textLength <= 0) { + return nullptr; + } + CharLayout * newChild = nullptr; + for (int i = 0; i < textLength; i++) { + newChild = new CharLayout(text[i]); + pointedExpressionLayout()->addBrother(this, newChild); + } + assert(newChild != nullptr); + return newChild; +} + } From 940f2cf38746c42e5542d4984ecbf13f1685e430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 11:25:33 +0100 Subject: [PATCH 039/459] [poincare] Delete empty layouts when adding something next to them. Change-Id: Ie89fa84edb0bdd57ead42fac68cbb564c5327556 --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/layout/empty_layout.cpp | 4 ++++ poincare/src/layout/empty_layout.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 1e48236df..5398dee72 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -47,7 +47,7 @@ public: bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); - void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index fe9a28222..5d8919441 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -15,6 +15,10 @@ ExpressionLayout * EmptyLayout::clone() const { return layout; } +void EmptyLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { + replaceWith(brother, true); +} + bool EmptyLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Ask the parent. diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 5573b0207..2c746faba 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -10,6 +10,7 @@ class EmptyLayout : public StaticLayoutHierarchy<0> { public: EmptyLayout(); ExpressionLayout * clone() const override; + void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: From 7b2c48465e17a7f92389b979fbc564d1b82b37e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 13:29:23 +0100 Subject: [PATCH 040/459] [expression_editor] Handle Exp, Log, Power, Sqrt and Square events. Change-Id: I96ab58d6f66fcb6aa95ba849d927236cfb5fcc28 --- apps/expression_editor/controller.cpp | 27 ++++++++ .../poincare/expression_layout_cursor.h | 5 ++ poincare/src/expression_layout_cursor.cpp | 69 +++++++++++++++++-- .../src/layout/bracket_left_right_layout.cpp | 6 +- poincare/src/layout/bracket_right_layout.cpp | 11 +-- poincare/src/layout/empty_visible_layout.h | 2 +- .../layout/parenthesis_left_right_layout.cpp | 2 +- 7 files changed, 104 insertions(+), 18 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 7e747e03d..1ed4f7d7e 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -64,6 +64,14 @@ bool Controller::handleMoveEvent(Ion::Events::Event event) { if (event == Ion::Events::Down) { return m_cursor.moveDown(); } + if (event == Ion::Events::ShiftLeft) { + //TODO + return false; + } + if (event == Ion::Events::ShiftRight) { + //TODO + return false; + } return false; } @@ -71,6 +79,25 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { if (event == Ion::Events::Division) { return m_cursor.addEmptyFractionLayout(); } + if (event == Ion::Events::XNT) { + //TODO + return nullptr; + } + if (event == Ion::Events::Exp) { + return m_cursor.addEmptyExponentialLayout(); + } + if (event == Ion::Events::Log) { + return m_cursor.addEmptyLogarithmLayout(); + } + if (event == Ion::Events::Power) { + return m_cursor.addEmptyPowerLayout(); + } + if (event == Ion::Events::Sqrt) { + return m_cursor.addEmptyRootLayout(); + } + if (event == Ion::Events::Square) { + return m_cursor.addEmptySquarePowerLayout(); + } if (event.hasText()) { return m_cursor.insertText(event.text()); } diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 88b29d81f..d7bb195ff 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -43,7 +43,12 @@ public: bool moveDown(); /* Edition */ + ExpressionLayout * addEmptyExponentialLayout(); ExpressionLayout * addEmptyFractionLayout(); + ExpressionLayout * addEmptyLogarithmLayout(); + ExpressionLayout * addEmptyPowerLayout(); + ExpressionLayout * addEmptyRootLayout(); + ExpressionLayout * addEmptySquarePowerLayout(); ExpressionLayout * insertText(const char * text); private: diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 1fc9935bc..8db913a3f 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,8 +1,15 @@ #include #include #include //TODO move from there. -#include //TODO move from there. +#include //TODO move from there. #include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. +#include //TODO move from there. +#include #include namespace Poincare { @@ -45,6 +52,14 @@ bool ExpressionLayoutCursor::moveDown() { return m_pointedExpressionLayout->moveDown(this); } +ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { + CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + pointedExpressionLayout()->addBrother(this, newChild); + return child2; +} + ExpressionLayout * ExpressionLayoutCursor::addEmptyFractionLayout() { EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); @@ -53,15 +68,61 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyFractionLayout() { return child1; } +ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { + StringLayout * child1 = new StringLayout("log", 3); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Subscript, false); + m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout = newChild; + m_position = Position::Right; + return insertText("()"); +} + +ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { + EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + m_pointedExpressionLayout->addBrother(this, newChild); + return child1; +} + +ExpressionLayout * ExpressionLayoutCursor::addEmptyRootLayout() { + EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); + NthRootLayout * newChild = new NthRootLayout(child1, child2, false); + m_pointedExpressionLayout->addBrother(this, newChild); + return child1; +} + +ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { + EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + CharLayout * child2 = new CharLayout('2'); + EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + m_pointedExpressionLayout->addBrother(this, newChild); + return child1; +} + ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { int textLength = strlen(text); if (textLength <= 0) { return nullptr; } - CharLayout * newChild = nullptr; + ExpressionLayout * newChild = nullptr; for (int i = 0; i < textLength; i++) { - newChild = new CharLayout(text[i]); - pointedExpressionLayout()->addBrother(this, newChild); + if (text[i] == '(') { + newChild = new ParenthesisLeftLayout(); + } else if (text[i] == ')') { + newChild = new ParenthesisRightLayout(); + } else if (text[i] == '[') { + newChild = new BracketLeftLayout(); + } else if (text[i] == ']') { + newChild = new BracketRightLayout(); + } else { + newChild = new CharLayout(text[i]); + } + m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout = newChild; + m_position = Position::Right; } assert(newChild != nullptr); return newChild; diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index 98d01121e..3a43c0536 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -9,7 +9,7 @@ namespace Poincare { BracketLeftRightLayout::BracketLeftRightLayout() : StaticLayoutHierarchy<0>(), - m_operandHeight(36) //TODO + m_operandHeight(18) //TODO { } @@ -50,12 +50,12 @@ bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { KDSize BracketLeftRightLayout::computeSize() { //TODO: compute the operandHeight according to the brothers - return KDSize(k_externWidthMargin + k_lineThickness + k_bracketWidth + k_widthMargin, m_operandHeight); + return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, m_operandHeight); } void BracketLeftRightLayout::computeBaseline() { //TODO: compute the operandHeight according to the brothers - m_baseline = m_operandHeight; + m_baseline = m_operandHeight/2; m_baselined = true; } diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp index 86c43e66f..c6f8bbb14 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -10,15 +10,8 @@ ExpressionLayout * BracketRightLayout::clone() const { void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { //TODO Make sure m_operandHeight is up-to-date. ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); - ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); } } - - - - - - - diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 7a88565b9..1a549d9ce 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -20,7 +20,7 @@ private: constexpr static KDCoordinate k_width = 7; constexpr static KDCoordinate k_height = 13; constexpr static KDCoordinate k_marginWidth = 1; - constexpr static KDCoordinate k_marginHeight = 3; + constexpr static KDCoordinate k_marginHeight = 2; constexpr static KDCoordinate k_lineThickness = 1; KDColor m_fillRectColor; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 1baceff6b..0764efa73 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -9,7 +9,7 @@ namespace Poincare { ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : StaticLayoutHierarchy<0>(), - m_operandHeight(36) //TODO + m_operandHeight(18) //TODO { computeBaseline(); } From 8289e24cfec9579e151e7718b420d8fdd90226c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 13:43:31 +0100 Subject: [PATCH 041/459] [expression_editor] Handle XNT event. Change-Id: I0af832ec0f693c445e424d21795b14cfb4e54622 --- apps/expression_editor/controller.cpp | 3 +-- poincare/include/poincare/expression_layout.h | 6 +++++- poincare/include/poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 6 ++++++ poincare/src/layout/expression_layout.cpp | 7 +++++++ poincare/src/layout/sequence_layout.cpp | 4 ++++ poincare/src/layout/sequence_layout.h | 1 + 7 files changed, 25 insertions(+), 3 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 1ed4f7d7e..40563a736 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -80,8 +80,7 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { return m_cursor.addEmptyFractionLayout(); } if (event == Ion::Events::XNT) { - //TODO - return nullptr; + return m_cursor.addXNTCharLayout(); } if (event == Ion::Events::Exp) { return m_cursor.addEmptyExponentialLayout(); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 5398dee72..021f891da 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -63,13 +63,17 @@ public: bool moveUpInside(ExpressionLayoutCursor * cursor); virtual bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); bool moveDownInside(ExpressionLayoutCursor * cursor); + + /* Other */ + virtual char XNTChar() const; + protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; virtual KDSize computeSize() = 0; virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; void detachChildAtIndex(int i); - virtual void moveCursorInsideAtDirection ( + virtual void moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout ** childResult, diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index d7bb195ff..5b9dfae37 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -49,6 +49,7 @@ public: ExpressionLayout * addEmptyPowerLayout(); ExpressionLayout * addEmptyRootLayout(); ExpressionLayout * addEmptySquarePowerLayout(); + ExpressionLayout * addXNTCharLayout(); ExpressionLayout * insertText(const char * text); private: diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 8db913a3f..19016af2c 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -102,6 +102,12 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { return child1; } +ExpressionLayout * ExpressionLayoutCursor::addXNTCharLayout() { + CharLayout * newChild = new CharLayout(m_pointedExpressionLayout->XNTChar()); + m_pointedExpressionLayout->addBrother(this, newChild); + return newChild; +} + ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { int textLength = strlen(text); if (textLength <= 0) { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 3a92820d7..cb2bdb2a0 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -189,6 +189,13 @@ void ExpressionLayout::detachChild(const ExpressionLayout * e) { } } +char ExpressionLayout::XNTChar() const { + if (m_parent == nullptr) { + return 'x'; + } + return m_parent->XNTChar(); +} + void ExpressionLayout::detachChildAtIndex(int i) { ExpressionLayout ** op = const_cast(children()); if (op[i] != nullptr && op[i]->parent() == this) { diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 3955f77b3..691a9a29c 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -128,6 +128,10 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +char SequenceLayout::XNTChar() const { + return 'n'; +} + ExpressionLayout * SequenceLayout::upperBoundLayout() { return editableChild(0); } diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 6e186982d..98e100420 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -14,6 +14,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + char XNTChar() const override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; ExpressionLayout * lowerBoundLayout(); From 37af76512441009f5c793c3df628745937bda0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 13:55:50 +0100 Subject: [PATCH 042/459] [expression_editor] Edit when the cursor points to the main layout. Change-Id: Idc11cfca8aa318803ba243f6649cad6f8662f7f6 --- poincare/src/layout/expression_layout.cpp | 19 +++++++++++++++---- poincare/src/layout/horizontal_layout.cpp | 6 ------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index cb2bdb2a0..06321efe7 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -125,12 +125,23 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay if (m_parent->addChildAtIndex(brother, brotherIndex)) { return; } - } - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - replaceWithJuxtapositionOf(brother, this, false); + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + replaceWithJuxtapositionOf(brother, this, false); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + replaceWithJuxtapositionOf(this, brother, false); return; } - replaceWithJuxtapositionOf(this, brother, false); + // If there is no parent, the pointed layout is the main horizontal layout. + // Add the "brother" as a child. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + addChildAtIndex(brother, 0); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + addChildAtIndex(brother, numberOfChildren()); + return; } bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index dc627bee9..0be29923c 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -61,9 +61,6 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: the child is the leftmost. // Ask the parent. if (m_parent) { - // Only move the cursor if the layout has a parent: If not, the cursor - // would go on the extrema of the main HorizontalLayout, which prevents - // the user from adding more text. cursor->setPointedExpressionLayout(this); return m_parent->moveLeft(cursor); } @@ -111,9 +108,6 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: the child is the rightmost. // Ask the parent. if (m_parent) { - // Only move the cursor if the layout has a parent: If not, the cursor - // would go on the extrema of the main HorizontalLayout, which prevents - // the user from adding more text. cursor->setPointedExpressionLayout(this); return m_parent->moveRight(cursor); } From c24de3c06915659ce6fcef5ff8a36d46268cfbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 13:58:31 +0100 Subject: [PATCH 043/459] [expression_editor] Handle ShiftLeft and ShiftRight events. Change-Id: Id416d1c95d023b8a0a4348a2570dd332615aa2b8 --- apps/expression_editor/controller.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 40563a736..3be04567e 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -65,12 +65,17 @@ bool Controller::handleMoveEvent(Ion::Events::Event event) { return m_cursor.moveDown(); } if (event == Ion::Events::ShiftLeft) { - //TODO - return false; + // The cursor should never point to the main HorizontalLayout. + m_cursor.setPointedExpressionLayout(m_expressionLayout); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Left); + m_cursor.setPositionInside(0); + return true; } if (event == Ion::Events::ShiftRight) { - //TODO - return false; + m_cursor.setPointedExpressionLayout(m_expressionLayout); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); + m_cursor.setPositionInside(0); + return true; } return false; } From 0d8b6d5ace517d50c007299a06cae14cebaaeb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 15:24:50 +0100 Subject: [PATCH 044/459] [escher/poincare] Handle toolbox input (VERY DIRTY). Change-Id: I01de0ddd6f6500df278e3b4104110f6335289be1 --- apps/expression_editor/app.h | 3 ++ apps/expression_editor/controller.cpp | 19 ++++++++- apps/expression_editor/controller.h | 7 ++++ apps/math_toolbox.cpp | 40 ++++++++++++------- apps/math_toolbox.h | 4 +- escher/include/escher/toolbox_message_tree.h | 8 +++- .../poincare/expression_layout_cursor.h | 1 + poincare/include/poincare_layouts.h | 32 +++++++++++++++ poincare/src/expression_layout_cursor.cpp | 4 ++ 9 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 poincare/include/poincare_layouts.h diff --git a/apps/expression_editor/app.h b/apps/expression_editor/app.h index f90805121..84b537833 100644 --- a/apps/expression_editor/app.h +++ b/apps/expression_editor/app.h @@ -2,6 +2,7 @@ #define EXPRESSION_EDITOR_APP_H #include +#include #include "controller.h" #include "expression_and_layout.h" @@ -25,9 +26,11 @@ public: private: ExpressionAndLayout m_expressionAndLayout; }; + MathToolbox * mathToolbox() { return &m_toolbox; } private: App(Container * container, Snapshot * snapshot); Controller m_controller; + MathToolbox m_toolbox; }; } diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 3be04567e..f29c14c61 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,4 +1,5 @@ #include "controller.h" +#include using namespace Poincare; @@ -32,7 +33,23 @@ bool Controller::handleEvent(Ion::Events::Event event) { m_view.cursorPositionChanged(); return true; } - return false; + return Responder::handleEvent(event); +} + +Toolbox * Controller::toolbox() { + ExpressionEditor::App * expressionEditorApp = static_cast(app()); + return expressionEditorApp->mathToolbox(); +} + +void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayout * pointedLayout) { + if (layout == nullptr) { + return; + } + m_cursor.addLayout(layout); + m_cursor.setPointedExpressionLayout(pointedLayout); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); + m_cursor.setPositionInside(0); + m_view.cursorPositionChanged(); } bool Controller::privateHandleEvent(Ion::Events::Event event) { diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index e285ff8a8..f34518ff5 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -17,6 +17,13 @@ public: View * view() override { return &m_view; } void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; + + /* Responder */ + Toolbox * toolbox() override; + + /* Callback for Toolbox */ + void insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayout * pointedLayout); + private: bool privateHandleEvent(Ion::Events::Event event); bool handleMoveEvent(Ion::Events::Event event); diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index caa25e6dc..b0e319531 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -9,8 +9,8 @@ * subtree, the edited text is set at I18n::Message::Default. */ const ToolboxMessageTree calculChildren[4] = { - ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg), - ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg), + ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), + ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, new IntegralLayout(new EmptyVisibleLayout(), new EmptyVisibleLayout, new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2(new EmptyVisibleLayout(), new StringLayout("dx",2))), 2, false), false)), ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; @@ -102,22 +102,34 @@ MathToolbox::MathToolbox() : Toolbox(nullptr, I18n::translate(rootModel()->label { } -TextField * MathToolbox::sender() { - return (TextField *)Toolbox::sender(); +TextField * MathToolbox::textFieldSender() { + return static_cast(Toolbox::sender()); +} + +ExpressionEditor::Controller * MathToolbox::expressionEditorControllerSender() { + return static_cast(Toolbox::sender()); } bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { - m_selectableTableView.deselectTable(); - ToolboxMessageTree * messageTree = selectedMessageTree; - const char * editedText = I18n::translate(messageTree->insertedText()); - if (!sender()->isEditing()) { - sender()->setEditing(true); + if (0) { + m_selectableTableView.deselectTable(); + ToolboxMessageTree * messageTree = selectedMessageTree; + const char * editedText = I18n::translate(messageTree->insertedText()); + if (!textFieldSender()->isEditing()) { + textFieldSender()->setEditing(true); + } + char strippedEditedText[strlen(editedText)]; + Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedEditedText); + textFieldSender()->insertTextAtLocation(strippedEditedText, textFieldSender()->cursorLocation()); + int newCursorLocation = textFieldSender()->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedEditedText); + textFieldSender()->setCursorLocation(newCursorLocation); + app()->dismissModalViewController(); + return true; } - char strippedEditedText[strlen(editedText)]; - Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedEditedText); - sender()->insertTextAtLocation(strippedEditedText, sender()->cursorLocation()); - int newCursorLocation = sender()->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedEditedText); - sender()->setCursorLocation(newCursorLocation); + // Deal with ExpressionEditor::Controller for now. + m_selectableTableView.deselectTable(); + ExpressionLayout * newLayout = selectedMessageTree->layout()->clone(); + expressionEditorControllerSender()->insertLayoutAtCursor(newLayout, newLayout->editableChild(2)->editableChild(0)); app()->dismissModalViewController(); return true; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 0579969de..9da44865b 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -4,12 +4,14 @@ #define MATRICES_ARE_DEFINED 1 #include #include +#include class MathToolbox : public Toolbox { public: MathToolbox(); protected: - TextField * sender() override; + TextField * textFieldSender(); + ExpressionEditor::Controller * expressionEditorControllerSender(); bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; MessageTableCellWithMessage * leafCellAtIndex(int index) override; diff --git a/escher/include/escher/toolbox_message_tree.h b/escher/include/escher/toolbox_message_tree.h index 10e5cb336..aebf25db4 100644 --- a/escher/include/escher/toolbox_message_tree.h +++ b/escher/include/escher/toolbox_message_tree.h @@ -2,23 +2,27 @@ #define ESCHER_TOOLBOX_MESSAGE_TREE_H #include +#include class ToolboxMessageTree : public MessageTree { public: - constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0) : + constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, Poincare::ExpressionLayout * layout = nullptr) : MessageTree(label, numberOfChildren), m_children(children), m_text(text), - m_insertedText(insertedText) + m_insertedText(insertedText), + m_layout(layout) { }; const MessageTree * children(int index) const override; I18n::Message text() const; I18n::Message insertedText() const; + Poincare::ExpressionLayout * layout() const { return m_layout; } private: const ToolboxMessageTree * m_children; I18n::Message m_text; I18n::Message m_insertedText; + Poincare::ExpressionLayout * m_layout; }; #endif diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 5b9dfae37..5813fee8c 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -43,6 +43,7 @@ public: bool moveDown(); /* Edition */ + void addLayout(ExpressionLayout * layout); ExpressionLayout * addEmptyExponentialLayout(); ExpressionLayout * addEmptyFractionLayout(); ExpressionLayout * addEmptyLogarithmLayout(); diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h new file mode 100644 index 000000000..f3d71feae --- /dev/null +++ b/poincare/include/poincare_layouts.h @@ -0,0 +1,32 @@ +#ifndef POINCARE_LAYOUTS_H +#define POINCARE_LAYOUTS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 19016af2c..d10c759e6 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -52,6 +52,10 @@ bool ExpressionLayoutCursor::moveDown() { return m_pointedExpressionLayout->moveDown(this); } +void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { + pointedExpressionLayout()->addBrother(this, layout); +} + ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); From 14f2e08872160198b245bb1e523cffa0780b0305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 18:01:24 +0100 Subject: [PATCH 045/459] [poincare/escher] Tell which layout is pointed when adding from toolbox. Change-Id: I84c82ea887e3e7759da7d407532dc7d63174f1ac --- apps/math_toolbox.cpp | 29 ++++++++++++++++++-- escher/include/escher/toolbox_message_tree.h | 10 +++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index b0e319531..c9e4ae3ec 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -8,10 +8,29 @@ * and the text which would be edited by clicking on the row. When the node is a * subtree, the edited text is set at I18n::Message::Default. */ +const int pointedLayoutPathIntegral[] = {2, 0}; +const int pointedLayoutPathSum[] = {2}; const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), - ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, new IntegralLayout(new EmptyVisibleLayout(), new EmptyVisibleLayout, new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2(new EmptyVisibleLayout(), new StringLayout("dx",2))), 2, false), false)), - ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg), + ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, + new IntegralLayout( + new EmptyVisibleLayout(), + new EmptyVisibleLayout(), + new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + new EmptyVisibleLayout(), + new StringLayout("dx",2))), 2, false), false), + const_cast(&pointedLayoutPathIntegral[0]), + 2), + ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, + new SumLayout( + new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + new StringLayout("n=",2), + new EmptyVisibleLayout())), 2, false), + new EmptyVisibleLayout(), + new EmptyVisibleLayout(), + false), + const_cast(&pointedLayoutPathSum[0]), + 1), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; const ToolboxMessageTree complexChildren[5] = { @@ -129,7 +148,11 @@ bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { // Deal with ExpressionEditor::Controller for now. m_selectableTableView.deselectTable(); ExpressionLayout * newLayout = selectedMessageTree->layout()->clone(); - expressionEditorControllerSender()->insertLayoutAtCursor(newLayout, newLayout->editableChild(2)->editableChild(0)); + ExpressionLayout * pointedLayout = newLayout; + for (int i = 0; i < selectedMessageTree->pointedPathLength(); i++) { + pointedLayout = pointedLayout->editableChild(selectedMessageTree->pointedPath()[i]); + } + expressionEditorControllerSender()->insertLayoutAtCursor(newLayout, pointedLayout); app()->dismissModalViewController(); return true; } diff --git a/escher/include/escher/toolbox_message_tree.h b/escher/include/escher/toolbox_message_tree.h index aebf25db4..253ce36ce 100644 --- a/escher/include/escher/toolbox_message_tree.h +++ b/escher/include/escher/toolbox_message_tree.h @@ -6,23 +6,29 @@ class ToolboxMessageTree : public MessageTree { public: - constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, Poincare::ExpressionLayout * layout = nullptr) : + constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, Poincare::ExpressionLayout * layout = nullptr, int * pointedLayoutPath = nullptr, int pointedLayoutPathLength = 0) : MessageTree(label, numberOfChildren), m_children(children), m_text(text), m_insertedText(insertedText), - m_layout(layout) + m_layout(layout), + m_pointedLayoutPath(pointedLayoutPath), + m_pointedLayoutPathLength(pointedLayoutPathLength) { }; const MessageTree * children(int index) const override; I18n::Message text() const; I18n::Message insertedText() const; Poincare::ExpressionLayout * layout() const { return m_layout; } + int * pointedPath() const { return m_pointedLayoutPath; } + int pointedPathLength() const { return m_pointedLayoutPathLength; } private: const ToolboxMessageTree * m_children; I18n::Message m_text; I18n::Message m_insertedText; Poincare::ExpressionLayout * m_layout; + int * m_pointedLayoutPath; + int m_pointedLayoutPathLength; }; #endif From b47a5fa939bf51d002b89f57cfb532608f75b94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 18:03:11 +0100 Subject: [PATCH 046/459] [poincare] Handle parentheses sizing. Change-Id: I3f790c0eb73b566dd7de7089957ea0d4306821c2 --- apps/expression_editor/controller.cpp | 1 + poincare/include/poincare/expression_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 3 +- .../src/layout/parenthesis_left_layout.cpp | 37 +++++++++++++++++-- poincare/src/layout/parenthesis_left_layout.h | 3 ++ .../layout/parenthesis_left_right_layout.cpp | 20 ++++++---- .../layout/parenthesis_left_right_layout.h | 5 ++- .../src/layout/parenthesis_right_layout.cpp | 35 ++++++++++++++++-- .../src/layout/parenthesis_right_layout.h | 3 ++ 9 files changed, 95 insertions(+), 16 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index f29c14c61..625ac72a0 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -49,6 +49,7 @@ void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayou m_cursor.setPointedExpressionLayout(pointedLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); m_cursor.setPositionInside(0); + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.cursorPositionChanged(); } diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 021f891da..5ffac5992 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -31,7 +31,7 @@ public: KDPoint absoluteOrigin(); KDSize size(); KDCoordinate baseline(); - void invalidAllSizesPositionsAndBaselines(); + virtual void invalidAllSizesPositionsAndBaselines(); /* Hierarchy */ virtual const ExpressionLayout * const * children() const = 0; @@ -65,6 +65,8 @@ public: bool moveDownInside(ExpressionLayoutCursor * cursor); /* Other */ + virtual bool isLeftParenthesis() const { return false; } + virtual bool isRightParenthesis() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 06321efe7..9f19d4040 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -13,7 +13,8 @@ ExpressionLayout::ExpressionLayout() : m_sized(false), m_baselined(false), m_positioned(false), - m_frame(KDRectZero) { + m_frame(KDRectZero) +{ } const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2) { diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 43e3939db..6af8a7172 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -32,7 +32,6 @@ ExpressionLayout * ParenthesisLeftLayout::clone() const { } void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, @@ -41,7 +40,7 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -50,8 +49,40 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_lineThickness, - m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } +void ParenthesisLeftLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = 18; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightParenthesis()) { + return; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void ParenthesisLeftLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightParenthesis()) { + break; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; +} + } diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index ad0b60906..538d5c2de 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -9,8 +9,11 @@ class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + bool isLeftParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; } diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 0764efa73..f3b77ee95 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -9,9 +9,13 @@ namespace Poincare { ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : StaticLayoutHierarchy<0>(), - m_operandHeight(18) //TODO + m_operandHeightComputed(false) { - computeBaseline(); +} + +void ParenthesisLeftRightLayout::invalidAllSizesPositionsAndBaselines() { + m_operandHeightComputed = false; + ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -49,13 +53,15 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { } KDSize ParenthesisLeftRightLayout::computeSize() { - //TODO: compute the operandHeight according to the brothers - return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, m_operandHeight); + return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, operandHeight()); } -void ParenthesisLeftRightLayout::computeBaseline() { - m_baseline = m_operandHeight/2; //TODO - m_baselined = true; +KDCoordinate ParenthesisLeftRightLayout::operandHeight() { + if (!m_operandHeightComputed) { + computeOperandHeight(); + m_operandHeightComputed = true; + } + return m_operandHeight; } KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 67381f10a..3ad0a296b 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLeftRightLayout(); + void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; @@ -19,8 +20,10 @@ public: protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; - void computeBaseline() override; + KDCoordinate operandHeight(); + virtual void computeOperandHeight() = 0; KDPoint positionOfChild(ExpressionLayout * child) override; + bool m_operandHeightComputed; uint16_t m_operandHeight; }; } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index d9a8d4c6c..55fc71743 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -32,7 +32,6 @@ ExpressionLayout * ParenthesisRightLayout::clone() const { } void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, p.y() + ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, @@ -41,7 +40,7 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -50,10 +49,40 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_widthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+2, ParenthesisLeftRightLayout::k_lineThickness, - m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } +void ParenthesisRightLayout::computeOperandHeight() { + m_operandHeight = 18; + assert(m_parent != nullptr); + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftParenthesis()) { + return; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void ParenthesisRightLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftParenthesis()) { + break; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; +} + } diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 7daba2368..c03d19efd 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -9,8 +9,11 @@ class ParenthesisRightLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + bool isRightParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; } From 38d1da9e6df9e2f1fbb81528c1828b7f767479bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 18:03:55 +0100 Subject: [PATCH 047/459] [poincare] Fix bug in IntegralLayout navigation assert. Change-Id: Idecb17678d1e858aca9d453c8e0f44988005c2b0 --- poincare/src/layout/integral_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 4e912dd91..ae3db3355 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -101,7 +101,7 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(upperBoundLayout()); return true; } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); // Case: Right. // Ask the parent. if (m_parent) { From b327989975e49eaa70c504a3810a38742cefdd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Dec 2017 18:04:37 +0100 Subject: [PATCH 048/459] [poincare] Change StringLayout navigation to handle dx in integrals. The cursor should avoid being on the left or right of a string layout, otherwise there will be problems when serializing an integral. Change-Id: If801247638e3d5eb3e36deaafbe9179759b48034 --- poincare/src/layout/string_layout.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index 43996cd7d..f2be896e3 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -43,18 +43,27 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { // A StringLayout is not editable, and the cursor cannot go inside it. assert(cursor->pointedExpressionLayout() == this); + assert(m_parent != nullptr); // Case: Left. // Go Right. + // If there is a Right brother, go Left of it. Else go Right of the grandparent. + // //TODO explain that it is because of integrals and baselayouts. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + int indexOfThis = m_parent->indexOfChild(this); + if (m_parent->editableChild(indexOfThis+1) != nullptr) { + cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis+1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + if (m_parent->parent()) { + cursor->setPointedExpressionLayout(const_cast(m_parent->parent())); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } } // Case: Right. // Ask the parent. - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; + return m_parent->moveRight(cursor); } void StringLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { From ad3ca09ba1e1cf1c1191347615da80d591d7221c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 09:46:15 +0100 Subject: [PATCH 049/459] [poincare] Handle nested parentheses when computing height and baseline. Change-Id: I15f266f1dddd1eb49b4d713348f8031c51104a6b --- .../src/layout/parenthesis_left_layout.cpp | 16 ++++++++++++-- .../src/layout/parenthesis_right_layout.cpp | 21 ++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 6af8a7172..f191d68ee 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -56,11 +56,17 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio void ParenthesisLeftLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = 18; + int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isRightParenthesis()) { - return; + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + return; + } + } else if (brother->isLeftParenthesis()) { + currentNumberOfOpenParentheses++; } KDCoordinate brotherHeight = brother->size().height(); if (brotherHeight > m_operandHeight) { @@ -72,11 +78,17 @@ void ParenthesisLeftLayout::computeOperandHeight() { void ParenthesisLeftLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; + int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isRightParenthesis()) { - break; + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + break; + } + } else if (brother->isLeftParenthesis()) { + currentNumberOfOpenParentheses++; } if (brother->baseline() > m_baseline) { m_baseline = brother->baseline(); diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 55fc71743..d3b0efb0d 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -54,14 +54,19 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi } void ParenthesisRightLayout::computeOperandHeight() { - m_operandHeight = 18; assert(m_parent != nullptr); + m_operandHeight = 18; + int currentNumberOfOpenParentheses = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isLeftParenthesis()) { - return; - } - KDCoordinate brotherHeight = brother->size().height(); + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + return; + } + } else if (brother->isRightParenthesis()) { + currentNumberOfOpenParentheses++; + } KDCoordinate brotherHeight = brother->size().height(); if (brotherHeight > m_operandHeight) { m_operandHeight = brotherHeight; } @@ -71,10 +76,16 @@ void ParenthesisRightLayout::computeOperandHeight() { void ParenthesisRightLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; + int currentNumberOfOpenParentheses = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isLeftParenthesis()) { - break; + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + break; + } + } else if (brother->isRightParenthesis()) { + currentNumberOfOpenParentheses++; } if (brother->baseline() > m_baseline) { m_baseline = brother->baseline(); From c697b77437beea3b53f34c8c42f464c9174c4cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 10:41:12 +0100 Subject: [PATCH 050/459] [poincare] UneditableParenthesisLayout left and right. Change-Id: Ib5d7fdb887513270a70fe77a287ccfd638fea098 --- poincare/Makefile | 2 ++ .../uneditable_parenthesis_left_layout.cpp | 33 +++++++++++++++++++ .../uneditable_parenthesis_left_layout.h | 18 ++++++++++ .../uneditable_parenthesis_right_layout.cpp | 33 +++++++++++++++++++ .../uneditable_parenthesis_right_layout.h | 18 ++++++++++ 5 files changed, 104 insertions(+) create mode 100644 poincare/src/layout/uneditable_parenthesis_left_layout.cpp create mode 100644 poincare/src/layout/uneditable_parenthesis_left_layout.h create mode 100644 poincare/src/layout/uneditable_parenthesis_right_layout.cpp create mode 100644 poincare/src/layout/uneditable_parenthesis_right_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index d5e88b035..d20f96750 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -114,6 +114,8 @@ objs += $(addprefix poincare/src/layout/,\ static_layout_hierarchy.o\ string_layout.o\ sum_layout.o\ + uneditable_parenthesis_left_layout.o\ + uneditable_parenthesis_right_layout.o\ ) tests += $(addprefix poincare/test/,\ diff --git a/poincare/src/layout/uneditable_parenthesis_left_layout.cpp b/poincare/src/layout/uneditable_parenthesis_left_layout.cpp new file mode 100644 index 000000000..5281934ee --- /dev/null +++ b/poincare/src/layout/uneditable_parenthesis_left_layout.cpp @@ -0,0 +1,33 @@ +#include "uneditable_parenthesis_left_layout.h" +#include +extern "C" { +#include +} + +namespace Poincare { + +ExpressionLayout * UneditableParenthesisLeftLayout::clone() const { + return new UneditableParenthesisLeftLayout(); +} + +bool UneditableParenthesisLeftLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return m_parent->moveLeft(cursor); + } + return false; +} + +bool UneditableParenthesisLeftLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return m_parent->moveRight(cursor); + } + return false; +} + +} diff --git a/poincare/src/layout/uneditable_parenthesis_left_layout.h b/poincare/src/layout/uneditable_parenthesis_left_layout.h new file mode 100644 index 000000000..b3b693330 --- /dev/null +++ b/poincare/src/layout/uneditable_parenthesis_left_layout.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_UNEDITABLE_PARENTHESIS_LEFT_LAYOUT_H +#define POINCARE_UNEDITABLE_PARENTHESIS_LEFT_LAYOUT_H + +#include + +namespace Poincare { + +class UneditableParenthesisLeftLayout : public ParenthesisLeftLayout { +public: + using ParenthesisLeftLayout::ParenthesisLeftLayout; + ExpressionLayout * clone() const override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; +}; + +} + +#endif diff --git a/poincare/src/layout/uneditable_parenthesis_right_layout.cpp b/poincare/src/layout/uneditable_parenthesis_right_layout.cpp new file mode 100644 index 000000000..bba558231 --- /dev/null +++ b/poincare/src/layout/uneditable_parenthesis_right_layout.cpp @@ -0,0 +1,33 @@ +#include "uneditable_parenthesis_right_layout.h" +#include +extern "C" { +#include +} + +namespace Poincare { + +ExpressionLayout * UneditableParenthesisRightLayout::clone() const { + return new UneditableParenthesisRightLayout(); +} + +bool UneditableParenthesisRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return m_parent->moveLeft(cursor); + } + return false; +} + +bool UneditableParenthesisRightLayout::moveRight(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + // Ask the parent. + if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return m_parent->moveRight(cursor); + } + return false; +} + +} diff --git a/poincare/src/layout/uneditable_parenthesis_right_layout.h b/poincare/src/layout/uneditable_parenthesis_right_layout.h new file mode 100644 index 000000000..2025f4a25 --- /dev/null +++ b/poincare/src/layout/uneditable_parenthesis_right_layout.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_UNEDITABLE_PARENTHESIS_RIGHT_LAYOUT_H +#define POINCARE_UNEDITABLE_PARENTHESIS_RIGHT_LAYOUT_H + +#include + +namespace Poincare { + +class UneditableParenthesisRightLayout : public ParenthesisRightLayout { +public: + using ParenthesisRightLayout::ParenthesisRightLayout; + ExpressionLayout * clone() const override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; +}; + +} + +#endif From 95b82adbe36f55c22117b20925aa5007ded87850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 10:41:54 +0100 Subject: [PATCH 051/459] [poincare] Added uneditable parentheses around the sum layout argument. Change-Id: Ib80000b4d41fbb36b318ba9266eb7680c9f1285a --- apps/math_toolbox.cpp | 4 +- poincare/src/layout/sequence_layout.cpp | 2 - poincare/src/layout/sequence_layout.h | 8 +- poincare/src/layout/sum_layout.cpp | 138 +++++++++++++++++++++++- poincare/src/layout/sum_layout.h | 7 +- 5 files changed, 148 insertions(+), 11 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index c9e4ae3ec..d1295a2fb 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -9,7 +9,7 @@ * subtree, the edited text is set at I18n::Message::Default. */ const int pointedLayoutPathIntegral[] = {2, 0}; -const int pointedLayoutPathSum[] = {2}; +const int pointedLayoutPathSum[] = {2, 1}; const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, @@ -30,7 +30,7 @@ const ToolboxMessageTree calculChildren[4] = { new EmptyVisibleLayout(), false), const_cast(&pointedLayoutPathSum[0]), - 1), + 2), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; const ToolboxMessageTree complexChildren[5] = { diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 691a9a29c..364fd3ed7 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -103,7 +103,6 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * } // If the cursor is Left of the argument, move it to the upper bound. if (argumentLayout() - && previousLayout == argumentLayout() && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { assert(upperBoundLayout() != nullptr); @@ -119,7 +118,6 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() - && previousLayout == argumentLayout() && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { assert(lowerBoundLayout() != nullptr); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 98e100420..e2eb0e57f 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -17,14 +17,14 @@ public: char XNTChar() const override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; + constexpr static KDCoordinate k_argumentWidthMargin = 2; ExpressionLayout * lowerBoundLayout(); ExpressionLayout * upperBoundLayout(); - ExpressionLayout * argumentLayout(); -private: + virtual ExpressionLayout * argumentLayout(); KDSize computeSize() override; - void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - constexpr static KDCoordinate k_argumentWidthMargin = 2; +private: + void computeBaseline() override; }; } diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 4515eedef..d9febe8ae 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -1,4 +1,8 @@ #include "sum_layout.h" +#include "horizontal_layout.h" +#include "uneditable_parenthesis_left_layout.h" +#include "uneditable_parenthesis_right_layout.h" +#include #include #include @@ -22,19 +26,149 @@ const uint8_t symbolPixel[SumLayout::k_symbolHeight][SumLayout::k_symbolWidth] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; +SumLayout::SumLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : + SequenceLayout(lowerBound, upperBound, argument, cloneOperands) +{ + UneditableParenthesisLeftLayout * parLeft = new UneditableParenthesisLeftLayout(); + UneditableParenthesisRightLayout * parRight = new UneditableParenthesisRightLayout(); + HorizontalLayout * horLayout = new HorizontalLayout(); + ExpressionLayout * argLayout = editableChild(2); + // We cannot call argument() because it is overrided to handle completely + // built SumLayouts, not SumLayouts in construction. + argLayout->replaceWith(horLayout, false); + horLayout->addChildAtIndex(parLeft, 0); + horLayout->addChildAtIndex(argLayout, 1); + horLayout->addChildAtIndex(parRight, 2); +} + ExpressionLayout * SumLayout::clone() const { SumLayout * layout = new SumLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); return layout; } +ExpressionLayout * SumLayout::argumentLayout() { + return editableChild(2)->editableChild(1); +} + +bool SumLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the bounds. + // Go Left of the sum. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && ((lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || (upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()))) + { + cursor->setPointedExpressionLayout(this); + return true; + } + // Case: Left of the argument. + // Go Right of the lower bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && argumentLayout() + && cursor->pointedExpressionLayout() == editableChild(2)) + { + assert(lowerBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(lowerBoundLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the argument and move Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(argumentLayout() != nullptr); + cursor->setPointedExpressionLayout(argumentLayout()); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool SumLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the bounds. + // Go Left of the argument. + if (cursor->position() == ExpressionLayoutCursor::Position::Right + && ((lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || (upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()))) + { + assert(argumentLayout() != nullptr); + cursor->setPointedExpressionLayout(argumentLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right of the argument. + // Ask the parent. + if (cursor->position() == ExpressionLayoutCursor::Position::Right + && argumentLayout() + && cursor->pointedExpressionLayout() == editableChild(2)) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the upper bound. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(upperBoundLayout() != nullptr); + cursor->setPointedExpressionLayout(upperBoundLayout()); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize upperBoundSize = upperBoundLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), - k_symbolWidth, k_symbolHeight); + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); } +KDSize SumLayout::computeSize() { + KDSize argumentSize = editableChild(2)->size(); + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); + return KDSize( + max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), + m_baseline + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) + ); +} + +KDPoint SumLayout::positionOfChild(ExpressionLayout * child) { + KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize upperBoundSize = upperBoundLayout()->size(); + KDCoordinate x = 0; + KDCoordinate y = 0; + if (child == lowerBoundLayout()) { + x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); + y = m_baseline + k_symbolHeight/2 + k_boundHeightMargin; + } else if (child == upperBoundLayout()) { + x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); + y = m_baseline - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); + } else if (child == editableChild(2)) { + x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; + y = m_baseline - argumentLayout()->baseline(); + } else { + assert(false); + } + return KDPoint(x,y); +} + } diff --git a/poincare/src/layout/sum_layout.h b/poincare/src/layout/sum_layout.h index 7218e866f..23d5f698f 100644 --- a/poincare/src/layout/sum_layout.h +++ b/poincare/src/layout/sum_layout.h @@ -7,10 +7,15 @@ namespace Poincare { class SumLayout : public SequenceLayout { public: - using SequenceLayout::SequenceLayout; + SumLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); ExpressionLayout * clone() const override; + ExpressionLayout * argumentLayout() override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + KDPoint positionOfChild(ExpressionLayout * child) override; }; } From b2962abd92557e3180a5b5b6d3eaddf95a038bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 10:53:58 +0100 Subject: [PATCH 052/459] [poincare] Make the Root layout wider to see the cursor position. Change-Id: Iba5ebb30935820c68224ff2aa0e0be2223d8a50d --- poincare/src/layout/nth_root_layout.cpp | 14 +++++++++----- poincare/src/layout/nth_root_layout.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index a52194a0f..3609284e1 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -164,16 +164,20 @@ void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, p.y() + m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, k_leftRadixWidth, k_leftRadixHeight); ctx->blendRectWithMask(leftRadixFrame, expressionColor, (const uint8_t *)radixPixel, (KDColor *)workingBuffer); + // If the indice is higher than the root. if (indexSize.height() + k_indexHeight > radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin) { + // Vertical radix bar ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, k_radixLineThickness, radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); + // Horizontal radix bar ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, - radicandSize.width() + 2*k_widthMargin, + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, k_radixLineThickness), expressionColor); - ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin, + // Right radix bar + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, k_radixLineThickness, k_rightRadixHeight + k_radixLineThickness), expressionColor); @@ -184,9 +188,9 @@ void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, p.y(), - radicandSize.width() + 2*k_widthMargin, + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, k_radixLineThickness), expressionColor); - ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin, + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, p.y(), k_radixLineThickness, k_rightRadixHeight + k_radixLineThickness), expressionColor); @@ -198,7 +202,7 @@ KDSize NthRootLayout::computeSize() { KDSize radicandSize = radicandLayout()->size(); KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); return KDSize( - indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width(), + indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width() + k_radixHorizontalOverflow, m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin ); } diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index aa7d81814..8f54033a7 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -22,6 +22,7 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_rightRadixHeight = 2; + constexpr static KDCoordinate k_radixHorizontalOverflow = 2; constexpr static KDCoordinate k_indexHeight = 5; constexpr static KDCoordinate k_heightMargin = 2; constexpr static KDCoordinate k_widthMargin = 1; From aa4ae376b3ece90bcc39c480f1fc9d03ab5d5e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 11:16:48 +0100 Subject: [PATCH 053/459] [poincare] Fixed the IntegralLayout navigation. The cursor now avoids pointing at the integrand horizontal layout or left of dx layout. It insteads points at the children of the horizontal integrand layout that are not "dx", so an EmptyVisibleLayout can be properly overwritten when needed. Change-Id: Ie5eced3761d2d8f49f02530336981a1285b459fd --- poincare/src/layout/integral_layout.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index ae3db3355..755a27635 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -58,8 +58,8 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Right of the integrand, Left of "dx". if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()); - return integrandLayout()->moveLeft(cursor); + cursor->setPointedExpressionLayout(integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-2)); + return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. @@ -80,7 +80,7 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { && cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()); + cursor->setPointedExpressionLayout(integrandLayout()->editableChild(0)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } @@ -95,7 +95,7 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { } assert(cursor->pointedExpressionLayout() == this); // Case: Left of the integral. - // Go ti the upper bound. + // Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); cursor->setPointedExpressionLayout(upperBoundLayout()); From 428be61703444271a66b559868a474741ded65a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 11:29:44 +0100 Subject: [PATCH 054/459] [poincare] Fix navigation in Sum or Sequence layouts. Avoid adding text Left or Right of "n=". Change-Id: I03c980f25bae1cb89feaa9d733bfb3fe5294fed0 --- poincare/src/layout/sequence_layout.cpp | 4 ++-- poincare/src/layout/string_layout.cpp | 23 +++++++++++++++++------ poincare/src/layout/sum_layout.cpp | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 364fd3ed7..360578568 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -31,7 +31,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { && cursor->pointedExpressionLayout() == argumentLayout()) { assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()); + cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -114,7 +114,7 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && previousLayout == upperBoundLayout()) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor); + return lowerBoundLayout()->editableChild(1)->moveDownInside(cursor); } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index f2be896e3..adea25f99 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -27,10 +27,21 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { // A StringLayout is not editable, and the cursor cannot go inside it. assert(cursor->pointedExpressionLayout() == this); // Case: Right. - // Go Left. + // If there is a Left brother, go Right of it. Else go Left of the + // grandparent. We need to do this to avoid adding text left or right of a + // string layout, for instance left of "n=" in a Sum layout. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + int indexOfThis = m_parent->indexOfChild(this); + if (m_parent->editableChild(indexOfThis-1) != nullptr) { + cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis-1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + if (m_parent->parent()) { + cursor->setPointedExpressionLayout(const_cast(m_parent->parent())); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } } // Case: Left. // Ask the parent. @@ -45,9 +56,9 @@ bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); assert(m_parent != nullptr); // Case: Left. - // Go Right. - // If there is a Right brother, go Left of it. Else go Right of the grandparent. - // //TODO explain that it is because of integrals and baselayouts. + // If there is a Right brother, go Left of it. Else go Right of the + // grandparent. We need to do this to avoid adding text left or right of a + // string layout, for instance right of "dx" in an integral layout. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfThis = m_parent->indexOfChild(this); if (m_parent->editableChild(indexOfThis+1) != nullptr) { diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index d9febe8ae..ef3027cbf 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -69,7 +69,7 @@ bool SumLayout::moveLeft(ExpressionLayoutCursor * cursor) { && cursor->pointedExpressionLayout() == editableChild(2)) { assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()); + cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } From 693fb5e400d3eb61057b6482d22e2bd8012f8f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 11:57:34 +0100 Subject: [PATCH 055/459] [poincare] Clean Layouts. Do not compute the baseline at construction, and use base class constructors. Change-Id: I4361a6d92d7652b2aae2d662388b8d2c90afd3ce --- poincare/src/layout/baseline_relative_layout.cpp | 1 - poincare/src/layout/bracket_layout.cpp | 6 ------ poincare/src/layout/bracket_layout.h | 2 +- poincare/src/layout/char_layout.cpp | 1 - poincare/src/layout/condensed_sum_layout.cpp | 6 ------ poincare/src/layout/condensed_sum_layout.h | 2 +- poincare/src/layout/conjugate_layout.cpp | 6 ------ poincare/src/layout/conjugate_layout.h | 2 +- poincare/src/layout/empty_layout.cpp | 6 ------ poincare/src/layout/empty_layout.h | 2 +- poincare/src/layout/empty_visible_layout.cpp | 1 - poincare/src/layout/fraction_layout.cpp | 6 ------ poincare/src/layout/fraction_layout.h | 2 +- poincare/src/layout/grid_layout.cpp | 1 - poincare/src/layout/horizontal_layout.cpp | 11 ----------- poincare/src/layout/horizontal_layout.h | 3 +-- poincare/src/layout/integral_layout.cpp | 6 ------ poincare/src/layout/integral_layout.h | 2 +- poincare/src/layout/nth_root_layout.cpp | 6 ------ poincare/src/layout/nth_root_layout.h | 2 +- poincare/src/layout/parenthesis_layout.cpp | 1 - poincare/src/layout/sequence_layout.cpp | 6 ------ poincare/src/layout/sequence_layout.h | 2 +- 23 files changed, 9 insertions(+), 74 deletions(-) diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 39b0bac48..6947ed585 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -9,7 +9,6 @@ BaselineRelativeLayout::BaselineRelativeLayout(ExpressionLayout * base, Expressi StaticLayoutHierarchy(base, indice, cloneOperands), m_type(type) { - computeBaseline(); } ExpressionLayout * BaselineRelativeLayout::clone() const { diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 1ad946b87..38303abf7 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -7,12 +7,6 @@ extern "C" { namespace Poincare { -BracketLayout::BracketLayout(ExpressionLayout * operandLayout, bool cloneOperands) : - StaticLayoutHierarchy<1>(operandLayout, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * BracketLayout::clone() const { BracketLayout * layout = new BracketLayout(const_cast(this)->operandLayout(), true); return layout; diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index b9beeb4c7..8de75000d 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -7,7 +7,7 @@ namespace Poincare { class BracketLayout : public StaticLayoutHierarchy<1> { public: - BracketLayout(ExpressionLayout * operandLayout, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index 22357ddfc..866814bda 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -10,7 +10,6 @@ CharLayout::CharLayout(char c, KDText::FontSize fontSize) : m_char(c), m_fontSize(fontSize) { - computeBaseline(); } ExpressionLayout * CharLayout::clone() const { diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 04babee19..a7a511e9e 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -5,12 +5,6 @@ namespace Poincare { -CondensedSumLayout::CondensedSumLayout(ExpressionLayout * base, ExpressionLayout * subscript, ExpressionLayout * superscript, bool cloneOperands) : - StaticLayoutHierarchy<3>(base, subscript, superscript, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * CondensedSumLayout::clone() const { CondensedSumLayout * layout = new CondensedSumLayout(const_cast(this)->baseLayout(), const_cast(this)->subscriptLayout(), const_cast(this)->superscriptLayout(), true); return layout; diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index fa9179acd..20795398d 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -7,7 +7,7 @@ namespace Poincare { class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: - CondensedSumLayout(ExpressionLayout * base, ExpressionLayout * subscript, ExpressionLayout * superscript, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 97317f5dc..19957fe20 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -8,12 +8,6 @@ extern "C" { namespace Poincare { -ConjugateLayout::ConjugateLayout(ExpressionLayout * operand, bool cloneOperands) : - StaticLayoutHierarchy<1>(operand, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * ConjugateLayout::clone() const { ConjugateLayout * layout = new ConjugateLayout(const_cast(this)->operandLayout(), true); return layout; diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 732e89e49..c4b4454df 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -7,7 +7,7 @@ namespace Poincare { class ConjugateLayout : public StaticLayoutHierarchy<1> { public: - ConjugateLayout(ExpressionLayout * operand, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 5d8919441..88871bb7c 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -4,12 +4,6 @@ namespace Poincare { -EmptyLayout::EmptyLayout() : - StaticLayoutHierarchy<0>() -{ - m_baseline = 0; -} - ExpressionLayout * EmptyLayout::clone() const { EmptyLayout * layout = new EmptyLayout(); return layout; diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 2c746faba..9ca0b9b28 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -8,7 +8,7 @@ namespace Poincare { class EmptyLayout : public StaticLayoutHierarchy<0> { public: - EmptyLayout(); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index f6cdaf7b4..f4291ef24 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -8,7 +8,6 @@ EmptyVisibleLayout::EmptyVisibleLayout() : EmptyLayout(), m_fillRectColor(KDColor::RGB24(0xffd370)) //TODO make static or in Palette? { - computeBaseline(); } ExpressionLayout * EmptyVisibleLayout::clone() const { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 6fd6651b3..b642671c1 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -6,12 +6,6 @@ namespace Poincare { -FractionLayout::FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator, bool cloneOperands) : - StaticLayoutHierarchy<2>(numerator, denominator, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * FractionLayout::clone() const { FractionLayout * layout = new FractionLayout(const_cast(this)->numeratorLayout(), const_cast(this)->denominatorLayout(), true); return layout; diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 670718879..0bbb85ac3 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -7,7 +7,7 @@ namespace Poincare { class FractionLayout : public StaticLayoutHierarchy<2> { public: - FractionLayout(ExpressionLayout * numerator, ExpressionLayout * denominator, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 504a9c65d..9821533de 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -12,7 +12,6 @@ GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int n m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { - computeBaseline(); } ExpressionLayout * GridLayout::clone() const { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 0be29923c..6f2f882f1 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -10,17 +10,6 @@ extern "C" { namespace Poincare { -HorizontalLayout::HorizontalLayout() : - DynamicLayoutHierarchy() -{ -} - -HorizontalLayout::HorizontalLayout(ExpressionLayout ** childrenLayouts, int childrenCount, bool cloneOperands) : - DynamicLayoutHierarchy(childrenLayouts, childrenCount, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * HorizontalLayout::clone() const { HorizontalLayout * layout = new HorizontalLayout(const_cast(children()), numberOfChildren(), true); return layout; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index d6f8bba01..b3f1129dd 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -7,8 +7,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { public: - HorizontalLayout(); - HorizontalLayout(ExpressionLayout ** layouts, int childrenCount, bool cloneOperands); + using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; /* Navigation */ diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 755a27635..59164adb7 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -19,12 +19,6 @@ const uint8_t bottomSymbolPixel[IntegralLayout::k_symbolHeight][IntegralLayout:: {0xFF, 0xFF, 0x00, 0x00}, }; -IntegralLayout::IntegralLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * integrand, bool cloneOperands) : - StaticLayoutHierarchy<3>(upperBound, lowerBound, integrand, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * IntegralLayout::clone() const { IntegralLayout * layout = new IntegralLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->integrandLayout(), true); return layout; diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 7390f644a..67b0e5750 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -9,7 +9,7 @@ class IntegralLayout : public StaticLayoutHierarchy<3> { public: constexpr static KDCoordinate k_symbolHeight = 4; constexpr static KDCoordinate k_symbolWidth = 4; - IntegralLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * integrand, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 3609284e1..709e3df2f 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -16,12 +16,6 @@ const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_left {0xFF, 0xFF, 0xFF, 0xFF, 0x00}, }; -NthRootLayout::NthRootLayout(ExpressionLayout * radicand, ExpressionLayout * index, bool cloneOperands) : - StaticLayoutHierarchy<2>(radicand, index, cloneOperands) -{ - computeBaseline(); -} - ExpressionLayout * NthRootLayout::clone() const { NthRootLayout * layout = new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); return layout; diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 8f54033a7..5c1ad77d9 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -9,7 +9,7 @@ class NthRootLayout : public StaticLayoutHierarchy<2> { public: constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; - NthRootLayout(ExpressionLayout * radicand, ExpressionLayout * index, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index b5b48641f..0f9cbd1fc 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -15,7 +15,6 @@ ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operand, bool cloneOpera ExpressionLayout * leftParenthesis = new ParenthesisLeftLayout(); ExpressionLayout * rightParenthesis = new ParenthesisRightLayout(); build(ExpressionLayout::ExpressionLayoutArray3(leftParenthesis, operand, rightParenthesis), 3, cloneOperands); - computeBaseline(); } ExpressionLayout * ParenthesisLayout::clone() const { diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 360578568..708b7e1af 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -6,12 +6,6 @@ namespace Poincare { -SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : - StaticLayoutHierarchy<3>(upperBound, lowerBound, argument, cloneOperands) -{ - computeBaseline(); -} - bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the bounds. // Go Left of the sequence. diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index e2eb0e57f..7df9ce767 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -9,7 +9,7 @@ class SequenceLayout : public StaticLayoutHierarchy<3> { public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; - SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; From b0fd089d87c8129c82a88669348a44f6822d6318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 12:20:56 +0100 Subject: [PATCH 056/459] [poincare] Dynamic size of Bracket Left and Right layouts. Change-Id: Icd0654dc7b63639d4513946b24c0855ffcb38c87 --- poincare/include/poincare/expression_layout.h | 2 + poincare/src/layout/bracket_left_layout.cpp | 52 +++++++++++++++++-- poincare/src/layout/bracket_left_layout.h | 3 ++ .../src/layout/bracket_left_right_layout.cpp | 20 ++++--- .../src/layout/bracket_left_right_layout.h | 6 ++- poincare/src/layout/bracket_right_layout.cpp | 50 ++++++++++++++++-- poincare/src/layout/bracket_right_layout.h | 3 ++ .../src/layout/parenthesis_right_layout.cpp | 3 +- 8 files changed, 124 insertions(+), 15 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 5ffac5992..bf1d7dea9 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -67,6 +67,8 @@ public: /* Other */ virtual bool isLeftParenthesis() const { return false; } virtual bool isRightParenthesis() const { return false; } + virtual bool isLeftBracket() const { return false; } + virtual bool isRightBracket() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/bracket_left_layout.cpp index 07d4cb95e..e0e510572 100644 --- a/poincare/src/layout/bracket_left_layout.cpp +++ b/poincare/src/layout/bracket_left_layout.cpp @@ -1,4 +1,7 @@ #include "bracket_left_layout.h" +extern "C" { +#include +} namespace Poincare { @@ -8,10 +11,53 @@ ExpressionLayout * BracketLeftLayout::clone() const { } void BracketLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); +} + +void BracketLeftLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = BracketLeftRightLayout::k_minimalOperandHeight; + int currentNumberOfOpenBrackets = 1; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightBracket()) { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + return; + } + } else if (brother->isLeftBracket()) { + currentNumberOfOpenBrackets++; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void BracketLeftLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + int currentNumberOfOpenBrackets = 1; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightBracket()) { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if (brother->isLeftBracket()) { + currentNumberOfOpenBrackets++; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; } } diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index 8f46d06d9..1975b2fc0 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -9,8 +9,11 @@ class BracketLeftLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; + bool isLeftBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; } diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index 3a43c0536..d6eefaaa8 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -9,10 +9,15 @@ namespace Poincare { BracketLeftRightLayout::BracketLeftRightLayout() : StaticLayoutHierarchy<0>(), - m_operandHeight(18) //TODO + m_operandHeightComputed(false) { } +void BracketLeftRightLayout::invalidAllSizesPositionsAndBaselines() { + m_operandHeightComputed = false; + ExpressionLayout::invalidAllSizesPositionsAndBaselines(); +} + bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. @@ -49,14 +54,15 @@ bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { KDSize BracketLeftRightLayout::computeSize() { - //TODO: compute the operandHeight according to the brothers - return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, m_operandHeight); + return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight()); } -void BracketLeftRightLayout::computeBaseline() { - //TODO: compute the operandHeight according to the brothers - m_baseline = m_operandHeight/2; - m_baselined = true; +KDCoordinate BracketLeftRightLayout::operandHeight() { + if (!m_operandHeightComputed) { + computeOperandHeight(); + m_operandHeightComputed = true; + } + return m_operandHeight; } KDPoint BracketLeftRightLayout::positionOfChild(ExpressionLayout * child) { diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 838b9e00e..98ddffd93 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class BracketLeftRightLayout : public StaticLayoutHierarchy<0> { public: BracketLeftRightLayout(); + void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_bracketWidth = 5; @@ -15,9 +16,12 @@ public: constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_externWidthMargin = 2; protected: + constexpr static KDCoordinate k_minimalOperandHeight = 18; KDSize computeSize() override; - void computeBaseline() override; + KDCoordinate operandHeight(); + virtual void computeOperandHeight() = 0; KDPoint positionOfChild(ExpressionLayout * child) override; + bool m_operandHeightComputed; uint16_t m_operandHeight; }; } diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp index c6f8bbb14..8634d6947 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -1,4 +1,7 @@ #include "bracket_right_layout.h" +extern "C" { +#include +} namespace Poincare { @@ -8,10 +11,51 @@ ExpressionLayout * BracketRightLayout::clone() const { } void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. - ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, m_operandHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + m_operandHeight, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); +} + +void BracketRightLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = BracketLeftRightLayout::k_minimalOperandHeight; + int currentNumberOfOpenBrackets = 1; + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftBracket()) { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + return; + } + } else if (brother->isRightBracket()) { + currentNumberOfOpenBrackets++; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void BracketRightLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + int currentNumberOfOpenBrackets = 1; + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftBracket()) { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if (brother->isRightBracket()) { + currentNumberOfOpenBrackets++; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; } } diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index f2c25186a..788664f3e 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -9,8 +9,11 @@ class BracketRightLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; + bool isRightBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index d3b0efb0d..35202c273 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -66,7 +66,8 @@ void ParenthesisRightLayout::computeOperandHeight() { } } else if (brother->isRightParenthesis()) { currentNumberOfOpenParentheses++; - } KDCoordinate brotherHeight = brother->size().height(); + } + KDCoordinate brotherHeight = brother->size().height(); if (brotherHeight > m_operandHeight) { m_operandHeight = brotherHeight; } From 406d108aa50fda0bc8697087143b92cf98932244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 13:04:05 +0100 Subject: [PATCH 057/459] [poincare] Sandardize Bracket and Parenthesis minimal height. Change-Id: Iadfce26575d77182ecc12dd100fa9b70b9062802 --- escher/include/escher/metric.h | 1 + poincare/src/layout/bracket_left_layout.cpp | 3 ++- poincare/src/layout/bracket_left_right_layout.h | 1 - poincare/src/layout/bracket_right_layout.cpp | 3 ++- poincare/src/layout/parenthesis_left_layout.cpp | 3 ++- poincare/src/layout/parenthesis_right_layout.cpp | 3 ++- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/escher/include/escher/metric.h b/escher/include/escher/metric.h index 06c060a1c..429c6965a 100644 --- a/escher/include/escher/metric.h +++ b/escher/include/escher/metric.h @@ -27,6 +27,7 @@ public: constexpr static KDCoordinate ToolboxRowHeight = 40; constexpr static KDCoordinate FractionAndConjugateHorizontalOverflow = 2; constexpr static KDCoordinate FractionAndConjugateHorizontalMargin = 2; + constexpr static KDCoordinate MinimalBracketAndParenthesisHeight = 18; }; #endif diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/bracket_left_layout.cpp index e0e510572..324b7ae15 100644 --- a/poincare/src/layout/bracket_left_layout.cpp +++ b/poincare/src/layout/bracket_left_layout.cpp @@ -1,4 +1,5 @@ #include "bracket_left_layout.h" +#include extern "C" { #include } @@ -18,7 +19,7 @@ void BracketLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCol void BracketLeftLayout::computeOperandHeight() { assert(m_parent != nullptr); - m_operandHeight = BracketLeftRightLayout::k_minimalOperandHeight; + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; int numberOfBrothers = m_parent->numberOfChildren(); for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 98ddffd93..4af7a09a3 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -16,7 +16,6 @@ public: constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_externWidthMargin = 2; protected: - constexpr static KDCoordinate k_minimalOperandHeight = 18; KDSize computeSize() override; KDCoordinate operandHeight(); virtual void computeOperandHeight() = 0; diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp index 8634d6947..a1f5ce663 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -1,4 +1,5 @@ #include "bracket_right_layout.h" +#include extern "C" { #include } @@ -18,7 +19,7 @@ void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCo void BracketRightLayout::computeOperandHeight() { assert(m_parent != nullptr); - m_operandHeight = BracketLeftRightLayout::k_minimalOperandHeight; + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index f191d68ee..1bd3d416a 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -1,4 +1,5 @@ #include "parenthesis_left_layout.h" +#include extern "C" { #include #include @@ -55,7 +56,7 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio void ParenthesisLeftLayout::computeOperandHeight() { assert(m_parent != nullptr); - m_operandHeight = 18; + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 35202c273..b248e0150 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -1,4 +1,5 @@ #include "parenthesis_right_layout.h" +#include extern "C" { #include #include @@ -55,7 +56,7 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi void ParenthesisRightLayout::computeOperandHeight() { assert(m_parent != nullptr); - m_operandHeight = 18; + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenParentheses = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); From 1a3c3912374db56013be6566d3897449442d86d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 14:17:11 +0100 Subject: [PATCH 058/459] [expression_editor/poincare] General "delete" rule. Change-Id: I5c16f19aacdac312156f45c88c189adfb72f03e8 --- apps/expression_editor/controller.cpp | 13 +++++++ apps/expression_editor/controller.h | 1 + poincare/include/poincare/expression_layout.h | 2 ++ .../poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 4 +++ poincare/src/layout/expression_layout.cpp | 34 +++++++++++++++++++ 6 files changed, 55 insertions(+) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 625ac72a0..1679d3303 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -66,6 +66,11 @@ bool Controller::privateHandleEvent(Ion::Events::Event event) { m_view.layoutSubviews(); return true; } + if (handleDeleteEvent(event)) { + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); + m_view.layoutSubviews(); + return true; + } return false; } @@ -126,4 +131,12 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { return nullptr; } +bool Controller::handleDeleteEvent(Ion::Events::Event event) { + if (event == Ion::Events::Backspace) { + m_cursor.performBackspace(); + return true; + } + return false; +} + } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index f34518ff5..588c17d69 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -28,6 +28,7 @@ private: bool privateHandleEvent(Ion::Events::Event event); bool handleMoveEvent(Ion::Events::Event event); Poincare::ExpressionLayout * handleAddEvent(Ion::Events::Event event); + bool handleDeleteEvent(Ion::Events::Event event); ExpressionEditorView m_view; Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index bf1d7dea9..963c631b7 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -55,6 +55,8 @@ public: /* Dynamic Layout*/ virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } + virtual void removeChildAtIndex(int index, bool deleteAfterRemoval); + virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 5813fee8c..b92bff74e 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -52,6 +52,7 @@ public: ExpressionLayout * addEmptySquarePowerLayout(); ExpressionLayout * addXNTCharLayout(); ExpressionLayout * insertText(const char * text); + void performBackspace(); private: constexpr static KDCoordinate k_cursorHeight = 18; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index d10c759e6..71e6dad4f 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -138,5 +138,9 @@ ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { return newChild; } +void ExpressionLayoutCursor::performBackspace() { + m_pointedExpressionLayout->backspaceAtCursor(this); +} + } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 9f19d4040..fe06a8c55 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -201,6 +202,39 @@ void ExpressionLayout::detachChild(const ExpressionLayout * e) { } } +void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { + assert(index >= 0 && index < numberOfChildren()); + replaceChild(editableChild(index), new EmptyVisibleLayout(), deleteAfterRemoval); +} + +void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() != this || m_parent == nullptr) { + return; + } + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + m_parent->backspaceAtCursor(cursor); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (numberOfChildren() > 0) { + cursor->setPointedExpressionLayout(editableChild(numberOfChildren()-1)); + cursor->performBackspace(); + return; + } + int indexInParent = m_parent->indexOfChild(this); + ExpressionLayout * previousParent = m_parent; + previousParent->removeChildAtIndex(indexInParent, true); + if (indexInParent < previousParent->numberOfChildren()) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + int indexOfNewPointedLayout = indexInParent - 1; + assert(indexOfNewPointedLayout >= 0); + assert(indexOfNewPointedLayout < previousParent->numberOfChildren()); + cursor->setPointedExpressionLayout(previousParent->editableChild(indexOfNewPointedLayout)); +} + char ExpressionLayout::XNTChar() const { if (m_parent == nullptr) { return 'x'; From 69e003d1ef16198a953f542803ce02c68d415358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 14:26:31 +0100 Subject: [PATCH 059/459] [apps] Added layout for AbsoluteValue in toolbox. Change-Id: Ie686aabaa5c3f49af0298fbe0c8b9859e89f638f --- apps/expression_editor/controller.h | 2 +- apps/math_toolbox.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index 588c17d69..3910844fa 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -22,7 +22,7 @@ public: Toolbox * toolbox() override; /* Callback for Toolbox */ - void insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayout * pointedLayout); + void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); private: bool privateHandleEvent(Ion::Events::Event event); diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index d1295a2fb..c76336561 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -3,6 +3,8 @@ #include #include +using namespace Poincare; + /* TODO: find a shorter way to initialize tree models * We create one model tree: each node keeps the label of the row it refers to * and the text which would be edited by clicking on the row. When the node is a @@ -87,13 +89,19 @@ const ToolboxMessageTree predictionChildren[3] = { ToolboxMessageTree(I18n::Message::PredictionCommandWithArg, I18n::Message::Prediction, I18n::Message::PredictionCommandWithArg), ToolboxMessageTree(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommandWithArg)}; +const int pointedLayoutPathAbs[] = {0}; #if LIST_ARE_DEFINED -const ToolboxMessageTree menu[12] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg), +const ToolboxMessageTree menu[12] = { #elif MATRICES_ARE_DEFINED -const ToolboxMessageTree menu[11] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg), +const ToolboxMessageTree menu[11] = { #else -const ToolboxMessageTree menu[10] = {ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg), +const ToolboxMessageTree menu[10] = { #endif + ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg, nullptr, 0, + new AbsoluteValueLayout( + new EmptyVisibleLayout()), + const_cast(&pointedLayoutPathAbs[0]), + 1), ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg), ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg), ToolboxMessageTree(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), From 04be8e1cc2978a4f876a442436e18fdf95a0e7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 14:27:18 +0100 Subject: [PATCH 060/459] [poincare] Delete for BracketLayout. Change-Id: Ifb45ef3d556ccc3f6b1efb9fdca04f6411a3dfc9 --- poincare/src/layout/bracket_layout.cpp | 23 +++++++++++++++++++++++ poincare/src/layout/bracket_layout.h | 1 + 2 files changed, 24 insertions(+) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 38303abf7..f3433e3f2 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -12,6 +12,29 @@ ExpressionLayout * BracketLayout::clone() const { return layout; } +void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == operandLayout()) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(operandLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(previousParent); + return; + } + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPointedExpressionLayout(operandLayout()); + cursor->performBackspace(); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the operand. // Go Left of the brackets. diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 8de75000d..d11f51681 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -9,6 +9,7 @@ class BracketLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: From f307e15bac0582e4e0478b58acd796eb9877e854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 15:24:40 +0100 Subject: [PATCH 061/459] [poincare] Delete for HorizontalLayout. Change-Id: Iff983beccc14195b09d54b5b5db668b8f7d4eca7 --- .../poincare/dynamic_layout_hierarchy.h | 1 + poincare/include/poincare/expression_layout.h | 3 ++- .../src/layout/dynamic_layout_hierarchy.cpp | 19 +++++++++++++++ poincare/src/layout/empty_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 23 ++++++++++++++++++- poincare/src/layout/horizontal_layout.cpp | 15 ++++++++++++ poincare/src/layout/horizontal_layout.h | 3 +++ 7 files changed, 63 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 54da3dfa9..dafe85166 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -21,6 +21,7 @@ public: const ExpressionLayout * const * children() const override { return m_children; }; bool addChildAtIndex(ExpressionLayout * operand, int index) override; + void removeChildAtIndex(int index, bool deleteAfterRemoval) override; protected: const ExpressionLayout ** m_children; int m_numberOfChildren; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 963c631b7..dcac65950 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -50,7 +50,7 @@ public: virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); - void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); + virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); void detachChild(const ExpressionLayout * e); // Removes a child WITHOUT deleting it /* Dynamic Layout*/ @@ -71,6 +71,7 @@ public: virtual bool isRightParenthesis() const { return false; } virtual bool isLeftBracket() const { return false; } virtual bool isRightBracket() const { return false; } + virtual bool isEmpty() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 667347d46..d0bdac6d4 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -1,4 +1,5 @@ #include +#include "empty_visible_layout.h" extern "C" { #include #include @@ -60,4 +61,22 @@ bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index return true; } +void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemoval) { + if (deleteAfterRemoval) { + delete m_children[index]; + } else { + const_cast(m_children[index])->setParent(nullptr); + } + m_numberOfChildren--; + if (m_numberOfChildren == 0) { + ExpressionLayout * emptyVisibleLayout = new EmptyVisibleLayout(); + replaceWith(emptyVisibleLayout); + return; + } + for (int j=index; jpointedExpressionLayout() != this || m_parent == nullptr) { + + int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); + if (indexOfPointedExpression >= 0) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (indexOfPointedExpression == 0) { + cursor->setPointedExpressionLayout(this); + } else { + cursor->setPointedExpressionLayout(editableChild(indexOfPointedExpression - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + cursor->performBackspace(); + return; + } + assert(cursor->pointedExpressionLayout() == this); + if (m_parent == nullptr) { return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { @@ -223,6 +237,13 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } int indexInParent = m_parent->indexOfChild(this); ExpressionLayout * previousParent = m_parent; + if (previousParent->numberOfChildren() == 1) { + ExpressionLayout * newLayout = new EmptyVisibleLayout(); + replaceWith(newLayout, true); + cursor->setPointedExpressionLayout(newLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } previousParent->removeChildAtIndex(indexInParent, true); if (indexInParent < previousParent->numberOfChildren()) { cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent)); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 6f2f882f1..ec015a18b 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -15,6 +15,21 @@ ExpressionLayout * HorizontalLayout::clone() const { return layout; } +void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { + if (newChild->isEmpty()) { + if (numberOfChildren() > 1) { + removeChildAtIndex(indexOfChild(const_cast(oldChild)), deleteOldChild); + delete newChild; + return; + } + if (m_parent) { + replaceWith(newChild); + return; + } + } + ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); +} + bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index b3f1129dd..0390d9804 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -10,6 +10,9 @@ public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; + /* Hierarchy */ + void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; + /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; From f39b365902dd80ee0d4dfcc9c66b6222d2b3dd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 17:16:20 +0100 Subject: [PATCH 062/459] [poincare] Delete for BaselineRelativeLayout. Change-Id: I7b16c52d7eaa0c5a6398aca9a34a017447593737 --- poincare/include/poincare/expression_layout.h | 1 + .../src/layout/baseline_relative_layout.cpp | 31 +++++++++++++++++++ .../src/layout/baseline_relative_layout.h | 1 + .../src/layout/dynamic_layout_hierarchy.cpp | 4 +-- poincare/src/layout/horizontal_layout.cpp | 24 +++++++++++++- poincare/src/layout/horizontal_layout.h | 5 +++ 6 files changed, 63 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index dcac65950..5ec12341f 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -67,6 +67,7 @@ public: bool moveDownInside(ExpressionLayoutCursor * cursor); /* Other */ + virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } virtual bool isRightParenthesis() const { return false; } virtual bool isLeftBracket() const { return false; } diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 6947ed585..f2b58bb15 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -1,4 +1,5 @@ #include "baseline_relative_layout.h" +#include "empty_visible_layout.h" #include #include #include @@ -16,6 +17,36 @@ ExpressionLayout * BaselineRelativeLayout::clone() const { return layout; } +void BaselineRelativeLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == indiceLayout()) { + if (m_type == Type::Superscript) { + ExpressionLayout * base = baseLayout(); + ExpressionLayout * pointedLayout = base; + if (base->isHorizontal()) { + pointedLayout = base->editableChild(base->numberOfChildren()-1); + } + if (indiceLayout()->isEmpty()) { + replaceWith(base, true); + } + cursor->setPointedExpressionLayout(pointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + assert(m_type == Type::Subscript); + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(new EmptyVisibleLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(previousParent); + return; + } + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index 1e72783a8..f0cb1f7a0 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -13,6 +13,7 @@ public: }; BaselineRelativeLayout(ExpressionLayout * base, ExpressionLayout * indice, Type type, bool cloneOperands); ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index d0bdac6d4..4d3fdf6c8 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -68,11 +68,11 @@ void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemov const_cast(m_children[index])->setParent(nullptr); } m_numberOfChildren--; - if (m_numberOfChildren == 0) { + /*if (m_numberOfChildren == 0) { ExpressionLayout * emptyVisibleLayout = new EmptyVisibleLayout(); replaceWith(emptyVisibleLayout); return; - } + }*/ for (int j=index; jisEmpty()) { if (numberOfChildren() > 1) { + if (!newChild->hasAncestor(oldChild)) { + delete newChild; + } removeChildAtIndex(indexOfChild(const_cast(oldChild)), deleteOldChild); - delete newChild; return; } if (m_parent) { @@ -27,6 +29,13 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio return; } } + if (newChild->isHorizontal()) { + // Steal the children of the new layout then destroy it. + int indexForInsertion = indexOfChild(const_cast(oldChild)); + mergeChildrenAtIndex(newChild, indexForInsertion + 1); + removeChildAtIndex(indexForInsertion, deleteOldChild); + return; + } ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); } @@ -176,6 +185,19 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } +void HorizontalLayout::mergeChildrenAtIndex(ExpressionLayout * eL, int index) { + int indexOfEL = indexOfChild(eL); + if (indexOfEL >= 0) { + removeChildAtIndex(indexOfEL, false); + } + int numChildren = eL->numberOfChildren(); + for (int i = 0; i < numChildren; i++) { + ExpressionLayout * currentChild = eL->editableChild(0); + eL->removeChildAtIndex(0, false); + addChildAtIndex(currentChild, index+i); + } +} + bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Prevent looping fom child to parent if (previousPreviousLayout == this) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 0390d9804..2c0bfc6a8 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -18,11 +18,16 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + + /* Other */ + bool isHorizontal() const override { return true; } + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; + void mergeChildrenAtIndex(ExpressionLayout * eL, int index); // WITHOUT delete. private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); int indexOfChild(ExpressionLayout * eL) const; From 8563f24aa2b518b480745bbcf0d97a485a11dbfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 17:32:13 +0100 Subject: [PATCH 063/459] [poincare] Add layout to Conjugate in toolbox. Change-Id: I793a16a7e34e6affe2fe3facd9bd17bee77431d8 --- apps/math_toolbox.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index c76336561..8a8d24182 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -35,12 +35,17 @@ const ToolboxMessageTree calculChildren[4] = { 2), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; +const int pointedLayoutPathConj[] = {0}; const ToolboxMessageTree complexChildren[5] = { ToolboxMessageTree(I18n::Message::AbsCommandWithArg,I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommandWithArg), ToolboxMessageTree(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommandWithArg), ToolboxMessageTree(I18n::Message::ReCommandWithArg, I18n::Message::RealPart, I18n::Message::ReCommandWithArg), ToolboxMessageTree(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommandWithArg), - ToolboxMessageTree(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommandWithArg)}; + ToolboxMessageTree(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommandWithArg, nullptr, 0, + new ConjugateLayout( + new EmptyVisibleLayout()), + const_cast(&pointedLayoutPathConj[0]), + 1)}; const ToolboxMessageTree probabilityChildren[2] = { ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg), From 7ce93eb847caba725a523c5989b62f71f31447b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Dec 2017 17:32:39 +0100 Subject: [PATCH 064/459] [poincare] Delete for ConjugateLayout. Change-Id: I065a3a3b90f1e7d533ba54ddb4aad0a7df70ac87 --- poincare/src/layout/conjugate_layout.cpp | 17 +++++++++++++++++ poincare/src/layout/conjugate_layout.h | 1 + 2 files changed, 18 insertions(+) diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 19957fe20..5e74f9b21 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -13,6 +13,23 @@ ExpressionLayout * ConjugateLayout::clone() const { return layout; } +void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == operandLayout()) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(operandLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(previousParent); + return; + } + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the operand. // Move Left. diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index c4b4454df..366c824a5 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -9,6 +9,7 @@ class ConjugateLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: From 2d40e35fe8a12501ceea1b224d17cd1e74020a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 10:01:03 +0100 Subject: [PATCH 065/459] [poincare] Delete for FractionLayout. Change-Id: Ifbbe5c434d278e8223ada3d368c1e948712567d2 --- poincare/src/layout/fraction_layout.cpp | 72 +++++++++++++++++++++++ poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/horizontal_layout.cpp | 8 +++ poincare/src/layout/horizontal_layout.h | 1 + 4 files changed, 82 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index b642671c1..671643e30 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -1,4 +1,6 @@ #include "fraction_layout.h" +#include "empty_visible_layout.h" +#include "horizontal_layout.h" #include #include #include @@ -11,6 +13,76 @@ ExpressionLayout * FractionLayout::clone() const { return layout; } +void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // If the cursor is on the left of the denominator, replace the fraction with + // a horizontal juxtaposition of the numerator and the denominator. + if (cursor->pointedExpressionLayout() == denominatorLayout()) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (numeratorLayout()->isEmpty()) { + if (denominatorLayout()->isEmpty()) { + // If the numerator and the denominator are empty, replace the fraction + // with an empty layout. + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(new EmptyVisibleLayout(), true); + // Place the cursor on the right of the left brother ofthe fraction if + // there is one. + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(previousParent); + return; + } + // If the numerator is empty but not the denominator, replace the fraction + // with its denominator. Place the cursor on the left of the denominator. + ExpressionLayout * nextPointedLayout = denominatorLayout(); + if (denominatorLayout()->isHorizontal()) { + nextPointedLayout = denominatorLayout()->editableChild(0); + } + replaceWith(denominatorLayout(), true); + cursor->setPointedExpressionLayout(nextPointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + // If the denominator is empty but not the numerator, replace the fraction + // with the numerator and place the cursor on its right. + if (denominatorLayout()->isEmpty()) { + ExpressionLayout * nextPointedLayout = numeratorLayout(); + if (numeratorLayout()->isHorizontal()) { + nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); + } + replaceWith(numeratorLayout(), true); + cursor->setPointedExpressionLayout(nextPointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // If neither the numerator nor the denominator are empty, replace the + // fraction with a juxtaposition of the numerator and denominator. Place the + // cursor in the middle of the juxtaposition, which is right of the + // numerator. + ExpressionLayout * nextPointedLayout = numeratorLayout(); + if (numeratorLayout()->isHorizontal()) { + nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); + } + ExpressionLayout * numerator = numeratorLayout(); + ExpressionLayout * denominator = denominatorLayout(); + detachChild(numerator); + detachChild(denominator); + HorizontalLayout * newLayout = new HorizontalLayout(); + newLayout->addOrMergeChildAtIndex(denominator, 0); + newLayout->addOrMergeChildAtIndex(numerator, 0); + // Add the denominator before the numerator to have the right order. + replaceWith(newLayout, true); + cursor->setPointedExpressionLayout(nextPointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the numerator or the denominator. // Go Left of the fraction. diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 0bbb85ac3..296b31ccc 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -9,6 +9,7 @@ class FractionLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index b8a4891fc..cd94aa8d8 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -39,6 +39,14 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); } +void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index) { + if (eL->isHorizontal()) { + mergeChildrenAtIndex(eL, index); + return; + } + addChildAtIndex(eL, index); +} + bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 2c0bfc6a8..87cf0bd33 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -12,6 +12,7 @@ public: /* Hierarchy */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; + void addOrMergeChildAtIndex(ExpressionLayout * eL, int index); /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; From 2c261f7ea93f9b410fc6b223853f833d562b3292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 11:07:50 +0100 Subject: [PATCH 066/459] [poincare] Cleaned duplicate indexOfChild() method. Change-Id: I03fc6cd4e1afe45f609828ae0e32865c8510bf14 --- poincare/src/layout/expression_layout.cpp | 3 +++ poincare/src/layout/horizontal_layout.cpp | 12 ------------ poincare/src/layout/horizontal_layout.h | 1 - 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 9750c14f8..5fdae5833 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -98,6 +98,9 @@ const ExpressionLayout * ExpressionLayout::child(int i) const { } int ExpressionLayout::indexOfChild(ExpressionLayout * child) const { + if (child == nullptr) { + return -1; + } for (int i = 0; i < numberOfChildren(); i++) { if (children()[i] == child) { return i; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index cd94aa8d8..303fb23db 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -250,16 +250,4 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } -int HorizontalLayout::indexOfChild(ExpressionLayout * eL) const { - if (eL == nullptr) { - return -1; - } - for (int i = 0; i < numberOfChildren(); i++) { - if (child(i) == eL) { - return i; - } - } - return -1; -} - } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 87cf0bd33..7c58113b9 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -31,7 +31,6 @@ protected: void mergeChildrenAtIndex(ExpressionLayout * eL, int index); // WITHOUT delete. private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); - int indexOfChild(ExpressionLayout * eL) const; }; } From fccd9b484b810992fa0bde800cac5dd53a4e82d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 13:19:15 +0100 Subject: [PATCH 067/459] [poincare] Added UneditableHorizontalTrioLayout. Change-Id: Ifd9fd6a0a0714853c1a8cd428b65076b704a8211 --- poincare/Makefile | 1 + poincare/include/poincare_layouts.h | 1 + .../uneditable_horizontal_trio_layout.cpp | 156 ++++++++++++++++++ .../uneditable_horizontal_trio_layout.h | 42 +++++ 4 files changed, 200 insertions(+) create mode 100644 poincare/src/layout/uneditable_horizontal_trio_layout.cpp create mode 100644 poincare/src/layout/uneditable_horizontal_trio_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index d20f96750..b49e17a2c 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -114,6 +114,7 @@ objs += $(addprefix poincare/src/layout/,\ static_layout_hierarchy.o\ string_layout.o\ sum_layout.o\ + uneditable_horizontal_trio_layout.o\ uneditable_parenthesis_left_layout.o\ uneditable_parenthesis_right_layout.o\ ) diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index f3d71feae..4c339e285 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -28,5 +28,6 @@ #include #include #include +#include #endif diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp new file mode 100644 index 000000000..15b03993c --- /dev/null +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp @@ -0,0 +1,156 @@ +#include "uneditable_horizontal_trio_layout.h" +#include "empty_visible_layout.h" +#include +extern "C" { +#include +} + +namespace Poincare { + +ExpressionLayout * UneditableHorizontalTrioLayout::clone() const { + UneditableHorizontalTrioLayout * layout = new UneditableHorizontalTrioLayout( + const_cast(this)->leftLayout(), + const_cast(this)->centerLayout(), + const_cast(this)->rightLayout(), + true); + return layout; +} + +void UneditableHorizontalTrioLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(new EmptyVisibleLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(previousParent); + return; + } + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + +bool UneditableHorizontalTrioLayout::moveLeft(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == centerLayout()) { + // Case: Center layout. + // Go Left. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + // Case: Right. + // Go Right of the center layout's last child if it has one, else go Right + // of the center layout. + ExpressionLayout * grandChild = centerLayout()->editableChild(centerLayout()->numberOfChildren()-1); + if (grandChild != nullptr) { + cursor->setPointedExpressionLayout(grandChild); + return true; + } + cursor->setPointedExpressionLayout(centerLayout()); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool UneditableHorizontalTrioLayout::moveRight(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == centerLayout()) { + // Case: Center layout. + // Go Right. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + cursor->setPointedExpressionLayout(this); + return true; + } + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + // Case: Left. + // Go Left of the center layout's first child if it has one, else go Left of + // the center layout. + ExpressionLayout * grandChild = centerLayout()->editableChild(0); + if (grandChild != nullptr) { + cursor->setPointedExpressionLayout(grandChild); + return true; + } + cursor->setPointedExpressionLayout(centerLayout()); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +void UneditableHorizontalTrioLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +} + +KDSize UneditableHorizontalTrioLayout::computeSize() { + // TODO: This code is duplicated from horizontal_layout.cpp. + KDCoordinate totalWidth = 0; + int i = 0; + KDCoordinate max_under_baseline = 0; + KDCoordinate max_above_baseline = 0; + while (ExpressionLayout * c = editableChild(i++)) { + KDSize childSize = c->size(); + totalWidth += childSize.width(); + if (childSize.height() - c->baseline() > max_under_baseline) { + max_under_baseline = childSize.height() - c->baseline() ; + } + if (c->baseline() > max_above_baseline) { + max_above_baseline = c->baseline(); + } + } + return KDSize(totalWidth, max_under_baseline + max_above_baseline); +} + +void UneditableHorizontalTrioLayout::computeBaseline() { + // TODO: This code is duplicated from horizontal_layout.cpp. + m_baseline = 0; + for (int i = 0; i < numberOfChildren(); i++) { + if (editableChild(i)->baseline() > m_baseline) { + m_baseline = editableChild(i)->baseline(); + } + } + m_baselined = true; +} + +KDPoint UneditableHorizontalTrioLayout::positionOfChild(ExpressionLayout * child) { + // TODO: This code is duplicated from horizontal_layout.cpp. + KDCoordinate x = 0; + KDCoordinate y = 0; + int index = indexOfChild(child); + if (index > 0) { + ExpressionLayout * previousChild = editableChild(index-1); + assert(previousChild != nullptr); + x = previousChild->origin().x() + previousChild->size().width(); + } + y = baseline() - child->baseline(); + return KDPoint(x, y); +} + +ExpressionLayout * UneditableHorizontalTrioLayout::leftLayout() { + return editableChild(0); +} + +ExpressionLayout * UneditableHorizontalTrioLayout::centerLayout() { + return editableChild(1); +} + +ExpressionLayout * UneditableHorizontalTrioLayout::rightLayout() { + return editableChild(2); +} + +} diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.h b/poincare/src/layout/uneditable_horizontal_trio_layout.h new file mode 100644 index 000000000..d0a356c14 --- /dev/null +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.h @@ -0,0 +1,42 @@ +#ifndef POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H +#define POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H + +#include + +namespace Poincare { + +/* UneditableHorizontalTrioLayout has 3 children: a left and a right layout + * (usually parentheses or brackets), and a central layout. + * The cursor can only be: + * - Left or Right of the UneditableHorizontalTrioLayout, + * - Left or Right of the central layout if it is not an horizontal layout, + * - Inside the central layout if it is an horizontal layout. + * This way, the lateral children of an UneditableHorizontalTrioLayout cannot be + * edited, and it it will always have only 3 children. + * This layout can be used to create binomial coefficient layouts, matrix + * layouts or the argument of sum and product layouts. */ + +class UneditableHorizontalTrioLayout : public StaticLayoutHierarchy<3> { +public: + using StaticLayoutHierarchy::StaticLayoutHierarchy; + ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + + /* Navigation */ + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; + +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(ExpressionLayout * child) override; +private: + ExpressionLayout * leftLayout(); + ExpressionLayout * centerLayout(); + ExpressionLayout * rightLayout(); +}; + +} + +#endif From 6f81a6cceb44e7f6ae61182507bbd552f4349c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 10:30:54 +0100 Subject: [PATCH 068/459] [apps] Added layout for binomial coefficient in toolbox. Change-Id: I43bd6ff8a2f812d8bf524d60b559d1b227c0c79f --- apps/math_toolbox.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 8a8d24182..23eff77f3 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -47,8 +47,18 @@ const ToolboxMessageTree complexChildren[5] = { const_cast(&pointedLayoutPathConj[0]), 1)}; +const int pointedLayoutPathBinomial[] = {1,0}; const ToolboxMessageTree probabilityChildren[2] = { - ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg), + ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg, nullptr, 0, + new UneditableHorizontalTrioLayout( + new ParenthesisLeftLayout(), + new GridLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + new EmptyVisibleLayout(), + new EmptyVisibleLayout())), + 2, 1, false), + new ParenthesisRightLayout()), + const_cast(&pointedLayoutPathBinomial[0]), + 2), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommandWithArg)}; const ToolboxMessageTree arithmeticChildren[4] = { From 48e20abe73f828c21772fffdcff387fa806ecd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 13:28:16 +0100 Subject: [PATCH 069/459] [poincare] Navigation and delete in GridLayout. Change-Id: I8357150d9f15dd003ab97e09981d164d57235739 --- poincare/src/layout/expression_layout.cpp | 3 ++- poincare/src/layout/grid_layout.cpp | 31 ++++++++++++++++++++--- poincare/src/layout/grid_layout.h | 1 + poincare/src/layout/horizontal_layout.cpp | 12 +++++++++ poincare/src/layout/horizontal_layout.h | 1 + 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 5fdae5833..3b5bc8316 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -127,7 +127,8 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { if (m_parent) { int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; - if (m_parent->addChildAtIndex(brother, brotherIndex)) { + if (m_parent->isHorizontal()) { + m_parent->addChildAtIndex(brother, brotherIndex); return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 9821533de..2ad50f177 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -1,4 +1,5 @@ #include "grid_layout.h" +#include "empty_visible_layout.h" #include extern "C" { #include @@ -19,6 +20,30 @@ ExpressionLayout * GridLayout::clone() const { return layout; } +void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // If the cursor is on the left of the grid, delete the grid and its parent: A + // grid only exists for now in binomial coefficient and in matrices, and we + // want to delete their parentheses or brackets too. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); + if (indexOfPointedExpression >= 0 && childIsLeftOfGrid(indexOfPointedExpression)) { + assert(m_parent != nullptr); + assert(m_parent->parent() != nullptr); + ExpressionLayout * grandParent = const_cast(m_parent->parent()); + int indexInGrandParent = grandParent->indexOfChild(m_parent); + m_parent->replaceWith(new EmptyVisibleLayout(), true); + if (indexInGrandParent == 0) { + cursor->setPointedExpressionLayout(grandParent); + return; + } + cursor->setPointedExpressionLayout(grandParent->editableChild(indexInGrandParent-1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the last entry. @@ -38,7 +63,7 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Left of the grid cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return m_parent->moveLeft(cursor); } // Case: Left of another child. // Go Right of its brother on the left. @@ -72,10 +97,10 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Right) { if (childIsRightOfGrid(childIndex)) { // Case: Right of a child on the right of the grid. - // Go Right of the grid. + // Go Right of the grid and move Right. cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return m_parent->moveRight(cursor); } // Case: Right of another child. // Go Left of its brother on the right. diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 379fd642f..e2275511b 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -9,6 +9,7 @@ class GridLayout : public DynamicLayoutHierarchy { public: GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 303fb23db..38d125e6c 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -15,6 +15,18 @@ ExpressionLayout * HorizontalLayout::clone() const { return layout; } +void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // If the cursor was pointing left of the first child of the horizontal + // layout, make it point at the horizontal layout itself. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); + if (indexOfPointedExpression == 0) { + cursor->setPointedExpressionLayout(this); + } + } + ExpressionLayout::backspaceAtCursor(cursor); +} + void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { if (newChild->isEmpty()) { if (numberOfChildren() > 1) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 7c58113b9..a3aef1244 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -9,6 +9,7 @@ class HorizontalLayout : public DynamicLayoutHierarchy { public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Hierarchy */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; From 3baf483a8668a49c7bf288d193564662ed9fe781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 13:46:43 +0100 Subject: [PATCH 070/459] [poincare] Fixed StringLayout navigation bug. Change-Id: I73b99b6a4302b4487357a7e1cef563b43743554c --- poincare/src/layout/string_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index adea25f99..c31c31d71 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -32,7 +32,7 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { // string layout, for instance left of "n=" in a Sum layout. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { int indexOfThis = m_parent->indexOfChild(this); - if (m_parent->editableChild(indexOfThis-1) != nullptr) { + if (indexOfThis > 1) { cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; From 3415dde6c7b015143d39499d7ed12f7bda099729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 13:47:30 +0100 Subject: [PATCH 071/459] [poincare] Use uneditableHorizontalTrioLayout in SumLayout. Change-Id: I67c5c59d8cdb50506a105dd0929eaa1bc79bca1c --- poincare/src/layout/sum_layout.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index ef3027cbf..82737c7bb 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -1,7 +1,8 @@ #include "sum_layout.h" #include "horizontal_layout.h" -#include "uneditable_parenthesis_left_layout.h" -#include "uneditable_parenthesis_right_layout.h" +#include "parenthesis_left_layout.h" +#include "parenthesis_right_layout.h" +#include "uneditable_horizontal_trio_layout.h" #include #include #include @@ -27,18 +28,12 @@ const uint8_t symbolPixel[SumLayout::k_symbolHeight][SumLayout::k_symbolWidth] = }; SumLayout::SumLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : - SequenceLayout(lowerBound, upperBound, argument, cloneOperands) + SequenceLayout() { - UneditableParenthesisLeftLayout * parLeft = new UneditableParenthesisLeftLayout(); - UneditableParenthesisRightLayout * parRight = new UneditableParenthesisRightLayout(); - HorizontalLayout * horLayout = new HorizontalLayout(); - ExpressionLayout * argLayout = editableChild(2); - // We cannot call argument() because it is overrided to handle completely - // built SumLayouts, not SumLayouts in construction. - argLayout->replaceWith(horLayout, false); - horLayout->addChildAtIndex(parLeft, 0); - horLayout->addChildAtIndex(argLayout, 1); - horLayout->addChildAtIndex(parRight, 2); + ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); + ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); + UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, false); + build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(lowerBound, upperBound, horLayout)), 3, false); } ExpressionLayout * SumLayout::clone() const { From abdd85ddff3ce71fe003ac316a12587dc976b108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 14:33:33 +0100 Subject: [PATCH 072/459] [poincare] Delete for BaselineRelativeLayout (Editable or not). Change-Id: I86fb27c35859d742ff26f55397281c2585960b08 --- .../src/layout/baseline_relative_layout.cpp | 19 ++----- .../editable_baseline_relative_layout.cpp | 55 +++++++++++++++++++ .../editable_baseline_relative_layout.h | 1 + 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index f2b58bb15..725898139 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -18,21 +18,10 @@ ExpressionLayout * BaselineRelativeLayout::clone() const { } void BaselineRelativeLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == indiceLayout()) { - if (m_type == Type::Superscript) { - ExpressionLayout * base = baseLayout(); - ExpressionLayout * pointedLayout = base; - if (base->isHorizontal()) { - pointedLayout = base->editableChild(base->numberOfChildren()-1); - } - if (indiceLayout()->isEmpty()) { - replaceWith(base, true); - } - cursor->setPointedExpressionLayout(pointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - assert(m_type == Type::Subscript); + if (cursor->pointedExpressionLayout() == indiceLayout() + || (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right)) + { ExpressionLayout * previousParent = m_parent; int indexInParent = previousParent->indexOfChild(this); replaceWith(new EmptyVisibleLayout(), true); diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp index e5b0d29c1..9e72033d1 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ b/poincare/src/layout/editable_baseline_relative_layout.cpp @@ -1,4 +1,5 @@ #include "editable_baseline_relative_layout.h" +#include "empty_visible_layout.h" #include #include #include @@ -10,6 +11,60 @@ ExpressionLayout * EditableBaselineRelativeLayout::clone() const { return layout; } +void EditableBaselineRelativeLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == indiceLayout()) { + if (m_type == Type::Superscript) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + ExpressionLayout * base = baseLayout(); + ExpressionLayout * pointedLayout = base; + if (base->isHorizontal()) { + pointedLayout = base->editableChild(base->numberOfChildren()-1); + } + if (indiceLayout()->isEmpty()) { + if (baseLayout()->isEmpty()) { + // Case: Empty base and indice. + // Replace with an empty layout. + int indexInParent = m_parent->indexOfChild(this); + if (indexInParent == 0) { + pointedLayout = m_parent; + replaceWith(base, true); + cursor->setPointedExpressionLayout(pointedLayout); + return; + } + pointedLayout = m_parent->editableChild(indexInParent - 1); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + replaceWith(base, true); + cursor->setPointedExpressionLayout(pointedLayout); + return; + } + // Case: Empty indice only. + // Replace with the base. + replaceWith(base, true); + cursor->setPointedExpressionLayout(pointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Case: Non-empty indice. + // Move to the base. + cursor->setPointedExpressionLayout(pointedLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + assert(m_type == Type::Subscript); + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(new EmptyVisibleLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(previousParent); + return; + } + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the indice. // Go from the indice to the base. diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h index 22c5c968f..af60ba3b9 100644 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ b/poincare/src/layout/editable_baseline_relative_layout.h @@ -9,6 +9,7 @@ class EditableBaselineRelativeLayout : public BaselineRelativeLayout { public: using BaselineRelativeLayout::BaselineRelativeLayout; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; From 5d229b2ab0b8b338a65ffb44302600657376d1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 14:34:16 +0100 Subject: [PATCH 073/459] [poincare] Fixed StringLayout navigation. Change-Id: Ib89cf550bb22c3216db6364566d5b08abe9d3889 --- poincare/src/layout/string_layout.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index c31c31d71..55f638fce 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -37,11 +37,9 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } - if (m_parent->parent()) { - cursor->setPointedExpressionLayout(const_cast(m_parent->parent())); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } + cursor->setPointedExpressionLayout(m_parent); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; } // Case: Left. // Ask the parent. From 527fd9feabb161373a1c5242d472478ee6e0b803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 14:42:38 +0100 Subject: [PATCH 074/459] [poincare] Fixed FractionLayout delete. Change-Id: Idb8e5c4d71cf00c796a82ef1f41ea63b224752ba --- poincare/src/layout/fraction_layout.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 671643e30..aa95c224e 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -80,6 +80,12 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } + // If the cursor is on the left of the numerator, move Left of the fraction. + if (cursor->pointedExpressionLayout() == numeratorLayout()) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + cursor->setPointedExpressionLayout(this); + return; + } ExpressionLayout::backspaceAtCursor(cursor); } From 30b75bfef69faf8318435f42b7c5afbfc21279c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 14:50:39 +0100 Subject: [PATCH 075/459] [poincare] Delete for EmptyVisibleLayout. Change-Id: Iceda680d153ddf622a39a4f46274ce038401ca61 --- poincare/src/layout/empty_visible_layout.cpp | 12 ++++++++++++ poincare/src/layout/empty_visible_layout.h | 1 + 2 files changed, 13 insertions(+) diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index f4291ef24..a7ac20513 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -15,6 +15,18 @@ ExpressionLayout * EmptyVisibleLayout::clone() const { return layout; } +void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->backspaceAtCursor(cursor); + } +} + bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 1a549d9ce..65714d0ac 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -10,6 +10,7 @@ class EmptyVisibleLayout : public EmptyLayout { public: EmptyVisibleLayout(); ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; protected: From 2a3dc0a83a6d62d2f3b769a60a5bc55301de0bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 15:23:41 +0100 Subject: [PATCH 076/459] [poincare] Delete for integral layouts. Change-Id: I830b759108f857825a576d1dc37b2f85add7688a --- poincare/src/layout/integral_layout.cpp | 48 +++++++++++++++++++++++-- poincare/src/layout/integral_layout.h | 1 + 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 59164adb7..00031c26e 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -24,6 +24,49 @@ ExpressionLayout * IntegralLayout::clone() const { return layout; } +void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left the upper bound, lower bound or argument. + // Delete the integral, keep the integrand. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && ((upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()) + || (lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left))) + { + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + ExpressionLayout * dxLayout = integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-1); + replaceWith(integrandLayout(), true); + // Remove "dx" + int indexOfdx = previousParent->indexOfChild(dxLayout); + if (indexOfdx >= 0) { + previousParent->removeChildAtIndex(indexOfdx, true); + } + // Place the cursor on the right of the left brother of the integral if + // there is one. + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(previousParent); + return; + } + // If the cursor is on the right, move to the integrand. + if (cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Right)) { + assert(integrandLayout()->numberOfChildren() > 1); + ExpressionLayout * layoutLeftOfdx = integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-2); + cursor->setPointedExpressionLayout(layoutLeftOfdx); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + if (m_parent) { + return m_parent->backspaceAtCursor(cursor); + } +} + bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left the upper or lower bound. // Go Left of the integral. @@ -49,10 +92,11 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { } assert(cursor->pointedExpressionLayout() == this); // Case: Right of the integral. - // Go Right of the integrand, Left of "dx". + // Go Left of "dx". if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-2)); + cursor->setPointedExpressionLayout(integrandLayout()->editableChild(integrandLayout()->numberOfChildren() - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 67b0e5750..70d07eed4 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -11,6 +11,7 @@ public: constexpr static KDCoordinate k_symbolWidth = 4; using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; From df77faec28179751ef9644141114410edd84a9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 15:33:05 +0100 Subject: [PATCH 077/459] [poincare] Delete for RootLayout. Change-Id: I4555e94bfa887e63aa0a3e11eff8f3043b5803e7 --- poincare/src/layout/nth_root_layout.cpp | 43 +++++++++++++++++++++++++ poincare/src/layout/nth_root_layout.h | 1 + 2 files changed, 44 insertions(+) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 709e3df2f..005c67b27 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -21,6 +21,49 @@ ExpressionLayout * NthRootLayout::clone() const { return layout; } +void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left the index. + // Move Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && cursor->pointedExpressionLayout() == indexLayout()) + { + cursor->setPointedExpressionLayout(this); + return; + } + // Case: Left the radicand. + // Delete the root, keep the radicand. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && cursor->pointedExpressionLayout() == radicandLayout()) + { + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(radicandLayout()); + // Place the cursor on the right of the left brother of the root if there is + // one. + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(previousParent); + return; + } + // Case: Right. + // Move to the radicand. + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() ==ExpressionLayoutCursor::Position::Right) { + cursor->setPointedExpressionLayout(radicandLayout()); + return; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() ==ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->backspaceAtCursor(cursor); + } +} + bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the radicand. // Go the index if there is one, else go Left of the root. diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 5c1ad77d9..d5cceb77f 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -11,6 +11,7 @@ public: constexpr static KDCoordinate k_leftRadixWidth = 5; using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; From af232a8678c2ae57e1e16301d8f06db7a5a1ec81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 16:34:00 +0100 Subject: [PATCH 078/459] [poincare] Delete in SequenceLayout. Change-Id: Ie530516fcddde4d7a93d89993bab5cab30927faa --- poincare/src/layout/sequence_layout.cpp | 69 +++++++++++-- poincare/src/layout/sequence_layout.h | 3 +- poincare/src/layout/sum_layout.cpp | 128 ------------------------ poincare/src/layout/sum_layout.h | 7 +- 4 files changed, 61 insertions(+), 146 deletions(-) diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 708b7e1af..610324ca9 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -1,11 +1,60 @@ #include "sequence_layout.h" -#include "string_layout.h" +#include "parenthesis_left_layout.h" +#include "parenthesis_right_layout.h" +#include "uneditable_horizontal_trio_layout.h" #include #include #include namespace Poincare { +SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : + StaticLayoutHierarchy() +{ + ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); + ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); + UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands); + build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(lowerBound, upperBound, horLayout)), 3, cloneOperands); +} + +void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left of the bounds or of the argument. + // Delete the sequence, keep the argument. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && ((lowerBoundLayout() + && cursor->pointedExpressionLayout() == lowerBoundLayout()) + || (upperBoundLayout() + && cursor->pointedExpressionLayout() == upperBoundLayout()) + || cursor->pointedExpressionLayout() == argumentLayout())) + { + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(argumentLayout(), true); + // Place the cursor on the right of the left brother of the sequence if + // there is one. + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(previousParent); + return; + } + // Case: Right. + // Move inside the argument. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(argumentLayout()); + return; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + m_parent->backspaceAtCursor(cursor); +} + bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the bounds. // Go Left of the sequence. @@ -22,7 +71,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Right of the lower bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left && argumentLayout() - && cursor->pointedExpressionLayout() == argumentLayout()) + && cursor->pointedExpressionLayout() == editableChild(2)) { assert(lowerBoundLayout() != nullptr); cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); @@ -35,7 +84,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(argumentLayout() != nullptr); cursor->setPointedExpressionLayout(argumentLayout()); - return argumentLayout()->moveLeft(cursor); + return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left. @@ -64,13 +113,11 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. if (cursor->position() == ExpressionLayoutCursor::Position::Right && argumentLayout() - && cursor->pointedExpressionLayout() == argumentLayout()) + && cursor->pointedExpressionLayout() == editableChild(2)) { cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; } assert(cursor->pointedExpressionLayout() == this); // Case: Left. @@ -133,11 +180,11 @@ ExpressionLayout * SequenceLayout::lowerBoundLayout() { } ExpressionLayout * SequenceLayout::argumentLayout() { - return editableChild(2); + return editableChild(2)->editableChild(1); } KDSize SequenceLayout::computeSize() { - KDSize argumentSize = argumentLayout()->size(); + KDSize argumentSize = editableChild(2)->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( @@ -162,7 +209,7 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { } else if (child == upperBoundLayout()) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); y = m_baseline - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (child == argumentLayout()) { + } else if (child == editableChild(2)) { x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; y = m_baseline - argumentLayout()->baseline(); } else { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 7df9ce767..ca53827d8 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -9,7 +9,8 @@ class SequenceLayout : public StaticLayoutHierarchy<3> { public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; - using StaticLayoutHierarchy::StaticLayoutHierarchy; + SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 82737c7bb..c59ccb496 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -1,8 +1,4 @@ #include "sum_layout.h" -#include "horizontal_layout.h" -#include "parenthesis_left_layout.h" -#include "parenthesis_right_layout.h" -#include "uneditable_horizontal_trio_layout.h" #include #include #include @@ -27,105 +23,11 @@ const uint8_t symbolPixel[SumLayout::k_symbolHeight][SumLayout::k_symbolWidth] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; -SumLayout::SumLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : - SequenceLayout() -{ - ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); - ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); - UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, false); - build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(lowerBound, upperBound, horLayout)), 3, false); -} - ExpressionLayout * SumLayout::clone() const { SumLayout * layout = new SumLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); return layout; } -ExpressionLayout * SumLayout::argumentLayout() { - return editableChild(2)->editableChild(1); -} - -bool SumLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // Case: Left of the bounds. - // Go Left of the sum. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && ((lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) - || (upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()))) - { - cursor->setPointedExpressionLayout(this); - return true; - } - // Case: Left of the argument. - // Go Right of the lower bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && argumentLayout() - && cursor->pointedExpressionLayout() == editableChild(2)) - { - assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the argument and move Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(argumentLayout() != nullptr); - cursor->setPointedExpressionLayout(argumentLayout()); - return true; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool SumLayout::moveRight(ExpressionLayoutCursor * cursor) { - // Case: Right of the bounds. - // Go Left of the argument. - if (cursor->position() == ExpressionLayoutCursor::Position::Right - && ((lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) - || (upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()))) - { - assert(argumentLayout() != nullptr); - cursor->setPointedExpressionLayout(argumentLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Right of the argument. - // Ask the parent. - if (cursor->position() == ExpressionLayoutCursor::Position::Right - && argumentLayout() - && cursor->pointedExpressionLayout() == editableChild(2)) - { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the upper bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(upperBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(upperBoundLayout()); - return true; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize upperBoundSize = upperBoundLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); @@ -136,34 +38,4 @@ void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDCo ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); } -KDSize SumLayout::computeSize() { - KDSize argumentSize = editableChild(2)->size(); - KDSize lowerBoundSize = lowerBoundLayout()->size(); - KDSize upperBoundSize = upperBoundLayout()->size(); - return KDSize( - max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), - m_baseline + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) - ); -} - -KDPoint SumLayout::positionOfChild(ExpressionLayout * child) { - KDSize lowerBoundSize = lowerBoundLayout()->size(); - KDSize upperBoundSize = upperBoundLayout()->size(); - KDCoordinate x = 0; - KDCoordinate y = 0; - if (child == lowerBoundLayout()) { - x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); - y = m_baseline + k_symbolHeight/2 + k_boundHeightMargin; - } else if (child == upperBoundLayout()) { - x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); - y = m_baseline - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (child == editableChild(2)) { - x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; - y = m_baseline - argumentLayout()->baseline(); - } else { - assert(false); - } - return KDPoint(x,y); -} - } diff --git a/poincare/src/layout/sum_layout.h b/poincare/src/layout/sum_layout.h index 23d5f698f..7218e866f 100644 --- a/poincare/src/layout/sum_layout.h +++ b/poincare/src/layout/sum_layout.h @@ -7,15 +7,10 @@ namespace Poincare { class SumLayout : public SequenceLayout { public: - SumLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); + using SequenceLayout::SequenceLayout; ExpressionLayout * clone() const override; - ExpressionLayout * argumentLayout() override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDSize computeSize() override; - KDPoint positionOfChild(ExpressionLayout * child) override; }; } From 44cf9e8979036a8530c84e48b2f54bc23cf84c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 16:34:27 +0100 Subject: [PATCH 079/459] [poincare] Delete for StringLayout. Change-Id: I67ff432cb283ae2cd1d1acd86a0e2baef9dcbe29 --- poincare/src/layout/string_layout.cpp | 10 ++++++++++ poincare/src/layout/string_layout.h | 1 + 2 files changed, 11 insertions(+) diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index 55f638fce..d153214a8 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -23,6 +23,16 @@ ExpressionLayout * StringLayout::clone() const { return layout; } +void StringLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + m_parent->backspaceAtCursor(cursor); +} + bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { // A StringLayout is not editable, and the cursor cannot go inside it. assert(cursor->pointedExpressionLayout() == this); diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 0a3763811..48f405d33 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -15,6 +15,7 @@ public: StringLayout& operator=(const StringLayout& other) = delete; StringLayout& operator=(StringLayout&& other) = delete; ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; char * text() { return m_string; } bool moveLeft(ExpressionLayoutCursor * cursor) override; From 22b0042deddcd37b93ab2bbcd1c5c116b53b4af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 16:34:59 +0100 Subject: [PATCH 080/459] [poincare] Delete for UneditableHorizontalTrioLayout. Change-Id: Ide310278ed9444cf03dc02dc40c391ff9f3dfd16 --- .../uneditable_horizontal_trio_layout.cpp | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp index 15b03993c..e416dfbb3 100644 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp @@ -17,18 +17,38 @@ ExpressionLayout * UneditableHorizontalTrioLayout::clone() const { } void UneditableHorizontalTrioLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left of the center layout (for sequence layouts). + if (cursor->pointedExpressionLayout() == centerLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + ExpressionLayout * grandParent = const_cast(m_parent->parent()); + assert(grandParent != nullptr); + ExpressionLayout * parent = m_parent; + int indexInGrandParent = grandParent->indexOfChild(parent); + parent->replaceWith(centerLayout(), true); + // Place the cursor on the right of the left brother of the integral if + // there is one. + if (indexInGrandParent > 0) { + cursor->setPointedExpressionLayout(grandParent->editableChild(indexInGrandParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(grandParent); + return; + } + // Case: Right. + // Move to the argument. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(new EmptyVisibleLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(previousParent); + // Go Right of the center layout's last child if it has one, else go Right + // of the center layout. + if (centerLayout()->numberOfChildren() > 1) { + cursor->setPointedExpressionLayout(centerLayout()->editableChild(centerLayout()->numberOfChildren()-1)); return; } - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPointedExpressionLayout(centerLayout()); return; } ExpressionLayout::backspaceAtCursor(cursor); @@ -47,9 +67,8 @@ bool UneditableHorizontalTrioLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go Right of the center layout's last child if it has one, else go Right // of the center layout. - ExpressionLayout * grandChild = centerLayout()->editableChild(centerLayout()->numberOfChildren()-1); - if (grandChild != nullptr) { - cursor->setPointedExpressionLayout(grandChild); + if (centerLayout()->numberOfChildren() > 1) { + cursor->setPointedExpressionLayout(centerLayout()->editableChild(centerLayout()->numberOfChildren()-1)); return true; } cursor->setPointedExpressionLayout(centerLayout()); From 47f691c997b9389e00edd52e4a2b6e05f610312c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 16:35:36 +0100 Subject: [PATCH 081/459] [expression_editor] Empty initial layout. Change-Id: I00231be393bf65715f8f8647439c344fe7069851 --- apps/expression_editor/expression_and_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp index 0f777e586..3616751a4 100644 --- a/apps/expression_editor/expression_and_layout.cpp +++ b/apps/expression_editor/expression_and_layout.cpp @@ -1,6 +1,7 @@ #include "expression_and_layout.h" #include #include +#include namespace ExpressionEditor { @@ -39,7 +40,7 @@ ExpressionAndLayout::ExpressionAndLayout() { m_expression = Poincare::Expression::parse(expression); m_expressionLayout = new Poincare::HorizontalLayout(); - m_expressionLayout->addChildAtIndex(new Poincare::EditableStringLayout("1", 1), 0); + m_expressionLayout->addChildAtIndex(new Poincare::EmptyVisibleLayout(), 0); } ExpressionAndLayout::~ExpressionAndLayout() { if (m_expressionLayout) { From 2c5e1b99bb737d4af81ef2e821863f115781f1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 17:06:24 +0100 Subject: [PATCH 082/459] [poincare] Parameter for UneditableHorizontalTrioLayout navigation. This parameter specifies if the cursor can be left and right of the layout. Change-Id: Ia8d5ff45a471e964bf82e8db0465a5f07661884d --- apps/math_toolbox.cpp | 2 +- poincare/src/layout/sequence_layout.cpp | 2 +- .../uneditable_horizontal_trio_layout.cpp | 24 ++++++++++++++++--- .../uneditable_horizontal_trio_layout.h | 3 ++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 23eff77f3..b9fbc6a54 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -56,7 +56,7 @@ const ToolboxMessageTree probabilityChildren[2] = { new EmptyVisibleLayout(), new EmptyVisibleLayout())), 2, 1, false), - new ParenthesisRightLayout()), + new ParenthesisRightLayout(), false, true), const_cast(&pointedLayoutPathBinomial[0]), 2), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommandWithArg)}; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 610324ca9..f371911e1 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -13,7 +13,7 @@ SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * { ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); - UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands); + UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands, false); build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(lowerBound, upperBound, horLayout)), 3, cloneOperands); } diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp index e416dfbb3..ea8ff521d 100644 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp @@ -7,12 +7,18 @@ extern "C" { namespace Poincare { +UneditableHorizontalTrioLayout::UneditableHorizontalTrioLayout(ExpressionLayout * left, ExpressionLayout * central, ExpressionLayout * right, bool cloneOperands, bool cursorAllowedLeftAndRight) : + StaticLayoutHierarchy(left, central, right, cloneOperands), + m_cursorCanBeLeftOrRight(cursorAllowedLeftAndRight) +{ +} + ExpressionLayout * UneditableHorizontalTrioLayout::clone() const { UneditableHorizontalTrioLayout * layout = new UneditableHorizontalTrioLayout( const_cast(this)->leftLayout(), const_cast(this)->centerLayout(), const_cast(this)->rightLayout(), - true); + true, m_cursorCanBeLeftOrRight); return layout; } @@ -60,7 +66,13 @@ bool UneditableHorizontalTrioLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); cursor->setPointedExpressionLayout(this); - return true; + if (m_cursorCanBeLeftOrRight) { + return true; + } + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; } assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { @@ -89,7 +101,13 @@ bool UneditableHorizontalTrioLayout::moveRight(ExpressionLayoutCursor * cursor) // Go Right. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); cursor->setPointedExpressionLayout(this); - return true; + if (m_cursorCanBeLeftOrRight) { + return true; + } + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; } assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Left) { diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.h b/poincare/src/layout/uneditable_horizontal_trio_layout.h index d0a356c14..094b16d39 100644 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.h +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.h @@ -18,7 +18,7 @@ namespace Poincare { class UneditableHorizontalTrioLayout : public StaticLayoutHierarchy<3> { public: - using StaticLayoutHierarchy::StaticLayoutHierarchy; + UneditableHorizontalTrioLayout(ExpressionLayout * left, ExpressionLayout * central, ExpressionLayout * right, bool cloneOperands, bool cursorAllowedLeftAndRight); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; @@ -35,6 +35,7 @@ private: ExpressionLayout * leftLayout(); ExpressionLayout * centerLayout(); ExpressionLayout * rightLayout(); + bool m_cursorCanBeLeftOrRight; }; } From 894e8a603290f2168f71b6bd90c9b345a84f273e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 17:36:44 +0100 Subject: [PATCH 083/459] [poincare] Fix main layout edition. If its only child is empty, remove it before adding another child. Change-Id: I3047f17c69ff14787e172d99b6e0b3e1f4096f26 --- poincare/src/layout/expression_layout.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 3b5bc8316..d4410fb08 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -141,6 +141,10 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay } // If there is no parent, the pointed layout is the main horizontal layout. // Add the "brother" as a child. + // If there is only one empty child, remove it before adding the layout. + if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { + removeChildAtIndex(0, true); + } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { addChildAtIndex(brother, 0); return; From ceb124335789a01666ac91098066cabe0dd92b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 17:37:49 +0100 Subject: [PATCH 084/459] [poincare] Fix integral layout navigation. Change-Id: Id8e733dfc1c0e5c583a0d3e33ab4c0837c08e782 --- poincare/src/layout/integral_layout.cpp | 3 +-- poincare/src/layout/string_layout.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 00031c26e..a9ddb1298 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -96,8 +96,7 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); cursor->setPointedExpressionLayout(integrandLayout()->editableChild(integrandLayout()->numberOfChildren() - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return cursor->moveLeft(); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index d153214a8..e1e835993 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -42,7 +42,7 @@ bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { // string layout, for instance left of "n=" in a Sum layout. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { int indexOfThis = m_parent->indexOfChild(this); - if (indexOfThis > 1) { + if (indexOfThis > 0) { cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; From af2a57213514ec467f7fbdf1a4ab6a7a39cbf1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Dec 2017 17:45:06 +0100 Subject: [PATCH 085/459] [poincare] Fix fraction delete. Change-Id: I98d8fc4d835e753cca9138c42273fff43a58478c --- poincare/src/layout/fraction_layout.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index aa95c224e..889b66994 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -86,6 +86,13 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); return; } + // If the cursor is on the Right, move Left of the denominator. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(denominatorLayout()); + return; + } ExpressionLayout::backspaceAtCursor(cursor); } From 1773dcbc343f117af1c48e125defe744254d5358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 2 Jan 2018 11:15:48 +0100 Subject: [PATCH 086/459] [poincare] Fixed cases where baseline was used without computing it before. To access a layout's baseline, we should always use baseline() instead of m_baseline, in order to compute the baseline if it needs to be computed. Change-Id: I5e859108bb30b7e23e09beb82fe7046bfa25414f --- poincare/src/layout/nth_root_layout.cpp | 8 ++++---- poincare/src/layout/sequence_layout.cpp | 8 ++++---- poincare/src/layout/sum_layout.cpp | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 005c67b27..d23514edc 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -198,7 +198,7 @@ void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); KDColor workingBuffer[k_leftRadixWidth*k_leftRadixHeight]; KDRect leftRadixFrame(p.x() + indexSize.width() + k_widthMargin - k_leftRadixWidth, - p.y() + m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, + p.y() + baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, k_leftRadixWidth, k_leftRadixHeight); ctx->blendRectWithMask(leftRadixFrame, expressionColor, (const uint8_t *)radixPixel, (KDColor *)workingBuffer); // If the indice is higher than the root. @@ -240,7 +240,7 @@ KDSize NthRootLayout::computeSize() { KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); return KDSize( indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width() + k_radixHorizontalOverflow, - m_baseline + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin + baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin ); } @@ -260,10 +260,10 @@ KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); if (child == indexLayout()) { x = 0; - y = m_baseline - indexSize.height() - k_indexHeight; + y = baseline() - indexSize.height() - k_indexHeight; } else if (child == radicandLayout()) { x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; - y = m_baseline - radicandLayout()->baseline(); + y = baseline() - radicandLayout()->baseline(); } else { assert(false); } diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index f371911e1..d6db66cb7 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -189,7 +189,7 @@ KDSize SequenceLayout::computeSize() { KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), - m_baseline + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) + baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) ); } @@ -205,13 +205,13 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate y = 0; if (child == lowerBoundLayout()) { x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); - y = m_baseline + k_symbolHeight/2 + k_boundHeightMargin; + y = baseline() + k_symbolHeight/2 + k_boundHeightMargin; } else if (child == upperBoundLayout()) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); - y = m_baseline - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); + y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); } else if (child == editableChild(2)) { x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; - y = m_baseline - argumentLayout()->baseline(); + y = baseline() - argumentLayout()->baseline(); } else { assert(false); } diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index c59ccb496..8d198b249 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -31,9 +31,10 @@ ExpressionLayout * SumLayout::clone() const { void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize upperBoundSize = upperBoundLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDCoordinate argBaseline = argumentLayout()->baseline(); KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argBaseline /*argumentLayout()->baseline()*/-(k_symbolHeight+1)/2), k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); } From ccd25a360d6137a43f9fa9cdbf0c53d444b8ffb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 2 Jan 2018 16:11:06 +0100 Subject: [PATCH 087/459] [poincare] Serialize expression layout. We can now convert layouts into text: we will be able to parse them into an Expression. Change-Id: I82f4834c08f5b2c5fb294bdcb9a49257b574e20b --- apps/math_toolbox.cpp | 14 ++- poincare/include/poincare/expression_layout.h | 3 + poincare/include/poincare/layout_engine.h | 46 ++++++- poincare/src/layout/absolute_value_layout.h | 4 + .../src/layout/baseline_relative_layout.cpp | 22 ++++ .../src/layout/baseline_relative_layout.h | 1 + poincare/src/layout/bracket_layout.cpp | 22 ++++ poincare/src/layout/bracket_layout.h | 1 + poincare/src/layout/bracket_left_layout.h | 4 + poincare/src/layout/bracket_right_layout.h | 4 + poincare/src/layout/ceiling_layout.h | 4 + poincare/src/layout/char_layout.h | 4 + poincare/src/layout/condensed_sum_layout.h | 4 + poincare/src/layout/conjugate_layout.h | 4 + poincare/src/layout/empty_layout.cpp | 8 ++ poincare/src/layout/empty_layout.h | 2 + poincare/src/layout/floor_layout.h | 4 + poincare/src/layout/fraction_layout.cpp | 22 ++++ poincare/src/layout/fraction_layout.h | 2 + poincare/src/layout/grid_layout.cpp | 38 ++++++ poincare/src/layout/grid_layout.h | 3 + poincare/src/layout/horizontal_layout.h | 6 + poincare/src/layout/integral_layout.cpp | 53 ++++++++- poincare/src/layout/integral_layout.h | 9 ++ poincare/src/layout/nth_root_layout.h | 11 ++ poincare/src/layout/parenthesis_layout.h | 4 + poincare/src/layout/parenthesis_left_layout.h | 4 + .../src/layout/parenthesis_right_layout.h | 4 + poincare/src/layout/product_layout.cpp | 6 +- poincare/src/layout/product_layout.h | 2 + poincare/src/layout/sequence_layout.cpp | 61 ++++++++-- poincare/src/layout/sequence_layout.h | 4 +- poincare/src/layout/string_layout.cpp | 14 +++ poincare/src/layout/string_layout.h | 2 + poincare/src/layout/sum_layout.cpp | 6 +- poincare/src/layout/sum_layout.h | 2 + .../uneditable_horizontal_trio_layout.h | 5 + poincare/src/layout_engine.cpp | 112 +++++++++++++----- 38 files changed, 471 insertions(+), 50 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index b9fbc6a54..a1b29bf5c 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -10,17 +10,19 @@ using namespace Poincare; * and the text which would be edited by clicking on the row. When the node is a * subtree, the edited text is set at I18n::Message::Default. */ -const int pointedLayoutPathIntegral[] = {2, 0}; -const int pointedLayoutPathSum[] = {2, 1}; +const int pointedLayoutPathIntegral[] = {0, 0}; +const int pointedLayoutPathSum[] = {0, 1}; const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, new IntegralLayout( - new EmptyVisibleLayout(), - new EmptyVisibleLayout(), - new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + new HorizontalLayout( + const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( new EmptyVisibleLayout(), - new StringLayout("dx",2))), 2, false), false), + new StringLayout("dx",2))), 2, false), + new EmptyVisibleLayout(), + new EmptyVisibleLayout(), + false), const_cast(&pointedLayoutPathIntegral[0]), 2), ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 5ec12341f..f366a305f 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -66,6 +66,9 @@ public: virtual bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); bool moveDownInside(ExpressionLayoutCursor * cursor); + /* Expression Engine */ + virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; + /* Other */ virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index cf1bc1e00..e1b14d0ef 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -6,13 +6,53 @@ namespace Poincare { class LayoutEngine { + public: + /* Expression to ExpressionLayout */ static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); - typedef bool (*OperandNeedParenthesis)(const Expression * e); - static int writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis = [](const Expression * e) { return e->type() == Expression::Type::Opposite; }); - static int writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName); + /* Expression to Text */ + typedef bool (*OperandNeedsParenthesis)(const Expression * e); + static int writeInfixExpressionTextInBuffer( + const Expression * expression, + char * buffer, + int bufferSize, + const char * operatorName, + OperandNeedsParenthesis operandNeedsParenthesis = [](const Expression * e) { return e->type() == Expression::Type::Opposite; }); + static int writePrefixExpressionTextInBuffer( + const Expression * expression, + char * buffer, + int bufferSize, + const char * operatorName); + + /* ExpressionLayout to Text */ + typedef bool (*ChildNeedsParenthesis)(const char * operatorName); + static int writeInfixExpressionLayoutTextInBuffer( + const ExpressionLayout * expressionLayout, + char * buffer, + int bufferSize, + const char * operatorName, + int firstChildIndex = 0, + int lastChildIndex = -1, + ChildNeedsParenthesis childNeedsParenthesis = [](const char * operatorName) { + return (operatorName[1] == 0 && (operatorName[0] == powerChar || operatorName[0] == divideChar)); }); //TODO + static int writePrefixExpressionLayoutTextInBuffer( + const ExpressionLayout * expressionLayout, + char * buffer, + int bufferSize, + const char * operatorName, + bool writeFirstChild = true); + + /* Write one char in buffer */ + static int writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite); + +private: + static constexpr char powerChar = '^'; + static constexpr char divideChar = '/'; + // These two functions return the index of the null-terminating char. + static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, int firstChildIndex, int lastChildIndex, OperandNeedsParenthesis operandNeedsParenthesis, ChildNeedsParenthesis childNeedsParenthesis); + static int writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, bool writeFirstChild = true); }; } diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index 55691659c..0be2b78a8 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -2,6 +2,7 @@ #define POINCARE_ABSOLUTE_VALUE_LAYOUT_H #include "bracket_layout.h" +#include namespace Poincare { @@ -9,6 +10,9 @@ class AbsoluteValueLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "abs"); + } protected: KDCoordinate widthMargin() const override { return 2; } bool renderTopBar() const override { return false; } diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 725898139..133d6c563 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -1,6 +1,7 @@ #include "baseline_relative_layout.h" #include "empty_visible_layout.h" #include +#include #include #include @@ -70,6 +71,27 @@ bool BaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +int BaselineRelativeLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (m_type == Type::Subscript) { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } + int numberOfChars = LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "_{"); + if (numberOfChars < bufferSize - 1) { + //FIXME what if the buffer is not big enough? + buffer[numberOfChars++] = '}'; + buffer[numberOfChars] = 0; + } + return numberOfChars; + } + assert(m_type == Type::Superscript); + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); +} + ExpressionLayout * BaselineRelativeLayout::baseLayout() { return editableChild(0); } diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h index f0cb1f7a0..184f808a6 100644 --- a/poincare/src/layout/baseline_relative_layout.h +++ b/poincare/src/layout/baseline_relative_layout.h @@ -16,6 +16,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: ExpressionLayout * baseLayout(); ExpressionLayout * indiceLayout(); diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index f3433e3f2..993ad2204 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -1,5 +1,6 @@ #include "bracket_layout.h" #include +#include extern "C" { #include #include @@ -90,6 +91,27 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + + // Write the opening bracket + int numberOfChar = 0; + buffer[numberOfChar++] = '['; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + // Write the argument + numberOfChar += const_cast(this)->operandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the closing bracket + buffer[numberOfChar++] = ']'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + ExpressionLayout * BracketLayout::operandLayout() { return editableChild(0); } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index d11f51681..94b63398f 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -12,6 +12,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: ExpressionLayout * operandLayout(); KDCoordinate externWidthMargin() const { return 2; } diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index 1975b2fc0..35af9d32b 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -2,6 +2,7 @@ #define POINCARE_BRACKET_LEFT_LAYOUT_H #include +#include namespace Poincare { @@ -9,6 +10,9 @@ class BracketLeftLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '['); + } bool isLeftBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index 788664f3e..bc5af7548 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -2,6 +2,7 @@ #define POINCARE_BRACKET_RIGHT_LAYOUT_H #include +#include namespace Poincare { @@ -9,6 +10,9 @@ class BracketRightLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ']'); + } bool isRightBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/ceiling_layout.h b/poincare/src/layout/ceiling_layout.h index 1dd170093..b09c99f5a 100644 --- a/poincare/src/layout/ceiling_layout.h +++ b/poincare/src/layout/ceiling_layout.h @@ -2,6 +2,7 @@ #define POINCARE_CEILING_LAYOUT_H #include "bracket_layout.h" +#include namespace Poincare { @@ -9,6 +10,9 @@ class CeilingLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "ceil"); + } protected: bool renderBottomBar() const override { return false; } }; diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index d00625c09..47ba4e336 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -2,6 +2,7 @@ #define POINCARE_CHAR_LAYOUT_H #include +#include #include namespace Poincare { @@ -10,6 +11,9 @@ class CharLayout : public StaticLayoutHierarchy<0> { public: CharLayout(char c, KDText::FontSize fontSize = KDText::FontSize::Large); ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); + } char character() { return m_char; } bool moveLeft(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 20795398d..2647474cd 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -2,6 +2,7 @@ #define POINCARE_CONDENSED_SUM_LAYOUT_H #include +#include namespace Poincare { @@ -13,6 +14,9 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "sum"); + } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 366c824a5..203b1f1ca 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -2,6 +2,7 @@ #define POINCARE_CONJUGATE_LAYOUT_H #include +#include namespace Poincare { @@ -12,6 +13,9 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "conj"); + } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 88871bb7c..c7af45bf2 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -9,6 +9,14 @@ ExpressionLayout * EmptyLayout::clone() const { return layout; } +int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; +} + void EmptyLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { replaceWith(brother, true); } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 3688e4f21..5d82724f7 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -2,6 +2,7 @@ #define POINCARE_EMPTY_LAYOUT_H #include +#include #include namespace Poincare { @@ -13,6 +14,7 @@ public: void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; bool isEmpty() const override { return true; } protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { return; } diff --git a/poincare/src/layout/floor_layout.h b/poincare/src/layout/floor_layout.h index 1bfb7e8f3..5e5a9785b 100644 --- a/poincare/src/layout/floor_layout.h +++ b/poincare/src/layout/floor_layout.h @@ -2,6 +2,7 @@ #define POINCARE_FLOOR_LAYOUT_H #include "bracket_layout.h" +#include namespace Poincare { @@ -9,6 +10,9 @@ class FloorLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "floor"); + } protected: bool renderTopBar() const override { return false; } }; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 889b66994..71b9555aa 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -178,6 +178,28 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + // Write the first enclosing parenthesis. + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + // Write the content of the fraction + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, "/"); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the second enclosing parenthesis. + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + numeratorLayout()->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, size().width()-2*Metric::FractionAndConjugateHorizontalMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 296b31ccc..7c551df14 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -2,6 +2,7 @@ #define POINCARE_FRACTION_LAYOUT_H #include +#include namespace Poincare { @@ -14,6 +15,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 2ad50f177..b73636fc0 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -1,6 +1,7 @@ #include "grid_layout.h" #include "empty_visible_layout.h" #include +#include extern "C" { #include #include @@ -137,6 +138,43 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * pr return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +int GridLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + const ExpressionLayout * editableParent = const_cast(this)->parent(); + assert(editableParent != nullptr); + + // If the grid is a binomial coefficient: + if (editableParent->child(0)->isLeftParenthesis()) { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "binomial"); + } + + assert(editableParent->child(0)->isLeftBracket()); + // The grid is a matrix. + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + for (int i = 0; i < m_numberOfRows; i++) { + buffer[numberOfChar++] = '['; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, (i+1) * m_numberOfColumns - 1); + + buffer[numberOfChar++] = ']'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + if (i < m_numberOfRows - 1) { + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + } + + buffer[numberOfChar] = 0; + return numberOfChar; +} + KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index e2275511b..e5a6bde67 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -17,6 +17,9 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + /* Expression engine */ + int writeTextInBuffer(char * buffer, int bufferSize) const override; + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index a3aef1244..c4aa2a027 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -2,6 +2,7 @@ #define POINCARE_HORIZONTAL_LAYOUT_H #include +#include namespace Poincare { @@ -21,6 +22,11 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + /* Expression Engine */ + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); + } + /* Other */ bool isHorizontal() const override { return true; } diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index a9ddb1298..f41c8bf2c 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -20,7 +20,7 @@ const uint8_t bottomSymbolPixel[IntegralLayout::k_symbolHeight][IntegralLayout:: }; ExpressionLayout * IntegralLayout::clone() const { - IntegralLayout * layout = new IntegralLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->integrandLayout(), true); + IntegralLayout * layout = new IntegralLayout(const_cast(this)->integrandLayout(), const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), true); return layout; } @@ -181,6 +181,53 @@ bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + + // Write the operator name + int numberOfChar = strlcpy(buffer, "int", bufferSize); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + // Write the opening parenthesis + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + // Write the argument without the "dx" + ExpressionLayout * intLayout = const_cast(this)->integrandLayout(); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(intLayout, buffer+numberOfChar, bufferSize-numberOfChar, "", 0, intLayout->numberOfChildren()-2); + // TODO This works because the argument layout should always be an horizontal + // layout. + + // Write the comma + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the lower bound + numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + + // Write the comma + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the upper bound + numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + + // Write the closing parenthesis + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = integrandLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); @@ -232,7 +279,7 @@ KDPoint IntegralLayout::positionOfChild(ExpressionLayout * child) { } ExpressionLayout * IntegralLayout::upperBoundLayout() { - return editableChild(0); + return editableChild(2); } ExpressionLayout * IntegralLayout::lowerBoundLayout() { @@ -240,7 +287,7 @@ ExpressionLayout * IntegralLayout::lowerBoundLayout() { } ExpressionLayout * IntegralLayout::integrandLayout() { - return editableChild(2); + return editableChild(0); } } diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 70d07eed4..35e9769df 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -2,6 +2,7 @@ #define POINCARE_INTEGRAL_LAYOUT_H #include +#include namespace Poincare { @@ -11,11 +12,19 @@ public: constexpr static KDCoordinate k_symbolWidth = 4; using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + /* Dynamic Layout*/ void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + + /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + + /* Expression Engine */ + int writeTextInBuffer(char * buffer, int bufferSize) const override; + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index d5cceb77f..c04f5c7f2 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -2,6 +2,7 @@ #define POINCARE_NTH_ROOT_LAYOUT_H #include +#include namespace Poincare { @@ -11,11 +12,21 @@ public: constexpr static KDCoordinate k_leftRadixWidth = 5; using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + /* Dynamic Layout*/ void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + + /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + + /* Expression Engine */ + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "root"); + } + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 0757c6f5f..f7ed69efd 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -2,6 +2,7 @@ #define POINCARE_PARENTHESIS_LAYOUT_H #include +#include namespace Poincare { @@ -13,6 +14,9 @@ public: ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); + } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { }; diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 538d5c2de..782f9da01 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -2,6 +2,7 @@ #define POINCARE_PARENTHESIS_LEFT_LAYOUT_H #include +#include namespace Poincare { @@ -9,6 +10,9 @@ class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '('); + } bool isLeftParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index c03d19efd..137494443 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -2,6 +2,7 @@ #define POINCARE_PARENTHESIS_RIGHT_LAYOUT_H #include +#include namespace Poincare { @@ -9,6 +10,9 @@ class ParenthesisRightLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ')'); + } bool isRightParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index b344736dd..1be482165 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -5,10 +5,14 @@ namespace Poincare { ExpressionLayout * ProductLayout::clone() const { - ProductLayout * layout = new ProductLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); + ProductLayout * layout = new ProductLayout(const_cast(this)->argumentLayout(), const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), true); return layout; } +int ProductLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + return SequenceLayout::writeDerivedClassInBuffer("product", buffer, bufferSize); +} + void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize upperBoundSize = upperBoundLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); diff --git a/poincare/src/layout/product_layout.h b/poincare/src/layout/product_layout.h index ae68723be..72750ebbb 100644 --- a/poincare/src/layout/product_layout.h +++ b/poincare/src/layout/product_layout.h @@ -2,6 +2,7 @@ #define POINCARE_PRODUCT_LAYOUT_H #include "sequence_layout.h" +#include namespace Poincare { @@ -9,6 +10,7 @@ class ProductLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; private: diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index d6db66cb7..6b5e9cf85 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -14,7 +14,7 @@ SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands, false); - build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(lowerBound, upperBound, horLayout)), 3, cloneOperands); + build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(horLayout, lowerBound, upperBound)), 3, cloneOperands); } void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { @@ -71,7 +71,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Right of the lower bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left && argumentLayout() - && cursor->pointedExpressionLayout() == editableChild(2)) + && cursor->pointedExpressionLayout() == argumentWithParenthesesLayout()) { assert(lowerBoundLayout() != nullptr); cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); @@ -113,7 +113,7 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. if (cursor->position() == ExpressionLayoutCursor::Position::Right && argumentLayout() - && cursor->pointedExpressionLayout() == editableChild(2)) + && cursor->pointedExpressionLayout() == argumentWithParenthesesLayout()) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); @@ -171,8 +171,51 @@ char SequenceLayout::XNTChar() const { return 'n'; } +int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize) const { + assert(operatorName != nullptr); + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + + // Write the operator name + int numberOfChar = strlcpy(buffer, operatorName, bufferSize); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the opening parenthesis + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the argument + numberOfChar += const_cast(this)->argumentLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the comma + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the lower bound without the "n=" + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const_cast(this)->lowerBoundLayout(), buffer+numberOfChar, bufferSize-numberOfChar, "", 1); + // TODO This works because the lower bound layout should always be an + // horizontal layout. + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the comma + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the upper bound + numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the closing parenthesis + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + ExpressionLayout * SequenceLayout::upperBoundLayout() { - return editableChild(0); + return editableChild(2); } ExpressionLayout * SequenceLayout::lowerBoundLayout() { @@ -180,11 +223,15 @@ ExpressionLayout * SequenceLayout::lowerBoundLayout() { } ExpressionLayout * SequenceLayout::argumentLayout() { - return editableChild(2)->editableChild(1); + return argumentWithParenthesesLayout()->editableChild(1); +} + +ExpressionLayout * SequenceLayout::argumentWithParenthesesLayout() { + return editableChild(0); } KDSize SequenceLayout::computeSize() { - KDSize argumentSize = editableChild(2)->size(); + KDSize argumentSize = argumentWithParenthesesLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( @@ -209,7 +256,7 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { } else if (child == upperBoundLayout()) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (child == editableChild(2)) { + } else if (child == argumentWithParenthesesLayout()) { x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; y = baseline() - argumentLayout()->baseline(); } else { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index ca53827d8..418eb6d94 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -19,9 +19,11 @@ public: protected: constexpr static KDCoordinate k_boundHeightMargin = 2; constexpr static KDCoordinate k_argumentWidthMargin = 2; + int writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize) const; ExpressionLayout * lowerBoundLayout(); ExpressionLayout * upperBoundLayout(); - virtual ExpressionLayout * argumentLayout(); + ExpressionLayout * argumentLayout(); + ExpressionLayout * argumentWithParenthesesLayout(); KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp index e1e835993..af1ec891f 100644 --- a/poincare/src/layout/string_layout.cpp +++ b/poincare/src/layout/string_layout.cpp @@ -85,6 +85,20 @@ bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { return m_parent->moveRight(cursor); } +int StringLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = strlcpy(buffer, m_string, bufferSize); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + buffer[numberOfChar] = 0; + return numberOfChar; +} + void StringLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->drawString(m_string, p, m_fontSize, expressionColor, backgroundColor); } diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 48f405d33..40301736b 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -2,6 +2,7 @@ #define POINCARE_STRING_LAYOUT_H #include +#include #include namespace Poincare { @@ -20,6 +21,7 @@ public: char * text() { return m_string; } bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDPoint positionOfChild(ExpressionLayout * child) override; diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 8d198b249..857ae525e 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -24,10 +24,14 @@ const uint8_t symbolPixel[SumLayout::k_symbolHeight][SumLayout::k_symbolWidth] = }; ExpressionLayout * SumLayout::clone() const { - SumLayout * layout = new SumLayout(const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), const_cast(this)->argumentLayout(), true); + SumLayout * layout = new SumLayout(const_cast(this)->argumentLayout(), const_cast(this)->lowerBoundLayout(), const_cast(this)->upperBoundLayout(), true); return layout; } +int SumLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + return SequenceLayout::writeDerivedClassInBuffer("sum", buffer, bufferSize); +} + void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize upperBoundSize = upperBoundLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); diff --git a/poincare/src/layout/sum_layout.h b/poincare/src/layout/sum_layout.h index 7218e866f..4f8228921 100644 --- a/poincare/src/layout/sum_layout.h +++ b/poincare/src/layout/sum_layout.h @@ -2,6 +2,7 @@ #define POINCARE_SUM_LAYOUT_H #include "sequence_layout.h" +#include namespace Poincare { @@ -9,6 +10,7 @@ class SumLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.h b/poincare/src/layout/uneditable_horizontal_trio_layout.h index 094b16d39..484947dd5 100644 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.h +++ b/poincare/src/layout/uneditable_horizontal_trio_layout.h @@ -2,6 +2,7 @@ #define POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H #include +#include namespace Poincare { @@ -26,6 +27,10 @@ public: bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + /* Expression Engine */ + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); + } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 2690be522..89a6d6664 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -1,5 +1,5 @@ #include -#include "layout/editable_string_layout.h" +#include "layout/string_layout.h" #include "layout/parenthesis_layout.h" #include "layout/horizontal_layout.h" extern "C" { @@ -16,12 +16,12 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression ExpressionLayout** children_layouts = new ExpressionLayout * [2*numberOfOperands-1]; children_layouts[0] = expression->operand(0)->createLayout(); for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); } /* HorizontalLayout holds the children layouts so they do not need to be * deleted here. */ - ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1, false); + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1); delete[] children_layouts; return layout; } @@ -34,48 +34,80 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio int layoutIndex = 0; grandChildrenLayouts[layoutIndex++] = expression->operand(0)->createLayout(floatDisplayMode, complexFormat); for (int i = 1; i < numberOfOperands; i++) { - grandChildrenLayouts[layoutIndex++] = new EditableStringLayout(",", 1); + grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); grandChildrenLayouts[layoutIndex++] = expression->operand(i)->createLayout(floatDisplayMode, complexFormat); } /* HorizontalLayout holds the grand children layouts so they do not need to * be deleted */ - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1, false); + ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); delete [] grandChildrenLayouts; ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new EditableStringLayout(operatorName, strlen(operatorName)); + childrenLayouts[0] = new StringLayout(operatorName, strlen(operatorName)); childrenLayouts[1] = new ParenthesisLayout(argumentLayouts, false); /* Same comment as above */ - return new HorizontalLayout(childrenLayouts, 2, false); + return new HorizontalLayout(childrenLayouts, 2); } -int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis) { +int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedsParenthesis operandNeedsParenthesis) { + return writeInfixExpressionOrExpressionLayoutTextInBuffer(expression, nullptr, buffer, bufferSize, operatorName, 0, -1, operandNeedsParenthesis, [](const char * operatorName) { return true; }); +} + +int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName) { + return writePrefixExpressionOrExpressionLayoutTextInBuffer(expression, nullptr, buffer, bufferSize, operatorName); +} + +int LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis) { + return writeInfixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, operatorName, firstChildIndex, lastChildIndex, [](const Expression * e) { return true; }, childNeedsParenthesis); +} + +int LayoutEngine::writePrefixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, bool writeFirstChild) { + return writePrefixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, operatorName, writeFirstChild); +} + +int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, int firstChildIndex, int lastChildIndex, OperandNeedsParenthesis operandNeedsParenthesis, ChildNeedsParenthesis childNeedsParenthesis) { + assert(expression != nullptr || expressionLayout != nullptr); if (bufferSize == 0) { return -1; } buffer[bufferSize-1] = 0; int numberOfChar = 0; - int numberOfOperands = expression->numberOfOperands(); + int numberOfOperands = (expression != nullptr) ? expression->numberOfOperands() : expressionLayout->numberOfChildren(); assert(numberOfOperands > 1); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - if (operandNeedParenthesis(expression->operand(0))) { - buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; } - numberOfChar += expression->operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - if (operandNeedParenthesis(expression->operand(0))) { + + if ((expression != nullptr && operandNeedsParenthesis(expression->operand(firstChildIndex))) + || (expression == nullptr && childNeedsParenthesis(operatorName))) + { + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + } + + numberOfChar += (expression != nullptr) ? expression->operand(firstChildIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar) : expressionLayout->child(firstChildIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if ((expression != nullptr && operandNeedsParenthesis(expression->operand(firstChildIndex))) + || (expression == nullptr && childNeedsParenthesis(operatorName))) + { buffer[numberOfChar++] = ')'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } - for (int i=1; i= bufferSize-1) { return bufferSize-1; } numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - if (operandNeedParenthesis(expression->operand(i))) { + if ((expression != nullptr && operandNeedsParenthesis(expression->operand(i))) + || (expression == nullptr && childNeedsParenthesis(operatorName))) + { buffer[numberOfChar++] = '('; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } - numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - if (operandNeedParenthesis(expression->operand(i))) { + numberOfChar += (expression != nullptr) ? expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar) : expressionLayout->child(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if ((expression != nullptr && operandNeedsParenthesis(expression->operand(i))) + || (expression == nullptr && childNeedsParenthesis(operatorName))) + { buffer[numberOfChar++] = ')'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } @@ -84,24 +116,35 @@ int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression return numberOfChar; } -int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName) { + +int LayoutEngine::writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, bool writeFirstChild) { + assert(expression != nullptr || expressionLayout != nullptr); if (bufferSize == 0) { return -1; } buffer[bufferSize-1] = 0; - int numberOfChar = 0; - numberOfChar += strlcpy(buffer, operatorName, bufferSize); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + int numberOfChar = strlcpy(buffer, operatorName, bufferSize); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - int numberOfOperands = expression->numberOfOperands(); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + int numberOfOperands = (expression != nullptr) ? expression->numberOfOperands() : expressionLayout->numberOfChildren(); assert(numberOfOperands > 0); - numberOfChar += expression->operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - for (int i = 1; i < numberOfOperands; i++) { + if (!writeFirstChild) { + assert(numberOfOperands > 1); + } + int firstOperandIndex = writeFirstChild ? 0 : 1; + numberOfChar += (expression != nullptr) ? expression->operand(firstOperandIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar) : expressionLayout->child(firstOperandIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + for (int i = firstOperandIndex + 1; i < numberOfOperands; i++) { if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ','; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += (expression != nullptr) ? expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar) : expressionLayout->child(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); } if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ')'; @@ -109,4 +152,17 @@ int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expressio return numberOfChar; } +int LayoutEngine::writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite) { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } + buffer[0] = charToWrite; + buffer[1] = 0; + return 1; +} + } From 332cfb013f2f6045ef3b7ac078d4a854eafc6adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 2 Jan 2018 16:45:40 +0100 Subject: [PATCH 088/459] [ExpressionEditor] TextView to see serialization results. Just for development purposes. Change-Id: I8700818a8d5705e2c610bd448fbcc2deea6b9971 --- .../expression_editor/expression_editor_view.cpp | 16 +++++++++++++++- apps/expression_editor/expression_editor_view.h | 9 ++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/expression_editor/expression_editor_view.cpp b/apps/expression_editor/expression_editor_view.cpp index 5d1047e53..fe825654e 100644 --- a/apps/expression_editor/expression_editor_view.cpp +++ b/apps/expression_editor/expression_editor_view.cpp @@ -7,6 +7,7 @@ ExpressionEditorView::ExpressionEditorView(Responder * parentResponder, Poincare SolidColorView(KDColorWhite), m_scrollableExpressionViewWithCursor(parentResponder, expressionLayout, cursor) { + m_serializerTextView.setText("Hello"); } void ExpressionEditorView::cursorPositionChanged() { @@ -14,7 +15,20 @@ void ExpressionEditorView::cursorPositionChanged() { m_scrollableExpressionViewWithCursor.scrollToCursor(); } +void ExpressionEditorView::setText(const char * text) { + m_serializerTextView.setText(text); +} + +View * ExpressionEditorView::subviewAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return &m_scrollableExpressionViewWithCursor; + } + return &m_serializerTextView; +} + void ExpressionEditorView::layoutSubviews() { + m_serializerTextView.setFrame(KDRect(0, 0, bounds().width(), 20)); m_scrollableExpressionViewWithCursor.setFrame(KDRect( k_margin, k_margin, @@ -24,7 +38,7 @@ void ExpressionEditorView::layoutSubviews() { } KDSize ExpressionEditorView::minimalSizeForOptimalDisplay() const { - return m_scrollableExpressionViewWithCursor.minimalSizeForOptimalDisplay(); + return KDSize(300, 220); } diff --git a/apps/expression_editor/expression_editor_view.h b/apps/expression_editor/expression_editor_view.h index 49116463e..def2ec2b5 100644 --- a/apps/expression_editor/expression_editor_view.h +++ b/apps/expression_editor/expression_editor_view.h @@ -11,17 +11,16 @@ class ExpressionEditorView : public SolidColorView { public: ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); void cursorPositionChanged(); - int numberOfSubviews() const override { return 1; } + void setText(const char * text); + int numberOfSubviews() const override { return 2; } ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } - View * subviewAtIndex(int index) override { - assert(index == 0); - return &m_scrollableExpressionViewWithCursor; - } + View * subviewAtIndex(int index) override; void layoutSubviews() override; KDSize minimalSizeForOptimalDisplay() const override; private: constexpr static KDCoordinate k_margin = 10; ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; + BufferTextView m_serializerTextView; }; } From 5107343a448c0ec53f4c5284f63f30b0d0a5c1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 2 Jan 2018 17:01:40 +0100 Subject: [PATCH 089/459] [ExpressionEditor] Handle EXE events: show serialized layout. Change-Id: I19be0ab5263cba42caca2ca71fe0082f3339e473 --- apps/expression_editor/controller.cpp | 9 +++++++++ apps/expression_editor/controller.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 1679d3303..888192d9f 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -29,6 +29,10 @@ void Controller::didBecomeFirstResponder() { } bool Controller::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::EXE) { + serializeLayout(); + return true; + } if (privateHandleEvent(event)) { m_view.cursorPositionChanged(); return true; @@ -139,4 +143,9 @@ bool Controller::handleDeleteEvent(Ion::Events::Event event) { return false; } +void Controller::serializeLayout() { + m_expressionLayout->writeTextInBuffer(m_buffer, k_bufferSize); + m_view.setText(const_cast(m_buffer)); +} + } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index 3910844fa..e777e4103 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -29,9 +29,12 @@ private: bool handleMoveEvent(Ion::Events::Event event); Poincare::ExpressionLayout * handleAddEvent(Ion::Events::Event event); bool handleDeleteEvent(Ion::Events::Event event); + void serializeLayout(); ExpressionEditorView m_view; Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; + static constexpr int k_bufferSize = 256; + char m_buffer[k_bufferSize]; }; } From 3fe7295f6cfaff168ec705dd8d5a057f69f74e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 10:48:03 +0100 Subject: [PATCH 090/459] [poincare] ExpressionLayoutArray was a method, it is now a class. Change-Id: Iddde7ed9d8a8539193c6547a9e718865ff8e8cc7 --- apps/math_toolbox.cpp | 15 +++++++------- poincare/include/poincare.h | 1 + .../poincare/dynamic_layout_hierarchy.h | 3 ++- poincare/include/poincare/expression_layout.h | 2 -- .../poincare/expression_layout_array.h | 20 +++++++++++++++++++ poincare/src/layout/expression_layout.cpp | 15 -------------- poincare/src/layout/grid_layout.cpp | 2 +- poincare/src/layout/grid_layout.h | 2 +- poincare/src/layout/parenthesis_layout.cpp | 5 +++-- poincare/src/layout/sequence_layout.cpp | 3 ++- .../src/layout/static_layout_hierarchy.cpp | 5 +++-- 11 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 poincare/include/poincare/expression_layout_array.h diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index a1b29bf5c..1b569b848 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -1,5 +1,6 @@ #include "math_toolbox.h" #include "./shared/toolbox_helpers.h" +#include #include #include @@ -17,9 +18,9 @@ const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, new IntegralLayout( new HorizontalLayout( - const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + Poincare::ExpressionLayoutArray( new EmptyVisibleLayout(), - new StringLayout("dx",2))), 2, false), + new StringLayout("dx",2)).array(), 2, false), new EmptyVisibleLayout(), new EmptyVisibleLayout(), false), @@ -27,10 +28,10 @@ const ToolboxMessageTree calculChildren[4] = { 2), ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, new SumLayout( - new HorizontalLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( - new StringLayout("n=",2), - new EmptyVisibleLayout())), 2, false), new EmptyVisibleLayout(), + new HorizontalLayout(Poincare::ExpressionLayoutArray( + new StringLayout("n=",2), + new EmptyVisibleLayout()).array(), 2, false), new EmptyVisibleLayout(), false), const_cast(&pointedLayoutPathSum[0]), @@ -54,9 +55,9 @@ const ToolboxMessageTree probabilityChildren[2] = { ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg, nullptr, 0, new UneditableHorizontalTrioLayout( new ParenthesisLeftLayout(), - new GridLayout(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray2( + new GridLayout(Poincare::ExpressionLayoutArray( new EmptyVisibleLayout(), - new EmptyVisibleLayout())), + new EmptyVisibleLayout()).array(), 2, 1, false), new ParenthesisRightLayout(), false, true), const_cast(&pointedLayoutPathBinomial[0]), diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 3bd0a9a9b..9c2e8e8f1 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index dafe85166..0a7fd488e 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -2,6 +2,7 @@ #define POINCARE_DYNAMIC_LAYOUT_HIERARCHY_H #include +#include namespace Poincare { @@ -10,7 +11,7 @@ public: DynamicLayoutHierarchy(); DynamicLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands = true) : - DynamicLayoutHierarchy(ExpressionLayoutArray2(operand1, operand2), 2, cloneOperands) {} + DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2).array(), 2, cloneOperands) {} ~DynamicLayoutHierarchy(); DynamicLayoutHierarchy(const DynamicLayoutHierarchy & other) = delete; DynamicLayoutHierarchy(DynamicLayoutHierarchy && other) = delete; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index f366a305f..8664ed746 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -21,8 +21,6 @@ public: /* Constructor & Destructor */ ExpressionLayout(); virtual ~ExpressionLayout() = default; - static const ExpressionLayout * const * ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2); - static const ExpressionLayout * const * ExpressionLayoutArray3(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3); virtual ExpressionLayout * clone() const = 0; /* Rendering */ diff --git a/poincare/include/poincare/expression_layout_array.h b/poincare/include/poincare/expression_layout_array.h new file mode 100644 index 000000000..6bdae090b --- /dev/null +++ b/poincare/include/poincare/expression_layout_array.h @@ -0,0 +1,20 @@ +#ifndef POINCARE_EXPRESSION_LAYOUT_ARRAY_H +#define POINCARE_EXPRESSION_LAYOUT_ARRAY_H + +#include + +namespace Poincare { + +class ExpressionLayoutArray { +public: + ExpressionLayoutArray(const ExpressionLayout * eL1 = nullptr, const ExpressionLayout * eL2 = nullptr, const ExpressionLayout * eL3 = nullptr) : + m_data{eL1, eL2, eL3} + {} + const ExpressionLayout * const * array() { return const_cast(m_data); } +private: + const ExpressionLayout * m_data[3]; +}; + +} + +#endif diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index d4410fb08..797b016c5 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -18,21 +18,6 @@ ExpressionLayout::ExpressionLayout() : { } -const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2) { - static const ExpressionLayout * result[2] = {nullptr, nullptr}; - result[0] = e1; - result[1] = e2; - return result; -} - -const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray3(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3) { - static const ExpressionLayout * result[3] = {nullptr, nullptr, nullptr}; - result[0] = e1; - result[1] = e2; - result[2] = e3; - return result; -} - KDPoint ExpressionLayout::origin() { if (m_parent == nullptr) { return absoluteOrigin(); diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index b73636fc0..2d3152b09 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -9,7 +9,7 @@ extern "C" { namespace Poincare { -GridLayout::GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands) : +GridLayout::GridLayout(const ExpressionLayout * const * entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands) : DynamicLayoutHierarchy(entryLayouts, numberOfRows*numberOfColumns, cloneOperands), m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index e5a6bde67..a00dcb65d 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -7,7 +7,7 @@ namespace Poincare { class GridLayout : public DynamicLayoutHierarchy { public: - GridLayout(ExpressionLayout ** entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); + GridLayout(const ExpressionLayout * const * entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index 0f9cbd1fc..cb4c372e1 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -1,7 +1,8 @@ #include "parenthesis_layout.h" -#include #include "parenthesis_left_layout.h" #include "parenthesis_right_layout.h" +#include +#include extern "C" { #include #include @@ -14,7 +15,7 @@ ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operand, bool cloneOpera { ExpressionLayout * leftParenthesis = new ParenthesisLeftLayout(); ExpressionLayout * rightParenthesis = new ParenthesisRightLayout(); - build(ExpressionLayout::ExpressionLayoutArray3(leftParenthesis, operand, rightParenthesis), 3, cloneOperands); + build(ExpressionLayoutArray(leftParenthesis, operand, rightParenthesis).array(), 3, cloneOperands); } ExpressionLayout * ParenthesisLayout::clone() const { diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 6b5e9cf85..53842a678 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -3,6 +3,7 @@ #include "parenthesis_right_layout.h" #include "uneditable_horizontal_trio_layout.h" #include +#include #include #include @@ -14,7 +15,7 @@ SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands, false); - build(const_cast(Poincare::ExpressionLayout::ExpressionLayoutArray3(horLayout, lowerBound, upperBound)), 3, cloneOperands); + build(ExpressionLayoutArray(horLayout, lowerBound, upperBound).array(), 3, cloneOperands); } void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp index 27d6c68bb..d6d0d0a11 100644 --- a/poincare/src/layout/static_layout_hierarchy.cpp +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -27,13 +28,13 @@ StaticLayoutHierarchy<1>::StaticLayoutHierarchy(const ExpressionLayout * e, bool template<> StaticLayoutHierarchy<2>::StaticLayoutHierarchy(const ExpressionLayout * e1, const ExpressionLayout * e2, bool cloneChildren) : - StaticLayoutHierarchy(ExpressionLayoutArray2(e1, e2), cloneChildren) + StaticLayoutHierarchy(ExpressionLayoutArray(e1, e2).array(), cloneChildren) { } template<> StaticLayoutHierarchy<3>::StaticLayoutHierarchy(const ExpressionLayout * e1, const ExpressionLayout * e2, const ExpressionLayout * e3, bool cloneChildren) : - StaticLayoutHierarchy(ExpressionLayoutArray3(e1, e2, e3), cloneChildren) + StaticLayoutHierarchy(ExpressionLayoutArray(e1, e2, e3).array(), cloneChildren) { } From 8e30d10e43da8d85d6a312d35ebe7543fc21ad17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 11:00:20 +0100 Subject: [PATCH 091/459] [poincare] Changed the arguments order for Sequence layouts. Change-Id: I83c535c5d3e1d263343ab7f656b5c22c82049ad4 --- poincare/src/layout/sequence_layout.cpp | 6 +++++- poincare/src/layout/sequence_layout.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 53842a678..ed7d4e46e 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -9,13 +9,17 @@ namespace Poincare { -SequenceLayout::SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands) : +SequenceLayout::SequenceLayout(ExpressionLayout * argument, ExpressionLayout * lowerBound, ExpressionLayout * upperBound, bool cloneOperands) : StaticLayoutHierarchy() { ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands, false); build(ExpressionLayoutArray(horLayout, lowerBound, upperBound).array(), 3, cloneOperands); + if (cloneOperands) { + delete parLeft; + delete parRight; + } } void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 418eb6d94..0eeedfbd1 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -9,7 +9,7 @@ class SequenceLayout : public StaticLayoutHierarchy<3> { public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; - SequenceLayout(ExpressionLayout * lowerBound, ExpressionLayout * upperBound, ExpressionLayout * argument, bool cloneOperands); + SequenceLayout(ExpressionLayout * argument, ExpressionLayout * lowerBound, ExpressionLayout * upperBound, bool cloneOperands); void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; From 57dcf246752f7fdea99d29367de837f512d6b4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 11:00:53 +0100 Subject: [PATCH 092/459] [poincare] Changed names in StaticLayoutHierarchy::build. For debugging purposes. Change-Id: I10185978cbc590ba0016516e151ecba852bd4d72 --- poincare/src/layout/static_layout_hierarchy.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp index d6d0d0a11..76314772e 100644 --- a/poincare/src/layout/static_layout_hierarchy.cpp +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -48,15 +48,15 @@ StaticLayoutHierarchy::~StaticLayoutHierarchy() { } template -void StaticLayoutHierarchy::build(const ExpressionLayout * const * children, int numberOfChildren, bool cloneChildren) { - assert(children != nullptr); - assert(numberOfChildren <= T); - for (int i=0; i < numberOfChildren; i++) { - assert(children[i] != nullptr); - if (cloneChildren) { - m_children[i] = children[i]->clone(); +void StaticLayoutHierarchy::build(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands) { + assert(operands != nullptr); + assert(numberOfOperands <= T); + for (int i=0; i < numberOfOperands; i++) { + assert(operands[i] != nullptr); + if (cloneOperands) { + m_children[i] = operands[i]->clone(); } else { - m_children[i] = children[i]; + m_children[i] = operands[i]; } const_cast(m_children[i])->setParent(this); } From b4358ab99ab992cbd31c57d1f77ad27991d8fddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 11:02:10 +0100 Subject: [PATCH 093/459] [poincare] Changed assert condition in LayoutEngine. The function writeInfixExpressionOrExpressionLayoutTextInBuffer is now used by HorizontalLayout, which might have only 1 argument. Change-Id: Ic22baa4c43847fe1fd4a38e3180b4ae8bef18d19 --- poincare/src/layout_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 89a6d6664..a128948a1 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -72,7 +72,7 @@ int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expre buffer[bufferSize-1] = 0; int numberOfChar = 0; int numberOfOperands = (expression != nullptr) ? expression->numberOfOperands() : expressionLayout->numberOfChildren(); - assert(numberOfOperands > 1); + assert(numberOfOperands > 0); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } From 1ced6e23601bcdafc7884948a0d94a6a41f3c9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 14:29:03 +0100 Subject: [PATCH 094/459] [poincare] Empty ListData constructor. Change-Id: I882eb664d74399ab87ef9bd95bc1b255f5a5f87c --- poincare/include/poincare/list_data.h | 1 + poincare/src/list_data.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/poincare/include/poincare/list_data.h b/poincare/include/poincare/list_data.h index dede2436e..87f6a8f2a 100644 --- a/poincare/include/poincare/list_data.h +++ b/poincare/include/poincare/list_data.h @@ -7,6 +7,7 @@ namespace Poincare { class ListData { public: + ListData(); ListData(Expression * operand); ~ListData(); ListData(const ListData& other) = delete; diff --git a/poincare/src/list_data.cpp b/poincare/src/list_data.cpp index 110d6163c..c49ff5ff2 100644 --- a/poincare/src/list_data.cpp +++ b/poincare/src/list_data.cpp @@ -6,6 +6,11 @@ extern "C" { namespace Poincare { +ListData::ListData() : + m_numberOfOperands(0), + m_operands(new Expression*[0]) +{} + ListData::ListData(Expression * operand) : m_numberOfOperands(1), m_operands(new Expression*[1]) From 4fa64d837a4ff527dc8c1a94a11aac3f85904f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 14:29:41 +0100 Subject: [PATCH 095/459] [poincare] Parser rule for function_{args1}(args2). It is parsed as function(args2 concatenated with args1). Change-Id: I478cf7b34c6f49e5d258fe8f6af823a7d7b5941e --- poincare/src/expression_lexer.l | 1 + poincare/src/expression_parser.y | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 783e3de71..b2d04483e 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -155,6 +155,7 @@ inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; \] { return RIGHT_BRACKET; } \, { return COMMA; } \. { return DOT; } +\_ { return UNDERSCORE; } [ ]+ /* Ignore whitespaces */ . { return UNDEFINED_SYMBOL; } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index dff9e93b8..e48a16e0c 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -66,6 +66,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %token LEFT_BRACKET %token RIGHT_BRACKET %token COMMA +%token UNDERSCORE %token DOT %token EE %token ICOMPLEX @@ -102,8 +103,11 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %nonassoc RIGHT_PARENTHESIS %nonassoc LEFT_BRACKET %nonassoc RIGHT_BRACKET +%nonassoc LEFT_BRACE +%nonassoc RIGHT_BRACE %nonassoc FUNCTION %left COMMA +%nonassoc UNDERSCORE %nonassoc DIGITS %nonassoc DOT %nonassoc EE @@ -149,7 +153,7 @@ lstData: /* When approximating expressions to double, results are bounded by 1E308 (and * 1E-308 for small numbers). We thus accept decimals whose exponents are in * {-1000, 1000}. However, we have to compute the exponent first to decide - * wether to accept the decimal. The exponent of a Decimal is stored as an + * whether to accept the decimal. The exponent of a Decimal is stored as an * int32_t. We thus have to throw an error when the exponent computation might * overflow. Finally, we escape computation by throwing an error when the length * of the exponent digits is above 4 (0.00...-256 times-...01E1256=1E1000 is @@ -189,6 +193,13 @@ exp: | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } /* MATRICES_ARE_DEFINED */ | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); delete $2; } + | FUNCTION UNDERSCORE LEFT_BRACE lstData RIGHT_BRACE LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; int totalNumberOfArguments = $4->numberOfOperands()+$7->numberOfOperands(); +if (!$1->hasValidNumberOfOperands(totalNumberOfArguments)) { delete $1; delete $4; delete $7; YYERROR; }; +Poincare::ListData * arguments = new Poincare::ListData(); +for (int i = 0; i < $4->numberOfOperands(); i++) { arguments->pushExpression($4->operands()[i]); } +for (int i = 0; i < $7->numberOfOperands(); i++) { arguments->pushExpression($7->operands()[i]); } +$1->setArgument(arguments, totalNumberOfArguments, false); +$4->detachOperands(); delete $4; $7->detachOperands(); delete $7; arguments->detachOperands(); delete arguments;} | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), false); $3->detachOperands(); delete $3; } final_exp: From 62ffb424724ef8ac26b1baed38d26d8c605eca99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 15:50:56 +0100 Subject: [PATCH 096/459] [poincare] Fixed invalidation of layout baseline and position. When adding, replacing or detaching a child. Change-Id: I3ef212fbe270cee8d0e3a11402cc6df1228ee8d5 --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/layout/dynamic_layout_hierarchy.cpp | 2 ++ poincare/src/layout/expression_layout.cpp | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 8664ed746..8f59fc403 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -93,10 +93,10 @@ protected: ExpressionLayout * m_parent; bool m_sized; bool m_baselined; + bool m_positioned; private: bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); void replaceWithJuxtapositionOf(ExpressionLayout * firstLayout, ExpressionLayout * secondLayout); - bool m_positioned; KDRect m_frame; }; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 4d3fdf6c8..dba3cf394 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -58,6 +58,8 @@ bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index m_children = newChildren; m_numberOfChildren += 1; m_sized = false; + m_positioned = false; + m_baselined = false; return true; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 797b016c5..6364e64c1 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -184,6 +184,8 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio } } m_sized = false; + m_positioned = false; + m_baselined = false; } void ExpressionLayout::detachChild(const ExpressionLayout * e) { @@ -263,6 +265,8 @@ void ExpressionLayout::detachChildAtIndex(int i) { } op[i] = nullptr; m_sized = false; + m_positioned = false; + m_baselined = false; } bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { From 89760c0f427f8e61e6f1fa01ec9e3e964f6e753f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 17:15:40 +0100 Subject: [PATCH 097/459] [poincare] isCollapsable() for ExpressionLayouts. Tells whether the layout should be collapsed into the numerator (or denominator) of a new FractionLayout brother. Change-Id: Id5c2a55667bec56340d73c2a63dc704fa56c9815 --- poincare/include/poincare/expression_layout.h | 2 ++ poincare/src/layout/char_layout.cpp | 14 ++++++++++++++ poincare/src/layout/char_layout.h | 1 + poincare/src/layout/parenthesis_left_layout.cpp | 5 +++++ poincare/src/layout/parenthesis_left_layout.h | 1 + poincare/src/layout/parenthesis_right_layout.cpp | 5 +++++ poincare/src/layout/parenthesis_right_layout.h | 1 + 7 files changed, 29 insertions(+) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 8f59fc403..b3de44700 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -68,6 +68,8 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Other */ + virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } + // isCollapsable is used when adding a brother fraction: should the layout be inserted in the numerator (or denominator)? virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } virtual bool isRightParenthesis() const { return false; } diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index 866814bda..b4e67dc52 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -1,5 +1,6 @@ #include "char_layout.h" #include +#include #include #include @@ -49,6 +50,19 @@ bool CharLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +bool CharLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis <= 0 + && (m_char == '+' + || m_char == '-' + || m_char == '*' + || m_char == Ion::Charset::MultiplicationSign + || m_char == Ion::Charset::MiddleDot)) + { + return false; + } + return true; +} + void CharLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { char string[2] = {m_char, 0}; ctx->drawString(string, p, m_fontSize, expressionColor, backgroundColor); diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 47ba4e336..28323d228 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -18,6 +18,7 @@ public: char character() { return m_char; } bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDPoint positionOfChild(ExpressionLayout * child) override; diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 1bd3d416a..6cf4e8d68 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -32,6 +32,11 @@ ExpressionLayout * ParenthesisLeftLayout::clone() const { return layout; } +bool ParenthesisLeftLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis - 1 : *numberOfOpenParenthesis + 1; + return true; +} + void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_externHeightMargin, diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 782f9da01..03b3847c5 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -13,6 +13,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '('); } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; bool isLeftParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index b248e0150..8681a297b 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -32,6 +32,11 @@ ExpressionLayout * ParenthesisRightLayout::clone() const { return layout; } +bool ParenthesisRightLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis + 1 : *numberOfOpenParenthesis - 1; + return true; +} + void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, p.y() + ParenthesisLeftRightLayout::k_externHeightMargin, diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 137494443..134c08a24 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -13,6 +13,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ')'); } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; bool isRightParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; From 25c036a0785cf50b646dabd238728df0d1ed5f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 17:19:02 +0100 Subject: [PATCH 098/459] [expression_editor] Set cursor position according to the layout inserted. Change-Id: Iac33efdeb4b725ae6007282d323f446992873832 --- apps/expression_editor/controller.cpp | 3 --- poincare/src/expression_layout_cursor.cpp | 20 ++++++++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 888192d9f..7c717f585 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -63,9 +63,6 @@ bool Controller::privateHandleEvent(Ion::Events::Event event) { } ExpressionLayout * newPointedLayout = handleAddEvent(event); if (newPointedLayout != nullptr) { - m_cursor.setPointedExpressionLayout(newPointedLayout); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - m_cursor.setPositionInside(0); m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.layoutSubviews(); return true; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 71e6dad4f..f24cc664e 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -61,6 +61,8 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); pointedExpressionLayout()->addBrother(this, newChild); + setPointedExpressionLayout(child2); + setPosition(ExpressionLayoutCursor::Position::Left); return child2; } @@ -77,9 +79,11 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Subscript, false); m_pointedExpressionLayout->addBrother(this, newChild); - m_pointedExpressionLayout = newChild; - m_position = Position::Right; - return insertText("()"); + setPointedExpressionLayout(newChild); + setPosition(ExpressionLayoutCursor::Position::Right); + insertText("()"); + moveLeft(); + return child1; } ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { @@ -87,6 +91,8 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); m_pointedExpressionLayout->addBrother(this, newChild); + setPointedExpressionLayout(child1); + setPosition(ExpressionLayoutCursor::Position::Right); return child1; } @@ -95,6 +101,8 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyRootLayout() { EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); NthRootLayout * newChild = new NthRootLayout(child1, child2, false); m_pointedExpressionLayout->addBrother(this, newChild); + setPointedExpressionLayout(child1); + setPosition(ExpressionLayoutCursor::Position::Right); return child1; } @@ -103,12 +111,16 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { CharLayout * child2 = new CharLayout('2'); EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); m_pointedExpressionLayout->addBrother(this, newChild); - return child1; + setPointedExpressionLayout(newChild); + setPosition(ExpressionLayoutCursor::Position::Right); + return newChild; } ExpressionLayout * ExpressionLayoutCursor::addXNTCharLayout() { CharLayout * newChild = new CharLayout(m_pointedExpressionLayout->XNTChar()); m_pointedExpressionLayout->addBrother(this, newChild); + setPointedExpressionLayout(newChild); + setPosition(ExpressionLayoutCursor::Position::Right); return newChild; } From 8a7e4e598c2440c362a5d06614e128559ccf30a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Jan 2018 17:23:35 +0100 Subject: [PATCH 099/459] [expression_editor] Collapse brothers when adding a fraction. Change-Id: I4d75fae152fca4a6671abd1e444f6aaa27c168b5 --- apps/expression_editor/controller.cpp | 2 +- .../poincare/dynamic_layout_hierarchy.h | 2 + .../poincare/expression_layout_cursor.h | 2 +- poincare/src/expression_layout_cursor.cpp | 58 ++++++++++++++----- poincare/src/layout/horizontal_layout.cpp | 10 +++- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 7c717f585..2df023056 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -106,7 +106,7 @@ bool Controller::handleMoveEvent(Ion::Events::Event event) { ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { if (event == Ion::Events::Division) { - return m_cursor.addEmptyFractionLayout(); + return m_cursor.addFractionLayoutAndCollapseBrothers(); } if (event == Ion::Events::XNT) { return m_cursor.addXNTCharLayout(); diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 0a7fd488e..8e4cffd6a 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -10,6 +10,8 @@ class DynamicLayoutHierarchy : public ExpressionLayout { public: DynamicLayoutHierarchy(); DynamicLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); + DynamicLayoutHierarchy(const ExpressionLayout * operand, bool cloneOperands = true) : + DynamicLayoutHierarchy(ExpressionLayoutArray(operand).array(), 1, cloneOperands) {} DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands = true) : DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2).array(), 2, cloneOperands) {} ~DynamicLayoutHierarchy(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index b92bff74e..e6c5e9f71 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -45,7 +45,7 @@ public: /* Edition */ void addLayout(ExpressionLayout * layout); ExpressionLayout * addEmptyExponentialLayout(); - ExpressionLayout * addEmptyFractionLayout(); + ExpressionLayout * addFractionLayoutAndCollapseBrothers(); ExpressionLayout * addEmptyLogarithmLayout(); ExpressionLayout * addEmptyPowerLayout(); ExpressionLayout * addEmptyRootLayout(); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index f24cc664e..0f55d45fa 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,14 +1,5 @@ #include -#include -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. -#include //TODO move from there. +#include //TODO: finer include? #include #include @@ -66,12 +57,51 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { return child2; } -ExpressionLayout * ExpressionLayoutCursor::addEmptyFractionLayout() { - EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); +ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { + // Add a new FractionLayout + HorizontalLayout * child1 = new HorizontalLayout(new EmptyVisibleLayout()); + HorizontalLayout * child2 = new HorizontalLayout(new EmptyVisibleLayout()); FractionLayout * newChild = new FractionLayout(child1, child2, false); pointedExpressionLayout()->addBrother(this, newChild); - return child1; + + if (!newChild->parent()->isHorizontal()) { + setPointedExpressionLayout(child2->editableChild(0)); + setPosition(Position::Left); + return child2; + } + + int fractionIndexInParent = newChild->parent()->indexOfChild(newChild); + int numberOfBrothers = newChild->parent()->numberOfChildren(); + + // Collapse the brothers on the right + int numberOfOpenParenthesis = 0; + while (fractionIndexInParent < numberOfBrothers - 1) { + ExpressionLayout * rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); + if (rightBrother->isCollapsable(&numberOfOpenParenthesis, false)) { + newChild->editableParent()->removeChildAtIndex(fractionIndexInParent+1, false); + child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren()); + numberOfBrothers--; + } else { + break; + } + } + // Collapse the brothers on the left + numberOfOpenParenthesis = 0; + while (fractionIndexInParent > 0) { + ExpressionLayout * leftBrother = newChild->editableParent()->editableChild(fractionIndexInParent-1); + if (leftBrother->isCollapsable(&numberOfOpenParenthesis, true)) { + newChild->editableParent()->removeChildAtIndex(fractionIndexInParent-1, false); + child1->addOrMergeChildAtIndex(leftBrother, 0); + fractionIndexInParent--; + } else { + break; + } + } + // Set the cursor position + setPointedExpressionLayout(child2->editableChild(0)); + setPosition(Position::Left); + + return child2; } ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 38d125e6c..6a92ff30d 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -52,11 +52,17 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio } void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index) { + int newIndex = index; + if (numberOfChildren() > 0 && child(0)->isEmpty()) { + removeChildAtIndex(0, true); + newIndex = index == 0 ? 0 : index - 1; + } if (eL->isHorizontal()) { - mergeChildrenAtIndex(eL, index); + mergeChildrenAtIndex(eL, newIndex); return; } - addChildAtIndex(eL, index); + addChildAtIndex(eL, newIndex); + } bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { From 4009a0d87958f0ad9e65ff0a99788aa1be1ce90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 15:22:52 +0100 Subject: [PATCH 100/459] [poincare] VerticalOffsetLayout and mustHaveLeftBrother() for Layouts. Change-Id: Ibd4666806bb0af2a2babe892c8a9906747c18e9a --- poincare/Makefile | 1 + poincare/include/poincare/expression_layout.h | 1 + .../src/layout/vertical_offset_layout.cpp | 254 ++++++++++++++++++ poincare/src/layout/vertical_offset_layout.h | 37 +++ 4 files changed, 293 insertions(+) create mode 100644 poincare/src/layout/vertical_offset_layout.cpp create mode 100644 poincare/src/layout/vertical_offset_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index b49e17a2c..976ffb545 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -117,6 +117,7 @@ objs += $(addprefix poincare/src/layout/,\ uneditable_horizontal_trio_layout.o\ uneditable_parenthesis_left_layout.o\ uneditable_parenthesis_right_layout.o\ + vertical_offset_layout.o\ ) tests += $(addprefix poincare/test/,\ diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index b3de44700..5b3a927a8 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -70,6 +70,7 @@ public: /* Other */ virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } // isCollapsable is used when adding a brother fraction: should the layout be inserted in the numerator (or denominator)? + virtual bool mustHaveLeftBrother() const { return false; } virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } virtual bool isRightParenthesis() const { return false; } diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp new file mode 100644 index 000000000..10964d358 --- /dev/null +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -0,0 +1,254 @@ +#include "vertical_offset_layout.h" +#include "empty_visible_layout.h" +#include +#include +#include +#include + +namespace Poincare { + +VerticalOffsetLayout::VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands) : + StaticLayoutHierarchy(indice, cloneOperands), + m_type(type) +{ +} + +ExpressionLayout * VerticalOffsetLayout::clone() const { + VerticalOffsetLayout * layout = new VerticalOffsetLayout(const_cast(this)->indiceLayout(), m_type, true); + return layout; +} + +void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + if (cursor->pointedExpressionLayout() == indiceLayout()) { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + ExpressionLayout * base = baseLayout(); + if (indiceLayout()->isEmpty()) { + int indexInParent = m_parent->indexOfChild(this); + if (base->isEmpty()) { + // Case: Empty base and indice. + // Replace with the empty base layout. + if (indexInParent <= 1) { + cursor->setPointedExpressionLayout(m_parent); + } else { + cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent - 2)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + m_parent->removeChildAtIndex(indexInParent - 1, false); + replaceWith(base, true); + return; + } + // Case: Empty indice only. + // Delete the layout. + cursor->setPointedExpressionLayout(base); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + m_parent->removeChildAtIndex(indexInParent, true); + return; + } + // Case: Non-empty indice. + // Move Left of the VerticalOffsetLayout. + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + +bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the indice. + // Go Left. + if (indiceLayout() + && cursor->pointedExpressionLayout() == indiceLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the indice. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + return true; + } + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the indice. + // Go Right. + if (indiceLayout() + && cursor->pointedExpressionLayout() == indiceLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + cursor->setPointedExpressionLayout(this); + return true; + } + + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go to the indice. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + return true; + } + // Case: Right. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Case: Superscript. + if (m_type == VerticalOffsetLayout::Type::Superscript) { + // Case: Right. + // Move to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Left. + // Move to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Left)) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + } + // Case: Subscript. + // Case: Left or Right of the indice. + // Put the cursor at the same position, pointing this. + if (m_type == VerticalOffsetLayout::Type::Subscript + && indiceLayout() != nullptr + && (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left) + || cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right))) + { + cursor->setPointedExpressionLayout(this); + return true; + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + +bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Case: Subscript. + if (m_type == VerticalOffsetLayout::Type::Subscript) { + // Case: Right. + // Move to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + // Case: Left. + // Move to the indice. + if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Left)) { + assert(indiceLayout() != nullptr); + cursor->setPointedExpressionLayout(indiceLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + } + // Case: Superscript. + // Case: Left or Right of the indice. + // Put the cursor at the same position, pointing this. + if (m_type == VerticalOffsetLayout::Type::Superscript + && indiceLayout() != nullptr + && cursor->pointedExpressionLayout() == indiceLayout()) + { + cursor->setPointedExpressionLayout(this); + return true; + } + return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); +} + +int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (m_type == Type::Subscript) { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } + // If the layout is a subscript, write "_{indice}" + int numberOfChar = LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '_'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '{'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += const_cast(this)->indiceLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '}'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + return numberOfChar; + } + assert(m_type == Type::Superscript); + // If the layout is a superscript, write "^(indice)" + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); +} + +ExpressionLayout * VerticalOffsetLayout::indiceLayout() { + return editableChild(0); +} + +ExpressionLayout * VerticalOffsetLayout::baseLayout() { + int indexInParent = parent()->indexOfChild(this); + assert(indexInParent > 0); + return editableParent()->editableChild(indexInParent - 1); +} + +void VerticalOffsetLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // There is nothing to draw for a subscript/superscript, only the position of the child matters +} + +KDSize VerticalOffsetLayout::computeSize() { + KDSize indiceSize = indiceLayout()->size(); + KDCoordinate width = indiceSize.width(); + KDCoordinate height = 0; + if (m_type == Type::Subscript) { + height = positionOfChild(indiceLayout()).y()+ indiceLayout()->size().height(); + } else { + height = indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; + } + return KDSize(width, height); +} + +void VerticalOffsetLayout::computeBaseline() { + if (m_type == Type::Subscript) { + m_baseline = 0; + } else { + m_baseline = size().height(); + } + m_baselined = true; +} + +KDPoint VerticalOffsetLayout::positionOfChild(ExpressionLayout * child) { + assert(child == indiceLayout()); + if (m_type == Type::Superscript) { + return KDPointZero; + } + assert(m_type == Type::Subscript); + ExpressionLayout * base = baseLayout(); + return KDPoint(0, base->size().height() - base->baseline() - k_indiceHeight); +} + +} diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h new file mode 100644 index 000000000..bf3242cb7 --- /dev/null +++ b/poincare/src/layout/vertical_offset_layout.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_VERTICAL_OFFSET_LAYOUT_H +#define POINCARE_VERTICAL_OFFSET_LAYOUT_H + +#include + +namespace Poincare { + +class VerticalOffsetLayout : public StaticLayoutHierarchy<1> { +public: + enum class Type { + Subscript, + Superscript + }; + VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); + ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; + bool mustHaveLeftBrother() const override { return true; } +protected: + ExpressionLayout * indiceLayout(); + ExpressionLayout * baseLayout(); + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(ExpressionLayout * child) override; + Type m_type; +private: + constexpr static KDCoordinate k_indiceHeight = 5; +}; + +} + +#endif From 9753228a3dc585657509680a2f825d6fbce2dc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 15:27:10 +0100 Subject: [PATCH 101/459] [poincare] Use the VerticalOffsetLayouts. Change-Id: I6dfc61f95016fd9863b7a4b1f41dc1784560807b --- poincare/include/poincare_layouts.h | 1 + poincare/src/expression_layout_cursor.cpp | 61 ++++++++++++++++------- poincare/src/layout/horizontal_layout.cpp | 33 ++++++++++-- poincare/src/layout/horizontal_layout.h | 3 ++ 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 4c339e285..b06cc8993 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -29,5 +29,6 @@ #include #include #include +#include #endif diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 0f55d45fa..2007824ab 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,4 +1,5 @@ #include +#include #include //TODO: finer include? #include #include @@ -49,12 +50,12 @@ void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); - EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); + HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); pointedExpressionLayout()->addBrother(this, newChild); - setPointedExpressionLayout(child2); - setPosition(ExpressionLayoutCursor::Position::Left); - return child2; + setPointedExpressionLayout(offsetLayout->editableChild(0)); + setPosition(ExpressionLayoutCursor::Position::Right); + return offsetLayout; } ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { @@ -105,21 +106,37 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( } ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { - StringLayout * child1 = new StringLayout("log", 3); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); - EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Subscript, false); + HorizontalLayout * newChild = new HorizontalLayout( + ExpressionLayoutArray( + new CharLayout('l'), + new CharLayout('o'), + new CharLayout('g')).array(), + 3, + false); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Subscript, false); + newChild->addChildAtIndex(offsetLayout, 3); m_pointedExpressionLayout->addBrother(this, newChild); - setPointedExpressionLayout(newChild); + setPointedExpressionLayout(offsetLayout); setPosition(ExpressionLayoutCursor::Position::Right); insertText("()"); - moveLeft(); - return child1; + setPointedExpressionLayout(offsetLayout->editableChild(0)); + setPosition(ExpressionLayoutCursor::Position::Right); + return offsetLayout; } ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); + // If there is already a base + int numberOfOpenParenthesis = 0; + if (!m_pointedExpressionLayout->isEmpty() && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) { + m_pointedExpressionLayout->addBrother(this, offsetLayout); + setPointedExpressionLayout(offsetLayout->editableChild(0)); + setPosition(ExpressionLayoutCursor::Position::Left); + return offsetLayout; + } + // Else, add an empty base EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); - EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); @@ -137,13 +154,23 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyRootLayout() { } ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { + CharLayout * indiceLayout = new CharLayout('2'); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(indiceLayout, VerticalOffsetLayout::Type::Superscript, false); + // If there is already a base + int numberOfOpenParenthesis = 0; + if (!m_pointedExpressionLayout->isEmpty() && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) { + m_pointedExpressionLayout->addBrother(this, offsetLayout); + setPointedExpressionLayout(offsetLayout); + setPosition(ExpressionLayoutCursor::Position::Right); + return offsetLayout; + } + // Else, add an empty base EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); - CharLayout * child2 = new CharLayout('2'); - EditableBaselineRelativeLayout * newChild = new EditableBaselineRelativeLayout(child1, child2, BaselineRelativeLayout::Type::Superscript, false); + HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); m_pointedExpressionLayout->addBrother(this, newChild); - setPointedExpressionLayout(newChild); + setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); - return newChild; + return child1; } ExpressionLayout * ExpressionLayoutCursor::addXNTCharLayout() { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 6a92ff30d..f0a627346 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,4 +1,5 @@ #include "horizontal_layout.h" +#include "empty_visible_layout.h" #include "string_layout.h" #include @@ -30,24 +31,30 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { if (newChild->isEmpty()) { if (numberOfChildren() > 1) { + // If the new layout is empty and the horizontal layout has other + // children, just delete the old child. if (!newChild->hasAncestor(oldChild)) { delete newChild; } removeChildAtIndex(indexOfChild(const_cast(oldChild)), deleteOldChild); return; } + // If the new layout is empty and it was the only horizontal layout child, + // replace the horizontal layout with this empty layout. if (m_parent) { replaceWith(newChild); return; } } + // If the new child is also an horizontal layout, steal the children of the + // new layout then destroy it. if (newChild->isHorizontal()) { - // Steal the children of the new layout then destroy it. int indexForInsertion = indexOfChild(const_cast(oldChild)); mergeChildrenAtIndex(newChild, indexForInsertion + 1); removeChildAtIndex(indexForInsertion, deleteOldChild); return; } + // Else, just replace the child. ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); } @@ -167,6 +174,16 @@ bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayou return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, previousLayout, previousPreviousLayout); } +void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { + // If the child to remove is at index 0 and its right brother must have a left + // brother (e.g. it is a VerticalOffsetLayout), replace the child with an + // EmptyVisibleLayout instead of removing it. + if (index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { + addChildAtIndex(new EmptyVisibleLayout(), index + 1); + } + DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } @@ -217,11 +234,19 @@ void HorizontalLayout::mergeChildrenAtIndex(ExpressionLayout * eL, int index) { removeChildAtIndex(indexOfEL, false); } int numChildren = eL->numberOfChildren(); + int currentAdditionIndex = index; for (int i = 0; i < numChildren; i++) { - ExpressionLayout * currentChild = eL->editableChild(0); - eL->removeChildAtIndex(0, false); - addChildAtIndex(currentChild, index+i); + ExpressionLayout * currentChild = eL->editableChild(i); + // Do not add empty children if we can + if (!currentChild->isEmpty() + || i == numChildren - 1 + || (i < numChildren - 1 && eL->editableChild(i+1)->mustHaveLeftBrother())) + { + addChildAtIndex(currentChild, currentAdditionIndex++); + eL->detachChild(currentChild); + } } + delete eL; } bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index c4aa2a027..209fda198 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -22,6 +22,9 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + /* Dynamic layout */ + void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); From 98faf01b537404fdb9d2ae8d88ac2ed660c8bb0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 15:27:44 +0100 Subject: [PATCH 102/459] [poincare] Better Fraction collapsing. Change-Id: Ic898f522ae26cfcd5917f4da85715f85a5861b9f --- .../poincare/dynamic_layout_hierarchy.h | 2 + .../src/layout/dynamic_layout_hierarchy.cpp | 13 ++-- poincare/src/layout/expression_layout.cpp | 2 +- poincare/src/layout/fraction_layout.cpp | 75 ++++++++----------- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 8e4cffd6a..ec698cd46 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -25,6 +25,8 @@ public: bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + + bool isEmpty() const override; protected: const ExpressionLayout ** m_children; int m_numberOfChildren; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index dba3cf394..f2cea1145 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -70,15 +70,18 @@ void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemov const_cast(m_children[index])->setParent(nullptr); } m_numberOfChildren--; - /*if (m_numberOfChildren == 0) { - ExpressionLayout * emptyVisibleLayout = new EmptyVisibleLayout(); - replaceWith(emptyVisibleLayout); - return; - }*/ for (int j=index; jisEmpty())) + { + return true; + } + return false; } } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 6364e64c1..f3598d780 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -113,7 +113,7 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay if (m_parent) { int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; if (m_parent->isHorizontal()) { - m_parent->addChildAtIndex(brother, brotherIndex); + static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex); return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 71b9555aa..b499e96b9 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -18,55 +18,44 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // a horizontal juxtaposition of the numerator and the denominator. if (cursor->pointedExpressionLayout() == denominatorLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (numeratorLayout()->isEmpty()) { - if (denominatorLayout()->isEmpty()) { - // If the numerator and the denominator are empty, replace the fraction - // with an empty layout. - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(new EmptyVisibleLayout(), true); - // Place the cursor on the right of the left brother ofthe fraction if - // there is one. - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(previousParent); + if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { + // If the numerator and the denominator are empty, replace the fraction + // with an empty layout. + ExpressionLayout * previousParent = m_parent; + int indexInParent = previousParent->indexOfChild(this); + replaceWith(new EmptyVisibleLayout(), true); + // Place the cursor on the right of the left brother of the fraction if + // there is one. + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } - // If the numerator is empty but not the denominator, replace the fraction - // with its denominator. Place the cursor on the left of the denominator. - ExpressionLayout * nextPointedLayout = denominatorLayout(); - if (denominatorLayout()->isHorizontal()) { - nextPointedLayout = denominatorLayout()->editableChild(0); - } - replaceWith(denominatorLayout(), true); - cursor->setPointedExpressionLayout(nextPointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + // Else place the cursor on the Left of the parent. + cursor->setPointedExpressionLayout(previousParent); return; } - // If the denominator is empty but not the numerator, replace the fraction - // with the numerator and place the cursor on its right. - if (denominatorLayout()->isEmpty()) { - ExpressionLayout * nextPointedLayout = numeratorLayout(); - if (numeratorLayout()->isHorizontal()) { - nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); - } - replaceWith(numeratorLayout(), true); - cursor->setPointedExpressionLayout(nextPointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // If neither the numerator nor the denominator are empty, replace the - // fraction with a juxtaposition of the numerator and denominator. Place the - // cursor in the middle of the juxtaposition, which is right of the - // numerator. + + // Else, replace the fraction with a juxtaposition of the numerator and + // denominator. Place the cursor in the middle of the juxtaposition, which + // is right of the numerator. + + // Prepare the cursor position. ExpressionLayout * nextPointedLayout = numeratorLayout(); - if (numeratorLayout()->isHorizontal()) { + ExpressionLayoutCursor::Position nextPosition = ExpressionLayoutCursor::Position::Right; + if (numeratorLayout()->isEmpty()) { + int indexInParent = m_parent->indexOfChild(this); + if (indexInParent > 0) { + nextPointedLayout = m_parent->editableChild(indexInParent - 1); + } else { + nextPointedLayout = m_parent; + nextPosition = ExpressionLayoutCursor::Position::Left; + } + } else if (numeratorLayout()->isHorizontal()) { nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); } + + // Juxtapose. ExpressionLayout * numerator = numeratorLayout(); ExpressionLayout * denominator = denominatorLayout(); detachChild(numerator); @@ -77,7 +66,7 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // Add the denominator before the numerator to have the right order. replaceWith(newLayout, true); cursor->setPointedExpressionLayout(nextPointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor->setPosition(nextPosition); return; } // If the cursor is on the left of the numerator, move Left of the fraction. From 65d7fd7a01072e51653c68c8d3e194290b1a036d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 15:28:19 +0100 Subject: [PATCH 103/459] [poincare] Added comment to explain baselines. Change-Id: I769c55c48c80bdce6deb8a7fc23ccc36bdc398a9 --- poincare/include/poincare/expression_layout.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 5b3a927a8..e39253317 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -93,6 +93,9 @@ protected: int * resultPositionInside, int * resultScore); KDCoordinate m_baseline; + /* m_baseline is the signed vertical distance from the top of the layout to + * the fraction bar of an hypothetical fraction brother layout. If the top of + * the layout is under that bar, the baseline is negative. */ ExpressionLayout * m_parent; bool m_sized; bool m_baselined; From e8560f7b9789f1ac31b572bcbcc21c0e0cf481ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 15:29:03 +0100 Subject: [PATCH 104/459] [poincare] Fixed coding style. Change-Id: Ic57dfd53a3ae70cf71be08b73935c9f7649c2b76 --- poincare/src/layout/baseline_relative_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp index 133d6c563..824c1c286 100644 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ b/poincare/src/layout/baseline_relative_layout.cpp @@ -125,7 +125,7 @@ KDPoint BaselineRelativeLayout::positionOfChild(ExpressionLayout * child) { } if (child == indiceLayout()) { x = baseLayout()->size().width(); - y = m_type == Type::Superscript ? 0 : baseLayout()->size().height() - k_indiceHeight; + y = m_type == Type::Superscript ? 0 : baseLayout()->size().height() - k_indiceHeight; } return KDPoint(x,y); } From 0f5019442f1411d2179be3896dbfce7c09f31b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 16:00:24 +0100 Subject: [PATCH 105/459] [poincare] Fixed parenthesis collapsing bug. Pressing "(", "1", "/" collapsed the parenthesis. Change-Id: Iebd8925c1e8518013f0e0aa9a45bb42881583640 --- poincare/src/layout/parenthesis_left_layout.cpp | 3 +++ poincare/src/layout/parenthesis_right_layout.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 6cf4e8d68..e9e5f638e 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -33,6 +33,9 @@ ExpressionLayout * ParenthesisLeftLayout::clone() const { } bool ParenthesisLeftLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis == 0 && goingLeft) { + return false; + } *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis - 1 : *numberOfOpenParenthesis + 1; return true; } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 8681a297b..6d7f73eea 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -33,6 +33,9 @@ ExpressionLayout * ParenthesisRightLayout::clone() const { } bool ParenthesisRightLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis == 0 && !goingLeft) { + return false; + } *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis + 1 : *numberOfOpenParenthesis - 1; return true; } From 21ed3471b1386ce0243faace23f1e8c71f615e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 16:01:37 +0100 Subject: [PATCH 106/459] [poincare] Fixed parenthesis height computing. Before, it did not take the baseline into account. Change-Id: Ib1b220d7c07eab7002497671e9c6ffba8548acfb --- poincare/src/layout/parenthesis_left_layout.cpp | 16 ++++++++++++++-- poincare/src/layout/parenthesis_right_layout.cpp | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index e9e5f638e..6122d5d08 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -65,6 +65,8 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio void ParenthesisLeftLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; + KDCoordinate max_under_baseline = 0; + KDCoordinate max_above_baseline = 0; int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { @@ -72,15 +74,25 @@ void ParenthesisLeftLayout::computeOperandHeight() { if (brother->isRightParenthesis()) { currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; + } return; } } else if (brother->isLeftParenthesis()) { currentNumberOfOpenParentheses++; } KDCoordinate brotherHeight = brother->size().height(); - if (brotherHeight > m_operandHeight) { - m_operandHeight = brotherHeight; + KDCoordinate brotherBaseline = brother->baseline(); + if (brotherHeight - brotherBaseline > max_under_baseline) { + max_under_baseline = brotherHeight - brotherBaseline ; } + if (brotherBaseline > max_above_baseline) { + max_above_baseline = brotherBaseline; + } + } + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; } } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 6d7f73eea..9d3b2c50b 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -65,21 +65,33 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi void ParenthesisRightLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; + KDCoordinate max_under_baseline = 0; + KDCoordinate max_above_baseline = 0; int currentNumberOfOpenParentheses = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isLeftParenthesis()) { currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; + } return; } } else if (brother->isRightParenthesis()) { currentNumberOfOpenParentheses++; } KDCoordinate brotherHeight = brother->size().height(); - if (brotherHeight > m_operandHeight) { - m_operandHeight = brotherHeight; + KDCoordinate brotherBaseline = brother->baseline(); + if (brotherHeight - brotherBaseline > max_under_baseline) { + max_under_baseline = brotherHeight - brotherBaseline ; } + if (brotherBaseline > max_above_baseline) { + max_above_baseline = brotherBaseline; + } + } + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; } } From a998ae454132429863b31ce2a0ca3ac6e9068ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 5 Jan 2018 10:10:54 +0100 Subject: [PATCH 107/459] [poincare] Fixed parenthesis baseline computing. Change-Id: I38ecb8bab67280f6e452bc9ef404a00641060879 --- poincare/src/layout/parenthesis_left_layout.cpp | 17 +++++++++++++++-- .../src/layout/parenthesis_right_layout.cpp | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 6122d5d08..aaa91ede0 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -98,12 +98,25 @@ void ParenthesisLeftLayout::computeOperandHeight() { void ParenthesisLeftLayout::computeBaseline() { assert(m_parent != nullptr); - m_baseline = operandHeight()/2; int currentNumberOfOpenParentheses = 1; + int indexInParent = m_parent->indexOfChild(this); int numberOfBrothers = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + if (indexInParent == numberOfBrothers - 1) { + // The parenthesis is the rightmost child of its parent. + m_baseline = operandHeight()/2; + m_baselined = true; + return; + } + m_baseline = 0; + for (int i = indexInParent + 1; i < numberOfBrothers; i++) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isRightParenthesis()) { + if (i == indexInParent + 1) { + // If the parenthesis is immediately closed, we set the baseline to half + // the parenthesis height. + m_baseline = operandHeight()/2; + break; + } currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { break; diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 9d3b2c50b..e0346d42b 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -97,11 +97,24 @@ void ParenthesisRightLayout::computeOperandHeight() { void ParenthesisRightLayout::computeBaseline() { assert(m_parent != nullptr); - m_baseline = operandHeight()/2; int currentNumberOfOpenParentheses = 1; - for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + int indexInParent = m_parent->indexOfChild(this); + if (indexInParent == 0) { + // The parenthesis is the leftmost child of its parent. + m_baseline = operandHeight()/2; + m_baselined = true; + return; + } + m_baseline = 0; + for (int i = indexInParent - 1; i >= 0; i--) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isLeftParenthesis()) { + if (i == indexInParent - 1) { + // If the parenthesis is immediately closed, we set the baseline to half + // the parenthesis height. + m_baseline = operandHeight()/2; + break; + } currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { break; From 211227e6821e9c15ea44321ec57826da626ccf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 16:08:00 +0100 Subject: [PATCH 108/459] [poincare] Changed NthRootLayout deleting. Before, nested roots did not get deleted properly. Change-Id: I1d3dce28912a4843a372db8c3a0b479bd11b27f9 --- poincare/src/layout/nth_root_layout.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index d23514edc..2a166bf7d 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -38,8 +38,14 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout * previousParent = m_parent; int indexInParent = previousParent->indexOfChild(this); replaceWith(radicandLayout()); - // Place the cursor on the right of the left brother of the root if there is - // one. + // Place the cursor on the left of what replaced the root if possible. + if (indexInParent < previousParent->numberOfChildren()) { + cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + // Else place the cursor on the right of the left brother of the root if + // there is one. if (indexInParent > 0) { cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); From 23eccd2c75e7ca620a9b111a63b0d57231df4dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 16:49:51 +0100 Subject: [PATCH 109/459] [poincare] Cleaned the dynamic methods for layouts. Change-Id: I17db05b01c75a638a56fe2c197a175fd1b04840d --- .../poincare/dynamic_layout_hierarchy.h | 2 ++ poincare/include/poincare/expression_layout.h | 2 ++ .../src/layout/dynamic_layout_hierarchy.cpp | 34 +++++++++++++++++++ poincare/src/layout/expression_layout.cpp | 6 ++++ poincare/src/layout/horizontal_layout.cpp | 26 ++------------ poincare/src/layout/horizontal_layout.h | 1 - 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index ec698cd46..8099c50ef 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -23,8 +23,10 @@ public: int numberOfChildren() const override { return m_numberOfChildren; } const ExpressionLayout * const * children() const override { return m_children; }; + void addNonEmptyChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion); bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index); // WITHOUT delete. bool isEmpty() const override; protected: diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index e39253317..1277db657 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -50,6 +50,8 @@ public: ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); void detachChild(const ExpressionLayout * e); // Removes a child WITHOUT deleting it + void detachChildren(); //Removes all children WITHOUT deleting them + /* Dynamic Layout*/ virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index f2cea1145..707383ed4 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -42,6 +42,40 @@ DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { delete[] m_children; } +void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index) { + int indexOfEL = indexOfChild(eL); + if (indexOfEL >= 0) { + removeChildAtIndex(indexOfEL, false); + } + addNonEmptyChildrenAtIndex(eL->children(), eL->numberOfChildren(), index); + eL->detachChildren(); + delete eL; +} + +void DynamicLayoutHierarchy::addNonEmptyChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion) { + assert(numberOfOperands > 0); + const ExpressionLayout ** newOperands = new const ExpressionLayout * [m_numberOfChildren+numberOfOperands]; + int currentIndex = 0; + assert(indexForInsertion <= m_numberOfChildren); + for (int i=0; iisEmpty() + || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftBrother())) + { + const_cast(operands[i])->setParent(this); + newOperands[currentIndex++] = operands[i]; + } + } + for (int i=indexForInsertion; i= 0 && index <= m_numberOfChildren); const ExpressionLayout ** newChildren = new const ExpressionLayout * [m_numberOfChildren+1]; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index f3598d780..845ab35fd 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -197,6 +197,12 @@ void ExpressionLayout::detachChild(const ExpressionLayout * e) { } } +void ExpressionLayout::detachChildren() { + for (int i = 0; i = 0 && index < numberOfChildren()); replaceChild(editableChild(index), new EmptyVisibleLayout(), deleteAfterRemoval); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index f0a627346..0840332aa 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -50,7 +50,7 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio // new layout then destroy it. if (newChild->isHorizontal()) { int indexForInsertion = indexOfChild(const_cast(oldChild)); - mergeChildrenAtIndex(newChild, indexForInsertion + 1); + mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1); removeChildAtIndex(indexForInsertion, deleteOldChild); return; } @@ -65,11 +65,10 @@ void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index) newIndex = index == 0 ? 0 : index - 1; } if (eL->isHorizontal()) { - mergeChildrenAtIndex(eL, newIndex); + mergeChildrenAtIndex(static_cast(eL), newIndex); return; } addChildAtIndex(eL, newIndex); - } bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -228,27 +227,6 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -void HorizontalLayout::mergeChildrenAtIndex(ExpressionLayout * eL, int index) { - int indexOfEL = indexOfChild(eL); - if (indexOfEL >= 0) { - removeChildAtIndex(indexOfEL, false); - } - int numChildren = eL->numberOfChildren(); - int currentAdditionIndex = index; - for (int i = 0; i < numChildren; i++) { - ExpressionLayout * currentChild = eL->editableChild(i); - // Do not add empty children if we can - if (!currentChild->isEmpty() - || i == numChildren - 1 - || (i < numChildren - 1 && eL->editableChild(i+1)->mustHaveLeftBrother())) - { - addChildAtIndex(currentChild, currentAdditionIndex++); - eL->detachChild(currentChild); - } - } - delete eL; -} - bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Prevent looping fom child to parent if (previousPreviousLayout == this) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 209fda198..223263b22 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -38,7 +38,6 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - void mergeChildrenAtIndex(ExpressionLayout * eL, int index); // WITHOUT delete. private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); }; From bfe4735199f13a751c25159825ec4223e1613c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 16:50:25 +0100 Subject: [PATCH 110/459] [poincare] Fix bug when replacing child in Horizontal layout. Change-Id: I99b6e32932db27376c83eafe1a4ff5044b1d3334 --- poincare/src/layout/horizontal_layout.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 0840332aa..4af8b824f 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -29,6 +29,9 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { + if (newChild->hasAncestor(this)) { + newChild->editableParent()->detachChild(newChild); + } if (newChild->isEmpty()) { if (numberOfChildren() > 1) { // If the new layout is empty and the horizontal layout has other From 48dc38da569b9fea4ad1d69695718b454aa123a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 4 Jan 2018 17:47:59 +0100 Subject: [PATCH 111/459] [poincare] Fixed "dx" removal when deleting an IntegralLayout. Change-Id: I65494adf8d5bc732e95270ed6397b49a5303e7b0 --- poincare/src/layout/integral_layout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index f41c8bf2c..59756cd91 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -39,9 +39,9 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout * dxLayout = integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-1); replaceWith(integrandLayout(), true); // Remove "dx" - int indexOfdx = previousParent->indexOfChild(dxLayout); + int indexOfdx = dxLayout->parent()->indexOfChild(dxLayout); if (indexOfdx >= 0) { - previousParent->removeChildAtIndex(indexOfdx, true); + const_cast(dxLayout->parent())->removeChildAtIndex(indexOfdx, true); } // Place the cursor on the right of the left brother of the integral if // there is one. From 7c3b97fe36e26609c3f03825d2ed4c555a4826d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 5 Jan 2018 10:59:02 +0100 Subject: [PATCH 112/459] [poincare] Fixed fraction deletion. There was a problem with the new cursor position. Change-Id: Iac163e236b45b776fc98bdef75e2abc5d13c2b18 --- poincare/src/layout/fraction_layout.cpp | 37 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index b499e96b9..c7e6677d6 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -19,20 +19,31 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == denominatorLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { - // If the numerator and the denominator are empty, replace the fraction - // with an empty layout. - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(new EmptyVisibleLayout(), true); - // Place the cursor on the right of the left brother of the fraction if - // there is one. - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; + // If the numerator and the denominator are empty, move the cursor then + // replace the fraction with an empty layout. + // We need to perform these actions in this order because the replacement + // might delete the fraction's parent: if the parent is an + // HorizontalLayout and the fraction is its only child, the + // HorizontalLayout will be replaced by the new EmptyLayout. + ExpressionLayout * newEmptyLayout = new EmptyVisibleLayout(); + if (!m_parent->isHorizontal() + || (m_parent->isHorizontal() && m_parent->numberOfChildren() == 1)) + { + cursor->setPointedExpressionLayout(newEmptyLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } else { + assert(m_parent->isHorizontal()); + assert(m_parent->numberOfChildren() > 0); + int indexInParent = m_parent->indexOfChild(this); + if (indexInParent > 0) { + cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } else { + cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent + 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(previousParent); + replaceWith(newEmptyLayout, true); return; } From 4478885566fadb2cb2a6a37e39be52919a966d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 5 Jan 2018 11:51:38 +0100 Subject: [PATCH 113/459] [poincare] "Hard draw" dx in IntegralLayout, instead of layouting it. This simplifies the navigation, edition and serialization of IntegralLayout. Change-Id: I03360bf83eeb0cbd9524c992518dff125900e9a5 --- apps/math_toolbox.cpp | 9 ++--- poincare/src/layout/char_layout.h | 1 + poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/integral_layout.cpp | 47 +++++++++++++------------ 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 1b569b848..0798669b9 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -11,21 +11,18 @@ using namespace Poincare; * and the text which would be edited by clicking on the row. When the node is a * subtree, the edited text is set at I18n::Message::Default. */ -const int pointedLayoutPathIntegral[] = {0, 0}; +const int pointedLayoutPathIntegral[] = {0}; const int pointedLayoutPathSum[] = {0, 1}; const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, new IntegralLayout( - new HorizontalLayout( - Poincare::ExpressionLayoutArray( - new EmptyVisibleLayout(), - new StringLayout("dx",2)).array(), 2, false), + new EmptyVisibleLayout(), new EmptyVisibleLayout(), new EmptyVisibleLayout(), false), const_cast(&pointedLayoutPathIntegral[0]), - 2), + 1), ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, new SumLayout( new EmptyVisibleLayout(), diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 28323d228..cbdb775b8 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -16,6 +16,7 @@ public: } char character() { return m_char; } + KDText::FontSize fontSize() const { return m_fontSize; } bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 223263b22..ed0afc9a1 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { + friend class IntegralLayout; public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 59756cd91..4844e5a6f 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -1,4 +1,7 @@ #include "integral_layout.h" +#include "char_layout.h" +#include "horizontal_layout.h" +#include "string_layout.h" #include #include #include @@ -36,13 +39,7 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { { ExpressionLayout * previousParent = m_parent; int indexInParent = previousParent->indexOfChild(this); - ExpressionLayout * dxLayout = integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-1); replaceWith(integrandLayout(), true); - // Remove "dx" - int indexOfdx = dxLayout->parent()->indexOfChild(dxLayout); - if (indexOfdx >= 0) { - const_cast(dxLayout->parent())->removeChildAtIndex(indexOfdx, true); - } // Place the cursor on the right of the left brother of the integral if // there is one. if (indexInParent > 0) { @@ -55,10 +52,9 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { return; } // If the cursor is on the right, move to the integrand. - if (cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Right)) { - assert(integrandLayout()->numberOfChildren() > 1); - ExpressionLayout * layoutLeftOfdx = integrandLayout()->editableChild(integrandLayout()->numberOfChildren()-2); - cursor->setPointedExpressionLayout(layoutLeftOfdx); + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + cursor->setPointedExpressionLayout(integrandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } @@ -92,11 +88,11 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { } assert(cursor->pointedExpressionLayout() == this); // Case: Right of the integral. - // Go Left of "dx". + // Go to the integrand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()->editableChild(integrandLayout()->numberOfChildren() - 1)); - return cursor->moveLeft(); + cursor->setPointedExpressionLayout(integrandLayout()); + return true; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. @@ -117,18 +113,18 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { && cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()->editableChild(0)); + cursor->setPointedExpressionLayout(integrandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // Case: Right the integrand. - // Go Right and move Right. + // Go Right. if (integrandLayout() && cursor->pointedExpressionLayout() == integrandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(this); - return m_parent->moveRight(cursor); + return true; } assert(cursor->pointedExpressionLayout() == this); // Case: Left of the integral. @@ -199,11 +195,9 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { return bufferSize-1; } - // Write the argument without the "dx" + // Write the argument ExpressionLayout * intLayout = const_cast(this)->integrandLayout(); - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(intLayout, buffer+numberOfChar, bufferSize-numberOfChar, "", 0, intLayout->numberOfChildren()-2); - // TODO This works because the argument layout should always be an horizontal - // layout. + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(intLayout, buffer+numberOfChar, bufferSize-numberOfChar, ""); // Write the comma if (numberOfChar >= bufferSize-1) { return bufferSize-1; } @@ -232,6 +226,8 @@ void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDSize integrandSize = integrandLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; + + // Render the integral symbol. KDRect topSymbolFrame(p.x() + k_symbolWidth + k_lineThickness, p.y() + upperBoundSize.height() - k_boundHeightMargin, k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(topSymbolFrame, expressionColor, (const uint8_t *)topSymbolPixel, (KDColor *)workingBuffer); @@ -241,15 +237,22 @@ void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, ctx->blendRectWithMask(bottomSymbolFrame, expressionColor, (const uint8_t *)bottomSymbolPixel, (KDColor *)workingBuffer); ctx->fillRect(KDRect(p.x() + k_symbolWidth, p.y() + upperBoundSize.height() - k_boundHeightMargin, k_lineThickness, 2*k_boundHeightMargin+2*k_integrandHeigthMargin+integrandSize.height()), expressionColor); + + // Render "dx". + CharLayout * dummydx = new CharLayout('d'); + HorizontalLayout dummyLayout(integrandLayout()->clone(), dummydx, false); + KDPoint dxPosition = dummyLayout.positionOfChild(dummydx); + ctx->drawString("dx", dxPosition.translatedBy(p).translatedBy(positionOfChild(integrandLayout())), dummydx->fontSize(), expressionColor, backgroundColor); } KDSize IntegralLayout::computeSize() { + KDSize dxSize = StringLayout("dx", 2).size(); KDSize integrandSize = integrandLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( - k_symbolWidth+k_lineThickness+k_boundWidthMargin+max(lowerBoundSize.width(), upperBoundSize.width())+k_integrandWidthMargin+integrandSize.width(), - upperBoundSize.height()+ 2*k_integrandHeigthMargin+integrandSize.height()+lowerBoundSize.height()); + k_symbolWidth+k_lineThickness+k_boundWidthMargin+max(lowerBoundSize.width(), upperBoundSize.width())+k_integrandWidthMargin+integrandSize.width()+dxSize.width(), + upperBoundSize.height()+ 2*k_integrandHeigthMargin+max(integrandSize.height(), dxSize.height())+lowerBoundSize.height()); } void IntegralLayout::computeBaseline() { From 4cc107b15f24238694c8811b352508bbde8b6c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 5 Jan 2018 17:23:59 +0100 Subject: [PATCH 114/459] [poincare] "Hard draw" n= in SequenceLayout, instead of layouting it. Change-Id: I79aa6ab0f46c0a05a3c2fe1dd88b287dc09dac17 --- apps/math_toolbox.cpp | 4 +- poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/product_layout.cpp | 19 +++++--- poincare/src/layout/sequence_layout.cpp | 58 +++++++++++++++---------- poincare/src/layout/sequence_layout.h | 3 +- poincare/src/layout/string_layout.h | 1 + poincare/src/layout/sum_layout.cpp | 19 +++++--- 7 files changed, 66 insertions(+), 39 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 0798669b9..648bc194f 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -26,9 +26,7 @@ const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, new SumLayout( new EmptyVisibleLayout(), - new HorizontalLayout(Poincare::ExpressionLayoutArray( - new StringLayout("n=",2), - new EmptyVisibleLayout()).array(), 2, false), + new EmptyVisibleLayout(), new EmptyVisibleLayout(), false), const_cast(&pointedLayoutPathSum[0]), diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index ed0afc9a1..bb72a1740 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { friend class IntegralLayout; + friend class SequenceLayout; public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index 1be482165..c09a14dad 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -1,6 +1,7 @@ #include "product_layout.h" -#include -#include +#include "char_layout.h" +#include "horizontal_layout.h" +#include namespace Poincare { @@ -14,17 +15,23 @@ int ProductLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Compute sizes. KDSize upperBoundSize = upperBoundLayout()->size(); - KDSize lowerBoundSize = lowerBoundLayout()->size(); - ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + + // Render the Product symbol. + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_lineThickness, k_symbolHeight), expressionColor); - ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_symbolWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2)+k_symbolWidth, + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2)+k_symbolWidth, p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_lineThickness, k_symbolHeight), expressionColor); + + // Render the "n=". + SequenceLayout::render(ctx, p, expressionColor, backgroundColor); } } diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index ed7d4e46e..1446b83bb 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -1,4 +1,7 @@ #include "sequence_layout.h" +#include "char_layout.h" +#include "horizontal_layout.h" +#include "string_layout.h" #include "parenthesis_left_layout.h" #include "parenthesis_right_layout.h" #include "uneditable_horizontal_trio_layout.h" @@ -79,7 +82,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { && cursor->pointedExpressionLayout() == argumentWithParenthesesLayout()) { assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()->editableChild(1)); + cursor->setPointedExpressionLayout(lowerBoundLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } @@ -160,7 +163,7 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && previousLayout == upperBoundLayout()) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->editableChild(1)->moveDownInside(cursor); + return lowerBoundLayout()->moveDownInside(cursor); } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() @@ -199,10 +202,8 @@ int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer[numberOfChar++] = ','; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - // Write the lower bound without the "n=" - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const_cast(this)->lowerBoundLayout(), buffer+numberOfChar, bufferSize-numberOfChar, "", 1); - // TODO This works because the lower bound layout should always be an - // horizontal layout. + // Write the lower bound + numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma @@ -237,32 +238,31 @@ ExpressionLayout * SequenceLayout::argumentWithParenthesesLayout() { KDSize SequenceLayout::computeSize() { KDSize argumentSize = argumentWithParenthesesLayout()->size(); - KDSize lowerBoundSize = lowerBoundLayout()->size(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( - max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), - baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - argumentLayout()->baseline()) + max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), + baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSizeWithNEquals.height(), argumentSize.height() - argumentLayout()->baseline()) ); } -void SequenceLayout::computeBaseline() { - m_baseline = max(upperBoundLayout()->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); - m_baselined = true; -} - -KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { - KDSize lowerBoundSize = lowerBoundLayout()->size(); +KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { + ExpressionLayout * lowerBoundClone = lowerBoundLayout()->clone(); + HorizontalLayout dummyLayout1(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundClone).array(), 3, false); + KDSize lowerBoundSizeWithNEquals = dummyLayout1.size(); KDSize upperBoundSize = upperBoundLayout()->size(); KDCoordinate x = 0; KDCoordinate y = 0; - if (child == lowerBoundLayout()) { - x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); + if (eL == lowerBoundLayout()) { + x = dummyLayout1.positionOfChild(lowerBoundClone).x() + +max(max(0, (k_symbolWidth-lowerBoundSizeWithNEquals.width())/2), + (upperBoundSize.width()-lowerBoundSizeWithNEquals.width())/2); y = baseline() + k_symbolHeight/2 + k_boundHeightMargin; - } else if (child == upperBoundLayout()) { - x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); + } else if (eL == upperBoundLayout()) { + x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSizeWithNEquals.width()-upperBoundSize.width())/2); y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (child == argumentWithParenthesesLayout()) { - x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; + } else if (eL == argumentWithParenthesesLayout()) { + x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin; y = baseline() - argumentLayout()->baseline(); } else { assert(false); @@ -270,4 +270,18 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x,y); } +void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Render the "n=". + CharLayout * dummyN = new CharLayout('n'); + ExpressionLayout * lowerBoundClone = lowerBoundLayout()->clone(); + HorizontalLayout dummyLayout(ExpressionLayoutArray(dummyN, new CharLayout('='), lowerBoundClone).array(), 3, false); + KDPoint nEqualsPosition = positionOfChild(lowerBoundLayout()).translatedBy((dummyLayout.positionOfChild(lowerBoundClone)).opposite()).translatedBy(dummyLayout.positionOfChild(dummyN)); + ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN->fontSize(), expressionColor, backgroundColor); +} + +void SequenceLayout::computeBaseline() { + m_baseline = max(upperBoundLayout()->size().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); + m_baselined = true; +} + } diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 0eeedfbd1..8fd6e4f69 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -25,7 +25,8 @@ protected: ExpressionLayout * argumentLayout(); ExpressionLayout * argumentWithParenthesesLayout(); KDSize computeSize() override; - KDPoint positionOfChild(ExpressionLayout * child) override; + KDPoint positionOfChild(ExpressionLayout * eL) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; private: void computeBaseline() override; }; diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h index 40301736b..8ba55f65e 100644 --- a/poincare/src/layout/string_layout.h +++ b/poincare/src/layout/string_layout.h @@ -19,6 +19,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; char * text() { return m_string; } + KDText::FontSize fontSize() { return m_fontSize; } bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 857ae525e..88685d135 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -1,7 +1,7 @@ #include "sum_layout.h" -#include -#include -#include +#include "char_layout.h" +#include "horizontal_layout.h" +#include namespace Poincare { @@ -33,14 +33,19 @@ int SumLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Computes sizes. KDSize upperBoundSize = upperBoundLayout()->size(); - KDSize lowerBoundSize = lowerBoundLayout()->size(); - KDCoordinate argBaseline = argumentLayout()->baseline(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + + // Render the Sum symbol. KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; - KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), - p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argBaseline /*argumentLayout()->baseline()*/-(k_symbolHeight+1)/2), + KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); + + // Render the "n=". + SequenceLayout::render(ctx, p, expressionColor, backgroundColor); } } From 41310a4ecfac0d1fa6874f349e03854c1e3b1934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 10:57:07 +0100 Subject: [PATCH 115/459] [poincare] "Hard draw" the fixed parentheses in SequenceLayout. Change-Id: Id626c85a7db540148bf9cb05ddb968c3f807454f --- apps/math_toolbox.cpp | 4 +- poincare/src/layout/parenthesis_left_layout.h | 1 + .../src/layout/parenthesis_right_layout.h | 1 + poincare/src/layout/product_layout.cpp | 2 +- poincare/src/layout/sequence_layout.cpp | 45 +++++++++---------- poincare/src/layout/sequence_layout.h | 1 - poincare/src/layout/sum_layout.cpp | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 648bc194f..15ddc098f 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -12,7 +12,7 @@ using namespace Poincare; * subtree, the edited text is set at I18n::Message::Default. */ const int pointedLayoutPathIntegral[] = {0}; -const int pointedLayoutPathSum[] = {0, 1}; +const int pointedLayoutPathSum[] = {0}; const ToolboxMessageTree calculChildren[4] = { ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, @@ -30,7 +30,7 @@ const ToolboxMessageTree calculChildren[4] = { new EmptyVisibleLayout(), false), const_cast(&pointedLayoutPathSum[0]), - 2), + 1), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; const int pointedLayoutPathConj[] = {0}; diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 03b3847c5..9b4c34ced 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { + friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 134c08a24..7e1eb8578 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class ParenthesisRightLayout : public ParenthesisLeftRightLayout { + friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index c09a14dad..9ab4732b9 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -30,7 +30,7 @@ void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), k_lineThickness, k_symbolHeight), expressionColor); - // Render the "n=". + // Render the "n=" and the parentheses. SequenceLayout::render(ctx, p, expressionColor, backgroundColor); } diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 1446b83bb..468768646 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -1,28 +1,17 @@ #include "sequence_layout.h" #include "char_layout.h" #include "horizontal_layout.h" -#include "string_layout.h" #include "parenthesis_left_layout.h" #include "parenthesis_right_layout.h" -#include "uneditable_horizontal_trio_layout.h" #include #include -#include #include namespace Poincare { SequenceLayout::SequenceLayout(ExpressionLayout * argument, ExpressionLayout * lowerBound, ExpressionLayout * upperBound, bool cloneOperands) : - StaticLayoutHierarchy() + StaticLayoutHierarchy(argument, lowerBound, upperBound) { - ParenthesisLeftLayout * parLeft = new ParenthesisLeftLayout(); - ParenthesisRightLayout * parRight = new ParenthesisRightLayout(); - UneditableHorizontalTrioLayout * horLayout = new UneditableHorizontalTrioLayout(parLeft, argument, parRight, cloneOperands, false); - build(ExpressionLayoutArray(horLayout, lowerBound, upperBound).array(), 3, cloneOperands); - if (cloneOperands) { - delete parLeft; - delete parRight; - } } void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { @@ -79,7 +68,7 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Right of the lower bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left && argumentLayout() - && cursor->pointedExpressionLayout() == argumentWithParenthesesLayout()) + && cursor->pointedExpressionLayout() == argumentLayout()) { assert(lowerBoundLayout() != nullptr); cursor->setPointedExpressionLayout(lowerBoundLayout()); @@ -121,7 +110,7 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. if (cursor->position() == ExpressionLayoutCursor::Position::Right && argumentLayout() - && cursor->pointedExpressionLayout() == argumentWithParenthesesLayout()) + && cursor->pointedExpressionLayout() == argumentLayout()) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); @@ -229,20 +218,19 @@ ExpressionLayout * SequenceLayout::lowerBoundLayout() { } ExpressionLayout * SequenceLayout::argumentLayout() { - return argumentWithParenthesesLayout()->editableChild(1); -} - -ExpressionLayout * SequenceLayout::argumentWithParenthesesLayout() { return editableChild(0); } KDSize SequenceLayout::computeSize() { - KDSize argumentSize = argumentWithParenthesesLayout()->size(); KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + HorizontalLayout dummyLayout2(ExpressionLayoutArray(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis).array(), 3, false); + KDSize dummyLayoutSize = dummyLayout2.size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( - max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), - baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSizeWithNEquals.height(), argumentSize.height() - argumentLayout()->baseline()) + max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+dummyLayoutSize.width(), + baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSizeWithNEquals.height(), dummyLayoutSize.height() - argumentLayout()->baseline()) ); } @@ -251,6 +239,8 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { HorizontalLayout dummyLayout1(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundClone).array(), 3, false); KDSize lowerBoundSizeWithNEquals = dummyLayout1.size(); KDSize upperBoundSize = upperBoundLayout()->size(); + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), false); KDCoordinate x = 0; KDCoordinate y = 0; if (eL == lowerBoundLayout()) { @@ -261,8 +251,8 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { } else if (eL == upperBoundLayout()) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSizeWithNEquals.width()-upperBoundSize.width())/2); y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); - } else if (eL == argumentWithParenthesesLayout()) { - x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin; + } else if (eL == argumentLayout()) { + x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+dummyLeftParenthesis->size().width(); y = baseline() - argumentLayout()->baseline(); } else { assert(false); @@ -277,6 +267,15 @@ void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, HorizontalLayout dummyLayout(ExpressionLayoutArray(dummyN, new CharLayout('='), lowerBoundClone).array(), 3, false); KDPoint nEqualsPosition = positionOfChild(lowerBoundLayout()).translatedBy((dummyLayout.positionOfChild(lowerBoundClone)).opposite()).translatedBy(dummyLayout.positionOfChild(dummyN)); ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN->fontSize(), expressionColor, backgroundColor); + + // Render the parentheses. + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + HorizontalLayout dummyLayout2(ExpressionLayoutArray(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis).array(), 3, false); + KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); + KDPoint rightParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); + dummyLeftParenthesis->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); + dummyRightParenthesis->render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor); } void SequenceLayout::computeBaseline() { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 8fd6e4f69..8969398ce 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -23,7 +23,6 @@ protected: ExpressionLayout * lowerBoundLayout(); ExpressionLayout * upperBoundLayout(); ExpressionLayout * argumentLayout(); - ExpressionLayout * argumentWithParenthesesLayout(); KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * eL) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 88685d135..7906d2a0c 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -44,7 +44,7 @@ void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDCo k_symbolWidth, k_symbolHeight); ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); - // Render the "n=". + // Render the "n=" and the parentheses. SequenceLayout::render(ctx, p, expressionColor, backgroundColor); } From 83bd562fb85384b9a196d6b8bb606de891b61747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 11:05:34 +0100 Subject: [PATCH 116/459] [poincare] Fixed IntegralLayout serialization. The integrand was not properly written. Change-Id: I063ed0ee58986174a374cc6b06b49bd5ec4a4d7d --- poincare/src/layout/integral_layout.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 4844e5a6f..dfdae4e2d 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -196,27 +196,26 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } // Write the argument - ExpressionLayout * intLayout = const_cast(this)->integrandLayout(); - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(intLayout, buffer+numberOfChar, bufferSize-numberOfChar, ""); + numberOfChar += const_cast(this)->integrandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ','; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the lower bound numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ','; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the upper bound numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the closing parenthesis - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ')'; buffer[numberOfChar] = 0; return numberOfChar; From 55044d8e0b42f5219d0784322bfdf1cf750ea220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 14:39:35 +0100 Subject: [PATCH 117/459] [poincare] Update Expression's privateCreateLayout(). We use the new layouts and no longer the old ones such as StringLayout or BaselineRelativeLayout. Change-Id: Ic15167b694c3adab46f348c8f823ce19b3e5ef33 --- apps/math_toolbox.cpp | 4 +- .../poincare/dynamic_layout_hierarchy.h | 2 + poincare/include/poincare/layout_engine.h | 2 + poincare/include/poincare/product.h | 2 +- poincare/include/poincare/sum.h | 2 +- poincare/src/ceiling.cpp | 4 +- poincare/src/complex.cpp | 21 +++--- poincare/src/decimal.cpp | 4 +- poincare/src/factorial.cpp | 10 +-- poincare/src/integer.cpp | 10 +-- poincare/src/integral.cpp | 10 +-- poincare/src/layout_engine.cpp | 71 ++++++++++++------- poincare/src/logarithm.cpp | 32 ++++----- poincare/src/multiplication.cpp | 34 ++++----- poincare/src/naperian_logarithm.cpp | 3 - poincare/src/opposite.cpp | 23 +++--- poincare/src/parenthesis.cpp | 6 +- poincare/src/power.cpp | 50 +++++++------ poincare/src/product.cpp | 4 +- poincare/src/rational.cpp | 1 - poincare/src/sequence.cpp | 11 +-- poincare/src/store.cpp | 13 ++-- poincare/src/subtraction.cpp | 16 ++--- poincare/src/sum.cpp | 4 +- poincare/src/symbol.cpp | 47 +++++++++--- poincare/src/undefined.cpp | 6 +- 26 files changed, 219 insertions(+), 173 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 15ddc098f..612e4324f 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -48,13 +48,13 @@ const ToolboxMessageTree complexChildren[5] = { const int pointedLayoutPathBinomial[] = {1,0}; const ToolboxMessageTree probabilityChildren[2] = { ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg, nullptr, 0, - new UneditableHorizontalTrioLayout( + new HorizontalLayout( new ParenthesisLeftLayout(), new GridLayout(Poincare::ExpressionLayoutArray( new EmptyVisibleLayout(), new EmptyVisibleLayout()).array(), 2, 1, false), - new ParenthesisRightLayout(), false, true), + new ParenthesisRightLayout(), false), const_cast(&pointedLayoutPathBinomial[0]), 2), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommandWithArg)}; diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 8099c50ef..a75e9fc41 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -14,6 +14,8 @@ public: DynamicLayoutHierarchy(ExpressionLayoutArray(operand).array(), 1, cloneOperands) {} DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands = true) : DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2).array(), 2, cloneOperands) {} + DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, const ExpressionLayout * operand3, bool cloneOperands = true) : + DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2, operand3).array(), 3, cloneOperands) {} ~DynamicLayoutHierarchy(); DynamicLayoutHierarchy(const DynamicLayoutHierarchy & other) = delete; DynamicLayoutHierarchy(DynamicLayoutHierarchy && other) = delete; diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index e1b14d0ef..f5838d0f9 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -11,6 +11,8 @@ public: /* Expression to ExpressionLayout */ static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + static ExpressionLayout * createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout); + static ExpressionLayout * createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large); /* Expression to Text */ typedef bool (*OperandNeedsParenthesis)(const Expression * e); diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index ba5fe91c5..954a1aa20 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -13,7 +13,7 @@ public: private: const char * name() const override; int emptySequenceValue() const override; - ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; + ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const override; Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { return templatedApproximateWithNextTerm(a, b); } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 854e59d57..1aae88773 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -13,7 +13,7 @@ public: private: const char * name() const override; int emptySequenceValue() const override; - ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; + ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const override; Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { return templatedApproximateWithNextTerm(a, b); } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 3e1b551da..dc6b050b5 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -1,13 +1,13 @@ #include #include "layout/ceiling_layout.h" +#include +#include #include #include #include -#include extern "C" { #include } -#include namespace Poincare { diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index d4cb71a93..7ba3ac97a 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -1,14 +1,15 @@ #include +#include +#include "layout/horizontal_layout.h" +#include "layout/vertical_offset_layout.h" +#include +#include extern "C" { #include #include #include #include } -#include -#include "layout/editable_string_layout.h" -#include "layout/editable_baseline_relative_layout.h" -#include namespace Poincare { @@ -443,7 +444,7 @@ ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode fl if (std::isnan(r()) || (std::isnan(th()) && r() != 0)) { numberOfCharInBase = convertFloatToText(NAN, bufferBase, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode); - return new EditableStringLayout(bufferBase, numberOfCharInBase); + return LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); } if (r() != 1 || th() == 0) { numberOfCharInBase = convertFloatToText(r(), bufferBase, PrintFloat::k_maxFloatBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode); @@ -463,16 +464,20 @@ ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode fl bufferSuperscript[numberOfCharInSuperscript] = 0; } if (numberOfCharInSuperscript == 0) { - return new EditableStringLayout(bufferBase, numberOfCharInBase); + return LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); } - return new EditableBaselineRelativeLayout(new EditableStringLayout(bufferBase, numberOfCharInBase), new EditableStringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript, false); + ExpressionLayout * result = LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); + ExpressionLayout * exponentLayout = LayoutEngine::createStringLayout(bufferSuperscript, numberOfCharInSuperscript); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(exponentLayout, VerticalOffsetLayout::Type::Superscript, false); + (static_cast(result))->addChildAtIndex(offsetLayout, result->numberOfChildren()); + return result; } template ExpressionLayout * Complex::createCartesianLayout(Expression::FloatDisplayMode floatDisplayMode) const { char buffer[PrintFloat::k_maxComplexBufferLength]; int numberOfChars = convertComplexToText(buffer, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode, Expression::ComplexFormat::Cartesian, Ion::Charset::MiddleDot); - return new EditableStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars); } template class Complex; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 400866c16..4ad75aab4 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -9,8 +9,6 @@ extern "C" { #include } -#include "layout/editable_string_layout.h" - namespace Poincare { int Decimal::exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) { @@ -204,7 +202,7 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); - return new EditableStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars); } Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index da49dabf0..436b91067 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -1,5 +1,5 @@ #include -#include "layout/editable_string_layout.h" +#include "layout/char_layout.h" #include "layout/horizontal_layout.h" #include #include @@ -76,10 +76,10 @@ Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = new EditableStringLayout("!", 1); - return new HorizontalLayout(childrenLayouts, 2, false); + HorizontalLayout * result = new HorizontalLayout(); + result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0); + result->addChildAtIndex(new CharLayout('!'), result->numberOfChildren()); + return result; } int Factorial::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index cb27eb6ef..b35f601ea 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -1,13 +1,13 @@ #include +#include +#include +#include +#include extern "C" { #include #include #include } -#include -#include -#include "layout/editable_string_layout.h" -#include namespace Poincare { @@ -618,7 +618,7 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { ExpressionLayout * Integer::createLayout() const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); - return new EditableStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars); } template float Poincare::Integer::approximate() const; diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 596c838e2..4846a6c6b 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -8,7 +8,6 @@ extern "C" { #include #include } -#include "layout/string_layout.h" #include "layout/integral_layout.h" #include "layout/horizontal_layout.h" @@ -59,10 +58,11 @@ Complex * Integral::templatedApproximate(Context & context, AngleUnit angleUn ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = new StringLayout("dx", 2); - return new IntegralLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2, false), false); + return new IntegralLayout( + operand(0)->createLayout(floatDisplayMode, complexFormat), + operand(1)->createLayout(floatDisplayMode, complexFormat), + operand(2)->createLayout(floatDisplayMode, complexFormat), + false); } template diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index a128948a1..45621b54a 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -1,7 +1,9 @@ #include -#include "layout/string_layout.h" -#include "layout/parenthesis_layout.h" +#include "layout/char_layout.h" #include "layout/horizontal_layout.h" +#include "layout/parenthesis_left_layout.h" +#include "layout/parenthesis_right_layout.h" +#include "layout/string_layout.h" extern "C" { #include } @@ -13,39 +15,56 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression assert(complexFormat != Expression::ComplexFormat::Default); int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); - ExpressionLayout** children_layouts = new ExpressionLayout * [2*numberOfOperands-1]; - children_layouts[0] = expression->operand(0)->createLayout(); - for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + HorizontalLayout * result = new HorizontalLayout(); + result->addOrMergeChildAtIndex(expression->operand(0)->createLayout(), 0); + for (int i = 1; i < numberOfOperands; i++) { + result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result->numberOfChildren()); + result->addOrMergeChildAtIndex( + expression->operand(i)->type() == Expression::Type::Opposite ? + createParenthesedLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : + expression->operand(i)->createLayout(floatDisplayMode, complexFormat), + result->numberOfChildren()); } - /* HorizontalLayout holds the children layouts so they do not need to be - * deleted here. */ - ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1); - delete[] children_layouts; - return layout; + return result; } ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { assert(floatDisplayMode != Expression::FloatDisplayMode::Default); assert(complexFormat != Expression::ComplexFormat::Default); int numberOfOperands = expression->numberOfOperands(); - ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*numberOfOperands-1]; - int layoutIndex = 0; - grandChildrenLayouts[layoutIndex++] = expression->operand(0)->createLayout(floatDisplayMode, complexFormat); + HorizontalLayout * result = new HorizontalLayout(); + + // Add the operator name. + result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0); + + // Create the layout of arguments separated by commas. + HorizontalLayout * args = new HorizontalLayout(); + args->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0); for (int i = 1; i < numberOfOperands; i++) { - grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); - grandChildrenLayouts[layoutIndex++] = expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + args->addChildAtIndex(new CharLayout(','), args->numberOfChildren()); + args->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args->numberOfChildren()); } - /* HorizontalLayout holds the grand children layouts so they do not need to - * be deleted */ - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); - delete [] grandChildrenLayouts; - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout(operatorName, strlen(operatorName)); - childrenLayouts[1] = new ParenthesisLayout(argumentLayouts, false); - /* Same comment as above */ - return new HorizontalLayout(childrenLayouts, 2); + + // Add the parenthesed arguments. + result->addOrMergeChildAtIndex(createParenthesedLayout(args, false), result->numberOfChildren()); + return result; +} + +ExpressionLayout * LayoutEngine::createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize) { + assert(bufferSize > 0); + HorizontalLayout * resultLayout = new HorizontalLayout(); + for (int i = 0; i < bufferSize; i++) { + resultLayout->addChildAtIndex(new CharLayout(buffer[i], fontSize), i); + } + return resultLayout; +} + +ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout) { + HorizontalLayout * result = new HorizontalLayout(); + result->addChildAtIndex(new ParenthesisLeftLayout(), 0); + result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1); + result->addChildAtIndex(new ParenthesisRightLayout(), result->numberOfChildren()); + return result; } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedsParenthesis operandNeedsParenthesis) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index e55a830c5..e8f14dd94 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,25 +1,23 @@ #include -#include -#include -#include +#include "layout/horizontal_layout.h" +#include "layout/vertical_offset_layout.h" #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include #include #include extern "C" { #include #include } -#include "layout/editable_baseline_relative_layout.h" -#include "layout/editable_string_layout.h" -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" namespace Poincare { @@ -236,10 +234,12 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM if (numberOfOperands() == 1) { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new EditableBaselineRelativeLayout(new EditableStringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript, false); - childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); - return new HorizontalLayout(childrenLayouts, 2, false); + HorizontalLayout * result = new HorizontalLayout(); + result->addChildAtIndex(LayoutEngine::createStringLayout("log", strlen("log")), 0); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), VerticalOffsetLayout::Type::Subscript, false); + result->addChildAtIndex(offsetLayout, 1); + result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 2); + return result; } } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 98d420dd6..50d17d3b1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -1,26 +1,22 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include extern "C" { #include #include } -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "layout/string_layout.h" -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" namespace Poincare { diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 6b23eb695..9a4ff62b0 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -8,9 +8,6 @@ extern "C" { } #include #include -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" -#include "layout/string_layout.h" namespace Poincare { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index cda885309..ec0246192 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,16 +1,16 @@ #include +#include "layout/char_layout.h" +#include "layout/horizontal_layout.h" +#include #include +#include #include -#include #include +#include extern "C" { #include #include } -#include -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" -#include "layout/editable_string_layout.h" namespace Poincare { @@ -48,11 +48,14 @@ Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * children_layouts[2]; - char string[2] = {'-', '\0'}; - children_layouts[0] = new EditableStringLayout(string, 1); - children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false) : operand(0)->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(children_layouts, 2, false); + HorizontalLayout * result = new HorizontalLayout(new CharLayout('-'), false); + if (operand(0)->type() == Type::Opposite) { + result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1); + return result; + } + result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1); + return result; + } int Opposite::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 214f7ba08..eabde9d9b 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -1,9 +1,9 @@ +#include + extern "C" { #include #include } -#include -#include "layout/parenthesis_layout.h" namespace Poincare { @@ -20,7 +20,7 @@ Expression * Parenthesis::clone() const { ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); + return LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 3ae0c3b42..0677ca2c3 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -1,27 +1,29 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "layout/horizontal_layout.h" +#include "layout/vertical_offset_layout.h" + extern "C" { #include #include } -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "layout/editable_baseline_relative_layout.h" + namespace Poincare { @@ -121,7 +123,13 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = m_operands[1]->operand(0); } - return new EditableBaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript, false); + return new HorizontalLayout( + m_operands[0]->createLayout(floatDisplayMode, complexFormat), + new VerticalOffsetLayout( + indiceOperand->createLayout(floatDisplayMode, complexFormat), + VerticalOffsetLayout::Type::Superscript, + false), + false); } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index ee896bd98..ab07fbc0d 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -26,8 +26,8 @@ int Product::emptySequenceValue() const { return 1; } -ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { - return new ProductLayout(subscriptLayout, superscriptLayout, argumentLayout, false); +ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const { + return new ProductLayout(argumentLayout, subscriptLayout, superscriptLayout, false); } template diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 0929172f5..8bbaa31f7 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -7,7 +7,6 @@ extern "C" { } #include #include -#include "layout/string_layout.h" #include "layout/fraction_layout.h" namespace Poincare { diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 2aa201dad..b5022f94e 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -1,10 +1,8 @@ #include -#include #include -#include +#include #include -#include "layout/string_layout.h" -#include "layout/horizontal_layout.h" +#include extern "C" { #include #include @@ -16,10 +14,7 @@ namespace Poincare { ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout("n=", 2); - childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); - return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2, false), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); + return createSequenceLayoutWithArgumentLayouts(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat)); } template diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 03d1c90bb..fbfc5b16d 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -7,8 +7,8 @@ extern "C" { #include #include #include +#include "layout/char_layout.h" #include "layout/horizontal_layout.h" -#include "layout/editable_string_layout.h" namespace Poincare { @@ -28,12 +28,11 @@ int Store::writeTextInBuffer(char * buffer, int bufferSize) const { ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * childrenLayouts[3]; - childrenLayouts[0] = value()->createLayout(floatDisplayMode, complexFormat); - const char stoSymbol[2] = {Ion::Charset::Sto, 0}; - childrenLayouts[1] = new EditableStringLayout(stoSymbol, 1); - childrenLayouts[2] = symbol()->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(childrenLayouts, 3, false); + HorizontalLayout * result = new HorizontalLayout(); + result->addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0); + result->addChildAtIndex(new CharLayout(Ion::Charset::Sto), result->numberOfChildren()); + result->addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren()); + return result; } template diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 0d4ef8b45..95dab8d20 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -1,18 +1,14 @@ +#include +#include +#include +#include +#include +#include extern "C" { #include #include } -#include -#include -#include -#include -#include -#include -#include "layout/horizontal_layout.h" -#include "layout/string_layout.h" -#include "layout/parenthesis_layout.h" - namespace Poincare { Expression::Type Subtraction::type() const { diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 0578083e9..fe973047a 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -26,8 +26,8 @@ int Sum::emptySequenceValue() const { return 0; } -ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { - return new SumLayout(subscriptLayout, superscriptLayout, argumentLayout, false); +ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const { + return new SumLayout(argumentLayout, subscriptLayout, superscriptLayout, false); } template diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 5b55e8ffa..7791bb2c5 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -1,9 +1,10 @@ #include -#include #include -#include "layout/baseline_relative_layout.h" -#include "layout/string_layout.h" -#include "layout/editable_string_layout.h" +#include +#include +#include "layout/char_layout.h" +#include "layout/horizontal_layout.h" +#include "layout/vertical_offset_layout.h" #include extern "C" { #include @@ -132,25 +133,49 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); if (m_name == SpecialSymbols::Ans) { - return new EditableStringLayout("ans", 3); + return LayoutEngine::createStringLayout("ans", 3); } if (m_name == SpecialSymbols::un) { - return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); + return new HorizontalLayout( + new CharLayout('u'), + new VerticalOffsetLayout( + new CharLayout('n', KDText::FontSize::Small), + VerticalOffsetLayout::Type::Subscript, + false), + false); } if (m_name == SpecialSymbols::un1) { - return new BaselineRelativeLayout(new StringLayout("u", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); + return new HorizontalLayout( + new CharLayout('u'), + new VerticalOffsetLayout( + LayoutEngine::createStringLayout("n+1", 3, KDText::FontSize::Small), + VerticalOffsetLayout::Type::Subscript, + false), + false); } if (m_name == SpecialSymbols::vn) { - return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n",1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); + return new HorizontalLayout( + new CharLayout('v'), + new VerticalOffsetLayout( + new CharLayout('n', KDText::FontSize::Small), + VerticalOffsetLayout::Type::Subscript, + false), + false); } if (m_name == SpecialSymbols::vn1) { - return new BaselineRelativeLayout(new StringLayout("v", 1), new StringLayout("n+1",3, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript, false); + return new HorizontalLayout( + new CharLayout('v'), + new VerticalOffsetLayout( + LayoutEngine::createStringLayout("n+1", 3, KDText::FontSize::Small), + VerticalOffsetLayout::Type::Subscript, + false), + false); } if (isMatrixSymbol()) { const char mi[] = { 'M', (char)(m_name-(char)SpecialSymbols::M0+'0') }; - return new EditableStringLayout(mi, sizeof(mi)); + return LayoutEngine::createStringLayout(mi, sizeof(mi)); } - return new EditableStringLayout(&m_name, 1); + return LayoutEngine::createStringLayout(&m_name, 1); } int Symbol::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 36b55ff15..d08a811c6 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -1,8 +1,10 @@ #include +#include + extern "C" { #include +#include } -#include "layout/editable_string_layout.h" namespace Poincare { @@ -21,7 +23,7 @@ template Complex * Undefined::templatedApproximate(Context& conte ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { char buffer[16]; int numberOfChars = Complex::convertFloatToText(NAN, buffer, 16, 1, floatDisplayMode); - return new EditableStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars); } int Undefined::writeTextInBuffer(char * buffer, int bufferSize) const { From dadcd83924e2f247699e7b2739aa9eaa53d81640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 15:02:08 +0100 Subject: [PATCH 118/459] [poincare] Remove uses of outdated layouts, such as StringLayout. Change-Id: I55bb846371c224f8f2e739b759725b0e02759ebd --- apps/expression_editor/expression_and_layout.cpp | 1 - poincare/include/poincare_layouts.h | 6 ------ poincare/src/layout/expression_layout.cpp | 8 ++++---- poincare/src/layout/horizontal_layout.cpp | 2 -- poincare/src/layout/integral_layout.cpp | 3 +-- poincare/src/layout_engine.cpp | 1 - 6 files changed, 5 insertions(+), 16 deletions(-) diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp index 3616751a4..36f09fcfb 100644 --- a/apps/expression_editor/expression_and_layout.cpp +++ b/apps/expression_editor/expression_and_layout.cpp @@ -1,6 +1,5 @@ #include "expression_and_layout.h" #include -#include #include namespace ExpressionEditor { diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index b06cc8993..34191f18d 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -11,9 +10,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -26,9 +22,7 @@ #include #include #include -#include #include -#include #include #endif diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 845ab35fd..395194d39 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,9 +1,9 @@ +#include +#include "empty_visible_layout.h" +#include "horizontal_layout.h" +#include #include #include -#include -#include -#include -#include #include namespace Poincare { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 4af8b824f..24ebff1c3 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,8 +1,6 @@ #include "horizontal_layout.h" #include "empty_visible_layout.h" -#include "string_layout.h" #include - extern "C" { #include #include diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index dfdae4e2d..392525b16 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -1,7 +1,6 @@ #include "integral_layout.h" #include "char_layout.h" #include "horizontal_layout.h" -#include "string_layout.h" #include #include #include @@ -245,7 +244,7 @@ void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, } KDSize IntegralLayout::computeSize() { - KDSize dxSize = StringLayout("dx", 2).size(); + KDSize dxSize = HorizontalLayout(new CharLayout('d'), new CharLayout('x'), false).size(); KDSize integrandSize = integrandLayout()->size(); KDSize lowerBoundSize = lowerBoundLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 45621b54a..14a1f14f7 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -3,7 +3,6 @@ #include "layout/horizontal_layout.h" #include "layout/parenthesis_left_layout.h" #include "layout/parenthesis_right_layout.h" -#include "layout/string_layout.h" extern "C" { #include } From 36064eff59cc29d2dbdf0e5093add3e9c7513c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 15:00:49 +0100 Subject: [PATCH 119/459] [poincare] Remove outdated layouts, such as StringLayout. Change-Id: I351113cd9a14a1c48896ac9f56153a8513d36a16 --- poincare/Makefile | 7 - .../src/layout/baseline_relative_layout.cpp | 134 ---------- .../src/layout/baseline_relative_layout.h | 34 --- .../editable_baseline_relative_layout.cpp | 244 ------------------ .../editable_baseline_relative_layout.h | 21 -- .../src/layout/editable_string_layout.cpp | 122 --------- poincare/src/layout/editable_string_layout.h | 27 -- poincare/src/layout/string_layout.cpp | 121 --------- poincare/src/layout/string_layout.h | 37 --- .../uneditable_horizontal_trio_layout.cpp | 193 -------------- .../uneditable_horizontal_trio_layout.h | 48 ---- .../uneditable_parenthesis_left_layout.cpp | 33 --- .../uneditable_parenthesis_left_layout.h | 18 -- .../uneditable_parenthesis_right_layout.cpp | 33 --- .../uneditable_parenthesis_right_layout.h | 18 -- 15 files changed, 1090 deletions(-) delete mode 100644 poincare/src/layout/baseline_relative_layout.cpp delete mode 100644 poincare/src/layout/baseline_relative_layout.h delete mode 100644 poincare/src/layout/editable_baseline_relative_layout.cpp delete mode 100644 poincare/src/layout/editable_baseline_relative_layout.h delete mode 100644 poincare/src/layout/editable_string_layout.cpp delete mode 100644 poincare/src/layout/editable_string_layout.h delete mode 100644 poincare/src/layout/string_layout.cpp delete mode 100644 poincare/src/layout/string_layout.h delete mode 100644 poincare/src/layout/uneditable_horizontal_trio_layout.cpp delete mode 100644 poincare/src/layout/uneditable_horizontal_trio_layout.h delete mode 100644 poincare/src/layout/uneditable_parenthesis_left_layout.cpp delete mode 100644 poincare/src/layout/uneditable_parenthesis_left_layout.h delete mode 100644 poincare/src/layout/uneditable_parenthesis_right_layout.cpp delete mode 100644 poincare/src/layout/uneditable_parenthesis_right_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index 976ffb545..f9828e5fe 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -84,7 +84,6 @@ objs += $(addprefix poincare/src/,\ objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ - baseline_relative_layout.o\ bracket_layout.o\ bracket_left_layout.o\ bracket_left_right_layout.o\ @@ -94,8 +93,6 @@ objs += $(addprefix poincare/src/layout/,\ condensed_sum_layout.o\ conjugate_layout.o\ dynamic_layout_hierarchy.o\ - editable_baseline_relative_layout.o\ - editable_string_layout.o\ empty_layout.o\ empty_visible_layout.o\ expression_layout.o\ @@ -112,11 +109,7 @@ objs += $(addprefix poincare/src/layout/,\ product_layout.o\ sequence_layout.o\ static_layout_hierarchy.o\ - string_layout.o\ sum_layout.o\ - uneditable_horizontal_trio_layout.o\ - uneditable_parenthesis_left_layout.o\ - uneditable_parenthesis_right_layout.o\ vertical_offset_layout.o\ ) diff --git a/poincare/src/layout/baseline_relative_layout.cpp b/poincare/src/layout/baseline_relative_layout.cpp deleted file mode 100644 index 824c1c286..000000000 --- a/poincare/src/layout/baseline_relative_layout.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "baseline_relative_layout.h" -#include "empty_visible_layout.h" -#include -#include -#include -#include - -namespace Poincare { - -BaselineRelativeLayout::BaselineRelativeLayout(ExpressionLayout * base, ExpressionLayout * indice, Type type, bool cloneOperands) : - StaticLayoutHierarchy(base, indice, cloneOperands), - m_type(type) -{ -} - -ExpressionLayout * BaselineRelativeLayout::clone() const { - BaselineRelativeLayout * layout = new BaselineRelativeLayout(const_cast(this)->baseLayout(), const_cast(this)->indiceLayout(), m_type, true); - return layout; -} - -void BaselineRelativeLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == indiceLayout() - || (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right)) - { - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(new EmptyVisibleLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(previousParent); - return; - } - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - ExpressionLayout::backspaceAtCursor(cursor); -} - -bool BaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Left. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool BaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - // Case: Right. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -int BaselineRelativeLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - if (m_type == Type::Subscript) { - if (bufferSize == 0) { - return -1; - } - buffer[bufferSize-1] = 0; - if (bufferSize == 1) { - return 0; - } - int numberOfChars = LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "_{"); - if (numberOfChars < bufferSize - 1) { - //FIXME what if the buffer is not big enough? - buffer[numberOfChars++] = '}'; - buffer[numberOfChars] = 0; - } - return numberOfChars; - } - assert(m_type == Type::Superscript); - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); -} - -ExpressionLayout * BaselineRelativeLayout::baseLayout() { - return editableChild(0); -} - -ExpressionLayout * BaselineRelativeLayout::indiceLayout() { - return editableChild(1); -} - -void BaselineRelativeLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - // There is nothing to draw for a subscript/superscript, only the position of the children matters -} - -KDSize BaselineRelativeLayout::computeSize() { - KDSize baseSize = baseLayout()->size(); - KDSize indiceSize = indiceLayout()->size(); - return KDSize(baseSize.width() + indiceSize.width(), baseSize.height() + indiceSize.height() - k_indiceHeight); -} - -void BaselineRelativeLayout::computeBaseline() { - m_baseline = m_type == Type::Subscript ? baseLayout()->baseline() : - indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; - m_baselined = true; -} - -KDPoint BaselineRelativeLayout::positionOfChild(ExpressionLayout * child) { - KDCoordinate x = 0; - KDCoordinate y = 0; - if (child == baseLayout() && m_type == Type::Superscript) { - x = 0; - y = indiceLayout()->size().height() - k_indiceHeight; - } - if (child == indiceLayout()) { - x = baseLayout()->size().width(); - y = m_type == Type::Superscript ? 0 : baseLayout()->size().height() - k_indiceHeight; - } - return KDPoint(x,y); -} - -} - diff --git a/poincare/src/layout/baseline_relative_layout.h b/poincare/src/layout/baseline_relative_layout.h deleted file mode 100644 index 184f808a6..000000000 --- a/poincare/src/layout/baseline_relative_layout.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef POINCARE_BASELINE_RELATIVE_LAYOUT_H -#define POINCARE_BASELINE_RELATIVE_LAYOUT_H - -#include - -namespace Poincare { - -class BaselineRelativeLayout : public StaticLayoutHierarchy<2> { -public: - enum class Type { - Subscript, - Superscript - }; - BaselineRelativeLayout(ExpressionLayout * base, ExpressionLayout * indice, Type type, bool cloneOperands); - ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; -protected: - ExpressionLayout * baseLayout(); - ExpressionLayout * indiceLayout(); - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDSize computeSize() override; - void computeBaseline() override; - KDPoint positionOfChild(ExpressionLayout * child) override; - Type m_type; -private: - constexpr static KDCoordinate k_indiceHeight = 5; -}; - -} - -#endif diff --git a/poincare/src/layout/editable_baseline_relative_layout.cpp b/poincare/src/layout/editable_baseline_relative_layout.cpp deleted file mode 100644 index 9e72033d1..000000000 --- a/poincare/src/layout/editable_baseline_relative_layout.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "editable_baseline_relative_layout.h" -#include "empty_visible_layout.h" -#include -#include -#include - -namespace Poincare { - -ExpressionLayout * EditableBaselineRelativeLayout::clone() const { - EditableBaselineRelativeLayout * layout = new EditableBaselineRelativeLayout(const_cast(this)->baseLayout(), const_cast(this)->indiceLayout(), m_type, true); - return layout; -} - -void EditableBaselineRelativeLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == indiceLayout()) { - if (m_type == Type::Superscript) { - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - ExpressionLayout * base = baseLayout(); - ExpressionLayout * pointedLayout = base; - if (base->isHorizontal()) { - pointedLayout = base->editableChild(base->numberOfChildren()-1); - } - if (indiceLayout()->isEmpty()) { - if (baseLayout()->isEmpty()) { - // Case: Empty base and indice. - // Replace with an empty layout. - int indexInParent = m_parent->indexOfChild(this); - if (indexInParent == 0) { - pointedLayout = m_parent; - replaceWith(base, true); - cursor->setPointedExpressionLayout(pointedLayout); - return; - } - pointedLayout = m_parent->editableChild(indexInParent - 1); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - replaceWith(base, true); - cursor->setPointedExpressionLayout(pointedLayout); - return; - } - // Case: Empty indice only. - // Replace with the base. - replaceWith(base, true); - cursor->setPointedExpressionLayout(pointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Case: Non-empty indice. - // Move to the base. - cursor->setPointedExpressionLayout(pointedLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - assert(m_type == Type::Subscript); - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(new EmptyVisibleLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(previousParent); - return; - } - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - ExpressionLayout::backspaceAtCursor(cursor); -} - -bool EditableBaselineRelativeLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // Case: Left of the indice. - // Go from the indice to the base. - if (indiceLayout() - && cursor->pointedExpressionLayout() == indiceLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - assert(baseLayout() != nullptr); - cursor->setPointedExpressionLayout(baseLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - // Case: Left of the base. - // Ask the parent. - if (baseLayout() - && cursor->pointedExpressionLayout() == baseLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the indice. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - return true; - } - // Case: Left. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool EditableBaselineRelativeLayout::moveRight(ExpressionLayoutCursor * cursor) { - // Case: Right of the base. - // Go from the base to the indice. - if (baseLayout() - && cursor->pointedExpressionLayout() == baseLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Right of the indice. - // Go Right. - if (indiceLayout() - && cursor->pointedExpressionLayout() == indiceLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - cursor->setPointedExpressionLayout(this); - return true; - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the base and move Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(baseLayout() != nullptr); - cursor->setPointedExpressionLayout(baseLayout()); - return baseLayout()->moveRight(cursor); - } - // Case: Right. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - cursor->setPointedExpressionLayout(this); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -bool EditableBaselineRelativeLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - // If the baseline is a superscript: - if (m_type == BaselineRelativeLayout::Type::Superscript) { - // If the cursor is Right of the base layout, move it to the indice. - if (baseLayout() - && previousLayout == baseLayout() - && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Right)) - { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - cursor->setPositionInside(0); - return true; - } - // If the cursor is Right, move it to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - } - // If the baseline is a subscript: - if (m_type == BaselineRelativeLayout::Type::Subscript - && indiceLayout() - && previousLayout == indiceLayout()) - { - // If the cursor is Left of the indice layout, move it to the base. - if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(baseLayout() != nullptr); - cursor->setPointedExpressionLayout(baseLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - // If the cursor is Right of the indice layout, move it Right. - if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right)) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); -} - -bool EditableBaselineRelativeLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - // If the baseline is a subscript: - if (m_type == BaselineRelativeLayout::Type::Subscript) { - // If the cursor is Right of the base layout, move it to the indice. - if (baseLayout() - && previousLayout == baseLayout() - && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Right)) - { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - cursor->setPositionInside(0); - return true; - } - // If the cursor is Right, move it to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - } - // If the baseline is a superscript: - if (m_type == BaselineRelativeLayout::Type::Superscript - && indiceLayout() - && previousLayout == indiceLayout()) - { - // If the cursor is Left of the indice layout, move it to the base. - if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(baseLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - // If the cursor is Right of the indice layout, move it Right. - if (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right)) { - assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); - return true; - } - } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); -} - -} - diff --git a/poincare/src/layout/editable_baseline_relative_layout.h b/poincare/src/layout/editable_baseline_relative_layout.h deleted file mode 100644 index af60ba3b9..000000000 --- a/poincare/src/layout/editable_baseline_relative_layout.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef POINCARE_EDITABLE_BASELINE_RELATIVE_LAYOUT_H -#define POINCARE_EDITABLE_BASELINE_RELATIVE_LAYOUT_H - -#include "baseline_relative_layout.h" - -namespace Poincare { - -class EditableBaselineRelativeLayout : public BaselineRelativeLayout { -public: - using BaselineRelativeLayout::BaselineRelativeLayout; - ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; -}; - -} - -#endif diff --git a/poincare/src/layout/editable_string_layout.cpp b/poincare/src/layout/editable_string_layout.cpp deleted file mode 100644 index 951989192..000000000 --- a/poincare/src/layout/editable_string_layout.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "editable_string_layout.h" -#include -#include -#include - -namespace Poincare { - -ExpressionLayout * EditableStringLayout::clone() const { - EditableStringLayout * layout = new EditableStringLayout(m_string, strlen(m_string), m_fontSize); - return layout; -} - -bool EditableStringLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go before the last char. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - size_t stringLength = strlen(m_string); - if (stringLength > 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Inside); - cursor->setPositionInside(stringLength - 1); - return true; - } - if (stringLength == 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - assert(stringLength == 0); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } - // Case: Inside. - // Go one char left. - if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { - int cursorIndex = cursor->positionInside(); - assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); - if (cursorIndex == 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - cursor->setPositionInside(cursorIndex - 1); - return true; - } - // Case: Left. - // Ask the parent. - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool EditableStringLayout::moveRight(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go after the first char. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - size_t stringLength = strlen(m_string); - if (stringLength > 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Inside); - cursor->setPositionInside(1); - return true; - } - if (stringLength == 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - assert(stringLength == 0); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; - } - // Case: Inside. - // Go one char right. - if (cursor->position() == ExpressionLayoutCursor::Position::Inside) { - int cursorIndex = cursor->positionInside(); - assert(cursorIndex > 0 && cursorIndex < strlen(m_string)); - if (cursorIndex == strlen(m_string)-1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - cursor->setPositionInside(cursorIndex + 1); - return true; - } - // Case: Right. - // Ask the parent. - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -void EditableStringLayout::moveCursorInsideAtDirection ( - VerticalDirection direction, - ExpressionLayoutCursor * cursor, - ExpressionLayout ** childResult, - void * resultPosition, - int * resultPositionInside, - int * resultScore) -{ - ExpressionLayout::moveCursorInsideAtDirection(direction, cursor, childResult, resultPosition, resultPositionInside, resultScore); - ExpressionLayoutCursor::Position * castedResultPosition = static_cast(resultPosition); - // Check the distance to Inside cursors. - size_t stringLength = strlen(m_string); - int currentDistance = 0; - KDPoint cursorMiddleLeft = cursor->middleLeftPoint(); - for (int i = 1; i < stringLength; i++) { - currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Inside, i).squareDistanceTo(cursorMiddleLeft); - if (currentDistance < *resultScore) { - *childResult = this; - *castedResultPosition = ExpressionLayoutCursor::Position::Inside; - *resultPositionInside = i; - *resultScore = currentDistance; - } - } -} - -} diff --git a/poincare/src/layout/editable_string_layout.h b/poincare/src/layout/editable_string_layout.h deleted file mode 100644 index 147cb1622..000000000 --- a/poincare/src/layout/editable_string_layout.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef POINCARE_EDITABLE_STRING_LAYOUT_H -#define POINCARE_EDITABLE_STRING_LAYOUT_H - -#include "string_layout.h" -#include - -namespace Poincare { - -class EditableStringLayout : public StringLayout { -public: - using StringLayout::StringLayout; - ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; -private: - void moveCursorInsideAtDirection ( - VerticalDirection direction, - ExpressionLayoutCursor * cursor, - ExpressionLayout ** childResult, - void * resultPosition, - int * resultPositionInside, - int * resultScore) override; -}; - -} - -#endif diff --git a/poincare/src/layout/string_layout.cpp b/poincare/src/layout/string_layout.cpp deleted file mode 100644 index af1ec891f..000000000 --- a/poincare/src/layout/string_layout.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "string_layout.h" -#include -#include -#include - -namespace Poincare { - -StringLayout::StringLayout(const char * string, size_t length, KDText::FontSize fontSize) : - StaticLayoutHierarchy<0>(), - m_fontSize(fontSize) -{ - m_string = new char[length+1]; - memcpy(m_string, string, length); - m_string[length] = 0; -} - -StringLayout::~StringLayout() { - delete[] m_string; -} - -ExpressionLayout * StringLayout::clone() const { - StringLayout * layout = new StringLayout(m_string, strlen(m_string), m_fontSize); - return layout; -} - -void StringLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - m_parent->backspaceAtCursor(cursor); -} - -bool StringLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // A StringLayout is not editable, and the cursor cannot go inside it. - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // If there is a Left brother, go Right of it. Else go Left of the - // grandparent. We need to do this to avoid adding text left or right of a - // string layout, for instance left of "n=" in a Sum layout. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - int indexOfThis = m_parent->indexOfChild(this); - if (indexOfThis > 0) { - cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis-1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - cursor->setPointedExpressionLayout(m_parent); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Left. - // Ask the parent. - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool StringLayout::moveRight(ExpressionLayoutCursor * cursor) { - // A StringLayout is not editable, and the cursor cannot go inside it. - assert(cursor->pointedExpressionLayout() == this); - assert(m_parent != nullptr); - // Case: Left. - // If there is a Right brother, go Left of it. Else go Right of the - // grandparent. We need to do this to avoid adding text left or right of a - // string layout, for instance right of "dx" in an integral layout. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - int indexOfThis = m_parent->indexOfChild(this); - if (m_parent->editableChild(indexOfThis+1) != nullptr) { - cursor->setPointedExpressionLayout(m_parent->editableChild(indexOfThis+1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - if (m_parent->parent()) { - cursor->setPointedExpressionLayout(const_cast(m_parent->parent())); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - } - // Case: Right. - // Ask the parent. - return m_parent->moveRight(cursor); -} - -int StringLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - if (bufferSize == 0) { - return -1; - } - buffer[bufferSize-1] = 0; - int numberOfChar = strlcpy(buffer, m_string, bufferSize); - if (numberOfChar >= bufferSize-1) { - return bufferSize-1; - } - - buffer[numberOfChar] = 0; - return numberOfChar; -} - -void StringLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - ctx->drawString(m_string, p, m_fontSize, expressionColor, backgroundColor); -} - -KDPoint StringLayout::positionOfChild(ExpressionLayout * child) { - assert(false); // We should never be here - return KDPointZero; -} - -KDSize StringLayout::computeSize() { - return KDText::stringSize(m_string, m_fontSize); -} - -void StringLayout::computeBaseline() { - // Half height of the font. - m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; - m_baselined = true; -} - -} diff --git a/poincare/src/layout/string_layout.h b/poincare/src/layout/string_layout.h deleted file mode 100644 index 8ba55f65e..000000000 --- a/poincare/src/layout/string_layout.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef POINCARE_STRING_LAYOUT_H -#define POINCARE_STRING_LAYOUT_H - -#include -#include -#include - -namespace Poincare { - -class StringLayout : public StaticLayoutHierarchy<0> { -public: - StringLayout(const char * string, size_t length, KDText::FontSize fontSize = KDText::FontSize::Large); - ~StringLayout(); - StringLayout(const StringLayout& other) = delete; - StringLayout(StringLayout&& other) = delete; - StringLayout& operator=(const StringLayout& other) = delete; - StringLayout& operator=(StringLayout&& other) = delete; - ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - - char * text() { return m_string; } - KDText::FontSize fontSize() { return m_fontSize; } - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; -protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDPoint positionOfChild(ExpressionLayout * child) override; - KDSize computeSize() override; - void computeBaseline() override; - char * m_string; - KDText::FontSize m_fontSize; -}; - -} - -#endif diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp b/poincare/src/layout/uneditable_horizontal_trio_layout.cpp deleted file mode 100644 index ea8ff521d..000000000 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include "uneditable_horizontal_trio_layout.h" -#include "empty_visible_layout.h" -#include -extern "C" { -#include -} - -namespace Poincare { - -UneditableHorizontalTrioLayout::UneditableHorizontalTrioLayout(ExpressionLayout * left, ExpressionLayout * central, ExpressionLayout * right, bool cloneOperands, bool cursorAllowedLeftAndRight) : - StaticLayoutHierarchy(left, central, right, cloneOperands), - m_cursorCanBeLeftOrRight(cursorAllowedLeftAndRight) -{ -} - -ExpressionLayout * UneditableHorizontalTrioLayout::clone() const { - UneditableHorizontalTrioLayout * layout = new UneditableHorizontalTrioLayout( - const_cast(this)->leftLayout(), - const_cast(this)->centerLayout(), - const_cast(this)->rightLayout(), - true, m_cursorCanBeLeftOrRight); - return layout; -} - -void UneditableHorizontalTrioLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the center layout (for sequence layouts). - if (cursor->pointedExpressionLayout() == centerLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - ExpressionLayout * grandParent = const_cast(m_parent->parent()); - assert(grandParent != nullptr); - ExpressionLayout * parent = m_parent; - int indexInGrandParent = grandParent->indexOfChild(parent); - parent->replaceWith(centerLayout(), true); - // Place the cursor on the right of the left brother of the integral if - // there is one. - if (indexInGrandParent > 0) { - cursor->setPointedExpressionLayout(grandParent->editableChild(indexInGrandParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(grandParent); - return; - } - // Case: Right. - // Move to the argument. - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Go Right of the center layout's last child if it has one, else go Right - // of the center layout. - if (centerLayout()->numberOfChildren() > 1) { - cursor->setPointedExpressionLayout(centerLayout()->editableChild(centerLayout()->numberOfChildren()-1)); - return; - } - cursor->setPointedExpressionLayout(centerLayout()); - return; - } - ExpressionLayout::backspaceAtCursor(cursor); -} - -bool UneditableHorizontalTrioLayout::moveLeft(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == centerLayout()) { - // Case: Center layout. - // Go Left. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - cursor->setPointedExpressionLayout(this); - if (m_cursorCanBeLeftOrRight) { - return true; - } - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - // Case: Right. - // Go Right of the center layout's last child if it has one, else go Right - // of the center layout. - if (centerLayout()->numberOfChildren() > 1) { - cursor->setPointedExpressionLayout(centerLayout()->editableChild(centerLayout()->numberOfChildren()-1)); - return true; - } - cursor->setPointedExpressionLayout(centerLayout()); - return true; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool UneditableHorizontalTrioLayout::moveRight(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == centerLayout()) { - // Case: Center layout. - // Go Right. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - cursor->setPointedExpressionLayout(this); - if (m_cursorCanBeLeftOrRight) { - return true; - } - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; - } - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - // Case: Left. - // Go Left of the center layout's first child if it has one, else go Left of - // the center layout. - ExpressionLayout * grandChild = centerLayout()->editableChild(0); - if (grandChild != nullptr) { - cursor->setPointedExpressionLayout(grandChild); - return true; - } - cursor->setPointedExpressionLayout(centerLayout()); - return true; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -void UneditableHorizontalTrioLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { -} - -KDSize UneditableHorizontalTrioLayout::computeSize() { - // TODO: This code is duplicated from horizontal_layout.cpp. - KDCoordinate totalWidth = 0; - int i = 0; - KDCoordinate max_under_baseline = 0; - KDCoordinate max_above_baseline = 0; - while (ExpressionLayout * c = editableChild(i++)) { - KDSize childSize = c->size(); - totalWidth += childSize.width(); - if (childSize.height() - c->baseline() > max_under_baseline) { - max_under_baseline = childSize.height() - c->baseline() ; - } - if (c->baseline() > max_above_baseline) { - max_above_baseline = c->baseline(); - } - } - return KDSize(totalWidth, max_under_baseline + max_above_baseline); -} - -void UneditableHorizontalTrioLayout::computeBaseline() { - // TODO: This code is duplicated from horizontal_layout.cpp. - m_baseline = 0; - for (int i = 0; i < numberOfChildren(); i++) { - if (editableChild(i)->baseline() > m_baseline) { - m_baseline = editableChild(i)->baseline(); - } - } - m_baselined = true; -} - -KDPoint UneditableHorizontalTrioLayout::positionOfChild(ExpressionLayout * child) { - // TODO: This code is duplicated from horizontal_layout.cpp. - KDCoordinate x = 0; - KDCoordinate y = 0; - int index = indexOfChild(child); - if (index > 0) { - ExpressionLayout * previousChild = editableChild(index-1); - assert(previousChild != nullptr); - x = previousChild->origin().x() + previousChild->size().width(); - } - y = baseline() - child->baseline(); - return KDPoint(x, y); -} - -ExpressionLayout * UneditableHorizontalTrioLayout::leftLayout() { - return editableChild(0); -} - -ExpressionLayout * UneditableHorizontalTrioLayout::centerLayout() { - return editableChild(1); -} - -ExpressionLayout * UneditableHorizontalTrioLayout::rightLayout() { - return editableChild(2); -} - -} diff --git a/poincare/src/layout/uneditable_horizontal_trio_layout.h b/poincare/src/layout/uneditable_horizontal_trio_layout.h deleted file mode 100644 index 484947dd5..000000000 --- a/poincare/src/layout/uneditable_horizontal_trio_layout.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H -#define POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H - -#include -#include - -namespace Poincare { - -/* UneditableHorizontalTrioLayout has 3 children: a left and a right layout - * (usually parentheses or brackets), and a central layout. - * The cursor can only be: - * - Left or Right of the UneditableHorizontalTrioLayout, - * - Left or Right of the central layout if it is not an horizontal layout, - * - Inside the central layout if it is an horizontal layout. - * This way, the lateral children of an UneditableHorizontalTrioLayout cannot be - * edited, and it it will always have only 3 children. - * This layout can be used to create binomial coefficient layouts, matrix - * layouts or the argument of sum and product layouts. */ - -class UneditableHorizontalTrioLayout : public StaticLayoutHierarchy<3> { -public: - UneditableHorizontalTrioLayout(ExpressionLayout * left, ExpressionLayout * central, ExpressionLayout * right, bool cloneOperands, bool cursorAllowedLeftAndRight); - ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - - /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - - /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); - } -protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDSize computeSize() override; - void computeBaseline() override; - KDPoint positionOfChild(ExpressionLayout * child) override; -private: - ExpressionLayout * leftLayout(); - ExpressionLayout * centerLayout(); - ExpressionLayout * rightLayout(); - bool m_cursorCanBeLeftOrRight; -}; - -} - -#endif diff --git a/poincare/src/layout/uneditable_parenthesis_left_layout.cpp b/poincare/src/layout/uneditable_parenthesis_left_layout.cpp deleted file mode 100644 index 5281934ee..000000000 --- a/poincare/src/layout/uneditable_parenthesis_left_layout.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "uneditable_parenthesis_left_layout.h" -#include -extern "C" { -#include -} - -namespace Poincare { - -ExpressionLayout * UneditableParenthesisLeftLayout::clone() const { - return new UneditableParenthesisLeftLayout(); -} - -bool UneditableParenthesisLeftLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_parent->moveLeft(cursor); - } - return false; -} - -bool UneditableParenthesisLeftLayout::moveRight(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_parent->moveRight(cursor); - } - return false; -} - -} diff --git a/poincare/src/layout/uneditable_parenthesis_left_layout.h b/poincare/src/layout/uneditable_parenthesis_left_layout.h deleted file mode 100644 index b3b693330..000000000 --- a/poincare/src/layout/uneditable_parenthesis_left_layout.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_UNEDITABLE_PARENTHESIS_LEFT_LAYOUT_H -#define POINCARE_UNEDITABLE_PARENTHESIS_LEFT_LAYOUT_H - -#include - -namespace Poincare { - -class UneditableParenthesisLeftLayout : public ParenthesisLeftLayout { -public: - using ParenthesisLeftLayout::ParenthesisLeftLayout; - ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; -}; - -} - -#endif diff --git a/poincare/src/layout/uneditable_parenthesis_right_layout.cpp b/poincare/src/layout/uneditable_parenthesis_right_layout.cpp deleted file mode 100644 index bba558231..000000000 --- a/poincare/src/layout/uneditable_parenthesis_right_layout.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "uneditable_parenthesis_right_layout.h" -#include -extern "C" { -#include -} - -namespace Poincare { - -ExpressionLayout * UneditableParenthesisRightLayout::clone() const { - return new UneditableParenthesisRightLayout(); -} - -bool UneditableParenthesisRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_parent->moveLeft(cursor); - } - return false; -} - -bool UneditableParenthesisRightLayout::moveRight(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_parent->moveRight(cursor); - } - return false; -} - -} diff --git a/poincare/src/layout/uneditable_parenthesis_right_layout.h b/poincare/src/layout/uneditable_parenthesis_right_layout.h deleted file mode 100644 index 2025f4a25..000000000 --- a/poincare/src/layout/uneditable_parenthesis_right_layout.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_UNEDITABLE_PARENTHESIS_RIGHT_LAYOUT_H -#define POINCARE_UNEDITABLE_PARENTHESIS_RIGHT_LAYOUT_H - -#include - -namespace Poincare { - -class UneditableParenthesisRightLayout : public ParenthesisRightLayout { -public: - using ParenthesisRightLayout::ParenthesisRightLayout; - ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; -}; - -} - -#endif From 6526a82c1761711eeb15789c3b3fd8123cab5cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 15:11:58 +0100 Subject: [PATCH 120/459] [poincare] No "Inside" position for ExpressionLayoutCursor. Change-Id: Id979c372bb2c4acf8f8708380c7d1f2aeeb5ff06 --- apps/expression_editor/controller.cpp | 3 --- .../expression_view_with_cursor.cpp | 2 -- poincare/include/poincare/expression_layout.h | 3 +-- .../include/poincare/expression_layout_cursor.h | 11 +++-------- poincare/src/expression_layout_cursor.cpp | 15 ++++++--------- poincare/src/layout/expression_layout.cpp | 13 ++++--------- poincare/src/layout/nth_root_layout.cpp | 4 ---- 7 files changed, 14 insertions(+), 37 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 2df023056..052815e49 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -52,7 +52,6 @@ void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayou m_cursor.addLayout(layout); m_cursor.setPointedExpressionLayout(pointedLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - m_cursor.setPositionInside(0); m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.cursorPositionChanged(); } @@ -92,13 +91,11 @@ bool Controller::handleMoveEvent(Ion::Events::Event event) { // The cursor should never point to the main HorizontalLayout. m_cursor.setPointedExpressionLayout(m_expressionLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Left); - m_cursor.setPositionInside(0); return true; } if (event == Ion::Events::ShiftRight) { m_cursor.setPointedExpressionLayout(m_expressionLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - m_cursor.setPositionInside(0); return true; } return false; diff --git a/apps/expression_editor/expression_view_with_cursor.cpp b/apps/expression_editor/expression_view_with_cursor.cpp index 3f501434a..716d23492 100644 --- a/apps/expression_editor/expression_view_with_cursor.cpp +++ b/apps/expression_editor/expression_view_with_cursor.cpp @@ -41,8 +41,6 @@ void ExpressionViewWithCursor::layoutCursorSubview() { KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); if (m_cursor->position() == ExpressionLayoutCursor::Position::Right) { cursorX += m_cursor->pointedExpressionLayout()->size().width(); - } else if (m_cursor->position() == ExpressionLayoutCursor::Position::Inside) { - cursorX += m_cursor->positionInside() * KDText::charSize().width(); } KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor->pointedExpressionLayout()->baseline()-m_cursor->cursorHeight()/2); m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor->cursorHeight())); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 1277db657..c06f89633 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -87,12 +87,11 @@ protected: virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; void detachChildAtIndex(int i); - virtual void moveCursorInsideAtDirection ( + void moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout ** childResult, void * resultPosition, - int * resultPositionInside, int * resultScore); KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index e6c5e9f71..76b335f1c 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -10,14 +10,12 @@ class ExpressionLayoutCursor { public: enum class Position { Left, - Inside, Right }; ExpressionLayoutCursor() : m_pointedExpressionLayout(nullptr), - m_position(Position::Right), - m_positionInside(0) + m_position(Position::Right) {}; /* Getters and setters */ @@ -25,16 +23,14 @@ public: void setPointedExpressionLayout(ExpressionLayout * expressionLayout) { m_pointedExpressionLayout = expressionLayout; } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } - int positionInside() const { return m_positionInside; } - void setPositionInside(int positionInside) { m_positionInside = positionInside; } KDCoordinate cursorHeight() const { return k_cursorHeight; } /* Comparison */ - bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex = 0); + bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position); /* Position */ KDPoint middleLeftPoint(); - KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position, int positionInside = 0); + KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position); /* Move */ bool moveLeft(); @@ -58,7 +54,6 @@ private: constexpr static KDCoordinate k_cursorHeight = 18; ExpressionLayout * m_pointedExpressionLayout; Position m_position; - int m_positionInside; }; } diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 2007824ab..c8fac396b 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -6,26 +6,23 @@ namespace Poincare { -bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position, int positionIndex) { +bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position) { assert(expressionLayout != nullptr); - return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position, positionIndex); + return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position); } KDPoint ExpressionLayoutCursor::middleLeftPoint() { - return middleLeftPointOfCursor(m_pointedExpressionLayout, m_position, m_positionInside); + return middleLeftPointOfCursor(m_pointedExpressionLayout, m_position); } -KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position, int positionInside) { +KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position) { KDPoint layoutOrigin = expressionLayout->absoluteOrigin(); KDCoordinate y = layoutOrigin.y() + expressionLayout->baseline() - k_cursorHeight/2; if (position == Position::Left) { return KDPoint(layoutOrigin.x(), y); } - if (position == Position::Right) { - return KDPoint(layoutOrigin.x() + expressionLayout->size().width(), y); - } - assert(position == Position::Inside); - return KDPoint(layoutOrigin.x() + positionInside * KDText::charSize().width(), y); + assert(position == Position::Right); + return KDPoint(layoutOrigin.x() + expressionLayout->size().width(), y); } bool ExpressionLayoutCursor::moveLeft() { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 395194d39..c46fba418 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -301,12 +301,11 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; - int resultPositionInside = 0; // The distance between the cursor and its next position cannot be greater // than this initial value of score. int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; - moveCursorInsideAtDirection(direction, cursor, childResultPtr, &resultPosition, &resultPositionInside, &resultScore); + moveCursorInsideAtDirection(direction, cursor, childResultPtr, &resultPosition, &resultScore); // If there is a valid result if (*childResultPtr == nullptr) { @@ -314,7 +313,6 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC } cursor->setPointedExpressionLayout(*childResultPtr); cursor->setPosition(resultPosition); - cursor->setPositionInside(resultPositionInside); return true; } @@ -323,7 +321,6 @@ void ExpressionLayout::moveCursorInsideAtDirection ( ExpressionLayoutCursor * cursor, ExpressionLayout ** childResult, void * resultPosition, - int * resultPositionInside, int * resultScore) { ExpressionLayoutCursor::Position * castedResultPosition = static_cast(resultPosition); @@ -333,27 +330,25 @@ void ExpressionLayout::moveCursorInsideAtDirection ( if (layoutIsUnderOrAbove) { // Check the distance to a Left cursor. - int currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Left, 0).squareDistanceTo(cursorMiddleLeft); + int currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Left).squareDistanceTo(cursorMiddleLeft); if (currentDistance <= *resultScore ){ *childResult = this; *castedResultPosition = ExpressionLayoutCursor::Position::Left; - *resultPositionInside = 0; *resultScore = currentDistance; } // Check the distance to a Right cursor. - currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Right, 0).squareDistanceTo(cursorMiddleLeft); + currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Right).squareDistanceTo(cursorMiddleLeft); if (currentDistance < *resultScore) { *childResult = this; *castedResultPosition = ExpressionLayoutCursor::Position::Right; - *resultPositionInside = 0; *resultScore = currentDistance; } } if (layoutIsUnderOrAbove || layoutContains) { int childIndex = 0; while (child(childIndex++)) { - editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultPositionInside, resultScore); + editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultScore); } } } diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 2a166bf7d..8d8ab0aa1 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -162,7 +162,6 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p assert(indexLayout() != nullptr); cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - cursor->setPositionInside(0); return true; } // If the cursor is Left, move it to the index. @@ -172,7 +171,6 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p assert(indexLayout() != nullptr); cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - cursor->setPositionInside(0); return true; } return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); @@ -185,14 +183,12 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * assert(radicandLayout() != nullptr); cursor->setPointedExpressionLayout(radicandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - cursor->setPositionInside(0); return true; } // If the cursor is Left of the index, move it Left . if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Left)) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - cursor->setPositionInside(0); return true; } } From 61e50e1858e745d4c2dd479e4a90d576c633a95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:05:52 +0100 Subject: [PATCH 121/459] [poincare] ParenthesisLayout renders parentheses instead of layouting. ParenthesisLayout should be used for uneditable parenthesis, because its parentheses are drawn instead of being part of the Layout tree. Change-Id: Ibce7908fa271cd5e8cd7b2a2b5241d0ea42028f7 --- poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/parenthesis_layout.cpp | 112 +++++------------- poincare/src/layout/parenthesis_layout.h | 17 ++- poincare/src/layout/parenthesis_left_layout.h | 1 + .../layout/parenthesis_left_right_layout.cpp | 2 +- .../layout/parenthesis_left_right_layout.h | 1 + .../src/layout/parenthesis_right_layout.h | 1 + 7 files changed, 42 insertions(+), 93 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index bb72a1740..6b789e770 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { friend class IntegralLayout; + friend class ParenthesisLayout; friend class SequenceLayout; public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index cb4c372e1..ed81ff533 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -1,5 +1,7 @@ #include "parenthesis_layout.h" +#include "horizontal_layout.h" #include "parenthesis_left_layout.h" +#include "parenthesis_left_right_layout.h" #include "parenthesis_right_layout.h" #include #include @@ -10,31 +12,11 @@ extern "C" { namespace Poincare { -ParenthesisLayout::ParenthesisLayout(ExpressionLayout * operand, bool cloneOperands) : - StaticLayoutHierarchy<3>() -{ - ExpressionLayout * leftParenthesis = new ParenthesisLeftLayout(); - ExpressionLayout * rightParenthesis = new ParenthesisRightLayout(); - build(ExpressionLayoutArray(leftParenthesis, operand, rightParenthesis).array(), 3, cloneOperands); -} - ExpressionLayout * ParenthesisLayout::clone() const { - ParenthesisLayout * layout = new ParenthesisLayout(const_cast(this)->operandLayout(), true); - return layout; + return new ParenthesisLayout(const_cast(this)->operandLayout(), true); } bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // Case: Left of the Right parenthesis. - // Go to the operand and move left. - if (rightParenthesisLayout() - && cursor->pointedExpressionLayout() == rightParenthesisLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return operandLayout()->moveLeft(cursor); - } // Case: Left of the operand. // Go Left. if (operandLayout() @@ -44,30 +26,20 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); return true; } - // Case: Left of the Left parenthesis. - // Ask the parent. - if (leftParenthesisLayout() - && cursor->pointedExpressionLayout() == leftParenthesisLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; - } + assert(cursor->pointedExpressionLayout() == this); - // Case: Right of the parentheses. - // Go Right of the operand. + // Case: Right. + // Go to the operand and move left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); cursor->setPointedExpressionLayout(operandLayout()); - return true; + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return operandLayout()->moveLeft(cursor); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left of the parentheses. + + // Case: Left. // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->moveLeft(cursor); } @@ -75,17 +47,6 @@ bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { } bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { - // Case: Right of the Left parenthesis. - // Go to the operand and move Right. - if (leftParenthesisLayout() - && cursor->pointedExpressionLayout() == leftParenthesisLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return operandLayout()->moveRight(cursor); - } // Case: Right of the operand. // Go Right. if (operandLayout() @@ -95,29 +56,17 @@ bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); return true; } - // Case: Right of the Right parenthesis. - // Ask the parent. - if (rightParenthesisLayout() - && cursor->pointedExpressionLayout() == rightParenthesisLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; - } + assert(cursor->pointedExpressionLayout() == this); - // Case: Left of the parentheses. - // Go Left of the operand. + // Case: Left. + // Go Left of the operand and moveRight. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); cursor->setPointedExpressionLayout(operandLayout()); - return true; + return operandLayout()->moveRight(cursor);; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right of the parentheses. + // Case: Right. // Ask the parent. if (m_parent) { return m_parent->moveRight(cursor); @@ -125,9 +74,20 @@ bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +void ParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Render the parentheses. + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + HorizontalLayout dummyLayout(dummyLeftParenthesis, operandLayout()->clone(), dummyRightParenthesis, false); + KDPoint leftParenthesisPoint = positionOfChild(operandLayout()).translatedBy(dummyLayout.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout.positionOfChild(dummyLayout.editableChild(1)).opposite()); + KDPoint rightParenthesisPoint = positionOfChild(operandLayout()).translatedBy(dummyLayout.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout.positionOfChild(dummyLayout.editableChild(1)).opposite()); + dummyLeftParenthesis->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); + dummyRightParenthesis->render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor); +} + KDSize ParenthesisLayout::computeSize() { KDSize operandSize = operandLayout()->size(); - return KDSize(operandSize.width() + 2*leftParenthesisLayout()->size().width(), operandSize.height()); + return KDSize(operandSize.width() + 2*ParenthesisLeftRightLayout::parenthesisWidth(), operandSize.height()); } void ParenthesisLayout::computeBaseline() { @@ -136,29 +96,15 @@ void ParenthesisLayout::computeBaseline() { } KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { - if (child == leftParenthesisLayout()) { - return KDPoint(0, 0); - } if (child == operandLayout()) { - return KDPoint(leftParenthesisLayout()->size().width(), 0); - } - if (child == rightParenthesisLayout()) { - return KDPoint(operandLayout()->origin().x() + operandLayout()->size().width(), 0); + return KDPoint(ParenthesisLeftRightLayout::parenthesisWidth(), 0); } assert(false); return KDPointZero; } ExpressionLayout * ParenthesisLayout::operandLayout() { - return editableChild(1); -} - -ExpressionLayout * ParenthesisLayout::leftParenthesisLayout() { return editableChild(0); } -ExpressionLayout * ParenthesisLayout::rightParenthesisLayout() { - return editableChild(2); -} - } diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index f7ed69efd..af110702f 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -4,22 +4,23 @@ #include #include +/* ParenthesisLayout has one operand and renders the parentheses around it. + * This layout should thus be used for uneditable parentheses, e.g. to create + * binomial coefficient layouts. */ + namespace Poincare { -class ParenthesisLayout : public StaticLayoutHierarchy<3> { +class ParenthesisLayout : public StaticLayoutHierarchy<1> { public: - constexpr static KDCoordinate k_parenthesisCurveWidth = 5; - constexpr static KDCoordinate k_parenthesisCurveHeight = 7; - ParenthesisLayout(ExpressionLayout * operand, bool cloneOperands); + using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); } protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { - }; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; @@ -29,8 +30,6 @@ private: constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_lineThickness = 1; ExpressionLayout * operandLayout(); - ExpressionLayout * leftParenthesisLayout(); - ExpressionLayout * rightParenthesisLayout(); }; } diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 9b4c34ced..ea383da99 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { + friend class ParenthesisLayout; friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index f3b77ee95..060596fac 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -53,7 +53,7 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { } KDSize ParenthesisLeftRightLayout::computeSize() { - return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, operandHeight()); + return KDSize(parenthesisWidth(), operandHeight()); } KDCoordinate ParenthesisLeftRightLayout::operandHeight() { diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 3ad0a296b..8596d219b 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -11,6 +11,7 @@ public: void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; constexpr static KDCoordinate k_externWidthMargin = 1; diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 7e1eb8578..0c3f8ce7a 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class ParenthesisRightLayout : public ParenthesisLeftRightLayout { + friend class ParenthesisLayout; friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; From 6334e2f4353ca845488cb05040b2766e58e1f1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:09:57 +0100 Subject: [PATCH 122/459] [apps] Change MathToolbox's binomial coefficient layout. It now uses a Parenthesis layout. Change-Id: Ia83d7881a57bc91e41d125fef1e2a648d0278946 --- apps/math_toolbox.cpp | 8 +++----- poincare/src/layout/grid_layout.cpp | 4 ++++ poincare/src/layout/grid_layout.h | 6 ++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 612e4324f..1597980ba 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -45,16 +45,14 @@ const ToolboxMessageTree complexChildren[5] = { const_cast(&pointedLayoutPathConj[0]), 1)}; -const int pointedLayoutPathBinomial[] = {1,0}; +const int pointedLayoutPathBinomial[] = {0, 0}; const ToolboxMessageTree probabilityChildren[2] = { ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg, nullptr, 0, - new HorizontalLayout( - new ParenthesisLeftLayout(), + new ParenthesisLayout( new GridLayout(Poincare::ExpressionLayoutArray( new EmptyVisibleLayout(), new EmptyVisibleLayout()).array(), - 2, 1, false), - new ParenthesisRightLayout(), false), + 2, 1, false)), const_cast(&pointedLayoutPathBinomial[0]), 2), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommandWithArg)}; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 2d3152b09..5756d1c4c 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -138,6 +138,10 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * pr return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { + ExpressionLayout::removeChildAtIndex(index, deleteAfterRemoval); +} + int GridLayout::writeTextInBuffer(char * buffer, int bufferSize) const { const ExpressionLayout * editableParent = const_cast(this)->parent(); assert(editableParent != nullptr); diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index a00dcb65d..7d89e01e6 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -17,6 +17,12 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + + /* Dynamic layout */ + void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + //TODO: is this ok? If we want to delete the grid's children, we have to make + //sure no to call this function. + /* Expression engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; From 630c6256e1026256e1d6051288bba8844d7c453b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:14:44 +0100 Subject: [PATCH 123/459] [poincare] Removed tedious HorizontalLayout creations. There is a HorizontalLayout constructor that takes 3 layouts, so no need to use ExpressionLayoutArray. Change-Id: I51c6b9d44ead2b4d765aad6f5a2140641f4d076b --- poincare/src/layout/product_layout.cpp | 3 +-- poincare/src/layout/sequence_layout.cpp | 11 +++++------ poincare/src/layout/sum_layout.cpp | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index 9ab4732b9..2b9120db7 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -1,7 +1,6 @@ #include "product_layout.h" #include "char_layout.h" #include "horizontal_layout.h" -#include namespace Poincare { @@ -17,7 +16,7 @@ int ProductLayout::writeTextInBuffer(char * buffer, int bufferSize) const { void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Compute sizes. KDSize upperBoundSize = upperBoundLayout()->size(); - KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); // Render the Product symbol. ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 468768646..acb342c2b 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -4,7 +4,6 @@ #include "parenthesis_left_layout.h" #include "parenthesis_right_layout.h" #include -#include #include namespace Poincare { @@ -222,10 +221,10 @@ ExpressionLayout * SequenceLayout::argumentLayout() { } KDSize SequenceLayout::computeSize() { - KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); - HorizontalLayout dummyLayout2(ExpressionLayoutArray(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis).array(), 3, false); + HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDSize dummyLayoutSize = dummyLayout2.size(); KDSize upperBoundSize = upperBoundLayout()->size(); return KDSize( @@ -236,7 +235,7 @@ KDSize SequenceLayout::computeSize() { KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { ExpressionLayout * lowerBoundClone = lowerBoundLayout()->clone(); - HorizontalLayout dummyLayout1(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundClone).array(), 3, false); + HorizontalLayout dummyLayout1(new CharLayout('n'), new CharLayout('='), lowerBoundClone, false); KDSize lowerBoundSizeWithNEquals = dummyLayout1.size(); KDSize upperBoundSize = upperBoundLayout()->size(); ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); @@ -264,14 +263,14 @@ void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, // Render the "n=". CharLayout * dummyN = new CharLayout('n'); ExpressionLayout * lowerBoundClone = lowerBoundLayout()->clone(); - HorizontalLayout dummyLayout(ExpressionLayoutArray(dummyN, new CharLayout('='), lowerBoundClone).array(), 3, false); + HorizontalLayout dummyLayout(dummyN, new CharLayout('='), lowerBoundClone, false); KDPoint nEqualsPosition = positionOfChild(lowerBoundLayout()).translatedBy((dummyLayout.positionOfChild(lowerBoundClone)).opposite()).translatedBy(dummyLayout.positionOfChild(dummyN)); ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN->fontSize(), expressionColor, backgroundColor); // Render the parentheses. ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); - HorizontalLayout dummyLayout2(ExpressionLayoutArray(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis).array(), 3, false); + HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); KDPoint rightParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); dummyLeftParenthesis->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index 7906d2a0c..a38117c97 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -1,7 +1,6 @@ #include "sum_layout.h" #include "char_layout.h" #include "horizontal_layout.h" -#include namespace Poincare { @@ -35,7 +34,7 @@ int SumLayout::writeTextInBuffer(char * buffer, int bufferSize) const { void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Computes sizes. KDSize upperBoundSize = upperBoundLayout()->size(); - KDSize lowerBoundSizeWithNEquals = HorizontalLayout(ExpressionLayoutArray(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone()).array(), 3, false).size(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); // Render the Sum symbol. KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; From fda1840be4096dd3cea5b0545dc71e430a3833ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:19:24 +0100 Subject: [PATCH 124/459] [expression_editor] The button "log" inserts a logarithm without index. Change-Id: Ib82cccb076c34c69c3112ade7a41139da15e96c0 --- poincare/src/expression_layout_cursor.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index c8fac396b..c22d3430b 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -103,22 +103,9 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( } ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { - HorizontalLayout * newChild = new HorizontalLayout( - ExpressionLayoutArray( - new CharLayout('l'), - new CharLayout('o'), - new CharLayout('g')).array(), - 3, - false); - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Subscript, false); - newChild->addChildAtIndex(offsetLayout, 3); - m_pointedExpressionLayout->addBrother(this, newChild); - setPointedExpressionLayout(offsetLayout); - setPosition(ExpressionLayoutCursor::Position::Right); - insertText("()"); - setPointedExpressionLayout(offsetLayout->editableChild(0)); - setPosition(ExpressionLayoutCursor::Position::Right); - return offsetLayout; + ExpressionLayout * result = insertText("log()"); + setPosition(ExpressionLayoutCursor::Position::Left); + return result; } ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { From 8d188279eb1f44f8fcc176656b7c626ded72ba37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:46:57 +0100 Subject: [PATCH 125/459] [poincare] BoundedStaticLayoutHierarchy. Change-Id: I33a1f41458401be5aebbc183e692681b4418c861 --- poincare/Makefile | 1 + .../bounded_static_layout_hierarchy.h | 22 +++++++++++ .../bounded_static_layout_hierarchy.cpp | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 poincare/include/poincare/bounded_static_layout_hierarchy.h create mode 100644 poincare/src/layout/bounded_static_layout_hierarchy.cpp diff --git a/poincare/Makefile b/poincare/Makefile index f9828e5fe..9a1cc88da 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -84,6 +84,7 @@ objs += $(addprefix poincare/src/,\ objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ + bounded_static_layout_hierarchy.o\ bracket_layout.o\ bracket_left_layout.o\ bracket_left_right_layout.o\ diff --git a/poincare/include/poincare/bounded_static_layout_hierarchy.h b/poincare/include/poincare/bounded_static_layout_hierarchy.h new file mode 100644 index 000000000..42a0acc6b --- /dev/null +++ b/poincare/include/poincare/bounded_static_layout_hierarchy.h @@ -0,0 +1,22 @@ +#ifndef POINCARE_BOUNDED_STATIC_LAYOUT_HIERARCHY_H +#define POINCARE_BOUNDED_STATIC_LAYOUT_HIERARCHY_H + +#include + +namespace Poincare { + +template +class BoundedStaticLayoutHierarchy : public StaticLayoutHierarchy { +public: + BoundedStaticLayoutHierarchy(); + BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> + BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout1, const ExpressionLayout * expressionLayout2, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> + BoundedStaticLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); + int numberOfChildren() const override { return m_numberOfChildren; } +private: + int m_numberOfChildren; +}; + +} + +#endif diff --git a/poincare/src/layout/bounded_static_layout_hierarchy.cpp b/poincare/src/layout/bounded_static_layout_hierarchy.cpp new file mode 100644 index 000000000..12f986e61 --- /dev/null +++ b/poincare/src/layout/bounded_static_layout_hierarchy.cpp @@ -0,0 +1,37 @@ +#include +#include +extern "C" { +#include +} + +namespace Poincare { + +template +BoundedStaticLayoutHierarchy::BoundedStaticLayoutHierarchy() : + StaticLayoutHierarchy(), + m_numberOfChildren(0) +{ +} + +template +BoundedStaticLayoutHierarchy::BoundedStaticLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands) : + m_numberOfChildren(numberOfOperands) +{ + StaticLayoutHierarchy::build(operands, numberOfOperands, cloneOperands); +} + +template<> +BoundedStaticLayoutHierarchy<2>::BoundedStaticLayoutHierarchy(const ExpressionLayout * e, bool cloneOperands) : + BoundedStaticLayoutHierarchy((ExpressionLayout **)&e, 1, cloneOperands) +{ +} + +template<> +BoundedStaticLayoutHierarchy<2>::BoundedStaticLayoutHierarchy(const ExpressionLayout * e1, const ExpressionLayout * e2, bool cloneOperands) : + BoundedStaticLayoutHierarchy(ExpressionLayoutArray(e1, e2).array(), 2, cloneOperands) +{ +} + +template class Poincare::BoundedStaticLayoutHierarchy<2>; + +} From 29e877ec92f6b8a2c66b782e4de27dc6c4f60752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:47:26 +0100 Subject: [PATCH 126/459] [poincare] NthRootLayout is now a BoundedStaticLayoutHierarchy. It can now handle having an index or not (simple square root layout). Change-Id: I7a3795c62873fa0a356719b8d572dd5a5be53c94 --- apps/expression_editor/controller.cpp | 2 +- .../poincare/expression_layout_cursor.h | 2 +- poincare/src/expression_layout_cursor.cpp | 5 ++- poincare/src/layout/nth_root_layout.cpp | 33 +++++++++++-------- poincare/src/layout/nth_root_layout.h | 6 ++-- .../src/layout/static_layout_hierarchy.cpp | 3 +- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 052815e49..8e9c77078 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -118,7 +118,7 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { return m_cursor.addEmptyPowerLayout(); } if (event == Ion::Events::Sqrt) { - return m_cursor.addEmptyRootLayout(); + return m_cursor.addEmptySquareRootLayout(); } if (event == Ion::Events::Square) { return m_cursor.addEmptySquarePowerLayout(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 76b335f1c..779cd9318 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -44,7 +44,7 @@ public: ExpressionLayout * addFractionLayoutAndCollapseBrothers(); ExpressionLayout * addEmptyLogarithmLayout(); ExpressionLayout * addEmptyPowerLayout(); - ExpressionLayout * addEmptyRootLayout(); + ExpressionLayout * addEmptySquareRootLayout(); ExpressionLayout * addEmptySquarePowerLayout(); ExpressionLayout * addXNTCharLayout(); ExpressionLayout * insertText(const char * text); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index c22d3430b..1070b4167 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -127,10 +127,9 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { return child1; } -ExpressionLayout * ExpressionLayoutCursor::addEmptyRootLayout() { +ExpressionLayout * ExpressionLayoutCursor::addEmptySquareRootLayout() { EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); - EmptyVisibleLayout * child2 = new EmptyVisibleLayout(); - NthRootLayout * newChild = new NthRootLayout(child1, child2, false); + NthRootLayout * newChild = new NthRootLayout(child1, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 8d8ab0aa1..8831869c7 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -17,14 +17,18 @@ const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_left }; ExpressionLayout * NthRootLayout::clone() const { - NthRootLayout * layout = new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); - return layout; + if (numberOfChildren() == 1) { + return new NthRootLayout(const_cast(this)->radicandLayout(), true); + } + assert(numberOfChildren() == 2); + return new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); } void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // Case: Left the index. // Move Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Left + if (indexLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Left && cursor->pointedExpressionLayout() == indexLayout()) { cursor->setPointedExpressionLayout(this); @@ -64,7 +68,7 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } // Case: Left. // Ask the parent. - assert(cursor->position() ==ExpressionLayoutCursor::Position::Left); + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->backspaceAtCursor(cursor); } @@ -155,20 +159,20 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is Left of the radicand, move it to the index. - if (radicandLayout() + if (indexLayout() + && radicandLayout() && previousLayout == radicandLayout() && cursor->positionIsEquivalentTo(radicandLayout(), ExpressionLayoutCursor::Position::Left)) { - assert(indexLayout() != nullptr); cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; } // If the cursor is Left, move it to the index. - if (cursor->pointedExpressionLayout() == this + if (indexLayout() + && cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(indexLayout() != nullptr); cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; @@ -260,12 +264,12 @@ KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); - if (child == indexLayout()) { - x = 0; - y = baseline() - indexSize.height() - k_indexHeight; - } else if (child == radicandLayout()) { + if (child == radicandLayout()) { x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; y = baseline() - radicandLayout()->baseline(); + } else if (indexLayout() && child == indexLayout()) { + x = 0; + y = baseline() - indexSize.height() - k_indexHeight; } else { assert(false); } @@ -277,7 +281,10 @@ ExpressionLayout * NthRootLayout::radicandLayout() { } ExpressionLayout * NthRootLayout::indexLayout() { - return editableChild(1); + if (numberOfChildren() > 1) { + return editableChild(1); + } + return nullptr; } } diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index c04f5c7f2..fb2a54048 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -1,16 +1,16 @@ #ifndef POINCARE_NTH_ROOT_LAYOUT_H #define POINCARE_NTH_ROOT_LAYOUT_H -#include +#include #include namespace Poincare { -class NthRootLayout : public StaticLayoutHierarchy<2> { +class NthRootLayout : public BoundedStaticLayoutHierarchy<2> { public: constexpr static KDCoordinate k_leftRadixHeight = 8; constexpr static KDCoordinate k_leftRadixWidth = 5; - using StaticLayoutHierarchy::StaticLayoutHierarchy; + using BoundedStaticLayoutHierarchy::BoundedStaticLayoutHierarchy; ExpressionLayout * clone() const override; /* Dynamic Layout*/ diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp index 76314772e..224902945 100644 --- a/poincare/src/layout/static_layout_hierarchy.cpp +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -52,8 +52,7 @@ void StaticLayoutHierarchy::build(const ExpressionLayout * const * operands, assert(operands != nullptr); assert(numberOfOperands <= T); for (int i=0; i < numberOfOperands; i++) { - assert(operands[i] != nullptr); - if (cloneOperands) { + if (cloneOperands && operands[i] != nullptr) { m_children[i] = operands[i]->clone(); } else { m_children[i] = operands[i]; From 1fb2ab1829c261b65178696c94d25fdaf87ffaa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Jan 2018 16:56:33 +0100 Subject: [PATCH 127/459] [expression_editor] Multiplication button inserts multiplication dots. Change-Id: I9e87487a7419faef161378fc269e1d366c8e1a40 --- apps/expression_editor/controller.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 8e9c77078..8f686e47b 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,5 +1,6 @@ #include "controller.h" #include +#include using namespace Poincare; @@ -124,7 +125,12 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { return m_cursor.addEmptySquarePowerLayout(); } if (event.hasText()) { - return m_cursor.insertText(event.text()); + const char * textToInsert = event.text(); + if (textToInsert[0] == Ion::Charset::MultiplicationSign && textToInsert[1] == 0) { + const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; + return m_cursor.insertText(middleDotString); + } + return m_cursor.insertText(textToInsert); } return nullptr; } From 0575cd2d60f78c97b89ff8e24b211531fd787503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 09:50:04 +0100 Subject: [PATCH 128/459] [poincare] addBrother should first assess if the layout is horizontal. Before, if the cursor was Right of an HorizontalLayout, pressing "/" might put the whole HorizontalLayout as the numerator of the new fraction, because the fraction layout was added as a brother of the HorizontalLayout, not a child. Change-Id: I3b58920e48db49ccd4204c405362d148260461d4 --- poincare/src/layout/expression_layout.cpp | 31 +++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index c46fba418..4c0c196ee 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -110,32 +110,35 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { } void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - if (m_parent) { - int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; - if (m_parent->isHorizontal()) { - static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex); - return; + // First, assess the special case when the layout is horizontal. + // If so, add the "brother" as a child. + if (isHorizontal()) { + // If there is only one empty child, remove it before adding the layout. + if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { + removeChildAtIndex(0, true); } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - replaceWithJuxtapositionOf(brother, this, false); + addChildAtIndex(brother, 0); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - replaceWithJuxtapositionOf(this, brother, false); + addChildAtIndex(brother, numberOfChildren()); return; } - // If there is no parent, the pointed layout is the main horizontal layout. - // Add the "brother" as a child. - // If there is only one empty child, remove it before adding the layout. - if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { - removeChildAtIndex(0, true); + + // If the layout is not horizontal, it must have a parent. + assert(m_parent); + int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; + if (m_parent->isHorizontal()) { + static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex); + return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - addChildAtIndex(brother, 0); + replaceWithJuxtapositionOf(brother, this, false); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - addChildAtIndex(brother, numberOfChildren()); + replaceWithJuxtapositionOf(this, brother, false); return; } From 93f645c3319e9f3fe75d7f0b7a987051a63505c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 09:56:15 +0100 Subject: [PATCH 129/459] [poincare] Better comment for replacing HorizontalLayout with Empty. Change-Id: I6210d63e40f079e5886e7c29cf8e0e305142eb4b --- poincare/src/layout/horizontal_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 24ebff1c3..1ad87670c 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -41,7 +41,8 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio return; } // If the new layout is empty and it was the only horizontal layout child, - // replace the horizontal layout with this empty layout. + // replace the horizontal layout with this empty layout (only if this is not + // the main layout, so only if the layout has a parent. if (m_parent) { replaceWith(newChild); return; From d6fbcbaa00b33d152504d9982b7d1a9b66fa6784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 10:32:03 +0100 Subject: [PATCH 130/459] [poincare] Fixed serialization of square roots and Nth roots. Change-Id: I68f9af1c6fc59d97b1dfb547062cf976012a1e4f --- poincare/src/layout/nth_root_layout.cpp | 41 +++++++++++++++++++++++++ poincare/src/layout/nth_root_layout.h | 4 +-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 8831869c7..4e749d8c9 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -1,4 +1,5 @@ #include "nth_root_layout.h" +#include #include #include #include @@ -199,6 +200,46 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); } +static_assert('\x90' == Ion::Charset::Root, "Unicode error"); +int NthRootLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + // Case: root(x,n) + if (numberOfChildren() == 2 + && (const_cast(this))->indexLayout() + && !(const_cast(this))->indexLayout()->isEmpty()) + { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "root"); + } + // Case: squareRoot(x) + if (numberOfChildren() == 1) { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "\x90"); + } + // Case: root(x,empty) + // Write "'SquareRootSymbol'('radicandLayout')". + assert((const_cast(this))->indexLayout() && (const_cast(this))->indexLayout()->isEmpty()); + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + + buffer[numberOfChar++] = '\x90'; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + numberOfChar += (const_cast(this))->radicandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = radicandLayout()->size(); KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index fb2a54048..86a840b55 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -23,9 +23,7 @@ public: bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "root"); - } + int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; From aaca93e9149a6b428022b4e769581bc4dbb8c4ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 11:01:35 +0100 Subject: [PATCH 131/459] [poincare] Helper function to create log layouts. Change-Id: I4f43d11a48e1b8bdddb6660da11e3127778a0bae --- poincare/include/poincare/layout_engine.h | 4 ++++ poincare/src/layout_engine.cpp | 23 +++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index f5838d0f9..2b8c9984d 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -11,8 +11,12 @@ public: /* Expression to ExpressionLayout */ static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + + /* Create special layouts */ static ExpressionLayout * createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout); static ExpressionLayout * createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large); + static ExpressionLayout * createLogLayout(ExpressionLayout * argument, ExpressionLayout * index); + /* Expression to Text */ typedef bool (*OperandNeedsParenthesis)(const Expression * e); diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 14a1f14f7..f54bbba22 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -3,6 +3,7 @@ #include "layout/horizontal_layout.h" #include "layout/parenthesis_left_layout.h" #include "layout/parenthesis_right_layout.h" +#include "layout/vertical_offset_layout.h" extern "C" { #include } @@ -49,6 +50,16 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio return result; } +ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout) { + HorizontalLayout * result = new HorizontalLayout(); + result->addChildAtIndex(new ParenthesisLeftLayout(), 0); + if (layout != nullptr) { + result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1); + } + result->addChildAtIndex(new ParenthesisRightLayout(), result->numberOfChildren()); + return result; +} + ExpressionLayout * LayoutEngine::createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize) { assert(bufferSize > 0); HorizontalLayout * resultLayout = new HorizontalLayout(); @@ -58,12 +69,12 @@ ExpressionLayout * LayoutEngine::createStringLayout(const char * buffer, int buf return resultLayout; } -ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout) { - HorizontalLayout * result = new HorizontalLayout(); - result->addChildAtIndex(new ParenthesisLeftLayout(), 0); - result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1); - result->addChildAtIndex(new ParenthesisRightLayout(), result->numberOfChildren()); - return result; +ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, ExpressionLayout * index) { + HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(index, VerticalOffsetLayout::Type::Subscript, false); + resultLayout->addChildAtIndex(offsetLayout, resultLayout->numberOfChildren()); + resultLayout->addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout->numberOfChildren()); + return resultLayout; } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedsParenthesis operandNeedsParenthesis) { From 0431326c506ea5c3d5e39070ffc9dc92bdabe496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 11:02:03 +0100 Subject: [PATCH 132/459] [poincare] Use the helper LogLayout creation function. Change-Id: Id43437d3bb2a9e608c08435c6c75f3aa21ac450c --- poincare/src/logarithm.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index e8f14dd94..75f8a257d 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -234,12 +234,7 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM if (numberOfOperands() == 1) { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } - HorizontalLayout * result = new HorizontalLayout(); - result->addChildAtIndex(LayoutEngine::createStringLayout("log", strlen("log")), 0); - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), VerticalOffsetLayout::Type::Subscript, false); - result->addChildAtIndex(offsetLayout, 1); - result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 2); - return result; + return LayoutEngine::createLogLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); } } From bbd4cb6da92338174e0a2415130246dfdb60b9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 10:56:26 +0100 Subject: [PATCH 133/459] [apps] Added NthRoot and Log layouts in MathToolbox. Change-Id: I3efcf6d56acec542566d22e23b5e3b66fb0af5fc --- apps/math_toolbox.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 1597980ba..d59fdd2ce 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -101,6 +101,8 @@ const ToolboxMessageTree predictionChildren[3] = { ToolboxMessageTree(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommandWithArg)}; const int pointedLayoutPathAbs[] = {0}; +const int pointedLayoutPathRoot[] = {1}; +const int pointedLayoutPathLog[] = {3,0}; #if LIST_ARE_DEFINED const ToolboxMessageTree menu[12] = { #elif MATRICES_ARE_DEFINED @@ -113,8 +115,16 @@ const ToolboxMessageTree menu[10] = { new EmptyVisibleLayout()), const_cast(&pointedLayoutPathAbs[0]), 1), - ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg), - ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg), + ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg, nullptr, 0, + new NthRootLayout( + new EmptyVisibleLayout(), + new EmptyVisibleLayout()), + const_cast(&pointedLayoutPathRoot[0]), + 1), + ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg, nullptr, 0, + LayoutEngine::createLogLayout(nullptr, new EmptyVisibleLayout()), + const_cast(&pointedLayoutPathLog[0]), + 2), ToolboxMessageTree(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), ToolboxMessageTree(I18n::Message::ComplexNumber, I18n::Message::Default, I18n::Message::Default, complexChildren, 5), ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), From 5f8bda507563d0a75d75d278153504aa8852ebcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 11:07:48 +0100 Subject: [PATCH 134/459] [poincare] Clean LayoutEngine's writeInfixExpressionLayoutTextInBuffer. Change-Id: Ic8e958ef6d3ff965f76c2426d45323ac0d651d76 --- poincare/include/poincare/layout_engine.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 2b8c9984d..1f2f8bd82 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -42,7 +42,7 @@ public: int firstChildIndex = 0, int lastChildIndex = -1, ChildNeedsParenthesis childNeedsParenthesis = [](const char * operatorName) { - return (operatorName[1] == 0 && (operatorName[0] == powerChar || operatorName[0] == divideChar)); }); //TODO + return (operatorName[1] == 0 && (operatorName[0] == divideChar)); }); static int writePrefixExpressionLayoutTextInBuffer( const ExpressionLayout * expressionLayout, char * buffer, @@ -54,7 +54,6 @@ public: static int writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite); private: - static constexpr char powerChar = '^'; static constexpr char divideChar = '/'; // These two functions return the index of the null-terminating char. static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, const char * operatorName, int firstChildIndex, int lastChildIndex, OperandNeedsParenthesis operandNeedsParenthesis, ChildNeedsParenthesis childNeedsParenthesis); From 73e7f54c7c635d2c2955587f67d93267838ba1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 17:44:05 +0100 Subject: [PATCH 135/459] [expression_editor] Fixed Makefile for the dummy tests. Change-Id: I9f7a380a8271cb40258d8eada1fccf8ac60d04f8 --- apps/expression_editor/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/expression_editor/Makefile b/apps/expression_editor/Makefile index 7edd46555..137280e8a 100644 --- a/apps/expression_editor/Makefile +++ b/apps/expression_editor/Makefile @@ -19,8 +19,5 @@ tests += $(addprefix apps/expression_editor/test/,\ ) test_objs += $(addprefix apps/expression_editor/,\ - controller.o\ - expression_editor_view.o\ expression_view_with_cursor.o\ - scrollable_expression_view_with_cursor.o\ ) From 59c957b5fb1aa1115d18e310b0418b18b850c1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 15:31:25 +0100 Subject: [PATCH 136/459] [expression_editor] DIRTY COMMIT to display a layout value computation. Change-Id: I7a548afe4df9c863f5b5716a819f42141f7fb5c2 --- apps/expression_editor/controller.cpp | 27 ++++++++++++++++++- apps/expression_editor/controller.h | 3 +++ .../expression_editor_view.cpp | 15 ++++++++--- .../expression_editor_view.h | 4 ++- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 8f686e47b..814200eb8 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -1,5 +1,6 @@ #include "controller.h" #include +#include #include using namespace Poincare; @@ -9,7 +10,9 @@ namespace ExpressionEditor { Controller::Controller(Responder * parentResponder, ExpressionLayout * expressionLayout) : ViewController(parentResponder), m_view(parentResponder, expressionLayout, &m_cursor), - m_expressionLayout(expressionLayout) + m_expressionLayout(expressionLayout), + m_resultLayout(nullptr) + //m_context((GlobalContext *)((AppsContainer *)(app()->container()))->globalContext()) { m_cursor.setPointedExpressionLayout(expressionLayout->editableChild(0)); } @@ -32,6 +35,7 @@ void Controller::didBecomeFirstResponder() { bool Controller::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::EXE) { serializeLayout(); + computeResult(); return true; } if (privateHandleEvent(event)) { @@ -148,4 +152,25 @@ void Controller::serializeLayout() { m_view.setText(const_cast(m_buffer)); } +void Controller::computeResult() { + m_expressionLayout->writeTextInBuffer(m_buffer, k_bufferSize); + Expression * result = Expression::parse(m_buffer); + Expression * approxResult = nullptr; + if (result != nullptr) { + Expression::Simplify(&result,*(((AppsContainer *)(app()->container()))->globalContext())); + approxResult = result->approximate(*(((AppsContainer *)(app()->container()))->globalContext())); + delete m_resultLayout; + } else { + approxResult = new Undefined(); + } + m_resultLayout = approxResult->createLayout(); + m_view.setResult(m_resultLayout); + if (result != nullptr) { + delete result; + } + if (approxResult != nullptr) { + delete approxResult; + } +} + } diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index e777e4103..5a02edd17 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -30,11 +30,14 @@ private: Poincare::ExpressionLayout * handleAddEvent(Ion::Events::Event event); bool handleDeleteEvent(Ion::Events::Event event); void serializeLayout(); + void computeResult(); ExpressionEditorView m_view; Poincare::ExpressionLayout * m_expressionLayout; Poincare::ExpressionLayoutCursor m_cursor; static constexpr int k_bufferSize = 256; char m_buffer[k_bufferSize]; + Poincare::ExpressionLayout * m_resultLayout; + //Poincare::Context m_context; }; } diff --git a/apps/expression_editor/expression_editor_view.cpp b/apps/expression_editor/expression_editor_view.cpp index fe825654e..7fc386c89 100644 --- a/apps/expression_editor/expression_editor_view.cpp +++ b/apps/expression_editor/expression_editor_view.cpp @@ -5,7 +5,8 @@ namespace ExpressionEditor { ExpressionEditorView::ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor) : SolidColorView(KDColorWhite), - m_scrollableExpressionViewWithCursor(parentResponder, expressionLayout, cursor) + m_scrollableExpressionViewWithCursor(parentResponder, expressionLayout, cursor), + m_resultExpressionView() { m_serializerTextView.setText("Hello"); } @@ -19,19 +20,27 @@ void ExpressionEditorView::setText(const char * text) { m_serializerTextView.setText(text); } +void ExpressionEditorView::setResult(Poincare::ExpressionLayout * eL) { + m_resultExpressionView.setExpressionLayout(eL); +} + View * ExpressionEditorView::subviewAtIndex(int index) { - assert(index >= 0 && index < 2); + assert(index >= 0 && index < 3); if (index == 0) { return &m_scrollableExpressionViewWithCursor; } + if (index == 1) { + return &m_resultExpressionView; + } return &m_serializerTextView; } void ExpressionEditorView::layoutSubviews() { m_serializerTextView.setFrame(KDRect(0, 0, bounds().width(), 20)); + m_resultExpressionView.setFrame(KDRect(20, k_margin, bounds().width() - 2 * k_margin, 50)); m_scrollableExpressionViewWithCursor.setFrame(KDRect( k_margin, - k_margin, + 50+k_margin, bounds().width() - 2 * k_margin, bounds().height() - 2 * k_margin)); markRectAsDirty(bounds()); diff --git a/apps/expression_editor/expression_editor_view.h b/apps/expression_editor/expression_editor_view.h index def2ec2b5..2d0116b35 100644 --- a/apps/expression_editor/expression_editor_view.h +++ b/apps/expression_editor/expression_editor_view.h @@ -12,7 +12,8 @@ public: ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); void cursorPositionChanged(); void setText(const char * text); - int numberOfSubviews() const override { return 2; } + void setResult(Poincare::ExpressionLayout * result); + int numberOfSubviews() const override { return 3; } ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } View * subviewAtIndex(int index) override; void layoutSubviews() override; @@ -20,6 +21,7 @@ public: private: constexpr static KDCoordinate k_margin = 10; ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; + ExpressionView m_resultExpressionView; BufferTextView m_serializerTextView; }; From 5ec88dff8eaa60b5f6c2b1202befab5542ea84ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 15:44:16 +0100 Subject: [PATCH 137/459] [poincare] EmptyExpression now exist and can be parsed. Change-Id: I226026fc866c556d9bf4f57c3622f71136dc841c --- ion/include/ion/charset.h | 3 +- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/empty_expression.h | 29 ++++++++++++++++++++ poincare/include/poincare/expression.h | 2 ++ poincare/src/empty_expression.cpp | 28 +++++++++++++++++++ poincare/src/expression_lexer.l | 1 + poincare/src/expression_parser.y | 5 +++- 8 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 poincare/include/poincare/empty_expression.h create mode 100644 poincare/src/empty_expression.cpp diff --git a/ion/include/ion/charset.h b/ion/include/ion/charset.h index fb463525f..333c2c4c6 100644 --- a/ion/include/ion/charset.h +++ b/ion/include/ion/charset.h @@ -24,7 +24,8 @@ enum Charset : char { GreaterEqual = (char)146, MultiplicationSign = (char)147, MiddleDot = (char)148, - AlmostEqual = (char)149 + AlmostEqual = (char)149, + Empty = (char)150 // This char is used to be parsed into EmptyExpression. }; } diff --git a/poincare/Makefile b/poincare/Makefile index 9a1cc88da..a04201309 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -26,6 +26,7 @@ objs += $(addprefix poincare/src/,\ division_remainder.o\ division.o\ dynamic_hierarchy.o\ + empty_expression.o\ expression_layout_cursor.o\ expression_lexer.o\ expression_parser.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 9c2e8e8f1..88826ff40 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h new file mode 100644 index 000000000..e56ecc47a --- /dev/null +++ b/poincare/include/poincare/empty_expression.h @@ -0,0 +1,29 @@ +#ifndef POINCARE_EMPTY_EXPRESSION_H +#define POINCARE_EMPTY_EXPRESSION_H + +#include +#include + +namespace Poincare { + +/* An empty expression awaits completion by the user. */ + +class EmptyExpression : public StaticHierarchy<0> { +public: + Type type() const override { + return Type::EmptyExpression; + } + Expression * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override;private: + /* Layout */ + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + /* Evaluation */ + Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } + template Complex * templatedApproximate(Context& context, AngleUnit angleUnit) const; +}; + +} + +#endif + diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index e29dc0309..4436bce4c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -74,6 +74,7 @@ class Expression { friend class Trigonometry; friend class ApproximationEngine; friend class SimplificationEngine; + friend class EmptyExpression; public: enum class Type : uint8_t { @@ -136,6 +137,7 @@ public: MatrixTranspose, PredictionInterval, SimplificationRoot, + EmptyExpression }; enum class FloatDisplayMode { Decimal = 0, diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp new file mode 100644 index 000000000..b9d7ae2fd --- /dev/null +++ b/poincare/src/empty_expression.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +extern "C" { +#include +} + +namespace Poincare { + +Expression * EmptyExpression::clone() const { + return new EmptyExpression(); +} + +int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize) const { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, Ion::Charset::Empty); +} + +ExpressionLayout * EmptyExpression::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + return new EmptyVisibleLayout(); +} + +template Complex * EmptyExpression::templatedApproximate(Context& context, AngleUnit angleUnit) const { + return new Complex(Complex::Float(NAN)); +} + +} diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index b2d04483e..577e71acc 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -156,6 +156,7 @@ inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; \, { return COMMA; } \. { return DOT; } \_ { return UNDERSCORE; } +\x96 { poincare_expression_yylval.expression = new EmptyExpression(); return EMPTY; } [ ]+ /* Ignore whitespaces */ . { return UNDEFINED_SYMBOL; } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index e48a16e0c..0f53054f1 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -51,6 +51,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %token SYMBOL %token FUNCTION %token UNDEFINED +%token EMPTY /* Operator tokens */ %token PLUS @@ -114,6 +115,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %nonassoc ICOMPLEX %nonassoc UNDEFINED %nonassoc SYMBOL +%nonassoc EMPTY /* The "exp" symbol uses the "expression" part of the union. */ %type final_exp; @@ -129,7 +131,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char * have some heap-allocated data that need to be discarded. */ %destructor { delete $$; } FUNCTION -%destructor { delete $$; } UNDEFINED final_exp exp number +%destructor { delete $$; } UNDEFINED final_exp exp number EMPTY %destructor { delete $$; } lstData /* MATRICES_ARE_DEFINED */ %destructor { delete $$; } mtxData @@ -180,6 +182,7 @@ symb: * "exp MINUS exp". */ exp: UNDEFINED { $$ = $1; } + | EMPTY { $$ = $1; } | exp BANG { $$ = new Poincare::Factorial($1, false); } | number { $$ = $1; } | symb { $$ = $1; } From 1967fce13af15d720e05b0d903f26c7d011fc6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 15:45:28 +0100 Subject: [PATCH 138/459] [apps] Toolbox layouts are created by parsing the command of the cell. Change-Id: I511e8af2b2247d1df3ca968191566c2b3f01fe11 --- apps/math_toolbox.cpp | 95 ++++++++------------ apps/shared/toolbox_helpers.cpp | 17 ++++ apps/shared/toolbox_helpers.h | 2 + escher/Makefile | 1 - escher/include/escher/toolbox_message_tree.h | 11 +-- escher/src/toolbox_message_tree.cpp | 13 --- 6 files changed, 62 insertions(+), 77 deletions(-) delete mode 100644 escher/src/toolbox_message_tree.cpp diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index d59fdd2ce..55c160db9 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -11,50 +11,22 @@ using namespace Poincare; * and the text which would be edited by clicking on the row. When the node is a * subtree, the edited text is set at I18n::Message::Default. */ -const int pointedLayoutPathIntegral[] = {0}; -const int pointedLayoutPathSum[] = {0}; + const ToolboxMessageTree calculChildren[4] = { - ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg, nullptr, 0), - ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg, nullptr, 0, - new IntegralLayout( - new EmptyVisibleLayout(), - new EmptyVisibleLayout(), - new EmptyVisibleLayout(), - false), - const_cast(&pointedLayoutPathIntegral[0]), - 1), - ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg, nullptr, 0, - new SumLayout( - new EmptyVisibleLayout(), - new EmptyVisibleLayout(), - new EmptyVisibleLayout(), - false), - const_cast(&pointedLayoutPathSum[0]), - 1), + ToolboxMessageTree(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommandWithArg), + ToolboxMessageTree(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommandWithArg), + ToolboxMessageTree(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommandWithArg), ToolboxMessageTree(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommandWithArg)}; -const int pointedLayoutPathConj[] = {0}; const ToolboxMessageTree complexChildren[5] = { ToolboxMessageTree(I18n::Message::AbsCommandWithArg,I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommandWithArg), ToolboxMessageTree(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommandWithArg), ToolboxMessageTree(I18n::Message::ReCommandWithArg, I18n::Message::RealPart, I18n::Message::ReCommandWithArg), ToolboxMessageTree(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommandWithArg), - ToolboxMessageTree(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommandWithArg, nullptr, 0, - new ConjugateLayout( - new EmptyVisibleLayout()), - const_cast(&pointedLayoutPathConj[0]), - 1)}; + ToolboxMessageTree(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommandWithArg)}; -const int pointedLayoutPathBinomial[] = {0, 0}; const ToolboxMessageTree probabilityChildren[2] = { - ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg, nullptr, 0, - new ParenthesisLayout( - new GridLayout(Poincare::ExpressionLayoutArray( - new EmptyVisibleLayout(), - new EmptyVisibleLayout()).array(), - 2, 1, false)), - const_cast(&pointedLayoutPathBinomial[0]), - 2), + ToolboxMessageTree(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommandWithArg), ToolboxMessageTree(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommandWithArg)}; const ToolboxMessageTree arithmeticChildren[4] = { @@ -100,8 +72,6 @@ const ToolboxMessageTree predictionChildren[3] = { ToolboxMessageTree(I18n::Message::PredictionCommandWithArg, I18n::Message::Prediction, I18n::Message::PredictionCommandWithArg), ToolboxMessageTree(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommandWithArg)}; -const int pointedLayoutPathAbs[] = {0}; -const int pointedLayoutPathRoot[] = {1}; const int pointedLayoutPathLog[] = {3,0}; #if LIST_ARE_DEFINED const ToolboxMessageTree menu[12] = { @@ -110,21 +80,9 @@ const ToolboxMessageTree menu[11] = { #else const ToolboxMessageTree menu[10] = { #endif - ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg, nullptr, 0, - new AbsoluteValueLayout( - new EmptyVisibleLayout()), - const_cast(&pointedLayoutPathAbs[0]), - 1), - ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg, nullptr, 0, - new NthRootLayout( - new EmptyVisibleLayout(), - new EmptyVisibleLayout()), - const_cast(&pointedLayoutPathRoot[0]), - 1), - ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg, nullptr, 0, - LayoutEngine::createLogLayout(nullptr, new EmptyVisibleLayout()), - const_cast(&pointedLayoutPathLog[0]), - 2), + ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg), + ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg), + ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg, nullptr, 0, const_cast(&pointedLayoutPathLog[0]), 2), ToolboxMessageTree(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), ToolboxMessageTree(I18n::Message::ComplexNumber, I18n::Message::Default, I18n::Message::Default, complexChildren, 5), ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), @@ -175,13 +133,38 @@ bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { return true; } // Deal with ExpressionEditor::Controller for now. + ToolboxMessageTree * messageTree = selectedMessageTree; m_selectableTableView.deselectTable(); - ExpressionLayout * newLayout = selectedMessageTree->layout()->clone(); - ExpressionLayout * pointedLayout = newLayout; - for (int i = 0; i < selectedMessageTree->pointedPathLength(); i++) { - pointedLayout = pointedLayout->editableChild(selectedMessageTree->pointedPath()[i]); + // Translate the message and replace the arguments with Empty chars. + const char * editedText = I18n::translate(messageTree->insertedText()); + char strippedEditedText[strlen(editedText)]; + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedEditedText); + // Create the layout + Expression * resultExpression = Expression::parse(strippedEditedText); + if (resultExpression != nullptr) { + ExpressionLayout * resultLayout = resultExpression->createLayout(); + // Find the pointed layout. + ExpressionLayout * pointedLayout = resultLayout; + if (messageTree->pointedPath() != nullptr) { + for (int i = 0; i < messageTree->pointedPathLength(); i++) { + assert(messageTree->pointedPath()[i] < pointedLayout->numberOfChildren()); + pointedLayout = pointedLayout->editableChild(messageTree->pointedPath()[i]); + } + } else if (resultLayout->isHorizontal()) { + // If the layout is horizontal, pick the first open parenthesis. + for (int i = 0; i < resultLayout->numberOfChildren(); i++) { + if (resultLayout->editableChild(i)->isLeftParenthesis()) { + pointedLayout = resultLayout->editableChild(i); + break; + } + } + } else if (resultLayout->numberOfChildren() > 0) { + // Else, if the layout has children, pick the first one. + pointedLayout = resultLayout->editableChild(0); + } + // Insert the layout + expressionEditorControllerSender()->insertLayoutAtCursor(resultLayout, pointedLayout); } - expressionEditorControllerSender()->insertLayoutAtCursor(newLayout, pointedLayout); app()->dismissModalViewController(); return true; } diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index 333a38171..a1da1475f 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -1,4 +1,5 @@ #include "toolbox_helpers.h" +#include #include namespace Shared { @@ -40,5 +41,21 @@ void TextToInsertForCommandText(const char * command, char * buffer) { buffer[currentNewTextIndex] = 0; } +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer) { + const char * messageText = I18n::translate(message); + TextToInsertForCommandText(messageText, buffer); + size_t bufferLength = strlen(buffer); + for (size_t i = 0; i < bufferLength; i++) { + if (buffer[i] == '(' || buffer[i] == ',') { + // Shift the buffer to make room for the new char. Use memmove to avoid + // overwritting. + memmove(&buffer[i+2], &buffer[i+1], bufferLength - (i+1) + 1); + bufferLength++; + i++; + buffer[i] = Ion::Charset::Empty; + } + } +} + } } diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index e28e8e4cc..98539614d 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -17,6 +17,8 @@ void TextToInsertForCommandMessage(I18n::Message message, char * buffer); void TextToInsertForCommandText(const char * command, char * buffer); /* Removes the arguments from a command: * - Removes text between parentheses, except commas */ +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer); +/* Removes the arguments from a command and replaces them with empty chars. */ } } diff --git a/escher/Makefile b/escher/Makefile index a540f4c6b..3a1964bb1 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -70,7 +70,6 @@ objs += $(addprefix escher/src/,\ tiled_view.o\ timer.o\ toolbox.o\ - toolbox_message_tree.o\ view.o\ view_controller.o\ warning_controller.o\ diff --git a/escher/include/escher/toolbox_message_tree.h b/escher/include/escher/toolbox_message_tree.h index 253ce36ce..062271417 100644 --- a/escher/include/escher/toolbox_message_tree.h +++ b/escher/include/escher/toolbox_message_tree.h @@ -6,27 +6,24 @@ class ToolboxMessageTree : public MessageTree { public: - constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, Poincare::ExpressionLayout * layout = nullptr, int * pointedLayoutPath = nullptr, int pointedLayoutPathLength = 0) : + constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, int * pointedLayoutPath = nullptr, int pointedLayoutPathLength = 0) : MessageTree(label, numberOfChildren), m_children(children), m_text(text), m_insertedText(insertedText), - m_layout(layout), m_pointedLayoutPath(pointedLayoutPath), m_pointedLayoutPathLength(pointedLayoutPathLength) { }; - const MessageTree * children(int index) const override; - I18n::Message text() const; - I18n::Message insertedText() const; - Poincare::ExpressionLayout * layout() const { return m_layout; } + const MessageTree * children(int index) const override { return &m_children[index]; } + I18n::Message text() const { return m_text; } + I18n::Message insertedText() const { return m_insertedText; } int * pointedPath() const { return m_pointedLayoutPath; } int pointedPathLength() const { return m_pointedLayoutPathLength; } private: const ToolboxMessageTree * m_children; I18n::Message m_text; I18n::Message m_insertedText; - Poincare::ExpressionLayout * m_layout; int * m_pointedLayoutPath; int m_pointedLayoutPathLength; }; diff --git a/escher/src/toolbox_message_tree.cpp b/escher/src/toolbox_message_tree.cpp deleted file mode 100644 index 595e7e300..000000000 --- a/escher/src/toolbox_message_tree.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -I18n::Message ToolboxMessageTree::text() const { - return m_text; -} - -I18n::Message ToolboxMessageTree::insertedText() const { - return m_insertedText; -} - -const MessageTree * ToolboxMessageTree::children(int index) const { - return &m_children[index]; -} From 5d39f177ba7bf91560b97fa9e11dc349ea32739f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 15:46:15 +0100 Subject: [PATCH 139/459] [poincare] Decide to delete EmptyLayouts when merging HorizontalLay. A bool in HorizontalLayout::addOrMergeChildAtIndex decides whether to delete the Emtpy new HorizontalLayout children. Change-Id: Ie7acd7f5052891a929c2ae22cb74de389649cba2 --- .../poincare/dynamic_layout_hierarchy.h | 4 ++-- poincare/src/expression_layout_cursor.cpp | 4 ++-- poincare/src/factorial.cpp | 2 +- .../src/layout/dynamic_layout_hierarchy.cpp | 9 +++++---- poincare/src/layout/expression_layout.cpp | 2 +- poincare/src/layout/fraction_layout.cpp | 4 ++-- poincare/src/layout/horizontal_layout.cpp | 6 +++--- poincare/src/layout/horizontal_layout.h | 2 +- poincare/src/layout_engine.cpp | 19 ++++++++++--------- poincare/src/opposite.cpp | 4 ++-- poincare/src/store.cpp | 4 ++-- 11 files changed, 31 insertions(+), 29 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index a75e9fc41..a40a7fd13 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -25,10 +25,10 @@ public: int numberOfChildren() const override { return m_numberOfChildren; } const ExpressionLayout * const * children() const override { return m_children; }; - void addNonEmptyChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion); + void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren); bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; - void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index); // WITHOUT delete. + void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. bool isEmpty() const override; protected: diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 1070b4167..b723de7d0 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -77,7 +77,7 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( ExpressionLayout * rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); if (rightBrother->isCollapsable(&numberOfOpenParenthesis, false)) { newChild->editableParent()->removeChildAtIndex(fractionIndexInParent+1, false); - child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren()); + child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), true); numberOfBrothers--; } else { break; @@ -89,7 +89,7 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( ExpressionLayout * leftBrother = newChild->editableParent()->editableChild(fractionIndexInParent-1); if (leftBrother->isCollapsable(&numberOfOpenParenthesis, true)) { newChild->editableParent()->removeChildAtIndex(fractionIndexInParent-1, false); - child1->addOrMergeChildAtIndex(leftBrother, 0); + child1->addOrMergeChildAtIndex(leftBrother, 0, true); fractionIndexInParent--; } else { break; diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 436b91067..aebe1c98e 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -77,7 +77,7 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0); + result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); result->addChildAtIndex(new CharLayout('!'), result->numberOfChildren()); return result; } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 707383ed4..5e3c0c5ab 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -42,17 +42,17 @@ DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { delete[] m_children; } -void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index) { +void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { int indexOfEL = indexOfChild(eL); if (indexOfEL >= 0) { removeChildAtIndex(indexOfEL, false); } - addNonEmptyChildrenAtIndex(eL->children(), eL->numberOfChildren(), index); + addChildrenAtIndex(eL->children(), eL->numberOfChildren(), index, removeEmptyChildren); eL->detachChildren(); delete eL; } -void DynamicLayoutHierarchy::addNonEmptyChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion) { +void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { assert(numberOfOperands > 0); const ExpressionLayout ** newOperands = new const ExpressionLayout * [m_numberOfChildren+numberOfOperands]; int currentIndex = 0; @@ -61,7 +61,8 @@ void DynamicLayoutHierarchy::addNonEmptyChildrenAtIndex(const ExpressionLayout * newOperands[currentIndex++] = m_children[i]; } for (int i=0; iisEmpty() + if (!removeEmptyChildren + || !operands[i]->isEmpty() || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftBrother())) { const_cast(operands[i])->setParent(this); diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 4c0c196ee..9c0c45435 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -130,7 +130,7 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay assert(m_parent); int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; if (m_parent->isHorizontal()) { - static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex); + static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex, true); return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index c7e6677d6..f2c57ae87 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -72,8 +72,8 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { detachChild(numerator); detachChild(denominator); HorizontalLayout * newLayout = new HorizontalLayout(); - newLayout->addOrMergeChildAtIndex(denominator, 0); - newLayout->addOrMergeChildAtIndex(numerator, 0); + newLayout->addOrMergeChildAtIndex(denominator, 0, true); + newLayout->addOrMergeChildAtIndex(numerator, 0, true); // Add the denominator before the numerator to have the right order. replaceWith(newLayout, true); cursor->setPointedExpressionLayout(nextPointedLayout); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 1ad87670c..7594a6ff2 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -52,7 +52,7 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio // new layout then destroy it. if (newChild->isHorizontal()) { int indexForInsertion = indexOfChild(const_cast(oldChild)); - mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1); + mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); removeChildAtIndex(indexForInsertion, deleteOldChild); return; } @@ -60,14 +60,14 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); } -void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index) { +void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { int newIndex = index; if (numberOfChildren() > 0 && child(0)->isEmpty()) { removeChildAtIndex(0, true); newIndex = index == 0 ? 0 : index - 1; } if (eL->isHorizontal()) { - mergeChildrenAtIndex(static_cast(eL), newIndex); + mergeChildrenAtIndex(static_cast(eL), newIndex, removeEmptyChildren); return; } addChildAtIndex(eL, newIndex); diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 6b789e770..14cd7ce5e 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -17,7 +17,7 @@ public: /* Hierarchy */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; - void addOrMergeChildAtIndex(ExpressionLayout * eL, int index); + void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index f54bbba22..2070791c4 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -16,14 +16,14 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(expression->operand(0)->createLayout(), 0); + result->addOrMergeChildAtIndex(expression->operand(0)->createLayout(), 0, true); for (int i = 1; i < numberOfOperands; i++) { - result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result->numberOfChildren()); + result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result->numberOfChildren(), true); result->addOrMergeChildAtIndex( expression->operand(i)->type() == Expression::Type::Opposite ? createParenthesedLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat), - result->numberOfChildren()); + result->numberOfChildren(), true); } return result; } @@ -32,21 +32,22 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio assert(floatDisplayMode != Expression::FloatDisplayMode::Default); assert(complexFormat != Expression::ComplexFormat::Default); int numberOfOperands = expression->numberOfOperands(); + assert(numberOfOperands > 0); HorizontalLayout * result = new HorizontalLayout(); // Add the operator name. - result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0); + result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); // Create the layout of arguments separated by commas. HorizontalLayout * args = new HorizontalLayout(); - args->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0); + args->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0, true); for (int i = 1; i < numberOfOperands; i++) { args->addChildAtIndex(new CharLayout(','), args->numberOfChildren()); - args->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args->numberOfChildren()); + args->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args->numberOfChildren(), true); } // Add the parenthesed arguments. - result->addOrMergeChildAtIndex(createParenthesedLayout(args, false), result->numberOfChildren()); + result->addOrMergeChildAtIndex(createParenthesedLayout(args, false), result->numberOfChildren(), true); return result; } @@ -54,7 +55,7 @@ ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layo HorizontalLayout * result = new HorizontalLayout(); result->addChildAtIndex(new ParenthesisLeftLayout(), 0); if (layout != nullptr) { - result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1); + result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1, true); } result->addChildAtIndex(new ParenthesisRightLayout(), result->numberOfChildren()); return result; @@ -73,7 +74,7 @@ ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, Ex HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(index, VerticalOffsetLayout::Type::Subscript, false); resultLayout->addChildAtIndex(offsetLayout, resultLayout->numberOfChildren()); - resultLayout->addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout->numberOfChildren()); + resultLayout->addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout->numberOfChildren(), true); return resultLayout; } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index ec0246192..adabe0422 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -50,10 +50,10 @@ ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMo assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(new CharLayout('-'), false); if (operand(0)->type() == Type::Opposite) { - result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1); + result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1, false); return result; } - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1); + result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); return result; } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index fbfc5b16d..d9a4945f3 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -29,9 +29,9 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0); + result->addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0, false); result->addChildAtIndex(new CharLayout(Ion::Charset::Sto), result->numberOfChildren()); - result->addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren()); + result->addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), false); return result; } From 6144e9ec1cf9bb461b471b4b0f31351402113e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 16:38:56 +0100 Subject: [PATCH 140/459] [poincare] Remove EmptyLayout, keep EmptyVisibleLayout only. Change-Id: I99bfb397accc94551802a2726ab4b24483db9396 --- poincare/Makefile | 1 - poincare/src/layout/empty_layout.cpp | 49 -------------------- poincare/src/layout/empty_layout.h | 31 ------------- poincare/src/layout/empty_visible_layout.cpp | 14 +++++- poincare/src/layout/empty_visible_layout.h | 11 ++++- 5 files changed, 22 insertions(+), 84 deletions(-) delete mode 100644 poincare/src/layout/empty_layout.cpp delete mode 100644 poincare/src/layout/empty_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index a04201309..ce40174e4 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -95,7 +95,6 @@ objs += $(addprefix poincare/src/layout/,\ condensed_sum_layout.o\ conjugate_layout.o\ dynamic_layout_hierarchy.o\ - empty_layout.o\ empty_visible_layout.o\ expression_layout.o\ floor_layout.o\ diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp deleted file mode 100644 index c7af45bf2..000000000 --- a/poincare/src/layout/empty_layout.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "empty_layout.h" -#include -#include - -namespace Poincare { - -ExpressionLayout * EmptyLayout::clone() const { - EmptyLayout * layout = new EmptyLayout(); - return layout; -} - -int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - if (bufferSize == 0) { - return -1; - } - buffer[0] = 0; - return 0; -} - -void EmptyLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - replaceWith(brother, true); -} - -bool EmptyLayout::moveLeft(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool EmptyLayout::moveRight(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - // Ask the parent. - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -void EmptyLayout::computeBaseline() { - m_baseline = 0; - m_baselined = true; -} - -} diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h deleted file mode 100644 index 5d82724f7..000000000 --- a/poincare/src/layout/empty_layout.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef POINCARE_EMPTY_LAYOUT_H -#define POINCARE_EMPTY_LAYOUT_H - -#include -#include -#include - -namespace Poincare { - -class EmptyLayout : public StaticLayoutHierarchy<0> { -public: - using StaticLayoutHierarchy::StaticLayoutHierarchy; - ExpressionLayout * clone() const override; - void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; - bool isEmpty() const override { return true; } -protected: - virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override { return; } - virtual KDSize computeSize() override { return KDSizeZero; } - void computeBaseline() override; - KDPoint positionOfChild(ExpressionLayout * child) override { - assert(false); - return KDPointZero; - } -}; - -} - -#endif diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index a7ac20513..3ecceef79 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -5,7 +5,7 @@ namespace Poincare { EmptyVisibleLayout::EmptyVisibleLayout() : - EmptyLayout(), + StaticLayoutHierarchy(), m_fillRectColor(KDColor::RGB24(0xffd370)) //TODO make static or in Palette? { } @@ -15,6 +15,10 @@ ExpressionLayout * EmptyVisibleLayout::clone() const { return layout; } +void EmptyVisibleLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { + replaceWith(brother, true); +} + void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { @@ -59,6 +63,14 @@ bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; +} + void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 65714d0ac..f96eb0749 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -1,22 +1,29 @@ #ifndef POINCARE_EMPTY_VISIBLE_LAYOUT_H #define POINCARE_EMPTY_VISIBLE_LAYOUT_H -#include "empty_layout.h" +#include #include namespace Poincare { -class EmptyVisibleLayout : public EmptyLayout { +class EmptyVisibleLayout : public StaticLayoutHierarchy<0> { public: EmptyVisibleLayout(); ExpressionLayout * clone() const override; + void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; + bool isEmpty() const override { return true; } protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; virtual KDSize computeSize() override; void computeBaseline() override; + KDPoint positionOfChild(ExpressionLayout * child) override { + assert(false); + return KDPointZero; + } private: constexpr static KDCoordinate k_width = 7; constexpr static KDCoordinate k_height = 13; From cd9c0472c81e13e9b16005579725e7bb14b118e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 17:30:33 +0100 Subject: [PATCH 141/459] [poincare] BinomialCoefficientLayout. Change-Id: I3ea9d9d7d9dbf2884c458eb17340700e14648044 --- poincare/Makefile | 1 + poincare/include/poincare_layouts.h | 1 + poincare/src/binomial_coefficient.cpp | 11 +- .../layout/binomial_coefficient_layout.cpp | 161 ++++++++++++++++++ .../src/layout/binomial_coefficient_layout.h | 33 ++++ poincare/src/layout/grid_layout.h | 1 + poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/parenthesis_left_layout.h | 1 + .../src/layout/parenthesis_right_layout.h | 1 + 9 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 poincare/src/layout/binomial_coefficient_layout.cpp create mode 100644 poincare/src/layout/binomial_coefficient_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index ce40174e4..49bd3a0a5 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -85,6 +85,7 @@ objs += $(addprefix poincare/src/,\ objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ + binomial_coefficient_layout.o\ bounded_static_layout_hierarchy.o\ bracket_layout.o\ bracket_left_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 34191f18d..875963fe8 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index d770e25bf..8cf0a1d73 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -2,8 +2,7 @@ #include #include #include -#include "layout/parenthesis_layout.h" -#include "layout/grid_layout.h" +#include "layout/binomial_coefficient_layout.h" extern "C" { #include @@ -76,10 +75,10 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); - return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1, false), false); + return new BinomialCoefficientLayout( + operand(0)->createLayout(floatDisplayMode, complexFormat), + operand(1)->createLayout(floatDisplayMode, complexFormat), + false); } template diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp new file mode 100644 index 000000000..28b253081 --- /dev/null +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -0,0 +1,161 @@ +#include "binomial_coefficient_layout.h" +#include "empty_visible_layout.h" +#include "grid_layout.h" +#include "horizontal_layout.h" +#include "parenthesis_left_layout.h" +#include "parenthesis_left_right_layout.h" +#include "parenthesis_right_layout.h" +#include +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +ExpressionLayout * BinomialCoefficientLayout::clone() const { + return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); +} + +void BinomialCoefficientLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left of the children. + // Delete the layout. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && (cursor->pointedExpressionLayout() == nLayout() + || cursor->pointedExpressionLayout() == kLayout())) + { + assert(m_parent != nullptr); + int indexInParent = m_parent->indexOfChild(this); + ExpressionLayout * parent = m_parent; + replaceWith(new EmptyVisibleLayout(), true); + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(parent); + return; + } + cursor->setPointedExpressionLayout(parent->editableChild(indexInParent-1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; + } + ExpressionLayout::backspaceAtCursor(cursor); +} + +bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor) { + // Case: Left of the children. + // Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Left + && (cursor->pointedExpressionLayout() == nLayout() + || cursor->pointedExpressionLayout() == kLayout())) + { + cursor->setPointedExpressionLayout(this); + return true; + } + + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. + // Go to the kLayout. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + assert(kLayout() != nullptr); + cursor->setPointedExpressionLayout(kLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return true; + } + + // Case: Left. + // Ask the parent. + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (m_parent) { + return m_parent->moveLeft(cursor); + } + return false; +} + +bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Right of the children. + // Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Right + && (cursor->pointedExpressionLayout() == nLayout() + || cursor->pointedExpressionLayout() == kLayout())) + { + cursor->setPointedExpressionLayout(this); + return true; + } + + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Go Left of the nLayout. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + assert(nLayout() != nullptr); + cursor->setPointedExpressionLayout(nLayout()); + return true; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // Ask the parent. + if (m_parent) { + return m_parent->moveRight(cursor); + } + return false; +} + +bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Case: kLayout. + // Move to nLayout. + if (previousLayout == kLayout()) { + return nLayout()->moveUpInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + +bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + // Case: nLayout. + // Move to kLayout. + if (previousLayout == nLayout()) { + return kLayout()->moveDownInside(cursor); + } + return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); +} + +void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Render the parentheses. + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); + HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); + KDPoint leftParenthesisPoint = dummyLayout.positionOfChild(dummyLeftParenthesis); + KDPoint rightParenthesisPoint = dummyLayout.positionOfChild(dummyRightParenthesis); + dummyLeftParenthesis->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); + dummyRightParenthesis->render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor); +} + +KDSize BinomialCoefficientLayout::computeSize() { + KDSize coefficientsSize = GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true).size(); + return KDSize(coefficientsSize.width() + 2*ParenthesisLeftRightLayout::parenthesisWidth(), coefficientsSize.height()); +} + +void BinomialCoefficientLayout::computeBaseline() { + m_baseline = GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true).baseline(); + m_baselined = true; +} + +KDPoint BinomialCoefficientLayout::positionOfChild(ExpressionLayout * child) { + ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); + HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); + if (child == nLayout()) { + return dummyGridLayout->positionOfChild(dummyGridLayout->editableChild(0)).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); + } + assert(child == kLayout()); + return dummyGridLayout->positionOfChild(dummyGridLayout->editableChild(1)).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); +} + +ExpressionLayout * BinomialCoefficientLayout::nLayout() { + return editableChild(0); +} + +ExpressionLayout * BinomialCoefficientLayout::kLayout() { + return editableChild(1); +} + +} diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h new file mode 100644 index 000000000..9fee26479 --- /dev/null +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_BINOMIAL_COEFFICIENT_LAYOUT_H +#define POINCARE_BINOMIAL_COEFFICIENT_LAYOUT_H + +#include +#include + +namespace Poincare { + +class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { +public: + using StaticLayoutHierarchy::StaticLayoutHierarchy; + ExpressionLayout * clone() const override; + void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "binomial"); + } +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(ExpressionLayout * child) override; +private: + ExpressionLayout * kLayout(); + ExpressionLayout * nLayout(); +}; + +} + +#endif diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 7d89e01e6..4ed010675 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -6,6 +6,7 @@ namespace Poincare { class GridLayout : public DynamicLayoutHierarchy { + friend class BinomialCoefficientLayout; public: GridLayout(const ExpressionLayout * const * entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 14cd7ce5e..d25fa9921 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { + friend class BinomialCoefficientLayout; friend class IntegralLayout; friend class ParenthesisLayout; friend class SequenceLayout; diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index ea383da99..4e46265ec 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { friend class ParenthesisLayout; + friend class BinomialCoefficientLayout; friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 0c3f8ce7a..3e52cc862 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class ParenthesisRightLayout : public ParenthesisLeftRightLayout { friend class ParenthesisLayout; + friend class BinomialCoefficientLayout; friend class SequenceLayout; public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; From dc9ab66f4921f3ced0833d28b518627db6475c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 9 Jan 2018 17:31:23 +0100 Subject: [PATCH 142/459] [poincare] Remove ParenthesisLayout. Change-Id: I570e85eca45fb89fe0363a000dd7c12835996c15 --- poincare/Makefile | 1 - poincare/include/poincare_layouts.h | 1 - poincare/src/layout/horizontal_layout.h | 1 - poincare/src/layout/parenthesis_layout.cpp | 110 ------------------ poincare/src/layout/parenthesis_layout.h | 37 ------ poincare/src/layout/parenthesis_left_layout.h | 1 - .../src/layout/parenthesis_right_layout.h | 1 - 7 files changed, 152 deletions(-) delete mode 100644 poincare/src/layout/parenthesis_layout.cpp delete mode 100644 poincare/src/layout/parenthesis_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index 49bd3a0a5..38fe3cce4 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -104,7 +104,6 @@ objs += $(addprefix poincare/src/layout/,\ horizontal_layout.o\ integral_layout.o\ nth_root_layout.o\ - parenthesis_layout.o\ parenthesis_left_layout.o\ parenthesis_left_right_layout.o\ parenthesis_right_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 875963fe8..2f447e3f9 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index d25fa9921..1114dbd40 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -9,7 +9,6 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { friend class BinomialCoefficientLayout; friend class IntegralLayout; - friend class ParenthesisLayout; friend class SequenceLayout; public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp deleted file mode 100644 index ed81ff533..000000000 --- a/poincare/src/layout/parenthesis_layout.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "parenthesis_layout.h" -#include "horizontal_layout.h" -#include "parenthesis_left_layout.h" -#include "parenthesis_left_right_layout.h" -#include "parenthesis_right_layout.h" -#include -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -ExpressionLayout * ParenthesisLayout::clone() const { - return new ParenthesisLayout(const_cast(this)->operandLayout(), true); -} - -bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor) { - // Case: Left of the operand. - // Go Left. - if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - cursor->setPointedExpressionLayout(this); - return true; - } - - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the operand and move left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return operandLayout()->moveLeft(cursor); - } - - // Case: Left. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->moveLeft(cursor); - } - return false; -} - -bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor) { - // Case: Right of the operand. - // Go Right. - if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - cursor->setPointedExpressionLayout(this); - return true; - } - - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Left of the operand and moveRight. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - return operandLayout()->moveRight(cursor);; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. - if (m_parent) { - return m_parent->moveRight(cursor); - } - return false; -} - -void ParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - // Render the parentheses. - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); - ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); - HorizontalLayout dummyLayout(dummyLeftParenthesis, operandLayout()->clone(), dummyRightParenthesis, false); - KDPoint leftParenthesisPoint = positionOfChild(operandLayout()).translatedBy(dummyLayout.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout.positionOfChild(dummyLayout.editableChild(1)).opposite()); - KDPoint rightParenthesisPoint = positionOfChild(operandLayout()).translatedBy(dummyLayout.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout.positionOfChild(dummyLayout.editableChild(1)).opposite()); - dummyLeftParenthesis->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); - dummyRightParenthesis->render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor); -} - -KDSize ParenthesisLayout::computeSize() { - KDSize operandSize = operandLayout()->size(); - return KDSize(operandSize.width() + 2*ParenthesisLeftRightLayout::parenthesisWidth(), operandSize.height()); -} - -void ParenthesisLayout::computeBaseline() { - m_baseline = operandLayout()->baseline(); - m_baselined = true; -} - -KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { - if (child == operandLayout()) { - return KDPoint(ParenthesisLeftRightLayout::parenthesisWidth(), 0); - } - assert(false); - return KDPointZero; -} - -ExpressionLayout * ParenthesisLayout::operandLayout() { - return editableChild(0); -} - -} diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h deleted file mode 100644 index af110702f..000000000 --- a/poincare/src/layout/parenthesis_layout.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef POINCARE_PARENTHESIS_LAYOUT_H -#define POINCARE_PARENTHESIS_LAYOUT_H - -#include -#include - -/* ParenthesisLayout has one operand and renders the parentheses around it. - * This layout should thus be used for uneditable parentheses, e.g. to create - * binomial coefficient layouts. */ - -namespace Poincare { - -class ParenthesisLayout : public StaticLayoutHierarchy<1> { -public: - using StaticLayoutHierarchy::StaticLayoutHierarchy; - ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); - } -protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDSize computeSize() override; - void computeBaseline() override; - KDPoint positionOfChild(ExpressionLayout * child) override; -private: - constexpr static KDCoordinate k_externWidthMargin = 1; - constexpr static KDCoordinate k_externHeightMargin = 2; - constexpr static KDCoordinate k_widthMargin = 5; - constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayout * operandLayout(); -}; - -} - -#endif diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 4e46265ec..468385383 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -7,7 +7,6 @@ namespace Poincare { class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { - friend class ParenthesisLayout; friend class BinomialCoefficientLayout; friend class SequenceLayout; public: diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 3e52cc862..fb372b06c 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -7,7 +7,6 @@ namespace Poincare { class ParenthesisRightLayout : public ParenthesisLeftRightLayout { - friend class ParenthesisLayout; friend class BinomialCoefficientLayout; friend class SequenceLayout; public: From 663c90f764260429fbabaa500d3bfe928389db46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 11:20:10 +0100 Subject: [PATCH 143/459] [poincare] MatrixLayout. Change-Id: I57c67a95fadcfd7ea320d4fef49e45b4e166a40d --- poincare/Makefile | 1 + poincare/include/poincare_layouts.h | 1 + poincare/src/layout/bracket_left_layout.h | 1 + poincare/src/layout/bracket_right_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 66 +++++--------------- poincare/src/layout/grid_layout.h | 14 ++--- poincare/src/layout/horizontal_layout.h | 1 + poincare/src/layout/matrix_layout.cpp | 72 ++++++++++++++++++++++ poincare/src/layout/matrix_layout.h | 22 +++++++ 9 files changed, 122 insertions(+), 57 deletions(-) create mode 100644 poincare/src/layout/matrix_layout.cpp create mode 100644 poincare/src/layout/matrix_layout.h diff --git a/poincare/Makefile b/poincare/Makefile index 38fe3cce4..2ef8a3100 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -103,6 +103,7 @@ objs += $(addprefix poincare/src/layout/,\ grid_layout.o\ horizontal_layout.o\ integral_layout.o\ + matrix_layout.o\ nth_root_layout.o\ parenthesis_left_layout.o\ parenthesis_left_right_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 2f447e3f9..818351031 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index 35af9d32b..77f9f00bb 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class BracketLeftLayout : public BracketLeftRightLayout { + friend class MatrixLayout; public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index bc5af7548..726d23694 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class BracketRightLayout : public BracketLeftRightLayout { + friend class MatrixLayout; public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 5756d1c4c..cd64875a4 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -22,25 +22,28 @@ ExpressionLayout * GridLayout::clone() const { } void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // If the cursor is on the left of the grid, delete the grid and its parent: A - // grid only exists for now in binomial coefficient and in matrices, and we - // want to delete their parentheses or brackets too. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0 && childIsLeftOfGrid(indexOfPointedExpression)) { + // Case: Left of a left child grid. + // Delete the grid. assert(m_parent != nullptr); - assert(m_parent->parent() != nullptr); - ExpressionLayout * grandParent = const_cast(m_parent->parent()); - int indexInGrandParent = grandParent->indexOfChild(m_parent); - m_parent->replaceWith(new EmptyVisibleLayout(), true); - if (indexInGrandParent == 0) { - cursor->setPointedExpressionLayout(grandParent); + int indexInParent = m_parent->indexOfChild(this); + // Set the new cursor position before deleting. + if (indexInParent == 0) { + cursor->setPointedExpressionLayout(m_parent); return; } - cursor->setPointedExpressionLayout(grandParent->editableChild(indexInGrandParent-1)); + cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); + // Delete this. + replaceWith(new EmptyVisibleLayout(), true); return; } + // Case: Left of another child of the grid. + // Move Left. + moveLeft(cursor); + return; } ExpressionLayout::backspaceAtCursor(cursor); } @@ -64,7 +67,7 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go Left of the grid cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_parent->moveLeft(cursor); + return true; } // Case: Left of another child. // Go Right of its brother on the left. @@ -98,10 +101,10 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Right) { if (childIsRightOfGrid(childIndex)) { // Case: Right of a child on the right of the grid. - // Go Right of the grid and move Right. + // Go Right of the grid. cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_parent->moveRight(cursor); + return true; } // Case: Right of another child. // Go Left of its brother on the right. @@ -142,43 +145,6 @@ void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { ExpressionLayout::removeChildAtIndex(index, deleteAfterRemoval); } -int GridLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - const ExpressionLayout * editableParent = const_cast(this)->parent(); - assert(editableParent != nullptr); - - // If the grid is a binomial coefficient: - if (editableParent->child(0)->isLeftParenthesis()) { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "binomial"); - } - - assert(editableParent->child(0)->isLeftBracket()); - // The grid is a matrix. - if (bufferSize == 0) { - return -1; - } - buffer[bufferSize-1] = 0; - int numberOfChar = 0; - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - - for (int i = 0; i < m_numberOfRows; i++) { - buffer[numberOfChar++] = '['; - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, (i+1) * m_numberOfColumns - 1); - - buffer[numberOfChar++] = ']'; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - - if (i < m_numberOfRows - 1) { - buffer[numberOfChar++] = ','; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - } - } - - buffer[numberOfChar] = 0; - return numberOfChar; -} - KDCoordinate GridLayout::rowBaseline(int i) { KDCoordinate rowBaseline = 0; for (int j = 0; j < m_numberOfColumns; j++) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 4ed010675..c9853bd30 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -18,20 +18,23 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; - //TODO: is this ok? If we want to delete the grid's children, we have to make - //sure no to call this function. + // TODO: This function replaces the child with an EmptyVisibleLayout. Is this + // ok? If we want to delete the grid's children, we have to make sure no to + // call this function. /* Expression engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; + int indexOfChild(ExpressionLayout * eL) const; + int m_numberOfRows; + int m_numberOfColumns; private: constexpr static KDCoordinate k_gridEntryMargin = 6; KDCoordinate rowBaseline(int i); @@ -39,13 +42,10 @@ private: KDCoordinate height(); KDCoordinate columnWidth(int j); KDCoordinate width(); - int indexOfChild(ExpressionLayout * eL) const; bool childIsLeftOfGrid(int index) const; bool childIsRightOfGrid(int index) const; bool childIsTopOfGrid(int index) const; bool childIsBottomOfGrid(int index) const; - int m_numberOfRows; - int m_numberOfColumns; }; } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 1114dbd40..2e664a39c 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -9,6 +9,7 @@ namespace Poincare { class HorizontalLayout : public DynamicLayoutHierarchy { friend class BinomialCoefficientLayout; friend class IntegralLayout; + friend class MatrixLayout; friend class SequenceLayout; public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp new file mode 100644 index 000000000..40f452f45 --- /dev/null +++ b/poincare/src/layout/matrix_layout.cpp @@ -0,0 +1,72 @@ +#include "matrix_layout.h" +#include "horizontal_layout.h" +#include "bracket_left_layout.h" +#include "bracket_right_layout.h" +#include +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +ExpressionLayout * MatrixLayout::clone() const { + MatrixLayout * layout = new MatrixLayout(children(), m_numberOfRows, m_numberOfColumns, true); + return layout; +} + +int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + // The grid is a matrix. + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + buffer[numberOfChar++] = '['; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + for (int i = 0; i < m_numberOfRows; i++) { + buffer[numberOfChar++] = '['; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, (i+1) * m_numberOfColumns - 1); + + buffer[numberOfChar++] = ']'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + buffer[numberOfChar++] = ']'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void MatrixLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); + BracketRightLayout * dummyRightBracket = new BracketRightLayout(); + ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); + KDPoint leftBracketPoint = dummyLayout.positionOfChild(dummyLeftBracket); + KDPoint rightBracketPoint = dummyLayout.positionOfChild(dummyRightBracket); + dummyLeftBracket->render(ctx, p.translatedBy(leftBracketPoint), expressionColor, backgroundColor); + dummyRightBracket->render(ctx, p.translatedBy(rightBracketPoint), expressionColor, backgroundColor); +} + +KDSize MatrixLayout::computeSize() { + BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); + BracketRightLayout * dummyRightBracket = new BracketRightLayout(); +ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); + return dummyLayout.size(); +} + +KDPoint MatrixLayout::positionOfChild(ExpressionLayout * child) { + BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); + BracketRightLayout * dummyRightBracket = new BracketRightLayout(); +ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); + return GridLayout::positionOfChild(child).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); +} + +} diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h new file mode 100644 index 000000000..910917846 --- /dev/null +++ b/poincare/src/layout/matrix_layout.h @@ -0,0 +1,22 @@ +#ifndef POINCARE_MATRIX_LAYOUT_H +#define POINCARE_MATRIX_LAYOUT_H + +#include + +namespace Poincare { + +class MatrixLayout : public GridLayout { +public: + using GridLayout::GridLayout; + ExpressionLayout * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + KDPoint positionOfChild(ExpressionLayout * child) override; +}; + +} + +#endif + From 2c562fdf7a2518742ec06373221463dc779d6f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 11:27:10 +0100 Subject: [PATCH 144/459] [expression_editor] Insert an empty matrix when adding a bracket. Change-Id: I5bf6ab9e097637e0e49f0941fe02e4f5a8e373a2 --- apps/expression_editor/controller.cpp | 11 ++++++++--- .../include/poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index 814200eb8..fdf9702cd 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -130,9 +130,14 @@ ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { } if (event.hasText()) { const char * textToInsert = event.text(); - if (textToInsert[0] == Ion::Charset::MultiplicationSign && textToInsert[1] == 0) { - const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - return m_cursor.insertText(middleDotString); + if (textToInsert[1] == 0) { + if (textToInsert[0] == Ion::Charset::MultiplicationSign) { + const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; + return m_cursor.insertText(middleDotString); + } + if (textToInsert[0] == '[' || textToInsert[0] == ']') { + return m_cursor.addEmptyMatrixLayout(); + } } return m_cursor.insertText(textToInsert); } diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 779cd9318..a4f5dbb85 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -43,6 +43,7 @@ public: ExpressionLayout * addEmptyExponentialLayout(); ExpressionLayout * addFractionLayoutAndCollapseBrothers(); ExpressionLayout * addEmptyLogarithmLayout(); + ExpressionLayout * addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); ExpressionLayout * addEmptyPowerLayout(); ExpressionLayout * addEmptySquareRootLayout(); ExpressionLayout * addEmptySquarePowerLayout(); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index b723de7d0..aebbd16b2 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -108,6 +108,21 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { return result; } +ExpressionLayout * ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { + assert(numberOfRows > 0); + assert(numberOfColumns > 0); + int numberOfchildren = (numberOfRows+1)*(numberOfColumns+1); + ExpressionLayout * children[numberOfchildren]; + for (int i = 0; i < numberOfchildren; i++) { + children[i] = new EmptyVisibleLayout(); + } + ExpressionLayout * matrixLayout = new MatrixLayout(const_cast(const_cast(children)), numberOfRows+1, numberOfColumns+1, false); + m_pointedExpressionLayout->addBrother(this, matrixLayout); + setPointedExpressionLayout(matrixLayout->editableChild(0)); + setPosition(ExpressionLayoutCursor::Position::Right); + return matrixLayout; +} + ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); // If there is already a base From 592c12cf0819c0959d7853472d209152e0f3c5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 11:36:42 +0100 Subject: [PATCH 145/459] [poincare] EmptyVisibleLayouts can be Yellow or Grey. Change-Id: Iac07105df5cbf5bcc70b84302a7bf39783716d50 --- poincare/src/layout/empty_visible_layout.cpp | 10 ++++++---- poincare/src/layout/empty_visible_layout.h | 10 +++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index 3ecceef79..e62f812f0 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -1,12 +1,13 @@ #include "empty_visible_layout.h" #include +#include #include namespace Poincare { -EmptyVisibleLayout::EmptyVisibleLayout() : +EmptyVisibleLayout::EmptyVisibleLayout(Color color) : StaticLayoutHierarchy(), - m_fillRectColor(KDColor::RGB24(0xffd370)) //TODO make static or in Palette? + m_color(color) { } @@ -72,8 +73,9 @@ int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), m_fillRectColor); + KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); } KDSize EmptyVisibleLayout::computeSize() { diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index f96eb0749..ae5a5e5c2 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -8,7 +8,11 @@ namespace Poincare { class EmptyVisibleLayout : public StaticLayoutHierarchy<0> { public: - EmptyVisibleLayout(); + enum class Color { + Yellow, + Grey + }; + EmptyVisibleLayout(Color color = Color::Yellow); ExpressionLayout * clone() const override; void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; @@ -16,6 +20,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; bool isEmpty() const override { return true; } + void setColor(Color color) { m_color = color; } protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; virtual KDSize computeSize() override; @@ -30,8 +35,7 @@ private: constexpr static KDCoordinate k_marginWidth = 1; constexpr static KDCoordinate k_marginHeight = 2; constexpr static KDCoordinate k_lineThickness = 1; - - KDColor m_fillRectColor; + Color m_color; }; } From d105dcc7f9df13c5070ba206a43aeb41a31325b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 12:02:53 +0100 Subject: [PATCH 146/459] [expression_editor] Grey outer cells for MatrixLayout. Change-Id: Iaf33ccd6c746843803b6a971a2b37eaf495fa766 --- poincare/src/expression_layout_cursor.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index aebbd16b2..3f89545d9 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -111,10 +111,15 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { ExpressionLayout * ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { assert(numberOfRows > 0); assert(numberOfColumns > 0); - int numberOfchildren = (numberOfRows+1)*(numberOfColumns+1); - ExpressionLayout * children[numberOfchildren]; - for (int i = 0; i < numberOfchildren; i++) { - children[i] = new EmptyVisibleLayout(); + ExpressionLayout * children[(numberOfRows+1)*(numberOfColumns+1)]; + for (int i = 0; i < numberOfRows + 1; i++) { + for (int j = 0; j < numberOfColumns + 1; j++) { + if (i < numberOfRows && j < numberOfColumns) { + children[i*(numberOfColumns+1)+j] = new EmptyVisibleLayout(EmptyVisibleLayout::Color::Yellow); + } else { + children[i*(numberOfColumns+1)+j] = new EmptyVisibleLayout(EmptyVisibleLayout::Color::Grey); + } + } } ExpressionLayout * matrixLayout = new MatrixLayout(const_cast(const_cast(children)), numberOfRows+1, numberOfColumns+1, false); m_pointedExpressionLayout->addBrother(this, matrixLayout); From 03e33e05e7bba5d3155feb0817907abcaf098bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 14:38:21 +0100 Subject: [PATCH 147/459] [poincare] Layout invalidation when adding children to DynamicLayouts. Change-Id: Ib4609a5e14cce0c5bae44c90629446caea75c164 --- poincare/src/layout/dynamic_layout_hierarchy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 5e3c0c5ab..ce8c5fa28 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -75,6 +75,9 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * delete[] m_children; m_children = newOperands; m_numberOfChildren = currentIndex; + m_sized = false; + m_positioned = false; + m_baselined = false; } bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index) { From e821ed2ad9e5d3c94a666d4155e57cef65730eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 14:40:00 +0100 Subject: [PATCH 148/459] [poincare] Add a row or a column to a GridLayout. Change-Id: I3e58ce84c05c9d64481942e6e7896409a20ddb8a --- poincare/src/layout/grid_layout.cpp | 37 +++++++++++++++++++++-------- poincare/src/layout/grid_layout.h | 11 ++++++--- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index cd64875a4..bc5b2d7b7 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -226,33 +226,50 @@ KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -int GridLayout::indexOfChild(ExpressionLayout * eL) const { - for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { - if (eL == child(i)) { - return i; - } +void GridLayout::addEmptyRow(EmptyVisibleLayout::Color color) { + ExpressionLayout * newChildren[m_numberOfColumns]; + for (int i = 0; i < m_numberOfColumns; i++) { + newChildren[i] = new EmptyVisibleLayout(color); + } + addChildrenAtIndex(const_cast(const_cast(newChildren)), m_numberOfColumns, numberOfChildren(), false); + m_numberOfRows++; +} + +void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { + m_numberOfColumns++; + for (int i = 0; i < m_numberOfRows; i++) { + addChildAtIndex(new EmptyVisibleLayout(color), i*m_numberOfColumns + m_numberOfColumns-1); } - return -1; } bool GridLayout::childIsLeftOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == 0; + return columnAtIndex(index) == 0; } bool GridLayout::childIsRightOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return (index - m_numberOfColumns * (int)(index / m_numberOfColumns)) == m_numberOfColumns - 1; + return columnAtIndex(index) == m_numberOfColumns - 1; } bool GridLayout::childIsTopOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return index < m_numberOfColumns; + return rowAtIndex(index) == 0; } bool GridLayout::childIsBottomOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return index > (m_numberOfRows - 1) * m_numberOfColumns - 1; + return rowAtIndex(index) == m_numberOfRows - 1; +} + +int GridLayout::rowAtIndex(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return (int)(index / m_numberOfColumns); +} + +int GridLayout::columnAtIndex(int index) const { + assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); + return index - m_numberOfColumns * rowAtIndex(index); } } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index c9853bd30..4315910c5 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -2,6 +2,7 @@ #define POINCARE_GRID_LAYOUT_H #include +#include "empty_visible_layout.h" namespace Poincare { @@ -32,7 +33,11 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - int indexOfChild(ExpressionLayout * eL) const; + void addEmptyRow(EmptyVisibleLayout::Color color); + void addEmptyColumn(EmptyVisibleLayout::Color color); + bool childIsRightOfGrid(int index) const; + bool childIsBottomOfGrid(int index) const; + int rowAtIndex(int index) const; int m_numberOfRows; int m_numberOfColumns; private: @@ -43,9 +48,9 @@ private: KDCoordinate columnWidth(int j); KDCoordinate width(); bool childIsLeftOfGrid(int index) const; - bool childIsRightOfGrid(int index) const; bool childIsTopOfGrid(int index) const; - bool childIsBottomOfGrid(int index) const; + int columnAtIndex(int index) const; + }; } From a499363747b16b966a531fed90aee5b75ccc2bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 14:40:42 +0100 Subject: [PATCH 149/459] [poincare] Editing a grey empty layout adds a Matrix row/column. Change-Id: I37b0c22fd2242d1361146833c3de2f24c296fd66 --- poincare/src/layout/empty_visible_layout.cpp | 8 +++++ poincare/src/layout/matrix_layout.cpp | 35 ++++++++++++++++++-- poincare/src/layout/matrix_layout.h | 2 +- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index e62f812f0..bddbda688 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -1,4 +1,5 @@ #include "empty_visible_layout.h" +#include "matrix_layout.h" #include #include #include @@ -17,7 +18,14 @@ ExpressionLayout * EmptyVisibleLayout::clone() const { } void EmptyVisibleLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { + Color currentColor = m_color; + int indexInParent = m_parent->indexOfChild(this); + ExpressionLayout * parent = m_parent; replaceWith(brother, true); + if (currentColor == Color::Grey) { + // The parent is a MatrixLayout. + static_cast(parent)->newRowOrColumnAtIndex(indexInParent); + } } void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 40f452f45..95fa9de8a 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -1,4 +1,5 @@ #include "matrix_layout.h" +#include "empty_visible_layout.h" #include "horizontal_layout.h" #include "bracket_left_layout.h" #include "bracket_right_layout.h" @@ -28,11 +29,11 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[numberOfChar++] = '['; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - for (int i = 0; i < m_numberOfRows; i++) { + for (int i = 0; i < m_numberOfRows - 1; i++) { buffer[numberOfChar++] = '['; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, (i+1) * m_numberOfColumns - 1); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + m_numberOfColumns - 2); buffer[numberOfChar++] = ']'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } @@ -42,6 +43,36 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { return numberOfChar; } +void MatrixLayout::newRowOrColumnAtIndex(int index) { + bool shouldAddNewRow = GridLayout::childIsBottomOfGrid(index); + int correspondingRow = rowAtIndex(index); + // We need to compute this bool before modifying the layout.:w + // + if (GridLayout::childIsRightOfGrid(index)) { + // Color the grey EmptyVisibleLayouts of the column in yellow. + int correspondingColumn = m_numberOfColumns - 1; + for (int i = 0; i < m_numberOfRows - 1; i++) { + ExpressionLayout * lastLayoutOfRow = editableChild(i*m_numberOfColumns+correspondingColumn); + if (lastLayoutOfRow->isEmpty()) { + static_cast(lastLayoutOfRow)->setColor(EmptyVisibleLayout::Color::Yellow); + } + } + // Add a column of grey EmptyVisibleLayouts on the right. + GridLayout::addEmptyColumn(EmptyVisibleLayout::Color::Grey); + } + if (shouldAddNewRow) { + // Color the grey EmptyVisibleLayouts of the row in yellow. + for (int i = 0; i < m_numberOfColumns - 1; i++) { + ExpressionLayout * lastLayoutOfColumn = editableChild(correspondingRow*m_numberOfColumns+i); + if (lastLayoutOfColumn->isEmpty()) { + static_cast(lastLayoutOfColumn)->setColor(EmptyVisibleLayout::Color::Yellow); + } + } + // Add a row of grey EmptyVisibleLayouts at the bottom. + GridLayout::addEmptyRow(EmptyVisibleLayout::Color::Grey); + } +} + void MatrixLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); BracketRightLayout * dummyRightBracket = new BracketRightLayout(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 910917846..48db8bf3c 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -10,6 +10,7 @@ public: using GridLayout::GridLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + void newRowOrColumnAtIndex(int index); protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -19,4 +20,3 @@ protected: } #endif - From 1717b470c819f195599185a9590bc85411299986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 18:15:06 +0100 Subject: [PATCH 150/459] [poincare] When replacing a layout, ask the parent to move the cursor. Change-Id: I0ddb0e791d328c2f141aefc604569ef4fcc6c0c5 --- poincare/include/poincare/expression_layout.h | 9 ++- .../layout/binomial_coefficient_layout.cpp | 10 +--- poincare/src/layout/bracket_layout.cpp | 14 ++--- poincare/src/layout/conjugate_layout.cpp | 12 +--- poincare/src/layout/expression_layout.cpp | 19 ++++++ poincare/src/layout/fraction_layout.cpp | 24 +------- poincare/src/layout/grid_layout.cpp | 59 +++++++++++-------- poincare/src/layout/grid_layout.h | 6 +- poincare/src/layout/horizontal_layout.cpp | 41 ++++++++++++- poincare/src/layout/horizontal_layout.h | 2 + poincare/src/layout/integral_layout.cpp | 13 +--- poincare/src/layout/matrix_layout.cpp | 17 +++++- poincare/src/layout/matrix_layout.h | 1 + poincare/src/layout/nth_root_layout.cpp | 19 +----- poincare/src/layout/sequence_layout.cpp | 13 +--- .../src/layout/vertical_offset_layout.cpp | 8 +-- 16 files changed, 134 insertions(+), 133 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index c06f89633..691f0f768 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -43,17 +43,16 @@ public: ExpressionLayout * editableParent() { return m_parent; } bool hasAncestor(const ExpressionLayout * e) const; + /* Dynamic Layout */ bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); - virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); - ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); + virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); + ExpressionLayout * replaceWithAndMoveCursor(ExpressionLayout * newChild, bool deleteAfterReplace, ExpressionLayoutCursor * cursor); virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); + virtual void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); void detachChild(const ExpressionLayout * e); // Removes a child WITHOUT deleting it void detachChildren(); //Removes all children WITHOUT deleting them - - - /* Dynamic Layout*/ virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } virtual void removeChildAtIndex(int index, bool deleteAfterRemoval); virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 28b253081..0342a1b6f 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -26,15 +26,7 @@ void BinomialCoefficientLayout::backspaceAtCursor(ExpressionLayoutCursor * curso || cursor->pointedExpressionLayout() == kLayout())) { assert(m_parent != nullptr); - int indexInParent = m_parent->indexOfChild(this); - ExpressionLayout * parent = m_parent; - replaceWith(new EmptyVisibleLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(parent); - return; - } - cursor->setPointedExpressionLayout(parent->editableChild(indexInParent-1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); return; } ExpressionLayout::backspaceAtCursor(cursor); diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 993ad2204..6d1222e14 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -14,19 +14,15 @@ ExpressionLayout * BracketLayout::clone() const { } void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left of the operand. + // Delete the brackets, keep the operand. if (cursor->pointedExpressionLayout() == operandLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(operandLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(previousParent); - return; - } - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + replaceWithAndMoveCursor(operandLayout(), true, cursor); return; } + // Case: Right. + // Move Right of the operand. assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPointedExpressionLayout(operandLayout()); diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 5e74f9b21..645514896 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -14,17 +14,11 @@ ExpressionLayout * ConjugateLayout::clone() const { } void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { + // Case: Left of the operand. + // Delete the conjugate, keep the operand. if (cursor->pointedExpressionLayout() == operandLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(operandLayout(), true); - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(previousParent); - return; - } - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + replaceWithAndMoveCursor(operandLayout(), true, cursor); return; } ExpressionLayout::backspaceAtCursor(cursor); diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 9c0c45435..8587ea8e6 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -164,6 +164,12 @@ ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout return layout; } +ExpressionLayout * ExpressionLayout::replaceWithAndMoveCursor(ExpressionLayout * newChild, bool deleteAfterReplace, ExpressionLayoutCursor * cursor) { + assert(m_parent != nullptr); + m_parent->replaceChildAndMoveCursor(this, newChild, deleteAfterReplace, cursor); + return newChild; +} + void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { assert(newChild != nullptr); // Caution: handle the case where we replace an operand with a descendant of ours. @@ -191,6 +197,19 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio m_baselined = false; } +void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + int oldChildIndex = indexOfChild(const_cast(oldChild)); + assert(oldChildIndex >= 0); + if (oldChildIndex == 0) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } else { + cursor->setPointedExpressionLayout(editableChild(oldChildIndex - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + replaceChild(oldChild, newChild, deleteOldChild); +} + void ExpressionLayout::detachChild(const ExpressionLayout * e) { ExpressionLayout ** op = const_cast(children()); for (int i = 0; i < numberOfChildren(); i++) { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index f2c57ae87..c425a8e4f 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -21,29 +21,7 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { // If the numerator and the denominator are empty, move the cursor then // replace the fraction with an empty layout. - // We need to perform these actions in this order because the replacement - // might delete the fraction's parent: if the parent is an - // HorizontalLayout and the fraction is its only child, the - // HorizontalLayout will be replaced by the new EmptyLayout. - ExpressionLayout * newEmptyLayout = new EmptyVisibleLayout(); - if (!m_parent->isHorizontal() - || (m_parent->isHorizontal() && m_parent->numberOfChildren() == 1)) - { - cursor->setPointedExpressionLayout(newEmptyLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - } else { - assert(m_parent->isHorizontal()); - assert(m_parent->numberOfChildren() > 0); - int indexInParent = m_parent->indexOfChild(this); - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - } else { - cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent + 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - } - } - replaceWith(newEmptyLayout, true); + replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); return; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index bc5b2d7b7..39790b4d6 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -24,28 +24,33 @@ ExpressionLayout * GridLayout::clone() const { void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); - if (indexOfPointedExpression >= 0 && childIsLeftOfGrid(indexOfPointedExpression)) { - // Case: Left of a left child grid. - // Delete the grid. - assert(m_parent != nullptr); - int indexInParent = m_parent->indexOfChild(this); - // Set the new cursor position before deleting. - if (indexInParent == 0) { - cursor->setPointedExpressionLayout(m_parent); + if (indexOfPointedExpression >= 0) { + if (childIsLeftOfGrid(indexOfPointedExpression)) { + // Case: Left of a left child grid. + // Delete the grid. + assert(m_parent != nullptr); + replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); return; } - cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent-1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - // Delete this. - replaceWith(new EmptyVisibleLayout(), true); + // Case: Left of another child of the grid. + // Move Left. + moveLeft(cursor); return; } - // Case: Left of another child of the grid. - // Move Left. - moveLeft(cursor); - return; + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. + // Ask the parent. + if (m_parent) { + return m_parent->backspaceAtCursor(cursor); + } } - ExpressionLayout::backspaceAtCursor(cursor); + // Case: Right. + // Move to the last child. + assert(cursor->pointedExpressionLayout() == this); + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + cursor->setPointedExpressionLayout(editableChild((m_numberOfRows-1)*(m_numberOfColumns-1))); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + return; } bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -244,32 +249,38 @@ void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { bool GridLayout::childIsLeftOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return columnAtIndex(index) == 0; + return columnAtChildIndex(index) == 0; } bool GridLayout::childIsRightOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return columnAtIndex(index) == m_numberOfColumns - 1; + return columnAtChildIndex(index) == m_numberOfColumns - 1; } bool GridLayout::childIsTopOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return rowAtIndex(index) == 0; + return rowAtChildIndex(index) == 0; } bool GridLayout::childIsBottomOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return rowAtIndex(index) == m_numberOfRows - 1; + return rowAtChildIndex(index) == m_numberOfRows - 1; } -int GridLayout::rowAtIndex(int index) const { +int GridLayout::rowAtChildIndex(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); return (int)(index / m_numberOfColumns); } -int GridLayout::columnAtIndex(int index) const { +int GridLayout::columnAtChildIndex(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); - return index - m_numberOfColumns * rowAtIndex(index); + return index - m_numberOfColumns * rowAtChildIndex(index); +} + +int GridLayout::indexAtRowColumn(int rowIndex, int columnIndex) const { + assert(rowIndex >= 0 && rowIndex < m_numberOfRows); + assert(columnIndex >= 0 && columnIndex < m_numberOfColumns); + return rowIndex * m_numberOfColumns + columnIndex; } } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 4315910c5..bee1df01a 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -37,7 +37,9 @@ protected: void addEmptyColumn(EmptyVisibleLayout::Color color); bool childIsRightOfGrid(int index) const; bool childIsBottomOfGrid(int index) const; - int rowAtIndex(int index) const; + int rowAtChildIndex(int index) const; + int columnAtChildIndex(int index) const; + int indexAtRowColumn(int rowIndex, int columnIndex) const; int m_numberOfRows; int m_numberOfColumns; private: @@ -49,8 +51,6 @@ private: KDCoordinate width(); bool childIsLeftOfGrid(int index) const; bool childIsTopOfGrid(int index) const; - int columnAtIndex(int index) const; - }; } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 7594a6ff2..62159aa03 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -27,9 +27,18 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { + privateReplaceChild(oldChild, newChild, deleteOldChild, nullptr); +} + +void HorizontalLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + privateReplaceChild(oldChild, newChild, deleteOldChild, cursor); +} + +void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { if (newChild->hasAncestor(this)) { newChild->editableParent()->detachChild(newChild); } + int oldChildIndex = indexOfChild(const_cast(oldChild)); if (newChild->isEmpty()) { if (numberOfChildren() > 1) { // If the new layout is empty and the horizontal layout has other @@ -38,13 +47,27 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio delete newChild; } removeChildAtIndex(indexOfChild(const_cast(oldChild)), deleteOldChild); + if (cursor == nullptr) { + return; + } + if (oldChildIndex == 0) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + cursor->setPointedExpressionLayout(editableChild(oldChildIndex -1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } // If the new layout is empty and it was the only horizontal layout child, // replace the horizontal layout with this empty layout (only if this is not // the main layout, so only if the layout has a parent. if (m_parent) { - replaceWith(newChild); + if (cursor) { + replaceWithAndMoveCursor(newChild, deleteOldChild, cursor); + return; + } + replaceWith(newChild, deleteOldChild); return; } } @@ -54,10 +77,26 @@ void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, Expressio int indexForInsertion = indexOfChild(const_cast(oldChild)); mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); removeChildAtIndex(indexForInsertion, deleteOldChild); + if (cursor == nullptr) { + return; + } + if (oldChildIndex == 0) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + cursor->setPointedExpressionLayout(editableChild(oldChildIndex -1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } // Else, just replace the child. ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); + if (cursor == nullptr) { + return; + } + cursor->setPointedExpressionLayout(newChild); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; } void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 2e664a39c..98a2d9380 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -18,6 +18,7 @@ public: /* Hierarchy */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; + void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ @@ -44,6 +45,7 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); + void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); }; } diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 392525b16..3ce10c2d1 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -36,18 +36,7 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { && cursor->pointedExpressionLayout() == lowerBoundLayout()) || cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(integrandLayout(), true); - // Place the cursor on the right of the left brother of the integral if - // there is one. - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(previousParent); + replaceWithAndMoveCursor(integrandLayout(), true, cursor); return; } // If the cursor is on the right, move to the integrand. diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 95fa9de8a..5ad8a03d5 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -17,6 +17,21 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } +void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + int oldChildIndex = indexOfChild(const_cast(oldChild)); + int rowIndex = rowAtChildIndex(oldChildIndex); + int columnIndex = columnAtChildIndex(oldChildIndex); + replaceChild(oldChild, newChild, deleteOldChild); + int newIndex = indexAtRowColumn(rowIndex, columnIndex); + if (newIndex < numberOfChildren()) { + cursor->setPointedExpressionLayout(editableChild(newIndex)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + cursor->setPointedExpressionLayout(editableChild(numberOfChildren())); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); +} + int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { // The grid is a matrix. if (bufferSize == 0) { @@ -45,7 +60,7 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { void MatrixLayout::newRowOrColumnAtIndex(int index) { bool shouldAddNewRow = GridLayout::childIsBottomOfGrid(index); - int correspondingRow = rowAtIndex(index); + int correspondingRow = rowAtChildIndex(index); // We need to compute this bool before modifying the layout.:w // if (GridLayout::childIsRightOfGrid(index)) { diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 48db8bf3c..83008d440 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -9,6 +9,7 @@ class MatrixLayout : public GridLayout { public: using GridLayout::GridLayout; ExpressionLayout * clone() const override; + void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; void newRowOrColumnAtIndex(int index); protected: diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 4e749d8c9..d2df334fe 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -40,24 +40,7 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Left && cursor->pointedExpressionLayout() == radicandLayout()) { - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(radicandLayout()); - // Place the cursor on the left of what replaced the root if possible. - if (indexInParent < previousParent->numberOfChildren()) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - } - // Else place the cursor on the right of the left brother of the root if - // there is one. - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(previousParent); + replaceWithAndMoveCursor(radicandLayout(), true, cursor); return; } // Case: Right. diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index acb342c2b..da31a3400 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -23,18 +23,7 @@ void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { && cursor->pointedExpressionLayout() == upperBoundLayout()) || cursor->pointedExpressionLayout() == argumentLayout())) { - ExpressionLayout * previousParent = m_parent; - int indexInParent = previousParent->indexOfChild(this); - replaceWith(argumentLayout(), true); - // Place the cursor on the right of the left brother of the sequence if - // there is one. - if (indexInParent > 0) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - // Else place the cursor on the Left of the parent. - cursor->setPointedExpressionLayout(previousParent); + replaceWithAndMoveCursor(argumentLayout(), true, cursor); return; } // Case: Right. diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 10964d358..003ba0452 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -27,14 +27,8 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (base->isEmpty()) { // Case: Empty base and indice. // Replace with the empty base layout. - if (indexInParent <= 1) { - cursor->setPointedExpressionLayout(m_parent); - } else { - cursor->setPointedExpressionLayout(m_parent->editableChild(indexInParent - 2)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - } m_parent->removeChildAtIndex(indexInParent - 1, false); - replaceWith(base, true); + replaceWithAndMoveCursor(base, true, cursor); return; } // Case: Empty indice only. From 95327d0afc5d48bc618d208881b8b8dc7dd0aa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 10 Jan 2018 17:32:23 +0100 Subject: [PATCH 151/459] [poincare] Remove empty row/column in MatrixLayout. Change-Id: I58f7b7f5e1256afd769f773bef8caea43a40c7a1 --- apps/expression_editor/controller.cpp | 3 +- .../expression_and_layout.cpp | 1 - .../poincare/dynamic_layout_hierarchy.h | 1 + poincare/include/poincare/expression_layout.h | 2 + .../src/layout/bracket_left_right_layout.h | 2 +- .../src/layout/dynamic_layout_hierarchy.cpp | 31 ++++++++++- poincare/src/layout/expression_layout.cpp | 42 +++++++++----- poincare/src/layout/grid_layout.cpp | 16 ++++++ poincare/src/layout/grid_layout.h | 2 + poincare/src/layout/horizontal_layout.cpp | 2 +- poincare/src/layout/matrix_layout.cpp | 55 ++++++++++++++++++- poincare/src/layout/matrix_layout.h | 6 ++ 12 files changed, 142 insertions(+), 21 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index fdf9702cd..f19771346 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -12,9 +12,8 @@ Controller::Controller(Responder * parentResponder, ExpressionLayout * expressio m_view(parentResponder, expressionLayout, &m_cursor), m_expressionLayout(expressionLayout), m_resultLayout(nullptr) - //m_context((GlobalContext *)((AppsContainer *)(app()->container()))->globalContext()) { - m_cursor.setPointedExpressionLayout(expressionLayout->editableChild(0)); + m_cursor.setPointedExpressionLayout(expressionLayout); } void Controller::didBecomeFirstResponder() { diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp index 36f09fcfb..24e0f3df4 100644 --- a/apps/expression_editor/expression_and_layout.cpp +++ b/apps/expression_editor/expression_and_layout.cpp @@ -39,7 +39,6 @@ ExpressionAndLayout::ExpressionAndLayout() { m_expression = Poincare::Expression::parse(expression); m_expressionLayout = new Poincare::HorizontalLayout(); - m_expressionLayout->addChildAtIndex(new Poincare::EmptyVisibleLayout(), 0); } ExpressionAndLayout::~ExpressionAndLayout() { if (m_expressionLayout) { diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index a40a7fd13..4157d15fe 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -28,6 +28,7 @@ public: void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren); bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. bool isEmpty() const override; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 691f0f768..715ad8fbe 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -55,6 +55,7 @@ public: void detachChildren(); //Removes all children WITHOUT deleting them virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } virtual void removeChildAtIndex(int index, bool deleteAfterRemoval); + virtual void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor); virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ @@ -78,6 +79,7 @@ public: virtual bool isLeftBracket() const { return false; } virtual bool isRightBracket() const { return false; } virtual bool isEmpty() const { return false; } + virtual bool isMatrix() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 4af7a09a3..98cf4e875 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -11,11 +11,11 @@ public: void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; +protected: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_externWidthMargin = 2; -protected: KDSize computeSize() override; KDCoordinate operandHeight(); virtual void computeOperandHeight() = 0; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index ce8c5fa28..7678abd18 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -1,5 +1,6 @@ #include #include "empty_visible_layout.h" +#include extern "C" { #include #include @@ -113,9 +114,37 @@ void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemov } } +void DynamicLayoutHierarchy::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { + assert(index >= 0 && index < numberOfChildren()); + assert(cursor->pointedExpressionLayout() == child(index)); + if (numberOfChildren() == 1) { + if (m_parent) { + if (!deleteAfterRemoval) { + detachChild(editableChild(0)); + } + m_parent->removePointedChildAtIndexAndMoveCursor(m_parent->indexOfChild(this), true, cursor); + return; + } + removeChildAtIndex(index, deleteAfterRemoval); + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + removeChildAtIndex(index, deleteAfterRemoval); + if (index < numberOfChildren()) { + cursor->setPointedExpressionLayout(editableChild(index)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + int indexOfNewPointedLayout = index - 1; + assert(indexOfNewPointedLayout >= 0); + assert(indexOfNewPointedLayout < numberOfChildren()); + cursor->setPointedExpressionLayout(editableChild(indexOfNewPointedLayout)); +} + bool DynamicLayoutHierarchy::isEmpty() const { if (m_numberOfChildren == 0 - || (m_numberOfChildren == 1&& child(0)->isEmpty())) + || (m_numberOfChildren == 1 && child(0)->isEmpty())) { return true; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 8587ea8e6..f79a62e0e 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,6 +1,7 @@ #include #include "empty_visible_layout.h" #include "horizontal_layout.h" +#include "matrix_layout.h" #include #include #include @@ -230,10 +231,26 @@ void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { replaceChild(editableChild(index), new EmptyVisibleLayout(), deleteAfterRemoval); } -void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { + assert(index >= 0 && index < numberOfChildren()); + assert(cursor->pointedExpressionLayout() == child(index)); + removeChildAtIndex(index, deleteAfterRemoval); + if (index < numberOfChildren()) { + cursor->setPointedExpressionLayout(editableChild(index)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; + } + int indexOfNewPointedLayout = index - 1; + assert(indexOfNewPointedLayout >= 0); + assert(indexOfNewPointedLayout < numberOfChildren()); + cursor->setPointedExpressionLayout(editableChild(indexOfNewPointedLayout)); +} +void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { + // Case: The pointed layout is a child. + // Point to the previous child, else to this. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (indexOfPointedExpression == 0) { cursor->setPointedExpressionLayout(this); @@ -245,14 +262,20 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { return; } assert(cursor->pointedExpressionLayout() == this); + // Case: this is the pointed layout. if (m_parent == nullptr) { + // If there is no parent, return. return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + // Case: Left. + // Ask the parent. m_parent->backspaceAtCursor(cursor); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. + // If the layout has children, move to the last one. if (numberOfChildren() > 0) { cursor->setPointedExpressionLayout(editableChild(numberOfChildren()-1)); cursor->performBackspace(); @@ -260,23 +283,16 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } int indexInParent = m_parent->indexOfChild(this); ExpressionLayout * previousParent = m_parent; - if (previousParent->numberOfChildren() == 1) { + // Case: Right. + // If the layout has no child and is only child, replace it with an empty layout. + /*if (previousParent->numberOfChildren() == 1) { ExpressionLayout * newLayout = new EmptyVisibleLayout(); replaceWith(newLayout, true); cursor->setPointedExpressionLayout(newLayout); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return; - } - previousParent->removeChildAtIndex(indexInParent, true); - if (indexInParent < previousParent->numberOfChildren()) { - cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - } - int indexOfNewPointedLayout = indexInParent - 1; - assert(indexOfNewPointedLayout >= 0); - assert(indexOfNewPointedLayout < previousParent->numberOfChildren()); - cursor->setPointedExpressionLayout(previousParent->editableChild(indexOfNewPointedLayout)); + }*/ + previousParent->removePointedChildAtIndexAndMoveCursor(indexInParent, true, cursor); } char ExpressionLayout::XNTChar() const { diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 39790b4d6..831c72f83 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -247,6 +247,22 @@ void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { } } +void GridLayout::deleteRowAtIndex(int index) { + assert(index >= 0 && index < m_numberOfRows); + for (int i = 0; i < m_numberOfColumns; i++) { + DynamicLayoutHierarchy::removeChildAtIndex(index * m_numberOfColumns, true); + } + m_numberOfRows--; +} + +void GridLayout::deleteColumnAtIndex(int index) { + assert(index >= 0 && index < m_numberOfColumns); + for (int i = (m_numberOfRows - 1) * m_numberOfColumns + index; i > -1; i-= m_numberOfColumns) { + DynamicLayoutHierarchy::removeChildAtIndex(i, true); + } + m_numberOfColumns--; +} + bool GridLayout::childIsLeftOfGrid(int index) const { assert(index >= 0 && index < m_numberOfRows*m_numberOfColumns); return columnAtChildIndex(index) == 0; diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index bee1df01a..dd03e309c 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -35,6 +35,8 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; void addEmptyRow(EmptyVisibleLayout::Color color); void addEmptyColumn(EmptyVisibleLayout::Color color); + void deleteRowAtIndex(int index); + void deleteColumnAtIndex(int index); bool childIsRightOfGrid(int index) const; bool childIsBottomOfGrid(int index) const; int rowAtChildIndex(int index) const; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 62159aa03..2f75b68e8 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -61,7 +61,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex } // If the new layout is empty and it was the only horizontal layout child, // replace the horizontal layout with this empty layout (only if this is not - // the main layout, so only if the layout has a parent. + // the main layout, so only if the layout has a parent). if (m_parent) { if (cursor) { replaceWithAndMoveCursor(newChild, deleteOldChild, cursor); diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 5ad8a03d5..eee2bcf42 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -17,6 +17,12 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } +void MatrixLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { + int oldChildIndex = indexOfChild(const_cast(oldChild)); + GridLayout::replaceChild(oldChild, newChild, deleteOldChild); + childWasReplacedAtIndex(oldChildIndex); +} + void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { int oldChildIndex = indexOfChild(const_cast(oldChild)); int rowIndex = rowAtChildIndex(oldChildIndex); @@ -59,6 +65,7 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } void MatrixLayout::newRowOrColumnAtIndex(int index) { + assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows); bool shouldAddNewRow = GridLayout::childIsBottomOfGrid(index); int correspondingRow = rowAtChildIndex(index); // We need to compute this bool before modifying the layout.:w @@ -73,7 +80,7 @@ void MatrixLayout::newRowOrColumnAtIndex(int index) { } } // Add a column of grey EmptyVisibleLayouts on the right. - GridLayout::addEmptyColumn(EmptyVisibleLayout::Color::Grey); + addEmptyColumn(EmptyVisibleLayout::Color::Grey); } if (shouldAddNewRow) { // Color the grey EmptyVisibleLayouts of the row in yellow. @@ -84,7 +91,30 @@ void MatrixLayout::newRowOrColumnAtIndex(int index) { } } // Add a row of grey EmptyVisibleLayouts at the bottom. - GridLayout::addEmptyRow(EmptyVisibleLayout::Color::Grey); + addEmptyRow(EmptyVisibleLayout::Color::Grey); + } +} + +void MatrixLayout::childWasReplacedAtIndex(int index) { + assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows); + int rowIndex = rowAtChildIndex(index); + int columnIndex = columnAtChildIndex(index); + bool rowIsEmpty = isRowEmpty(rowIndex); + bool columnIsEmpty = isColumnEmpty(columnIndex); + if (rowIsEmpty && m_numberOfRows > 2) { + deleteRowAtIndex(rowIndex); + } + if (columnIsEmpty && m_numberOfColumns > 2) { + deleteColumnAtIndex(columnIndex); + } + if (!rowIsEmpty && !columnIsEmpty) { + ExpressionLayout * newChild = editableChild(index); + if (newChild->isEmpty() + && (childIsRightOfGrid(index) + || childIsBottomOfGrid(index))) + { + static_cast(newChild)->setColor(EmptyVisibleLayout::Color::Grey); + } } } @@ -108,6 +138,7 @@ ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, } KDPoint MatrixLayout::positionOfChild(ExpressionLayout * child) { + assert(indexOfChild(child) > -1); BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); BracketRightLayout * dummyRightBracket = new BracketRightLayout(); ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); @@ -115,4 +146,24 @@ ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, return GridLayout::positionOfChild(child).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); } +bool MatrixLayout::isRowEmpty(int index) const { + assert(index >= 0 && index < m_numberOfRows); + for (int i = index * m_numberOfColumns; i < (index+1) * m_numberOfColumns; i++) { + if (!child(i)->isEmpty()) { + return false; + } + } + return true; +} + +bool MatrixLayout::isColumnEmpty(int index) const { + assert(index >= 0 && index < m_numberOfColumns); + for (int i = index; i < m_numberOfRows * m_numberOfColumns; i+= m_numberOfColumns) { + if (!child(i)->isEmpty()) { + return false; + } + } + return true; +} + } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 83008d440..047753ca4 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -9,13 +9,19 @@ class MatrixLayout : public GridLayout { public: using GridLayout::GridLayout; ExpressionLayout * clone() const override; + void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + bool isMatrix() const override { return true; } void newRowOrColumnAtIndex(int index); + void childWasReplacedAtIndex(int index); protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; +private: + bool isRowEmpty(int index) const; + bool isColumnEmpty(int index) const; }; } From f95bb46cc38e0dd2ff0010953474893dac81c504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 11:08:58 +0100 Subject: [PATCH 152/459] [poincare] Cleaned ExpressionLayout class. Change-Id: I03a49e1a2b199a70608792f0358ddde5a86118d6 --- poincare/include/poincare/expression_layout.h | 67 +++++++++----- poincare/src/layout/expression_layout.cpp | 91 +++++++++---------- poincare/src/layout/horizontal_layout.cpp | 6 +- poincare/src/layout/matrix_layout.cpp | 4 +- 4 files changed, 92 insertions(+), 76 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 715ad8fbe..473827679 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -32,38 +32,60 @@ public: virtual void invalidAllSizesPositionsAndBaselines(); /* Hierarchy */ + + // Children virtual const ExpressionLayout * const * children() const = 0; const ExpressionLayout * child(int i) const; ExpressionLayout * editableChild(int i) { return const_cast(child(i)); } virtual int numberOfChildren() const = 0; - int indexOfChild(ExpressionLayout * child) const; + int indexOfChild(const ExpressionLayout * child) const; - void setParent(ExpressionLayout * parent); + // Parent + void setParent(ExpressionLayout * parent) { m_parent = parent; } const ExpressionLayout * parent() const { return m_parent; } ExpressionLayout * editableParent() { return m_parent; } bool hasAncestor(const ExpressionLayout * e) const; /* Dynamic Layout */ - bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); + + // Add + virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + + // Replace virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); - ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); ExpressionLayout * replaceWithAndMoveCursor(ExpressionLayout * newChild, bool deleteAfterReplace, ExpressionLayoutCursor * cursor); virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); - virtual void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); - void detachChild(const ExpressionLayout * e); // Removes a child WITHOUT deleting it - void detachChildren(); //Removes all children WITHOUT deleting them - virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } + virtual void replaceChildAndMoveCursor( + const ExpressionLayout * oldChild, + ExpressionLayout * newChild, + bool deleteOldChild, + ExpressionLayoutCursor * cursor); + + // Detach + void detachChild(const ExpressionLayout * e); // Detach a child WITHOUT deleting it + void detachChildren(); // Detach all children WITHOUT deleting them + + // Remove virtual void removeChildAtIndex(int index, bool deleteAfterRemoval); virtual void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor); + + // User input + bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? virtual bool moveRight(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? - virtual bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); + virtual bool moveUp( + ExpressionLayoutCursor * cursor, + ExpressionLayout * previousLayout = nullptr, + ExpressionLayout * previousPreviousLayout = nullptr); + virtual bool moveDown( + ExpressionLayoutCursor * cursor, + ExpressionLayout * previousLayout = nullptr, + ExpressionLayout * previousPreviousLayout = nullptr); bool moveUpInside(ExpressionLayoutCursor * cursor); - virtual bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); bool moveDownInside(ExpressionLayoutCursor * cursor); /* Expression Engine */ @@ -71,7 +93,8 @@ public: /* Other */ virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } - // isCollapsable is used when adding a brother fraction: should the layout be inserted in the numerator (or denominator)? + /* isCollapsable is used when adding a brother fraction: should the layout be + * inserted in the numerator (or denominator)? */ virtual bool mustHaveLeftBrother() const { return false; } virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } @@ -87,24 +110,24 @@ protected: virtual KDSize computeSize() = 0; virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; + ExpressionLayout * m_parent; + KDCoordinate m_baseline; + /* m_baseline is the signed vertical distance from the top of the layout to + * the fraction bar of an hypothetical fraction brother layout. If the top of + * the layout is under that bar, the baseline is negative. */ + bool m_sized; + bool m_baselined; + bool m_positioned; +private: void detachChildAtIndex(int i); + bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); void moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout ** childResult, void * resultPosition, int * resultScore); - KDCoordinate m_baseline; - /* m_baseline is the signed vertical distance from the top of the layout to - * the fraction bar of an hypothetical fraction brother layout. If the top of - * the layout is under that bar, the baseline is negative. */ - ExpressionLayout * m_parent; - bool m_sized; - bool m_baselined; - bool m_positioned; -private: - bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); - void replaceWithJuxtapositionOf(ExpressionLayout * firstLayout, ExpressionLayout * secondLayout); + ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; }; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index f79a62e0e..76e7adcc4 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -10,8 +10,8 @@ namespace Poincare { ExpressionLayout::ExpressionLayout() : - m_baseline(0), m_parent(nullptr), + m_baseline(0), m_sized(false), m_baselined(false), m_positioned(false), @@ -19,6 +19,14 @@ ExpressionLayout::ExpressionLayout() : { } +void ExpressionLayout::draw(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + int i = 0; + while (ExpressionLayout * c = editableChild(i++)) { + c->draw(ctx, p, expressionColor, backgroundColor); + } + render(ctx, absoluteOrigin().translatedBy(p), expressionColor, backgroundColor); +} + KDPoint ExpressionLayout::origin() { if (m_parent == nullptr) { return absoluteOrigin(); @@ -28,14 +36,6 @@ KDPoint ExpressionLayout::origin() { } } -void ExpressionLayout::draw(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - int i = 0; - while (ExpressionLayout * c = editableChild(i++)) { - c->draw(ctx, p, expressionColor, backgroundColor); - } - render(ctx, absoluteOrigin().translatedBy(p), expressionColor, backgroundColor); -} - KDPoint ExpressionLayout::absoluteOrigin() { if (!m_positioned) { if (m_parent != nullptr) { @@ -83,7 +83,7 @@ const ExpressionLayout * ExpressionLayout::child(int i) const { return nullptr; } -int ExpressionLayout::indexOfChild(ExpressionLayout * child) const { +int ExpressionLayout::indexOfChild(const ExpressionLayout * child) const { if (child == nullptr) { return -1; } @@ -95,10 +95,6 @@ int ExpressionLayout::indexOfChild(ExpressionLayout * child) const { return -1; } -void ExpressionLayout::setParent(ExpressionLayout* parent) { - m_parent = parent; -} - bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { assert(m_parent != this); if (m_parent == e) { @@ -143,28 +139,12 @@ void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLay return; } -bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor) { - cursor->pointedExpressionLayout()->addBrother(cursor, newChild); - return true; -} - ExpressionLayout * ExpressionLayout::replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace) { assert(m_parent != nullptr); m_parent->replaceChild(this, newChild, deleteAfterReplace); return newChild; } -ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace) { - assert(m_parent != nullptr); - /* One of the children to juxtapose might be "this", so we first have to - * replace "this" with an horizontal layout, then add "this" to the layout. */ - ExpressionLayout * layout = new HorizontalLayout(); - m_parent->replaceChild(this, layout, deleteAfterReplace); - layout->addChildAtIndex(leftChild, 0); - layout->addChildAtIndex(rightChild, 1); - return layout; -} - ExpressionLayout * ExpressionLayout::replaceWithAndMoveCursor(ExpressionLayout * newChild, bool deleteAfterReplace, ExpressionLayoutCursor * cursor) { assert(m_parent != nullptr); m_parent->replaceChildAndMoveCursor(this, newChild, deleteAfterReplace, cursor); @@ -199,7 +179,7 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio } void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { - int oldChildIndex = indexOfChild(const_cast(oldChild)); + int oldChildIndex = indexOfChild(oldChild); assert(oldChildIndex >= 0); if (oldChildIndex == 0) { cursor->setPointedExpressionLayout(this); @@ -212,16 +192,12 @@ void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChi } void ExpressionLayout::detachChild(const ExpressionLayout * e) { - ExpressionLayout ** op = const_cast(children()); - for (int i = 0; i < numberOfChildren(); i++) { - if (op[i] == e) { - detachChildAtIndex(i); - } - } + assert(indexOfChild(e) >= 0); + detachChildAtIndex(indexOfChild(e)); } void ExpressionLayout::detachChildren() { - for (int i = 0; i setPointedExpressionLayout(editableChild(indexOfNewPointedLayout)); } + +bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor) { + cursor->pointedExpressionLayout()->addBrother(cursor, newChild); + return true; +} + void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { @@ -302,17 +284,6 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -void ExpressionLayout::detachChildAtIndex(int i) { - ExpressionLayout ** op = const_cast(children()); - if (op[i] != nullptr && op[i]->parent() == this) { - const_cast(op[i])->setParent(nullptr); - } - op[i] = nullptr; - m_sized = false; - m_positioned = false; - m_baselined = false; -} - bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (m_parent) { return m_parent->moveUp(cursor, this, previousLayout); @@ -335,6 +306,17 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor) { return moveInside(VerticalDirection::Down, cursor); } +void ExpressionLayout::detachChildAtIndex(int i) { + ExpressionLayout ** op = const_cast(children()); + if (op[i] != nullptr && op[i]->parent() == this) { + const_cast(op[i])->setParent(nullptr); + } + op[i] = nullptr; + m_sized = false; + m_positioned = false; + m_baselined = false; +} + bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor) { ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; @@ -391,4 +373,15 @@ void ExpressionLayout::moveCursorInsideAtDirection ( } } +ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace) { + assert(m_parent != nullptr); + /* One of the children to juxtapose might be "this", so we first have to + * replace "this" with an horizontal layout, then add "this" to the layout. */ + ExpressionLayout * layout = new HorizontalLayout(); + m_parent->replaceChild(this, layout, deleteAfterReplace); + layout->addChildAtIndex(leftChild, 0); + layout->addChildAtIndex(rightChild, 1); + return layout; +} + } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 2f75b68e8..0bc3fc214 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -38,7 +38,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex if (newChild->hasAncestor(this)) { newChild->editableParent()->detachChild(newChild); } - int oldChildIndex = indexOfChild(const_cast(oldChild)); + int oldChildIndex = indexOfChild(oldChild); if (newChild->isEmpty()) { if (numberOfChildren() > 1) { // If the new layout is empty and the horizontal layout has other @@ -46,7 +46,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex if (!newChild->hasAncestor(oldChild)) { delete newChild; } - removeChildAtIndex(indexOfChild(const_cast(oldChild)), deleteOldChild); + removeChildAtIndex(oldChildIndex, deleteOldChild); if (cursor == nullptr) { return; } @@ -74,7 +74,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex // If the new child is also an horizontal layout, steal the children of the // new layout then destroy it. if (newChild->isHorizontal()) { - int indexForInsertion = indexOfChild(const_cast(oldChild)); + int indexForInsertion = indexOfChild(oldChild); mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); removeChildAtIndex(indexForInsertion, deleteOldChild); if (cursor == nullptr) { diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index eee2bcf42..f88ddb27c 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -18,13 +18,13 @@ ExpressionLayout * MatrixLayout::clone() const { } void MatrixLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { - int oldChildIndex = indexOfChild(const_cast(oldChild)); + int oldChildIndex = indexOfChild(oldChild); GridLayout::replaceChild(oldChild, newChild, deleteOldChild); childWasReplacedAtIndex(oldChildIndex); } void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { - int oldChildIndex = indexOfChild(const_cast(oldChild)); + int oldChildIndex = indexOfChild(oldChild); int rowIndex = rowAtChildIndex(oldChildIndex); int columnIndex = columnAtChildIndex(oldChildIndex); replaceChild(oldChild, newChild, deleteOldChild); From 955c69f0b2aa1895a34f1e63c4517db87471f3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 11:24:07 +0100 Subject: [PATCH 153/459] [poincare] Changed isEmpty() in DynamicLayoutHierarchy. A DynamicLayoutHierarchy with only an empty children is not empty, but an horizontal layout with only an empty children is empty. Also, a DynamicLayoutHierarchy with no children is not empty (it should always be an intermediary state before adding children). Change-Id: I47b32379f42a95666d75df4d3ba79fabc34d2edc --- poincare/include/poincare/dynamic_layout_hierarchy.h | 1 - poincare/src/layout/dynamic_layout_hierarchy.cpp | 9 --------- poincare/src/layout/horizontal_layout.cpp | 8 ++++++++ poincare/src/layout/horizontal_layout.h | 1 + 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 4157d15fe..63518b122 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -31,7 +31,6 @@ public: void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. - bool isEmpty() const override; protected: const ExpressionLayout ** m_children; int m_numberOfChildren; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 7678abd18..8a54de8b3 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -142,13 +142,4 @@ void DynamicLayoutHierarchy::removePointedChildAtIndexAndMoveCursor(int index, b cursor->setPointedExpressionLayout(editableChild(indexOfNewPointedLayout)); } -bool DynamicLayoutHierarchy::isEmpty() const { - if (m_numberOfChildren == 0 - || (m_numberOfChildren == 1 && child(0)->isEmpty())) - { - return true; - } - return false; -} - } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 0bc3fc214..6a7b91e7a 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -224,6 +224,14 @@ void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); } +bool HorizontalLayout::isEmpty() const { + if (m_numberOfChildren == 1 && child(0)->isEmpty()) + { + return true; + } + return false; +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 98a2d9380..a8e932797 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -37,6 +37,7 @@ public: /* Other */ bool isHorizontal() const override { return true; } + bool isEmpty() const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; From 914b181e066160d6846ca5c5f0c9f5d4e0b3b155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 11:39:35 +0100 Subject: [PATCH 154/459] [poincare] Change the way to delete a matrix. Delete the matrix if the cursor was right of it. If the cursor is left of a child on the left, now just move Left. Change-Id: I4bccaec9f7c23c4da3dd1d9ab59c8fd6641d5a3f --- poincare/src/layout/grid_layout.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 831c72f83..6fb4874ac 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -25,14 +25,7 @@ void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { - if (childIsLeftOfGrid(indexOfPointedExpression)) { - // Case: Left of a left child grid. - // Delete the grid. - assert(m_parent != nullptr); - replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); - return; - } - // Case: Left of another child of the grid. + // Case: Left of child of the grid. // Move Left. moveLeft(cursor); return; @@ -45,12 +38,9 @@ void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } } // Case: Right. - // Move to the last child. - assert(cursor->pointedExpressionLayout() == this); - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - cursor->setPointedExpressionLayout(editableChild((m_numberOfRows-1)*(m_numberOfColumns-1))); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; + // Delete the grid. + assert(m_parent != nullptr); + replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); } bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { From bf4ccd76eaa3ac03714d888d1ca54d6db2e3bde3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 14:11:50 +0100 Subject: [PATCH 155/459] [poincare] Show grey squares in a matrix only if the cursor is in it. Change-Id: I2e622de51a9c7af7b676ae9bd7bb3e9681f5d051 --- apps/expression_editor/controller.cpp | 2 + poincare/include/poincare/expression_layout.h | 4 +- poincare/src/layout/empty_visible_layout.h | 1 + poincare/src/layout/grid_layout.cpp | 4 + poincare/src/layout/grid_layout.h | 4 +- poincare/src/layout/horizontal_layout.cpp | 16 ++- poincare/src/layout/matrix_layout.cpp | 113 +++++++++++++++++- poincare/src/layout/matrix_layout.h | 19 ++- 8 files changed, 155 insertions(+), 8 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index f19771346..cdce47736 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -62,6 +62,8 @@ void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayou bool Controller::privateHandleEvent(Ion::Events::Event event) { if (handleMoveEvent(event)) { + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); + m_view.layoutSubviews(); return true; } ExpressionLayout * newPointedLayout = handleAddEvent(event); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 473827679..a2f4ab83d 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -85,8 +85,8 @@ public: ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); - bool moveUpInside(ExpressionLayoutCursor * cursor); - bool moveDownInside(ExpressionLayoutCursor * cursor); + virtual bool moveUpInside(ExpressionLayoutCursor * cursor); + virtual bool moveDownInside(ExpressionLayoutCursor * cursor); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index ae5a5e5c2..4d454d97b 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -20,6 +20,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; bool isEmpty() const override { return true; } + Color color() const { return m_color; } void setColor(Color color) { m_color = color; } protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 6fb4874ac..bf3498872 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -228,6 +228,7 @@ void GridLayout::addEmptyRow(EmptyVisibleLayout::Color color) { } addChildrenAtIndex(const_cast(const_cast(newChildren)), m_numberOfColumns, numberOfChildren(), false); m_numberOfRows++; + invalidAllSizesPositionsAndBaselines(); } void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { @@ -235,6 +236,7 @@ void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { for (int i = 0; i < m_numberOfRows; i++) { addChildAtIndex(new EmptyVisibleLayout(color), i*m_numberOfColumns + m_numberOfColumns-1); } + invalidAllSizesPositionsAndBaselines(); } void GridLayout::deleteRowAtIndex(int index) { @@ -243,6 +245,7 @@ void GridLayout::deleteRowAtIndex(int index) { DynamicLayoutHierarchy::removeChildAtIndex(index * m_numberOfColumns, true); } m_numberOfRows--; + invalidAllSizesPositionsAndBaselines(); } void GridLayout::deleteColumnAtIndex(int index) { @@ -251,6 +254,7 @@ void GridLayout::deleteColumnAtIndex(int index) { DynamicLayoutHierarchy::removeChildAtIndex(i, true); } m_numberOfColumns--; + invalidAllSizesPositionsAndBaselines(); } bool GridLayout::childIsLeftOfGrid(int index) const { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index dd03e309c..5fac6e1ec 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -38,6 +38,8 @@ protected: void deleteRowAtIndex(int index); void deleteColumnAtIndex(int index); bool childIsRightOfGrid(int index) const; + bool childIsLeftOfGrid(int index) const; + bool childIsTopOfGrid(int index) const; bool childIsBottomOfGrid(int index) const; int rowAtChildIndex(int index) const; int columnAtChildIndex(int index) const; @@ -51,8 +53,6 @@ private: KDCoordinate height(); KDCoordinate columnWidth(int j); KDCoordinate width(); - bool childIsLeftOfGrid(int index) const; - bool childIsTopOfGrid(int index) const; }; } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 6a7b91e7a..45f1a9747 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -63,13 +63,27 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex // replace the horizontal layout with this empty layout (only if this is not // the main layout, so only if the layout has a parent). if (m_parent) { + if (!deleteOldChild) { + removeChildAtIndex(indexOfChild(oldChild), false); + } if (cursor) { - replaceWithAndMoveCursor(newChild, deleteOldChild, cursor); + replaceWithAndMoveCursor(newChild, true, cursor); return; } replaceWith(newChild, deleteOldChild); return; } + // If this is the main horizontal layout, the old child its only child and + // the new child is Empty, remove the old child and delete the new child. + assert(m_parent == nullptr); + removeChildAtIndex(0, deleteOldChild); + delete newChild; + if (cursor == nullptr) { + return; + } + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return; } // If the new child is also an horizontal layout, steal the children of the // new layout then destroy it. diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index f88ddb27c..afccc9260 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -17,6 +17,85 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } +bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor) { + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + if (childIndex >- 1 + && cursor->position() == ExpressionLayoutCursor::Position::Left + && childIsLeftOfGrid(childIndex)) + { + // Case: Left of a child on the left of the grid. + // Remove the grey squares of the grid, then go left of the grid. + assert(hasGreySquares()); + removeGreySquares(); + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + return true; + } + // Case: Right. + // Add the grey squares to the matrix, then move to the bottom right non empty + // nor grey child. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + assert(!hasGreySquares()); + addGreySquares(); + ExpressionLayout * lastChild = editableChild((m_numberOfColumns-1)*(m_numberOfRows-1)); + assert(lastChild != nullptr); + cursor->setPointedExpressionLayout(lastChild); + return true; + } + return GridLayout::moveLeft(cursor); +} + +bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) { + // Case: Left. + // Add the grey squares to the matrix,, then go to the first entry. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + assert(!hasGreySquares()); + addGreySquares(); + assert(m_numberOfColumns*m_numberOfRows >= 1); + ExpressionLayout * firstChild = editableChild(0); + assert(firstChild != nullptr); + cursor->setPointedExpressionLayout(firstChild); + return true; + } + // Case: The cursor points to a grid's child. + int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + if (childIndex >- 1 + && cursor->position() == ExpressionLayoutCursor::Position::Right + && childIsRightOfGrid(childIndex)) + { + // Case: Right of a child on the right of the grid. + // Remove the grey squares of the grid, then go left of the grid. + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + assert(hasGreySquares()); + removeGreySquares(); + return true; + } + return GridLayout::moveRight(cursor); +} + +bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor) { + bool result = GridLayout::moveUpInside(cursor); + if (result) { + assert(!hasGreySquares()); + addGreySquares(); + } + return result; +} + +bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor) { + bool result = GridLayout::moveDownInside(cursor); + if (result) { + assert(!hasGreySquares()); + addGreySquares(); + } + return result; +} + void MatrixLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { int oldChildIndex = indexOfChild(oldChild); GridLayout::replaceChild(oldChild, newChild, deleteOldChild); @@ -50,11 +129,13 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[numberOfChar++] = '['; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - for (int i = 0; i < m_numberOfRows - 1; i++) { + int maxRowIndex = hasGreySquares() ? m_numberOfRows - 1 : m_numberOfRows; + int maxColumnIndex = hasGreySquares() ? m_numberOfColumns - 2 : m_numberOfColumns - 1; + for (int i = 0; i < maxRowIndex; i++) { buffer[numberOfChar++] = '['; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + m_numberOfColumns - 2); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + maxColumnIndex); buffer[numberOfChar++] = ']'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } @@ -166,4 +247,32 @@ bool MatrixLayout::isColumnEmpty(int index) const { return true; } +void MatrixLayout::addGreySquares() { + if (!hasGreySquares()) { + addEmptyRow(EmptyVisibleLayout::Color::Grey); + addEmptyColumn(EmptyVisibleLayout::Color::Grey); + } +} + +void MatrixLayout::removeGreySquares() { + if (hasGreySquares()) { + deleteRowAtIndex(m_numberOfRows - 1); + deleteColumnAtIndex(m_numberOfColumns - 1); + } +} + +bool MatrixLayout::hasGreySquares() const { + assert(m_numberOfRows*m_numberOfColumns - 1 >= 0); + const ExpressionLayout * lastChild = child(m_numberOfRows * m_numberOfColumns - 1); + if (lastChild->isEmpty() + && !lastChild->isHorizontal() + && (static_cast(lastChild))->color() == EmptyVisibleLayout::Color::Grey) + { + assert(isRowEmpty(m_numberOfColumns - 1)); + assert(isColumnEmpty(m_numberOfRows - 1)); + return true; + } + return false; +} + } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 047753ca4..6a58bb0cd 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -9,19 +9,36 @@ class MatrixLayout : public GridLayout { public: using GridLayout::GridLayout; ExpressionLayout * clone() const override; + + /* Navigation */ + bool moveLeft(ExpressionLayoutCursor * cursor) override; + bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveUpInside(ExpressionLayoutCursor * cursor) override; + bool moveDownInside(ExpressionLayoutCursor * cursor) override; + + /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; + + /* Expression engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; + + /* Other */ bool isMatrix() const override { return true; } + + /* Special matrix method */ void newRowOrColumnAtIndex(int index); - void childWasReplacedAtIndex(int index); protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: + void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; + void addGreySquares(); + void removeGreySquares(); + bool hasGreySquares() const; }; } From e2bd7ddbe0cb9121fd9cebdfcdfab10811a2395c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 14:27:20 +0100 Subject: [PATCH 156/459] [poincare] Fixed deletion bug in MatrixLayout. Change-Id: I0dbc142468320fac4ed8969a3ef2684549315780 --- poincare/src/layout/matrix_layout.cpp | 6 ++++++ poincare/src/layout/matrix_layout.h | 1 + 2 files changed, 7 insertions(+) diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index afccc9260..7626efa06 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -117,6 +117,12 @@ void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, cursor->setPosition(ExpressionLayoutCursor::Position::Left); } +void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { + assert(index >= 0 && index < numberOfChildren()); + assert(cursor->pointedExpressionLayout() == child(index)); + replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); +} + int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { // The grid is a matrix. if (bufferSize == 0) { diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 6a58bb0cd..30dccb142 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -19,6 +19,7 @@ public: /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; + void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; /* Expression engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; From 16fad9f9fb7e47141a422124b314424116319983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 16:50:17 +0100 Subject: [PATCH 157/459] [poincare] Cleaned backspaceAtCursor for layouts. Change-Id: I232fa7af24a9983d3acfb3460042cb32bfcef81f --- poincare/include/poincare/expression_layout.h | 4 +- .../layout/binomial_coefficient_layout.cpp | 14 ----- .../src/layout/binomial_coefficient_layout.h | 1 - poincare/src/layout/bracket_layout.cpp | 17 ++---- poincare/src/layout/conjugate_layout.cpp | 30 ++++++++-- poincare/src/layout/conjugate_layout.h | 2 + poincare/src/layout/expression_layout.cpp | 38 +++--------- poincare/src/layout/fraction_layout.cpp | 19 +++--- poincare/src/layout/grid_layout.cpp | 22 ------- poincare/src/layout/grid_layout.h | 6 +- poincare/src/layout/horizontal_layout.cpp | 60 ++++++++++++++----- poincare/src/layout/integral_layout.cpp | 23 ++----- poincare/src/layout/matrix_layout.cpp | 1 - poincare/src/layout/nth_root_layout.cpp | 31 ++-------- poincare/src/layout/sequence_layout.cpp | 23 ++----- .../src/layout/vertical_offset_layout.cpp | 8 +++ 16 files changed, 121 insertions(+), 178 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index a2f4ab83d..e495c397c 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -75,8 +75,8 @@ public: virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ - virtual bool moveLeft(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? - virtual bool moveRight(ExpressionLayoutCursor * cursor) { return false; } //TODO should be virtual pure? + virtual bool moveLeft(ExpressionLayoutCursor * cursor) = 0; + virtual bool moveRight(ExpressionLayoutCursor * cursor) = 0; virtual bool moveUp( ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 0342a1b6f..aec65fd20 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -18,20 +18,6 @@ ExpressionLayout * BinomialCoefficientLayout::clone() const { return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); } -void BinomialCoefficientLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the children. - // Delete the layout. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && (cursor->pointedExpressionLayout() == nLayout() - || cursor->pointedExpressionLayout() == kLayout())) - { - assert(m_parent != nullptr); - replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); - return; - } - ExpressionLayout::backspaceAtCursor(cursor); -} - bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the children. // Go Left. diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 9fee26479..30dc3da69 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -10,7 +10,6 @@ class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 6d1222e14..38fd0b400 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -14,21 +14,14 @@ ExpressionLayout * BracketLayout::clone() const { } void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the operand. - // Delete the brackets, keep the operand. - if (cursor->pointedExpressionLayout() == operandLayout()) { - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + // Case: Right. + // Delete the layout, keep the operand. replaceWithAndMoveCursor(operandLayout(), true, cursor); return; } - // Case: Right. - // Move Right of the operand. - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(operandLayout()); - cursor->performBackspace(); - return; - } ExpressionLayout::backspaceAtCursor(cursor); } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 645514896..7323e1fd7 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -1,4 +1,5 @@ #include "conjugate_layout.h" +#include "empty_visible_layout.h" #include #include extern "C" { @@ -14,11 +15,13 @@ ExpressionLayout * ConjugateLayout::clone() const { } void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the operand. - // Delete the conjugate, keep the operand. - if (cursor->pointedExpressionLayout() == operandLayout()) { - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - replaceWithAndMoveCursor(operandLayout(), true, cursor); + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + // Case: Right. + // Move to the operand and delete. + cursor->setPointedExpressionLayout(operandLayout()); + cursor->performBackspace(); return; } ExpressionLayout::backspaceAtCursor(cursor); @@ -78,6 +81,23 @@ bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { return false; } +void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + assert(oldChild == operandLayout()); + if (newChild->isEmpty()) { + if (!deleteOldChild) { + detachChild(oldChild); + } + replaceWithAndMoveCursor(newChild, true, cursor); + return; + } + ExpressionLayout::replaceChildAndMoveCursor(oldChild, newChild, deleteOldChild, cursor); +} + +void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { + assert(index >= 0 && index < numberOfChildren()); + replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); +} + void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, p.y(), operandLayout()->size().width()+2*Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth), expressionColor); } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 203b1f1ca..f4846619f 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -13,6 +13,8 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; + void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; + void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "conj"); } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 76e7adcc4..8dfe2fb18 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -209,7 +209,6 @@ void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert(cursor->pointedExpressionLayout() == child(index)); removeChildAtIndex(index, deleteAfterRemoval); if (index < numberOfChildren()) { cursor->setPointedExpressionLayout(editableChild(index)); @@ -232,49 +231,30 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { // Case: The pointed layout is a child. - // Point to the previous child, else to this. + // Move Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (indexOfPointedExpression == 0) { - cursor->setPointedExpressionLayout(this); - } else { - cursor->setPointedExpressionLayout(editableChild(indexOfPointedExpression - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - } - cursor->performBackspace(); + cursor->moveLeft(); return; } assert(cursor->pointedExpressionLayout() == this); // Case: this is the pointed layout. if (m_parent == nullptr) { - // If there is no parent, return. + // Case: No parent. + // Return. return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { // Case: Left. // Ask the parent. - m_parent->backspaceAtCursor(cursor); + if (m_parent) { + m_parent->backspaceAtCursor(cursor); + } return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); // Case: Right. - // If the layout has children, move to the last one. - if (numberOfChildren() > 0) { - cursor->setPointedExpressionLayout(editableChild(numberOfChildren()-1)); - cursor->performBackspace(); - return; - } - int indexInParent = m_parent->indexOfChild(this); - ExpressionLayout * previousParent = m_parent; - // Case: Right. - // If the layout has no child and is only child, replace it with an empty layout. - /*if (previousParent->numberOfChildren() == 1) { - ExpressionLayout * newLayout = new EmptyVisibleLayout(); - replaceWith(newLayout, true); - cursor->setPointedExpressionLayout(newLayout); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - }*/ - previousParent->removePointedChildAtIndexAndMoveCursor(indexInParent, true, cursor); + // Delete the layout. + m_parent->removePointedChildAtIndexAndMoveCursor(m_parent->indexOfChild(this), true, cursor); } char ExpressionLayout::XNTChar() const { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index c425a8e4f..2f2d14dfe 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -14,13 +14,14 @@ ExpressionLayout * FractionLayout::clone() const { } void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // If the cursor is on the left of the denominator, replace the fraction with - // a horizontal juxtaposition of the numerator and the denominator. + // Case: Left of the denominator. + // Replace the fraction with a horizontal juxtaposition of the numerator and + // the denominator. if (cursor->pointedExpressionLayout() == denominatorLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { - // If the numerator and the denominator are empty, move the cursor then - // replace the fraction with an empty layout. + // Case: Numerator and denominator are empty. + // Move the cursor then replace the fraction with an empty layout. replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); return; } @@ -58,13 +59,9 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPosition(nextPosition); return; } - // If the cursor is on the left of the numerator, move Left of the fraction. - if (cursor->pointedExpressionLayout() == numeratorLayout()) { - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - cursor->setPointedExpressionLayout(this); - return; - } - // If the cursor is on the Right, move Left of the denominator. + + // Case: Right. + // Move Right of the denominator. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index bf3498872..e7af88579 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -21,28 +21,6 @@ ExpressionLayout * GridLayout::clone() const { return layout; } -void GridLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); - if (indexOfPointedExpression >= 0) { - // Case: Left of child of the grid. - // Move Left. - moveLeft(cursor); - return; - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Ask the parent. - if (m_parent) { - return m_parent->backspaceAtCursor(cursor); - } - } - // Case: Right. - // Delete the grid. - assert(m_parent != nullptr); - replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); -} - bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Right. // Go to the last entry. diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 5fac6e1ec..d7e2915f6 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -11,7 +11,6 @@ class GridLayout : public DynamicLayoutHierarchy { public: GridLayout(const ExpressionLayout * const * entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor) override; @@ -21,9 +20,8 @@ public: /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; - // TODO: This function replaces the child with an EmptyVisibleLayout. Is this - // ok? If we want to delete the grid's children, we have to make sure no to - // call this function. + // This function replaces the child with an EmptyVisibleLayout. To delete the + // grid's children, do not call this function. /* Expression engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 45f1a9747..19ee6021b 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -15,14 +15,47 @@ ExpressionLayout * HorizontalLayout::clone() const { } void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // If the cursor was pointing left of the first child of the horizontal - // layout, make it point at the horizontal layout itself. + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Left + && m_parent == nullptr) + { + // Case: Left and this is the main layout. + // Return. + return; + } + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right + && m_parent == nullptr + && numberOfChildren() == 0) + { + // Case: Right and this is the main layout with no children. + // Return. + return; + } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); - if (indexOfPointedExpression == 0) { - cursor->setPointedExpressionLayout(this); + if (indexOfPointedExpression >= 0) { + // Case: Left of a child. + // Point Right of the previous child. If there is no previous child, point + // Left of this. Perform another backspace. + if (indexOfPointedExpression == 0) { + cursor->setPointedExpressionLayout(this); + } else if (indexOfPointedExpression > 0) { + cursor->setPointedExpressionLayout(editableChild(indexOfPointedExpression - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + cursor->performBackspace(); + return; } } + assert(cursor->pointedExpressionLayout() == this); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + // Case: Right. + // Point to the last child and perform backspace. + cursor->setPointedExpressionLayout(editableChild(numberOfChildren() - 1)); + cursor->performBackspace(); + return; + } ExpressionLayout::backspaceAtCursor(cursor); } @@ -89,18 +122,17 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex // new layout then destroy it. if (newChild->isHorizontal()) { int indexForInsertion = indexOfChild(oldChild); + if (cursor != nullptr) { + if (oldChildIndex == numberOfChildren() - 1) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } else { + cursor->setPointedExpressionLayout(editableChild(oldChildIndex + 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } + } mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); removeChildAtIndex(indexForInsertion, deleteOldChild); - if (cursor == nullptr) { - return; - } - if (oldChildIndex == 0) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - } - cursor->setPointedExpressionLayout(editableChild(oldChildIndex -1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } // Else, just replace the child. diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 3ce10c2d1..80011c669 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -27,28 +27,15 @@ ExpressionLayout * IntegralLayout::clone() const { } void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left the upper bound, lower bound or argument. - // Delete the integral, keep the integrand. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && ((upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()) - || (lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) - || cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left))) + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) { + // Case: Right. + // Delete the layout, keep the integrand. replaceWithAndMoveCursor(integrandLayout(), true, cursor); return; } - // If the cursor is on the right, move to the integrand. - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(integrandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; - } - if (m_parent) { - return m_parent->backspaceAtCursor(cursor); - } + ExpressionLayout::backspaceAtCursor(cursor); } bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 7626efa06..ff18958fc 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -119,7 +119,6 @@ void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert(cursor->pointedExpressionLayout() == child(index)); replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); } diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index d2df334fe..77e4516ab 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -26,36 +26,15 @@ ExpressionLayout * NthRootLayout::clone() const { } void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left the index. - // Move Left. - if (indexLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left - && cursor->pointedExpressionLayout() == indexLayout()) - { - cursor->setPointedExpressionLayout(this); - return; - } - // Case: Left the radicand. - // Delete the root, keep the radicand. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && cursor->pointedExpressionLayout() == radicandLayout()) + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) { + // Case: Right. + // Delete the layout, keep the operand. replaceWithAndMoveCursor(radicandLayout(), true, cursor); return; } - // Case: Right. - // Move to the radicand. - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() ==ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(radicandLayout()); - return; - } - // Case: Left. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->backspaceAtCursor(cursor); - } + ExpressionLayout::backspaceAtCursor(cursor); } bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index da31a3400..8e871c118 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -14,30 +14,15 @@ SequenceLayout::SequenceLayout(ExpressionLayout * argument, ExpressionLayout * l } void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the bounds or of the argument. - // Delete the sequence, keep the argument. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && ((lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) - || (upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()) - || cursor->pointedExpressionLayout() == argumentLayout())) - { - replaceWithAndMoveCursor(argumentLayout(), true, cursor); - return; - } - // Case: Right. - // Move inside the argument. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(argumentLayout()); + // Case: Right. + // Delete the layout, keep the operand. + replaceWithAndMoveCursor(argumentLayout(), true, cursor); return; } - // Case: Left. - // Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - m_parent->backspaceAtCursor(cursor); + ExpressionLayout::backspaceAtCursor(cursor); } bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 003ba0452..2da4b08b3 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -44,6 +44,14 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); return; } + if (cursor->pointedExpressionLayout() == this + && cursor->position() == ExpressionLayoutCursor::Position::Right) + { + // Case: Right. + // Move to the indice. + cursor->setPointedExpressionLayout(indiceLayout()); + return; + } ExpressionLayout::backspaceAtCursor(cursor); } From 1e8935fc2e5a1b351f76a95f2b7b0e8f9211344e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 16:54:02 +0100 Subject: [PATCH 158/459] [poincare] Use MatrixLayout in Expression::Matrix::privateCreateLayout. Change-Id: I60a4212dd5206a8372f4355b9ff1287577428d1b --- poincare/src/matrix.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 09bcb7908..d8f9a8824 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -7,8 +7,7 @@ extern "C" { #include #include #include -#include "layout/grid_layout.h" -#include "layout/bracket_layout.h" +#include "layout/matrix_layout.h" #include #include #include @@ -102,7 +101,7 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode for (int i = 0; i < numberOfOperands(); i++) { childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); } - ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns(), false), false); + ExpressionLayout * layout = new MatrixLayout(childrenLayouts, numberOfRows(), numberOfColumns(), false); delete [] childrenLayouts; return layout; } From 735d79a0fcd04d90e73557103f25ea6a806cd3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 17:50:45 +0100 Subject: [PATCH 159/459] [apps/settings] Use the new layouts in the Settings app. Change-Id: Ic90a78cf58cac28f24b65c5e0c1776c61675bb98 --- apps/settings/Makefile | 1 + apps/settings/helpers.cpp | 27 +++++++++++++++++++++++++++ apps/settings/helpers.h | 15 +++++++++++++++ apps/settings/main_controller.cpp | 11 +++-------- apps/settings/sub_controller.cpp | 10 +++------- 5 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 apps/settings/helpers.cpp create mode 100644 apps/settings/helpers.h diff --git a/apps/settings/Makefile b/apps/settings/Makefile index ac039b8e7..9078f0463 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -3,6 +3,7 @@ snapshot_headers += apps/settings/app.h app_objs += $(addprefix apps/settings/,\ app.o\ + helpers.o\ language_controller.o\ main_controller.o\ settings_message_tree.o\ diff --git a/apps/settings/helpers.cpp b/apps/settings/helpers.cpp new file mode 100644 index 000000000..2581a0a4c --- /dev/null +++ b/apps/settings/helpers.cpp @@ -0,0 +1,27 @@ +#include "helpers.h" +#include +#include +#include "../../poincare/src/layout/horizontal_layout.h" +#include "../../poincare/src/layout/vertical_offset_layout.h" + +using namespace Poincare; + +namespace Settings { +namespace Helpers { + +ExpressionLayout * CartesianComplexFormat(KDText::FontSize fontSize) { + const char text[] = {'a','+', Ion::Charset::IComplex, 'b', ' '}; + return LayoutEngine::createStringLayout(text, sizeof(text), fontSize); +} + +ExpressionLayout * PolarComplexFormat(KDText::FontSize fontSize) { + const char base[] = {'r', Ion::Charset::Exponential}; + const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '}; + return new HorizontalLayout( + LayoutEngine::createStringLayout(base, sizeof(base), fontSize), + new VerticalOffsetLayout(LayoutEngine::createStringLayout(superscript, sizeof(superscript), fontSize), VerticalOffsetLayout::Type::Superscript, false), + false); +} + +} +} diff --git a/apps/settings/helpers.h b/apps/settings/helpers.h new file mode 100644 index 000000000..01dacd0ba --- /dev/null +++ b/apps/settings/helpers.h @@ -0,0 +1,15 @@ +#ifndef SETTINGS_HELPERS_H +#define SETTINGS_HELPERS_H + +#include + +namespace Settings { +namespace Helpers { + +Poincare::ExpressionLayout * CartesianComplexFormat(KDText::FontSize fontSize); +Poincare::ExpressionLayout * PolarComplexFormat(KDText::FontSize fontSize); + +} +} + +#endif diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 32a0f7c80..37c1fb4f6 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -1,10 +1,8 @@ #include "main_controller.h" +#include "helpers.h" #include "../global_preferences.h" #include "../i18n.h" -#include "../../poincare/src/layout/baseline_relative_layout.h" -#include "../../poincare/src/layout/string_layout.h" #include -#include using namespace Poincare; @@ -175,12 +173,9 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { m_complexFormatLayout = nullptr; } if (Preferences::sharedPreferences()->complexFormat() == Expression::ComplexFormat::Cartesian) { - const char text[] = {'a','+', Ion::Charset::IComplex, 'b', ' '}; - m_complexFormatLayout = new StringLayout(text, sizeof(text), KDText::FontSize::Small); + m_complexFormatLayout = Helpers::CartesianComplexFormat(KDText::FontSize::Small); } else { - const char base[] = {'r', Ion::Charset::Exponential}; - const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '}; - m_complexFormatLayout = new BaselineRelativeLayout(new StringLayout(base, sizeof(base), KDText::FontSize::Small), new StringLayout(superscript, sizeof(superscript), KDText::FontSize::Small), BaselineRelativeLayout::Type::Superscript); + m_complexFormatLayout = Helpers::PolarComplexFormat(KDText::FontSize::Small); } MessageTableCellWithChevronAndExpression * myExpCell = (MessageTableCellWithChevronAndExpression *)cell; myExpCell->setExpressionLayout(m_complexFormatLayout); diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp index 6d5b8ec4e..eacaededa 100644 --- a/apps/settings/sub_controller.cpp +++ b/apps/settings/sub_controller.cpp @@ -1,8 +1,7 @@ #include "sub_controller.h" +#include "helpers.h" #include "../global_preferences.h" #include "../apps_container.h" -#include "../../poincare/src/layout/baseline_relative_layout.h" -#include "../../poincare/src/layout/string_layout.h" #include #include @@ -22,11 +21,8 @@ SubController::SubController(Responder * parentResponder) : m_cells[i].setAccessoryFontSize(KDText::FontSize::Small); m_cells[i].setAccessoryTextColor(Palette::GreyDark); } - const char text[] = {'a','+', Ion::Charset::IComplex, 'b', ' '}; - m_complexFormatLayout[0] = new StringLayout(text, sizeof(text)); - const char base[] = {'r', Ion::Charset::Exponential}; - const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '}; - m_complexFormatLayout[1] = new BaselineRelativeLayout(new StringLayout(base, sizeof(base)), new StringLayout(superscript, sizeof(superscript)), BaselineRelativeLayout::Type::Superscript); + m_complexFormatLayout[0] = Helpers::CartesianComplexFormat(KDText::FontSize::Large); + m_complexFormatLayout[1] = Helpers::PolarComplexFormat(KDText::FontSize::Large); for (int i = 0; i < 2; i++) { m_complexFormatCells[i].setExpressionLayout(m_complexFormatLayout[i]); } From b7c0a15eb8ef336bad0841fb55c2011edd5f02b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Jan 2018 18:11:44 +0100 Subject: [PATCH 160/459] [apps/regression] Use the new layouts in the Regression app. Change-Id: I3813ed42c35d92e98f6d162ac3788a238f2f836e --- apps/regression/calculation_controller.cpp | 7 ++++--- apps/regression/store_controller.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 1a937c6ea..6201d910e 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -1,8 +1,9 @@ #include "calculation_controller.h" #include "../constant.h" #include "../apps_container.h" -#include "../../poincare/src/layout/baseline_relative_layout.h" -#include "../../poincare/src/layout/string_layout.h" +#include "../../poincare/src/layout/char_layout.h" +#include "../../poincare/src/layout/horizontal_layout.h" +#include "../../poincare/src/layout/vertical_offset_layout.h" #include #include @@ -21,7 +22,7 @@ CalculationController::CalculationController(Responder * parentResponder, Button m_calculationCells{}, m_store(store) { - m_r2Layout = new BaselineRelativeLayout(new StringLayout("r", 1, KDText::FontSize::Small), new StringLayout("2", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Superscript); + m_r2Layout = new HorizontalLayout(new CharLayout('r', KDText::FontSize::Small), new VerticalOffsetLayout(new CharLayout('2', KDText::FontSize::Small), VerticalOffsetLayout::Type::Superscript, false), false); } CalculationController::~CalculationController() { diff --git a/apps/regression/store_controller.cpp b/apps/regression/store_controller.cpp index 59617a330..e08bb358d 100644 --- a/apps/regression/store_controller.cpp +++ b/apps/regression/store_controller.cpp @@ -2,8 +2,9 @@ #include "app.h" #include "../apps_container.h" #include "../constant.h" -#include "../../poincare/src/layout/baseline_relative_layout.h" -#include "../../poincare/src/layout/string_layout.h" +#include "../../poincare/src/layout/char_layout.h" +#include "../../poincare/src/layout/horizontal_layout.h" +#include "../../poincare/src/layout/vertical_offset_layout.h" #include using namespace Poincare; @@ -15,8 +16,8 @@ StoreController::StoreController(Responder * parentResponder, Store * store, But Shared::StoreController(parentResponder, store, header), m_titleCells{} { - m_titleLayout[0] = new BaselineRelativeLayout(new StringLayout("X", 1, KDText::FontSize::Small), new StringLayout("i", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - m_titleLayout[1] = new BaselineRelativeLayout(new StringLayout("Y", 1, KDText::FontSize::Small), new StringLayout("i", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_titleLayout[0] = new HorizontalLayout(new CharLayout('X', KDText::FontSize::Small), new VerticalOffsetLayout(new CharLayout('i', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), false); + m_titleLayout[1] = new HorizontalLayout(new CharLayout('Y', KDText::FontSize::Small), new VerticalOffsetLayout(new CharLayout('i', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), false); } StoreController::~StoreController() { From a435c548dabd97b7a9d64cc6a42fa252dd9ef6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 12 Jan 2018 11:09:12 +0100 Subject: [PATCH 161/459] [apps/sequence] Use the new layouts in the Sequence app. Change-Id: I8b079bfabccd54472e0ba0fac17b87dbaf3678ee --- apps/Makefile | 2 +- apps/sequence/graph/term_sum_controller.cpp | 36 ++++++++++------ apps/sequence/list/sequence_toolbox.cpp | 40 +++++++++--------- .../list/type_parameter_controller.cpp | 11 +++-- apps/sequence/sequence.cpp | 42 ++++++++++++------- 5 files changed, 82 insertions(+), 49 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 9c3ecf405..16482bc60 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= expression_editor +EPSILON_APPS ?= expression_editor sequence settings statistics probability regression code include apps/shared/Makefile include apps/home/Makefile diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index cc136bd87..0681afad1 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -1,9 +1,10 @@ #include "term_sum_controller.h" #include "../../shared/text_field_delegate.h" -#include "../../../poincare/src/layout/baseline_relative_layout.h" +#include "../../../poincare/src/layout/char_layout.h" #include "../../../poincare/src/layout/condensed_sum_layout.h" -#include "../../../poincare/src/layout/string_layout.h" #include "../../../poincare/src/layout/horizontal_layout.h" +#include "../../../poincare/src/layout/vertical_offset_layout.h" +#include #include #include @@ -197,12 +198,16 @@ void TermSumController::LegendView::setSumSubscript(float start) { delete m_sumLayout; m_sumLayout = nullptr; } - const char sigma[] = {' ',Ion::Charset::CapitalSigma}; + const char sigma[] = {' ', Ion::Charset::CapitalSigma}; char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; Complex::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); - m_sum.setExpressionLayout(m_sumLayout); - m_sum.setAlignment(0.0f, 0.5f); + m_sumLayout = new CondensedSumLayout( + LayoutEngine::createStringLayout(sigma, sizeof(sigma), KDText::FontSize::Large), + LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), + nullptr, + false); + m_sum.setExpressionLayout(m_sumLayout); + m_sum.setAlignment(0.0f, 0.5f); } void TermSumController::LegendView::setSumSuperscript(float start, float end) { @@ -215,20 +220,27 @@ void TermSumController::LegendView::setSumSuperscript(float start, float end) { Complex::convertFloatToText(start, bufferStart, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); char bufferEnd[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; Complex::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), new StringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), new StringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small)); + m_sumLayout = new CondensedSumLayout( + LayoutEngine::createStringLayout(sigma, sizeof(sigma), KDText::FontSize::Large), + LayoutEngine::createStringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), + LayoutEngine::createStringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small), + false); m_sum.setExpressionLayout(m_sumLayout); m_sum.setAlignment(0.0f, 0.5f); } void TermSumController::LegendView::setSumResult(const char * sequenceName, double result) { - ExpressionLayout * childrenLayouts[3]; char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; strlcpy(buffer, "= ", 3); Complex::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); - childrenLayouts[2] = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); - childrenLayouts[1] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - childrenLayouts[0] = m_sumLayout; - m_sumLayout = new HorizontalLayout(childrenLayouts, 3); + m_sumLayout = new HorizontalLayout( + m_sumLayout, + new HorizontalLayout( + new CharLayout(sequenceName[0], KDText::FontSize::Small), + new VerticalOffsetLayout(new CharLayout('n', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false), + LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), + false); m_sum.setExpressionLayout(m_sumLayout); m_sum.setAlignment(0.5f, 0.5f); } diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index ed5a3f49b..fddc7d061 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -1,7 +1,9 @@ #include "sequence_toolbox.h" #include "../sequence_store.h" -#include "../../../poincare/src/layout/baseline_relative_layout.h" -#include "../../../poincare/src/layout/string_layout.h" +#include "../../../poincare/src/layout/char_layout.h" +#include "../../../poincare/src/layout/horizontal_layout.h" +#include "../../../poincare/src/layout/vertical_offset_layout.h" +#include #include using namespace Poincare; @@ -91,30 +93,30 @@ void SequenceToolbox::setExtraCells(const char * sequenceName, int recurrenceDep const char * otherSequenceName = SequenceStore::k_sequenceNames[1-sequenceIndex]; for (int j = 0; j < recurrenceDepth; j++) { const char * indice = j == 0 ? "n" : "n+1"; - m_addedCellLayout[j] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Large), new StringLayout(indice, strlen(indice), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - m_addedCellLayout[j+recurrenceDepth] = new BaselineRelativeLayout(new StringLayout(otherSequenceName, 1, KDText::FontSize::Large), new StringLayout(indice, strlen(indice), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_addedCellLayout[j] = new HorizontalLayout( + new CharLayout(sequenceName[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout(indice, strlen(indice), KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); + m_addedCellLayout[j+recurrenceDepth] = new HorizontalLayout( + new CharLayout(otherSequenceName[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout(indice, strlen(indice), KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } if (recurrenceDepth < 2) { const char * indice = recurrenceDepth == 0 ? "n" : (recurrenceDepth == 1 ? "n+1" : "n+2"); - m_addedCellLayout[2*recurrenceDepth] = new BaselineRelativeLayout(new StringLayout(otherSequenceName, 1, KDText::FontSize::Large), new StringLayout(indice, strlen(indice), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_addedCellLayout[2*recurrenceDepth] = new HorizontalLayout( + new CharLayout(otherSequenceName[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout(indice, strlen(indice), KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } } bool SequenceToolbox::selectAddedCell(int selectedRow){ - char buffer[10]; - BaselineRelativeLayout * layout = (BaselineRelativeLayout *)m_addedCellLayout[selectedRow]; - StringLayout * nameLayout = (StringLayout *)layout->baseLayout(); - StringLayout * subscriptLayout = (StringLayout *)layout->indiceLayout(); - int currentChar = 0; - strlcpy(buffer, nameLayout->text(), strlen(nameLayout->text())+1); - currentChar += strlen(nameLayout->text()); - buffer[currentChar++] = '('; - strlcpy(buffer+currentChar, subscriptLayout->text(), strlen(subscriptLayout->text())+1); - currentChar += strlen(subscriptLayout->text()); - buffer[currentChar++] = ')'; - buffer[currentChar] = 0; - sender()->insertTextAtLocation(buffer, sender()->cursorLocation()); - sender()->setCursorLocation(sender()->cursorLocation()+currentChar); + int bufferSize = 10; + char buffer[bufferSize]; + int currentChar = m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); + textFieldSender()->insertTextAtLocation(buffer, textFieldSender()->cursorLocation()); + textFieldSender()->setCursorLocation(textFieldSender()->cursorLocation()+currentChar); app()->dismissModalViewController(); return true; } diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index 037aaa98f..4c0bf513c 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -2,8 +2,10 @@ #include "list_controller.h" #include "../app.h" #include -#include "../../../poincare/src/layout/baseline_relative_layout.h" -#include "../../../poincare/src/layout/string_layout.h" +#include +#include "../../../poincare/src/layout/char_layout.h" +#include "../../../poincare/src/layout/horizontal_layout.h" +#include "../../../poincare/src/layout/vertical_offset_layout.h" using namespace Poincare; @@ -120,7 +122,10 @@ void TypeParameterController::willDisplayCellAtLocation(HighlightCell * cell, in delete m_expressionLayouts[j]; m_expressionLayouts[j] = nullptr; } - m_expressionLayouts[j] = new BaselineRelativeLayout(new StringLayout(nextName, 1, size), new StringLayout(subscripts[j], strlen(subscripts[j]), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_expressionLayouts[j] = new HorizontalLayout( + new CharLayout(nextName[0], size), + new VerticalOffsetLayout(LayoutEngine::createStringLayout(subscripts[j], strlen(subscripts[j]), KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); ExpressionTableCellWithPointer * myCell = (ExpressionTableCellWithPointer *)cell; myCell->setExpressionLayout(m_expressionLayouts[j]); } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 6658dbc0a..a7c204d59 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -1,8 +1,10 @@ #include "sequence.h" #include "sequence_store.h" #include "cache_context.h" -#include "../../poincare/src/layout/string_layout.h" -#include "../../poincare/src/layout/baseline_relative_layout.h" +#include +#include "../../poincare/src/layout/char_layout.h" +#include "../../poincare/src/layout/horizontal_layout.h" +#include "../../poincare/src/layout/vertical_offset_layout.h" #include #include @@ -227,7 +229,10 @@ int Sequence::numberOfElements() { Poincare::ExpressionLayout * Sequence::nameLayout() { if (m_nameLayout == nullptr) { - m_nameLayout = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_nameLayout = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Large), + new VerticalOffsetLayout(new CharLayout('n', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } return m_nameLayout; } @@ -235,13 +240,22 @@ Poincare::ExpressionLayout * Sequence::nameLayout() { Poincare::ExpressionLayout * Sequence::definitionName() { if (m_definitionName == nullptr) { if (m_type == Type::Explicit) { - m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n ", 2, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_definitionName = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout("n ", 2, KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } if (m_type == Type::SingleRecurrence) { - m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n+1 ", 4, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_definitionName = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout("n+1 ", 4, KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } if (m_type == Type::DoubleRecurrence) { - m_definitionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout("n+2 ", 4, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); + m_definitionName = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Large), + new VerticalOffsetLayout(LayoutEngine::createStringLayout("n+2 ", 4, KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } } return m_definitionName; @@ -251,12 +265,10 @@ Poincare::ExpressionLayout * Sequence::firstInitialConditionName() { char buffer[k_initialRankNumberOfDigits+1]; Integer(m_initialRank).writeTextInBuffer(buffer, k_initialRankNumberOfDigits+1); if (m_firstInitialConditionName == nullptr) { - if (m_type == Type::SingleRecurrence) { - m_firstInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - } - if (m_type == Type::DoubleRecurrence) { - m_firstInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - } + m_firstInitialConditionName = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Small), + new VerticalOffsetLayout(new CharLayout('0', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } return m_firstInitialConditionName; } @@ -266,8 +278,10 @@ Poincare::ExpressionLayout * Sequence::secondInitialConditionName() { Integer(m_initialRank+1).writeTextInBuffer(buffer, k_initialRankNumberOfDigits+1); if (m_secondInitialConditionName == nullptr) { if (m_type == Type::DoubleRecurrence) { - m_secondInitialConditionName = new BaselineRelativeLayout(new StringLayout(name(), 1), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); - + m_secondInitialConditionName = new HorizontalLayout( + new CharLayout(name()[0], KDText::FontSize::Small), + new VerticalOffsetLayout(new CharLayout('1', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + false); } } return m_secondInitialConditionName; From 2ed72127cb3093e00e3541fc4f5e886e1d731b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 12 Jan 2018 11:52:04 +0100 Subject: [PATCH 162/459] [poincare] Remove dangerous default arguments in poincare. Change-Id: I76f2bc057d73c7d151aed62b66eb69a91082910c --- .../include/poincare/bounded_static_layout_hierarchy.h | 6 +++--- poincare/include/poincare/dynamic_layout_hierarchy.h | 8 ++++---- poincare/include/poincare/expression_layout.h | 4 ++-- poincare/include/poincare/static_layout_hierarchy.h | 8 ++++---- poincare/src/expression_layout_cursor.cpp | 4 ++-- poincare/src/layout/horizontal_layout.h | 2 +- poincare/src/layout/matrix_layout.h | 2 +- poincare/src/layout/sequence_layout.cpp | 5 ----- poincare/src/layout/sequence_layout.h | 2 +- 9 files changed, 18 insertions(+), 23 deletions(-) diff --git a/poincare/include/poincare/bounded_static_layout_hierarchy.h b/poincare/include/poincare/bounded_static_layout_hierarchy.h index 42a0acc6b..a54036037 100644 --- a/poincare/include/poincare/bounded_static_layout_hierarchy.h +++ b/poincare/include/poincare/bounded_static_layout_hierarchy.h @@ -9,9 +9,9 @@ template class BoundedStaticLayoutHierarchy : public StaticLayoutHierarchy { public: BoundedStaticLayoutHierarchy(); - BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> - BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout1, const ExpressionLayout * expressionLayout2, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> - BoundedStaticLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); + BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout, bool cloneOperands); // Specialized constructor for StaticLayoutHierarchy<2> + BoundedStaticLayoutHierarchy(const ExpressionLayout * expressionLayout1, const ExpressionLayout * expressionLayout2, bool cloneOperands); // Specialized constructor for StaticLayoutHierarchy<2> + BoundedStaticLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands); int numberOfChildren() const override { return m_numberOfChildren; } private: int m_numberOfChildren; diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 63518b122..499f09cef 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -9,12 +9,12 @@ namespace Poincare { class DynamicLayoutHierarchy : public ExpressionLayout { public: DynamicLayoutHierarchy(); - DynamicLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands = true); - DynamicLayoutHierarchy(const ExpressionLayout * operand, bool cloneOperands = true) : + DynamicLayoutHierarchy(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands); + DynamicLayoutHierarchy(const ExpressionLayout * operand, bool cloneOperands) : DynamicLayoutHierarchy(ExpressionLayoutArray(operand).array(), 1, cloneOperands) {} - DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands = true) : + DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, bool cloneOperands) : DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2).array(), 2, cloneOperands) {} - DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, const ExpressionLayout * operand3, bool cloneOperands = true) : + DynamicLayoutHierarchy(const ExpressionLayout * operand1, const ExpressionLayout * operand2, const ExpressionLayout * operand3, bool cloneOperands) : DynamicLayoutHierarchy(ExpressionLayoutArray(operand1, operand2, operand3).array(), 3, cloneOperands) {} ~DynamicLayoutHierarchy(); DynamicLayoutHierarchy(const DynamicLayoutHierarchy & other) = delete; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index e495c397c..3cfd319a6 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -53,9 +53,9 @@ public: virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); // Replace - virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace = true); + virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace); ExpressionLayout * replaceWithAndMoveCursor(ExpressionLayout * newChild, bool deleteAfterReplace, ExpressionLayoutCursor * cursor); - virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true); + virtual void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild); virtual void replaceChildAndMoveCursor( const ExpressionLayout * oldChild, ExpressionLayout * newChild, diff --git a/poincare/include/poincare/static_layout_hierarchy.h b/poincare/include/poincare/static_layout_hierarchy.h index daf4bbc2c..57a31821a 100644 --- a/poincare/include/poincare/static_layout_hierarchy.h +++ b/poincare/include/poincare/static_layout_hierarchy.h @@ -9,10 +9,10 @@ template class StaticLayoutHierarchy : public ExpressionLayout { public: StaticLayoutHierarchy(); - StaticLayoutHierarchy(const ExpressionLayout * const * operands, bool cloneOperands = true); - StaticLayoutHierarchy(const ExpressionLayout * expression, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<1> - StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<2> - StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, const ExpressionLayout * expression3, bool cloneOperands = true); // Specialized constructor for StaticLayoutHierarchy<3> + StaticLayoutHierarchy(const ExpressionLayout * const * operands, bool cloneOperands); + StaticLayoutHierarchy(const ExpressionLayout * expression, bool cloneOperands); // Specialized constructor for StaticLayoutHierarchy<1> + StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, bool cloneOperands); // Specialized constructor for StaticLayoutHierarchy<2> + StaticLayoutHierarchy(const ExpressionLayout * expression1, const ExpressionLayout * expression2, const ExpressionLayout * expression3, bool cloneOperands); // Specialized constructor for StaticLayoutHierarchy<3> ~StaticLayoutHierarchy(); StaticLayoutHierarchy(const StaticLayoutHierarchy & other) = delete; StaticLayoutHierarchy(StaticLayoutHierarchy && other) = delete; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 3f89545d9..31ecfeb00 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -57,8 +57,8 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { // Add a new FractionLayout - HorizontalLayout * child1 = new HorizontalLayout(new EmptyVisibleLayout()); - HorizontalLayout * child2 = new HorizontalLayout(new EmptyVisibleLayout()); + HorizontalLayout * child1 = new HorizontalLayout(new EmptyVisibleLayout(), false); + HorizontalLayout * child2 = new HorizontalLayout(new EmptyVisibleLayout(), false); FractionLayout * newChild = new FractionLayout(child1, child2, false); pointedExpressionLayout()->addBrother(this, newChild); diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index a8e932797..8516fa977 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -17,7 +17,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Hierarchy */ - void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; + void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 30dccb142..b931bb51b 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -17,7 +17,7 @@ public: bool moveDownInside(ExpressionLayoutCursor * cursor) override; /* Dynamic layout */ - void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override; + void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 8e871c118..b9a91e85b 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -8,11 +8,6 @@ namespace Poincare { -SequenceLayout::SequenceLayout(ExpressionLayout * argument, ExpressionLayout * lowerBound, ExpressionLayout * upperBound, bool cloneOperands) : - StaticLayoutHierarchy(argument, lowerBound, upperBound) -{ -} - void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 8969398ce..ef92f3f68 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -7,9 +7,9 @@ namespace Poincare { class SequenceLayout : public StaticLayoutHierarchy<3> { public: + using StaticLayoutHierarchy::StaticLayoutHierarchy; constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; - SequenceLayout(ExpressionLayout * argument, ExpressionLayout * lowerBound, ExpressionLayout * upperBound, bool cloneOperands); void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; From f6a0a9235f5f221c975fc2a566eb691f15053271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 12 Jan 2018 14:55:25 +0100 Subject: [PATCH 163/459] [apps] Makefile. Enable all the apps. Change-Id: I50d93217a5ae657cccfed285a255ed470e619bf7 --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index 16482bc60..60e285088 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= expression_editor sequence settings statistics probability regression code +EPSILON_APPS ?= expression_editor calculation graph sequence settings statistics probability regression code include apps/shared/Makefile include apps/home/Makefile From 5ff32b8162d2926e5a3aac78d805f36543aadda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 12 Jan 2018 16:13:11 +0100 Subject: [PATCH 164/459] [expression_editor] Controller::handleAddEvent returns void. Change-Id: Iaac5fd3d0798f5c2e81d3c982198f402534f6dfe --- apps/expression_editor/controller.cpp | 37 +++++++++++------- apps/expression_editor/controller.h | 2 +- .../poincare/expression_layout_cursor.h | 18 ++++----- poincare/src/expression_layout_cursor.cpp | 39 +++++++------------ 4 files changed, 47 insertions(+), 49 deletions(-) diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index cdce47736..69ca7ac66 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -66,8 +66,7 @@ bool Controller::privateHandleEvent(Ion::Events::Event event) { m_view.layoutSubviews(); return true; } - ExpressionLayout * newPointedLayout = handleAddEvent(event); - if (newPointedLayout != nullptr) { + if (handleAddEvent(event)) { m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.layoutSubviews(); return true; @@ -107,42 +106,52 @@ bool Controller::handleMoveEvent(Ion::Events::Event event) { return false; } -ExpressionLayout * Controller::handleAddEvent(Ion::Events::Event event) { +bool Controller::handleAddEvent(Ion::Events::Event event) { if (event == Ion::Events::Division) { - return m_cursor.addFractionLayoutAndCollapseBrothers(); + m_cursor.addFractionLayoutAndCollapseBrothers(); + return true; } if (event == Ion::Events::XNT) { - return m_cursor.addXNTCharLayout(); + m_cursor.addXNTCharLayout(); + return true; } if (event == Ion::Events::Exp) { - return m_cursor.addEmptyExponentialLayout(); + m_cursor.addEmptyExponentialLayout(); + return true; } if (event == Ion::Events::Log) { - return m_cursor.addEmptyLogarithmLayout(); + m_cursor.addEmptyLogarithmLayout(); + return true; } if (event == Ion::Events::Power) { - return m_cursor.addEmptyPowerLayout(); + m_cursor.addEmptyPowerLayout(); + return true; } if (event == Ion::Events::Sqrt) { - return m_cursor.addEmptySquareRootLayout(); + m_cursor.addEmptySquareRootLayout(); + return true; } if (event == Ion::Events::Square) { - return m_cursor.addEmptySquarePowerLayout(); + m_cursor.addEmptySquarePowerLayout(); + return true; } if (event.hasText()) { const char * textToInsert = event.text(); if (textToInsert[1] == 0) { if (textToInsert[0] == Ion::Charset::MultiplicationSign) { const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - return m_cursor.insertText(middleDotString); + m_cursor.insertText(middleDotString); + return true; } if (textToInsert[0] == '[' || textToInsert[0] == ']') { - return m_cursor.addEmptyMatrixLayout(); + m_cursor.addEmptyMatrixLayout(); + return true; } } - return m_cursor.insertText(textToInsert); + m_cursor.insertText(textToInsert); + return true; } - return nullptr; + return false; } bool Controller::handleDeleteEvent(Ion::Events::Event event) { diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h index 5a02edd17..546d00680 100644 --- a/apps/expression_editor/controller.h +++ b/apps/expression_editor/controller.h @@ -27,7 +27,7 @@ public: private: bool privateHandleEvent(Ion::Events::Event event); bool handleMoveEvent(Ion::Events::Event event); - Poincare::ExpressionLayout * handleAddEvent(Ion::Events::Event event); + bool handleAddEvent(Ion::Events::Event event); bool handleDeleteEvent(Ion::Events::Event event); void serializeLayout(); void computeResult(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index a4f5dbb85..3a444399f 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -40,15 +40,15 @@ public: /* Edition */ void addLayout(ExpressionLayout * layout); - ExpressionLayout * addEmptyExponentialLayout(); - ExpressionLayout * addFractionLayoutAndCollapseBrothers(); - ExpressionLayout * addEmptyLogarithmLayout(); - ExpressionLayout * addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); - ExpressionLayout * addEmptyPowerLayout(); - ExpressionLayout * addEmptySquareRootLayout(); - ExpressionLayout * addEmptySquarePowerLayout(); - ExpressionLayout * addXNTCharLayout(); - ExpressionLayout * insertText(const char * text); + void addEmptyExponentialLayout(); + void addFractionLayoutAndCollapseBrothers(); + void addEmptyLogarithmLayout(); + void addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); + void addEmptyPowerLayout(); + void addEmptySquareRootLayout(); + void addEmptySquarePowerLayout(); + void addXNTCharLayout(); + void insertText(const char * text); void performBackspace(); private: diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 31ecfeb00..86c30a923 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -45,17 +45,16 @@ void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { pointedExpressionLayout()->addBrother(this, layout); } -ExpressionLayout * ExpressionLayoutCursor::addEmptyExponentialLayout() { +void ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); pointedExpressionLayout()->addBrother(this, newChild); setPointedExpressionLayout(offsetLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Right); - return offsetLayout; } -ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { +void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { // Add a new FractionLayout HorizontalLayout * child1 = new HorizontalLayout(new EmptyVisibleLayout(), false); HorizontalLayout * child2 = new HorizontalLayout(new EmptyVisibleLayout(), false); @@ -65,7 +64,7 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( if (!newChild->parent()->isHorizontal()) { setPointedExpressionLayout(child2->editableChild(0)); setPosition(Position::Left); - return child2; + return; } int fractionIndexInParent = newChild->parent()->indexOfChild(newChild); @@ -98,17 +97,14 @@ ExpressionLayout * ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers( // Set the cursor position setPointedExpressionLayout(child2->editableChild(0)); setPosition(Position::Left); - - return child2; } -ExpressionLayout * ExpressionLayoutCursor::addEmptyLogarithmLayout() { - ExpressionLayout * result = insertText("log()"); +void ExpressionLayoutCursor::addEmptyLogarithmLayout() { + insertText("log()"); setPosition(ExpressionLayoutCursor::Position::Left); - return result; } -ExpressionLayout * ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { +void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { assert(numberOfRows > 0); assert(numberOfColumns > 0); ExpressionLayout * children[(numberOfRows+1)*(numberOfColumns+1)]; @@ -125,10 +121,9 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows m_pointedExpressionLayout->addBrother(this, matrixLayout); setPointedExpressionLayout(matrixLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Right); - return matrixLayout; } -ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { +void ExpressionLayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); // If there is already a base int numberOfOpenParenthesis = 0; @@ -136,7 +131,7 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { m_pointedExpressionLayout->addBrother(this, offsetLayout); setPointedExpressionLayout(offsetLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Left); - return offsetLayout; + return; } // Else, add an empty base EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); @@ -144,19 +139,17 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptyPowerLayout() { m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); - return child1; } -ExpressionLayout * ExpressionLayoutCursor::addEmptySquareRootLayout() { +void ExpressionLayoutCursor::addEmptySquareRootLayout() { EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); NthRootLayout * newChild = new NthRootLayout(child1, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); - return child1; } -ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { +void ExpressionLayoutCursor::addEmptySquarePowerLayout() { CharLayout * indiceLayout = new CharLayout('2'); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(indiceLayout, VerticalOffsetLayout::Type::Superscript, false); // If there is already a base @@ -165,7 +158,7 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { m_pointedExpressionLayout->addBrother(this, offsetLayout); setPointedExpressionLayout(offsetLayout); setPosition(ExpressionLayoutCursor::Position::Right); - return offsetLayout; + return; } // Else, add an empty base EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); @@ -173,21 +166,19 @@ ExpressionLayout * ExpressionLayoutCursor::addEmptySquarePowerLayout() { m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); - return child1; } -ExpressionLayout * ExpressionLayoutCursor::addXNTCharLayout() { +void ExpressionLayoutCursor::addXNTCharLayout() { CharLayout * newChild = new CharLayout(m_pointedExpressionLayout->XNTChar()); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(newChild); setPosition(ExpressionLayoutCursor::Position::Right); - return newChild; } -ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { +void ExpressionLayoutCursor::insertText(const char * text) { int textLength = strlen(text); if (textLength <= 0) { - return nullptr; + return; } ExpressionLayout * newChild = nullptr; for (int i = 0; i < textLength; i++) { @@ -206,8 +197,6 @@ ExpressionLayout * ExpressionLayoutCursor::insertText(const char * text) { m_pointedExpressionLayout = newChild; m_position = Position::Right; } - assert(newChild != nullptr); - return newChild; } void ExpressionLayoutCursor::performBackspace() { From 01880d30c3de617f0af596eb744e65aa8249d283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 15 Jan 2018 11:53:54 +0100 Subject: [PATCH 165/459] [apps/Makefile] Keep only ExpressionEditor and Calculation apps. Change-Id: I34816ec88395114e4d6034f78918253652be5cc9 --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index 60e285088..f99c5bae4 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= expression_editor calculation graph sequence settings statistics probability regression code +EPSILON_APPS ?= expression_editor calculation include apps/shared/Makefile include apps/home/Makefile From c0a3aadae4f18ddbd00bba85fcecab291e4d9a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 15 Jan 2018 10:13:32 +0100 Subject: [PATCH 166/459] [escher] EditableExpressionView, its delegate and EVWithCursor. Change-Id: Icb05c756ff17e43a7b306bec685a6040eaec303a --- escher/Makefile | 2 + escher/include/escher.h | 3 + .../include/escher/editable_expression_view.h | 37 +++++ .../editable_expression_view_delegate.h | 19 +++ .../escher/expression_view_with_cursor.h | 36 +++++ escher/src/editable_expression_view.cpp | 134 ++++++++++++++++++ escher/src/expression_view_with_cursor.cpp | 51 +++++++ 7 files changed, 282 insertions(+) create mode 100644 escher/include/escher/editable_expression_view.h create mode 100644 escher/include/escher/editable_expression_view_delegate.h create mode 100644 escher/include/escher/expression_view_with_cursor.h create mode 100644 escher/src/editable_expression_view.cpp create mode 100644 escher/src/expression_view_with_cursor.cpp diff --git a/escher/Makefile b/escher/Makefile index 3a1964bb1..bf54220fe 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -12,6 +12,7 @@ objs += $(addprefix escher/src/,\ dynamic_view_controller.o\ editable_text_cell.o\ ellipsis_view.o\ + editable_expression_view.o\ even_odd_cell.o\ even_odd_cell_with_ellipsis.o\ even_odd_buffer_text_cell.o\ @@ -21,6 +22,7 @@ objs += $(addprefix escher/src/,\ expression_table_cell.o\ expression_table_cell_with_pointer.o\ expression_view.o\ + expression_view_with_cursor.o\ highlight_cell.o\ gauge_view.o\ image_view.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 2b3aac774..50dc65933 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -22,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h new file mode 100644 index 000000000..5d9f967a6 --- /dev/null +++ b/escher/include/escher/editable_expression_view.h @@ -0,0 +1,37 @@ +#ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_H +#define ESCHER_EDITABLE_EXPRESSION_VIEW_H + +#include +#include +#include +#include + +class EditableExpressionView : public ScrollableView, public ScrollViewDataSource { +public: + EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate = nullptr); + void setDelegate(EditableExpressionViewDelegate * delegate) { m_delegate = delegate; } + ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } + bool isEditing() const; + void setEditing(bool isEditing); + void scrollToCursor(); + + /* Responder */ + Toolbox * toolbox() override; + bool handleEvent(Ion::Events::Event event) override; + + bool editableExpressionViewShouldFinishEditing(Ion::Events::Event event); + + /* Callback for MathToolbox */ + void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); + + /* View */ + KDSize minimalSizeForOptimalDisplay() const override; + +private: + bool privateHandleEvent(Ion::Events::Event event); + void cursorOrLayoutChanged(); + ExpressionViewWithCursor m_expressionViewWithCursor; + EditableExpressionViewDelegate * m_delegate; +}; + +#endif diff --git a/escher/include/escher/editable_expression_view_delegate.h b/escher/include/escher/editable_expression_view_delegate.h new file mode 100644 index 000000000..6eb66bcdd --- /dev/null +++ b/escher/include/escher/editable_expression_view_delegate.h @@ -0,0 +1,19 @@ +#ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_DELEGATE_H +#define ESCHER_EDITABLE_EXPRESSION_VIEW_DELEGATE_H + +#include +#include + +class EditableExpressionView; + +class EditableExpressionViewDelegate { +public: + virtual bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; + virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; + /*virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; }; + virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) {return false;}; + virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool textHasChanged) { return returnValue; };*/ // TODO? + virtual Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) = 0; +}; + +#endif diff --git a/escher/include/escher/expression_view_with_cursor.h b/escher/include/escher/expression_view_with_cursor.h new file mode 100644 index 000000000..b362bb5f3 --- /dev/null +++ b/escher/include/escher/expression_view_with_cursor.h @@ -0,0 +1,36 @@ +#ifndef ESCHER_EXPRESSION_VIEW_WITH_CURSOR_H +#define ESCHER_EXPRESSION_VIEW_WITH_CURSOR_H + +#include +#include +#include +#include +#include + +class ExpressionViewWithCursor : public View { +public: + ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout); + Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } + bool isEditing() const { return m_isEditing; } + void setEditing(bool isEditing) { m_isEditing = isEditing; } + void cursorPositionChanged(); + KDRect cursorRect(); + const ExpressionView * expressionView() const { return &m_expressionView; } + /* View */ + KDSize minimalSizeForOptimalDisplay() const override; +private: + enum class Position { + Top, + Bottom + }; + int numberOfSubviews() const override { return 2; } + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + void layoutCursorSubview(); + Poincare::ExpressionLayoutCursor m_cursor; + ExpressionView m_expressionView; + TextCursorView m_cursorView; + bool m_isEditing; +}; + +#endif diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp new file mode 100644 index 000000000..ef3082d2c --- /dev/null +++ b/escher/src/editable_expression_view.cpp @@ -0,0 +1,134 @@ +#include +#include + +EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : + ScrollableView(parentResponder, &m_expressionViewWithCursor, this), + m_expressionViewWithCursor(expressionLayout), + m_delegate(delegate) +{ +} + +bool EditableExpressionView::isEditing() const { + return m_expressionViewWithCursor.isEditing(); +} + +void EditableExpressionView::setEditing(bool isEditing) { + m_expressionViewWithCursor.setEditing(isEditing); +} + +void EditableExpressionView::scrollToCursor() { + scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); +} + +Toolbox * EditableExpressionView::toolbox() { + if (m_delegate) { + return m_delegate->toolboxForEditableExpressionView(this); + } + return nullptr; +} + +bool EditableExpressionView::handleEvent(Ion::Events::Event event) { + if (privateHandleEvent(event)) { + cursorOrLayoutChanged(); + return true; + } + return false; +} + +bool EditableExpressionView::editableExpressionViewShouldFinishEditing(Ion::Events::Event event) { + return m_delegate->editableExpressionViewShouldFinishEditing(this, event); +} + +KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { + return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); +} + +bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Left) { + return m_expressionViewWithCursor.cursor()->moveLeft(); + } + if (event == Ion::Events::Right) { + return m_expressionViewWithCursor.cursor()->moveRight(); + } + if (event == Ion::Events::Up) { + return m_expressionViewWithCursor.cursor()->moveUp(); + } + if (event == Ion::Events::Down) { + return m_expressionViewWithCursor.cursor()->moveDown(); + } + if (event == Ion::Events::ShiftLeft) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); + return true; + } + if (event == Ion::Events::ShiftRight) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + return true; + } + if (event == Ion::Events::Division) { + m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); + return true; + } + if (event == Ion::Events::XNT) { + m_expressionViewWithCursor.cursor()->addXNTCharLayout(); + return true; + } + if (event == Ion::Events::Exp) { + m_expressionViewWithCursor.cursor()->addEmptyExponentialLayout(); + return true; + } + if (event == Ion::Events::Log) { + m_expressionViewWithCursor.cursor()->addEmptyLogarithmLayout(); + return true; + } + if (event == Ion::Events::Power) { + m_expressionViewWithCursor.cursor()->addEmptyPowerLayout(); + return true; + } + if (event == Ion::Events::Sqrt) { + m_expressionViewWithCursor.cursor()->addEmptySquareRootLayout(); + return true; + } + if (event == Ion::Events::Square) { + m_expressionViewWithCursor.cursor()->addEmptySquarePowerLayout(); + return true; + } + if (event.hasText()) { + const char * textToInsert = event.text(); + if (textToInsert[1] == 0) { + if (textToInsert[0] == Ion::Charset::MultiplicationSign) { + const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; + m_expressionViewWithCursor.cursor()->insertText(middleDotString); + return true; + } + if (textToInsert[0] == '[' || textToInsert[0] == ']') { + m_expressionViewWithCursor.cursor()->addEmptyMatrixLayout(); + return true; + } + } + m_expressionViewWithCursor.cursor()->insertText(textToInsert); + return true; + } + if (event == Ion::Events::Backspace) { + m_expressionViewWithCursor.cursor()->performBackspace(); + return true; + } + return false; +} + +void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout) { + if (layout == nullptr) { + return; + } + m_expressionViewWithCursor.cursor()->addLayout(layout); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); + cursorOrLayoutChanged(); +} + +void EditableExpressionView::cursorOrLayoutChanged() { + m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); + layoutSubviews(); +} diff --git a/escher/src/expression_view_with_cursor.cpp b/escher/src/expression_view_with_cursor.cpp new file mode 100644 index 000000000..b231aea65 --- /dev/null +++ b/escher/src/expression_view_with_cursor.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +using namespace Poincare; + +ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expressionLayout) : + m_cursor(), + m_expressionView(), + m_cursorView(), + m_isEditing(false) +{ + m_cursor.setPointedExpressionLayout(expressionLayout); + m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); + m_expressionView.setExpressionLayout(expressionLayout); +} + +void ExpressionViewWithCursor::cursorPositionChanged() { + layoutCursorSubview(); +} + +KDRect ExpressionViewWithCursor::cursorRect() { + return m_cursorView.frame(); +} + +KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { + KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); + return KDSize(expressionViewSize.width()+1, m_expressionView.minimalSizeForOptimalDisplay().height()); // +1 for the cursor +} + +View * ExpressionViewWithCursor::subviewAtIndex(int index) { + assert(index >= 0 && index < 2); + View * m_views[] = {&m_expressionView, &m_cursorView}; + return m_views[index]; +} + +void ExpressionViewWithCursor::layoutSubviews() { + m_expressionView.setFrame(bounds()); + layoutCursorSubview(); +} + +void ExpressionViewWithCursor::layoutCursorSubview() { + KDPoint expressionViewOrigin = m_expressionView.drawingOrigin(); + KDPoint cursoredExpressionViewOrigin = m_cursor.pointedExpressionLayout()->absoluteOrigin(); + KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); + if (m_cursor.position() == ExpressionLayoutCursor::Position::Right) { + cursorX += m_cursor.pointedExpressionLayout()->size().width(); + } + KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor.pointedExpressionLayout()->baseline()-m_cursor.cursorHeight()/2); + m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor.cursorHeight())); +} From ed82496b56d4bff408da2486a37020ad07237270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 15 Jan 2018 11:48:43 +0100 Subject: [PATCH 167/459] [apps] Handle EditableExpressionView in MathToolbox. Change-Id: Ic85cf67d225c60c90c3ad536d813bb489ceb6fe5 --- apps/math_toolbox.cpp | 105 ++++++++++++++++++++++-------------------- apps/math_toolbox.h | 7 ++- 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 55c160db9..f7a37dd10 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -104,67 +104,70 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbo const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbox, I18n::Message::Default, I18n::Message::Default, menu, 10); #endif -MathToolbox::MathToolbox() : Toolbox(nullptr, I18n::translate(rootModel()->label())) +MathToolbox::MathToolbox() : + Toolbox(nullptr, I18n::translate(rootModel()->label())), + m_action(actionForTextfield) { } -TextField * MathToolbox::textFieldSender() { - return static_cast(Toolbox::sender()); +void MathToolbox::setSenderAndAction(Responder * sender, Action action) { + setSender(sender); + m_action = action; } -ExpressionEditor::Controller * MathToolbox::expressionEditorControllerSender() { - return static_cast(Toolbox::sender()); +void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageTree * messageTree) { + EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); + // Translate the message and replace the arguments with Empty chars. + const char * textToInsert = I18n::translate(messageTree->insertedText()); + char strippedTextToInsert[strlen(textToInsert)]; + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + // Create the layout + Expression * resultExpression = Expression::parse(strippedTextToInsert); + if (resultExpression == nullptr) { + return; + } + ExpressionLayout * resultLayout = resultExpression->createLayout(); + // Find the pointed layout. + ExpressionLayout * pointedLayout = resultLayout; + if (messageTree->pointedPath() != nullptr) { + for (int i = 0; i < messageTree->pointedPathLength(); i++) { + assert(messageTree->pointedPath()[i] < pointedLayout->numberOfChildren()); + pointedLayout = pointedLayout->editableChild(messageTree->pointedPath()[i]); + } + } else if (resultLayout->isHorizontal()) { + // If the layout is horizontal, pick the first open parenthesis. + for (int i = 0; i < resultLayout->numberOfChildren(); i++) { + if (resultLayout->editableChild(i)->isLeftParenthesis()) { + pointedLayout = resultLayout->editableChild(i); + break; + } + } + } else if (resultLayout->numberOfChildren() > 0) { + // Else, if the layout has children, pick the first one. + pointedLayout = resultLayout->editableChild(0); + } + // Insert the layout + expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); +} + +void MathToolbox::actionForTextfield(void * sender, ToolboxMessageTree * messageTree) { + TextField * textFieldSender = static_cast(sender); + if (!textFieldSender->isEditing()) { + textFieldSender->setEditing(true); + } + const char * textToInsert = I18n::translate(messageTree->insertedText()); + char strippedTextToInsert[strlen(textToInsert)]; + // Translate the message and remove the arguments. + Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + textFieldSender->insertTextAtLocation(strippedTextToInsert, textFieldSender->cursorLocation()); + int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedTextToInsert); + textFieldSender->setCursorLocation(newCursorLocation); } bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { - if (0) { - m_selectableTableView.deselectTable(); - ToolboxMessageTree * messageTree = selectedMessageTree; - const char * editedText = I18n::translate(messageTree->insertedText()); - if (!textFieldSender()->isEditing()) { - textFieldSender()->setEditing(true); - } - char strippedEditedText[strlen(editedText)]; - Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedEditedText); - textFieldSender()->insertTextAtLocation(strippedEditedText, textFieldSender()->cursorLocation()); - int newCursorLocation = textFieldSender()->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedEditedText); - textFieldSender()->setCursorLocation(newCursorLocation); - app()->dismissModalViewController(); - return true; - } - // Deal with ExpressionEditor::Controller for now. ToolboxMessageTree * messageTree = selectedMessageTree; m_selectableTableView.deselectTable(); - // Translate the message and replace the arguments with Empty chars. - const char * editedText = I18n::translate(messageTree->insertedText()); - char strippedEditedText[strlen(editedText)]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedEditedText); - // Create the layout - Expression * resultExpression = Expression::parse(strippedEditedText); - if (resultExpression != nullptr) { - ExpressionLayout * resultLayout = resultExpression->createLayout(); - // Find the pointed layout. - ExpressionLayout * pointedLayout = resultLayout; - if (messageTree->pointedPath() != nullptr) { - for (int i = 0; i < messageTree->pointedPathLength(); i++) { - assert(messageTree->pointedPath()[i] < pointedLayout->numberOfChildren()); - pointedLayout = pointedLayout->editableChild(messageTree->pointedPath()[i]); - } - } else if (resultLayout->isHorizontal()) { - // If the layout is horizontal, pick the first open parenthesis. - for (int i = 0; i < resultLayout->numberOfChildren(); i++) { - if (resultLayout->editableChild(i)->isLeftParenthesis()) { - pointedLayout = resultLayout->editableChild(i); - break; - } - } - } else if (resultLayout->numberOfChildren() > 0) { - // Else, if the layout has children, pick the first one. - pointedLayout = resultLayout->editableChild(0); - } - // Insert the layout - expressionEditorControllerSender()->insertLayoutAtCursor(resultLayout, pointedLayout); - } + m_action(sender(), messageTree); app()->dismissModalViewController(); return true; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 9da44865b..6f06148d1 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -8,10 +8,12 @@ class MathToolbox : public Toolbox { public: + typedef void (*Action)(void * sender, ToolboxMessageTree * messageTree); MathToolbox(); + void setSenderAndAction(Responder * sender, Action action); + static void actionForEditableExpressionView(void * sender, ToolboxMessageTree * messageTree); + static void actionForTextfield(void * sender, ToolboxMessageTree * messageTree); protected: - TextField * textFieldSender(); - ExpressionEditor::Controller * expressionEditorControllerSender(); bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; MessageTableCellWithMessage * leafCellAtIndex(int index) override; @@ -19,6 +21,7 @@ protected: int maxNumberOfDisplayedRows() override; constexpr static int k_maxNumberOfDisplayedRows = 6; // = 240/40 private: + Action m_action; MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows]; }; From 8f58c33c31c71ddb85210b4998e6209d7adf1a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 15 Jan 2018 11:49:38 +0100 Subject: [PATCH 168/459] [apps] Dummy handling of EditableExpressionView in VariableBoxController. Change-Id: I565f613c13ee13d39efb652ae37f281e55f5d999 --- apps/variable_box_controller.cpp | 4 ++++ apps/variable_box_controller.h | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 33327e63a..72c2b9b63 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -292,6 +292,10 @@ void VariableBoxController::setTextFieldCaller(TextField * textField) { m_contentViewController.setTextFieldCaller(textField); } +void VariableBoxController::setEditableExpressionViewCaller(EditableExpressionView * editableExpressionView) { + //TODO +} + void VariableBoxController::viewWillAppear() { StackViewController::viewWillAppear(); m_contentViewController.resetPage(); diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 45218cd74..1617c1a31 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -13,6 +13,7 @@ public: VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; void setTextFieldCaller(TextField * textField); + void setEditableExpressionViewCaller(EditableExpressionView * editableExpressionView); void viewWillAppear() override; void viewDidDisappear() override; private: From 82229250a2750c43cface15d51e59e516ba5e022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 15 Jan 2018 11:50:48 +0100 Subject: [PATCH 169/459] [apps/Shared] EditableExpressionView delegate and delegate app. Change-Id: Ib6e0157e5523a37e4d652b8bd5063762cd0b6735 --- apps/shared/Makefile | 2 + .../editable_expression_view_delegate.cpp | 19 +++++++ .../editable_expression_view_delegate.h | 20 +++++++ ..._editable_expression_view_delegate_app.cpp | 52 +++++++++++++++++++ ...nd_editable_expression_view_delegate_app.h | 21 ++++++++ 5 files changed, 114 insertions(+) create mode 100644 apps/shared/editable_expression_view_delegate.cpp create mode 100644 apps/shared/editable_expression_view_delegate.h create mode 100644 apps/shared/text_field_and_editable_expression_view_delegate_app.cpp create mode 100644 apps/shared/text_field_and_editable_expression_view_delegate_app.h diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 83210f1da..40c3a475c 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -6,6 +6,7 @@ app_objs += $(addprefix apps/shared/,\ curve_view_cursor.o\ curve_view_range.o\ editable_cell_table_view_controller.o\ + editable_expression_view_delegate.o\ float_pair_store.o\ float_parameter_controller.o\ function.o\ @@ -37,6 +38,7 @@ app_objs += $(addprefix apps/shared/,\ store_controller.o\ store_parameter_controller.o\ tab_table_controller.o\ + text_field_and_editable_expression_view_delegate_app.o\ text_field_delegate.o\ text_field_delegate_app.o\ toolbox_helpers.o\ diff --git a/apps/shared/editable_expression_view_delegate.cpp b/apps/shared/editable_expression_view_delegate.cpp new file mode 100644 index 000000000..ab502a270 --- /dev/null +++ b/apps/shared/editable_expression_view_delegate.cpp @@ -0,0 +1,19 @@ +#include "editable_expression_view_delegate.h" + +using namespace Poincare; + +namespace Shared { + +bool EditableExpressionViewDelegate::editableExpressionViewShouldFinishEditing(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewShouldFinishEditing(editableExpressionView, event); +} + +bool EditableExpressionViewDelegate::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event); +} + +Toolbox * EditableExpressionViewDelegate::toolboxForEditableExpressionView(::EditableExpressionView * editableExpressionView) { + return textFieldAndEditableExpressionViewDelegateApp()->toolboxForEditableExpressionView(editableExpressionView); +} + +} diff --git a/apps/shared/editable_expression_view_delegate.h b/apps/shared/editable_expression_view_delegate.h new file mode 100644 index 000000000..438ae1acc --- /dev/null +++ b/apps/shared/editable_expression_view_delegate.h @@ -0,0 +1,20 @@ +#ifndef SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_H +#define SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_H + +#include +#include "text_field_and_editable_expression_view_delegate_app.h" + +namespace Shared { + +class EditableExpressionViewDelegate : public ::EditableExpressionViewDelegate { +public: + bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override; +private: + virtual TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() = 0; +}; + +} + +#endif diff --git a/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp b/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp new file mode 100644 index 000000000..2fd015231 --- /dev/null +++ b/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp @@ -0,0 +1,52 @@ +#include "text_field_and_editable_expression_view_delegate_app.h" +#include "../i18n.h" +#include "../apps_container.h" + +using namespace Poincare; + +namespace Shared { + +TextFieldAndEditableExpressionViewDelegateApp::TextFieldAndEditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : + TextFieldDelegateApp(container, snapshot, rootViewController), + EditableExpressionViewDelegate() +{ +} + +bool TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + return event == Ion::Events::OK || event == Ion::Events::EXE; +} + +bool TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event)) { + int bufferSize = 256; + char buffer[bufferSize]; + editableExpressionView->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + Expression * exp = Expression::parse(buffer); + if (exp != nullptr) { + delete exp; + } + if (exp == nullptr) { + editableExpressionView->app()->displayWarning(I18n::Message::SyntaxError); + return true; + } + } + if (event == Ion::Events::Var) { + if (!editableExpressionView->isEditing()) { + editableExpressionView->setEditing(true); + } + AppsContainer * appsContainer = (AppsContainer *)editableExpressionView->app()->container(); + VariableBoxController * variableBoxController = appsContainer->variableBoxController(); + variableBoxController->setEditableExpressionViewCaller(editableExpressionView); + editableExpressionView->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + return true; + } + return false; +} + +Toolbox * TextFieldAndEditableExpressionViewDelegateApp::toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) { + Toolbox * toolbox = container()->mathToolbox(); + static_cast(toolbox)->setSenderAndAction(editableExpressionView, MathToolbox::actionForEditableExpressionView); + return toolbox; +} + +} diff --git a/apps/shared/text_field_and_editable_expression_view_delegate_app.h b/apps/shared/text_field_and_editable_expression_view_delegate_app.h new file mode 100644 index 000000000..85bc85fc2 --- /dev/null +++ b/apps/shared/text_field_and_editable_expression_view_delegate_app.h @@ -0,0 +1,21 @@ +#ifndef SHARED_TEXT_FIELD_AND_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H +#define SHARED_TEXT_FIELD_AND_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H + +#include "text_field_delegate_app.h" +#include + +namespace Shared { + +class TextFieldAndEditableExpressionViewDelegateApp : public TextFieldDelegateApp, public EditableExpressionViewDelegate { +public: + virtual ~TextFieldAndEditableExpressionViewDelegateApp() = default; + bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override; +protected: + TextFieldAndEditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); +}; + +} + +#endif From 3ff998ec2c7c6242416342431b44cca8aa2b7b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 14:29:32 +0100 Subject: [PATCH 170/459] [poincare] Fix MatrixLayout size computation. Change-Id: Ib02c70d92d7d4e96c052f7f7671496115cf190f1 --- poincare/src/layout/bracket_left_right_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index d6eefaaa8..f39263fff 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -54,7 +54,7 @@ bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { KDSize BracketLeftRightLayout::computeSize() { - return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight()); + return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); } KDCoordinate BracketLeftRightLayout::operandHeight() { From 47ab766549bf5dec078233fdefc23b20534dc0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 14:30:08 +0100 Subject: [PATCH 171/459] [poincare/lexer] Parse the multiplication dot. Change-Id: I4b12c6c660a7890d7d00b03cad26af5e366b4eaf --- poincare/src/expression_lexer.l | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 577e71acc..57ed5769a 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -143,6 +143,7 @@ inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; \+ { return PLUS; } \- { return MINUS; } \x93 { return MULTIPLY; } +\x94 { return MULTIPLY; } \* { return MULTIPLY; } \/ { return DIVIDE; } \^ { return POW; } From 91c05b3bb759148476b96f70dd2b315166e8c3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 14:47:21 +0100 Subject: [PATCH 172/459] [apps/calculation] EditableExpressionView in calculation app. Change-Id: I8b67353682652695f7296f0222939930f4b21794 --- apps/calculation/app.cpp | 32 ++++- apps/calculation/app.h | 3 +- .../edit_expression_controller.cpp | 124 +++++++++++++++--- apps/calculation/edit_expression_controller.h | 37 ++++-- .../editable_expression_view_delegate.cpp | 16 +++ .../editable_expression_view_delegate.h | 4 + .../include/escher/editable_expression_view.h | 2 +- .../editable_expression_view_delegate.h | 7 +- escher/include/escher/expression_view.h | 1 + .../escher/expression_view_with_cursor.h | 4 +- escher/src/editable_expression_view.cpp | 44 ++++++- escher/src/expression_view.cpp | 7 +- escher/src/expression_view_with_cursor.cpp | 7 +- 13 files changed, 246 insertions(+), 42 deletions(-) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 701ce5926..21056ddb4 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -43,7 +43,7 @@ void App::Snapshot::tidy() { } App::App(Container * container, Snapshot * snapshot) : - TextFieldDelegateApp(container, snapshot, &m_editExpressionController), + TextFieldAndEditableExpressionViewDelegateApp(container, snapshot, &m_editExpressionController), m_localContext((GlobalContext *)((AppsContainer *)container)->globalContext(), snapshot->calculationStore()), m_historyController(&m_editExpressionController, snapshot->calculationStore()), m_editExpressionController(&m_modalViewController, &m_historyController, snapshot->calculationStore()) @@ -80,6 +80,36 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e return false; } +bool App::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidReceiveEvent(editableExpressionView, event)) { + return true; + } + /* Here, we check that the expression entered by the user can be printed with + * less than k_printedExpressionLength characters. Otherwise, we prevent the + * user from adding this expression to the calculation store. */ + if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event)) { + int bufferLength = TextField::maxBufferSize(); + char bufferForParsing[bufferLength]; + Poincare::ExpressionLayout * expressionLayout = editableExpressionView->expressionViewWithCursor()->expressionView()->expressionLayout(); + expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); + Expression * exp = Expression::parse(bufferForParsing); + if (exp == nullptr) { + editableExpressionView->app()->displayWarning(I18n::Message::SyntaxError); + return true; + } + char buffer[Calculation::k_printedExpressionSize]; + int length = exp->writeTextInBuffer(buffer, sizeof(buffer)); + delete exp; + /* if the buffer is totally full, it is VERY likely that writeTextInBuffer + * escaped before printing utterly the expression. */ + if (length >= Calculation::k_printedExpressionSize-1) { + displayWarning(I18n::Message::SyntaxError); + return true; + } + } + return false; +} + const char * App::XNT() { return "x"; } diff --git a/apps/calculation/app.h b/apps/calculation/app.h index a9b616599..4ec807891 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -10,7 +10,7 @@ namespace Calculation { -class App : public Shared::TextFieldDelegateApp { +class App : public Shared::TextFieldAndEditableExpressionViewDelegateApp { public: class Descriptor : public ::App::Descriptor { public: @@ -30,6 +30,7 @@ public: }; Poincare::Context * localContext() override; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; + bool editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; const char * XNT() override; private: App(Container * container, Snapshot * snapshot); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 0df8a0f17..90d8cd36d 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -1,5 +1,6 @@ #include "edit_expression_controller.h" #include "../apps_container.h" +#include "ion/display.h" #include "app.h" #include @@ -7,10 +8,11 @@ using namespace Shared; namespace Calculation { -EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate) : +EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate) : View(), m_mainView(subview), - m_textField(parentResponder, m_textBody, TextField::maxBufferSize(), textFieldDelegate) + m_textField(parentResponder, m_textBody, TextField::maxBufferSize(), textFieldDelegate), + m_editableExpressionView(parentResponder, new Poincare::HorizontalLayout(), editableExpressionViewDelegate) { m_textBody[0] = 0; } @@ -20,30 +22,55 @@ int EditExpressionController::ContentView::numberOfSubviews() const { } View * EditExpressionController::ContentView::subviewAtIndex(int index) { - View * views[2] = {m_mainView, &m_textField}; - return views[index]; + assert(index >= 0 && index < numberOfSubviews()); + if (index == 0) { + return m_mainView; + } + assert(index == 1); + if (editionIsInTextField()) { + return &m_textField; + } + return &m_editableExpressionView; } void EditExpressionController::ContentView::layoutSubviews() { - KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - k_textFieldHeight-k_separatorThickness); + KDCoordinate inputViewFrameHeight = inputViewHeight(); + KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight-k_separatorThickness); m_mainView->setFrame(mainViewFrame); - KDRect inputViewFrame(k_textMargin, bounds().height() - k_textFieldHeight, bounds().width()-k_textMargin, k_textFieldHeight); - m_textField.setFrame(inputViewFrame); + if (editionIsInTextField()) { + KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight + k_verticalMargin, bounds().width()-k_leftMargin, k_textFieldHeight - k_verticalMargin); + m_textField.setFrame(inputViewFrame); + m_editableExpressionView.setFrame(KDRectZero); + return; + } + KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight, bounds().width() - k_leftMargin, inputViewFrameHeight); + m_editableExpressionView.setFrame(inputViewFrame); + m_textField.setFrame(KDRectZero); } -void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { +void EditExpressionController::ContentView::reload() { + layoutSubviews(); + markRectAsDirty(bounds()); +} + +void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { + KDCoordinate inputViewFrameHeight = inputViewHeight(); // Draw the separator - ctx->fillRect(KDRect(0, bounds().height() -k_textFieldHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle); - // Color the margin - ctx->fillRect(KDRect(0, bounds().height() -k_textFieldHeight, k_textMargin, k_textFieldHeight), m_textField.backgroundColor()); + ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle); + // Color the left margin + ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, k_textFieldHeight), m_textField.backgroundColor()); + if (!editionIsInTextField()) { + // Color the upper margin + ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalMargin), m_textField.backgroundColor()); + } } -TextField * EditExpressionController::ContentView::textField() { - return &m_textField; +KDCoordinate EditExpressionController::ContentView::inputViewHeight() const { + return k_verticalMargin + (editionIsInTextField() ? k_textFieldHeight : editableExpressionViewHeight()); } -TableView * EditExpressionController::ContentView::mainView() { - return m_mainView; +KDCoordinate EditExpressionController::ContentView::editableExpressionViewHeight() const { + return KDCoordinate(min(0.6*Ion::Display::Height, max(k_textFieldHeight, m_editableExpressionView.minimalSizeForOptimalDisplay().height()+k_verticalMargin))); } EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) : @@ -67,7 +94,11 @@ void EditExpressionController::insertTextBody(const char * text) { bool EditExpressionController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Up) { if (m_calculationStore->numberOfCalculations() > 0) { - ((ContentView *)view())->textField()->setEditing(false, false); + if (((ContentView *)view())->editionIsInTextField()) { + ((ContentView *)view())->textField()->setEditing(false, false); + } else { + ((ContentView *)view())->editableExpressionView()->setEditing(false); + } app()->setFirstResponder(m_historyController); } return true; @@ -78,8 +109,13 @@ bool EditExpressionController::handleEvent(Ion::Events::Event event) { void EditExpressionController::didBecomeFirstResponder() { int lastRow = m_calculationStore->numberOfCalculations() > 0 ? m_calculationStore->numberOfCalculations()-1 : 0; m_historyController->scrollToCell(0, lastRow); - ((ContentView *)view())->textField()->setEditing(true, false); - app()->setFirstResponder(((ContentView *)view())->textField()); + if (((ContentView *)view())->editionIsInTextField()) { + ((ContentView *)view())->textField()->setEditing(true, false); + app()->setFirstResponder(((ContentView *)view())->textField()); + return; + } + ((ContentView *)view())->editableExpressionView()->setEditing(true); + app()->setFirstResponder(((ContentView *)view())->editableExpressionView()); } bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { @@ -110,21 +146,71 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField, return false; } +bool EditExpressionController::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { + bool layoutIsEmpty = expressionLayout()->isHorizontal() && expressionLayout()->numberOfChildren() == 0; + if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event) && layoutIsEmpty && m_calculationStore->numberOfCalculations() > 0) { + App * calculationApp = (App *)app(); + const char * lastTextBody = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1)->inputText(); + m_calculationStore->push(lastTextBody, calculationApp->localContext()); + m_historyController->reload(); + ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); + return true; + } + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event); +} + +bool EditExpressionController::editableExpressionViewDidFinishEditing(::EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { + App * calculationApp = (App *)app(); + expressionLayout()->writeTextInBuffer(const_cast(textBody()), ContentView::k_bufferLength); + m_calculationStore->push(textBody(), calculationApp->localContext()); + (const_cast(((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()))->setExpressionLayout(new Poincare::HorizontalLayout()); + reloadView(); + ((ContentView *)view())->editableExpressionView()->setEditing(true); + return true; +} + +bool EditExpressionController::editableExpressionViewDidAbortEditing(::EditableExpressionView * editableExpressionView, const char * text) { + ((ContentView *)view())->editableExpressionView()->setEditing(true); + //TODO ((ContentView *)view())->editableExpressionView()->editableExpressionView()->expressionViewWithCursor()->expressionView()->setLayout(; + return false; +} + +void EditExpressionController::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) { + assert(editableExpressionView == ((ContentView *)view())->editableExpressionView()); + reloadView(); +} + TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() { return (App *)app(); } +TextFieldAndEditableExpressionViewDelegateApp * EditExpressionController::textFieldAndEditableExpressionViewDelegateApp() { + return (App *)app(); +} + View * EditExpressionController::loadView() { - return new ContentView(this, (TableView *)m_historyController->view(), this); + return new ContentView(this, (TableView *)m_historyController->view(), this, this); } void EditExpressionController::unloadView(View * view) { delete view; } +void EditExpressionController::reloadView() { + ((ContentView *)view())->reload(); + m_historyController->reload(); + if (m_historyController->numberOfRows() > 0) { + ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); + } +} + void EditExpressionController::viewDidDisappear() { DynamicViewController::viewDidDisappear(); m_historyController->viewDidDisappear(); } +Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { + return ((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()->expressionLayout(); +} + } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 9c019fe4b..b9c8f4514 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -3,6 +3,7 @@ #include #include "../shared/text_field_delegate.h" +#include "../shared/editable_expression_view_delegate.h" #include "history_controller.h" #include "calculation_store.h" #include "text_field.h" @@ -11,7 +12,7 @@ namespace Calculation { class HistoryController; /* TODO: implement a split view */ -class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate { +class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::EditableExpressionViewDelegate { public: EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore); void didBecomeFirstResponder() override; @@ -19,30 +20,50 @@ public: bool handleEvent(Ion::Events::Event event) override; const char * textBody(); void insertTextBody(const char * text); -bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; + + /* TextFieldDelegate */ + bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(::TextField * textField, const char * text) override; + + /* EditableExpressionViewDelegate */ + bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; + bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override; + void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override; + private: class ContentView : public View { public: - ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate); + ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate); int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; - TextField * textField(); - TableView * mainView(); + void reload(); + TextField * textField() { return &m_textField; } + EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } + TableView * mainView() { return m_mainView; } void drawRect(KDContext * ctx, KDRect rect) const override; + bool editionIsInTextField() const { return true; } //TODO + static constexpr int k_bufferLength = TextField::maxBufferSize(); private: - static constexpr KDCoordinate k_textFieldHeight = 37; - static constexpr KDCoordinate k_textMargin= 5; + static constexpr KDCoordinate k_textFieldHeight = 32; //37 + static constexpr KDCoordinate k_leftMargin = 5; + static constexpr KDCoordinate k_verticalMargin = 9; constexpr static int k_separatorThickness = 1; + KDCoordinate inputViewHeight() const; + KDCoordinate editableExpressionViewHeight() const; TableView * m_mainView; TextField m_textField; - char m_textBody[TextField::maxBufferSize()]; + EditableExpressionView m_editableExpressionView; + char m_textBody[k_bufferLength]; }; View * loadView() override; void unloadView(View * view) override; + void reloadView(); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; + Shared::TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() override; + Poincare::ExpressionLayout * expressionLayout(); HistoryController * m_historyController; CalculationStore * m_calculationStore; }; diff --git a/apps/shared/editable_expression_view_delegate.cpp b/apps/shared/editable_expression_view_delegate.cpp index ab502a270..ff7542ed4 100644 --- a/apps/shared/editable_expression_view_delegate.cpp +++ b/apps/shared/editable_expression_view_delegate.cpp @@ -12,6 +12,22 @@ bool EditableExpressionViewDelegate::editableExpressionViewDidReceiveEvent(::Edi return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event); } +bool EditableExpressionViewDelegate::editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidFinishEditing(editableExpressionView, text, event); +} + +bool EditableExpressionViewDelegate::editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidAbortEditing(editableExpressionView, text); +} + +bool EditableExpressionViewDelegate::editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidHandleEvent(editableExpressionView, event, returnValue, expressionHasChanged); +} + +void EditableExpressionViewDelegate::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) { + return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidChangeSize(editableExpressionView); +} + Toolbox * EditableExpressionViewDelegate::toolboxForEditableExpressionView(::EditableExpressionView * editableExpressionView) { return textFieldAndEditableExpressionViewDelegateApp()->toolboxForEditableExpressionView(editableExpressionView); } diff --git a/apps/shared/editable_expression_view_delegate.h b/apps/shared/editable_expression_view_delegate.h index 438ae1acc..9c779b642 100644 --- a/apps/shared/editable_expression_view_delegate.h +++ b/apps/shared/editable_expression_view_delegate.h @@ -10,6 +10,10 @@ class EditableExpressionViewDelegate : public ::EditableExpressionViewDelegate { public: bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; + bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override; + bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) override; + void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override; Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override; private: virtual TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() = 0; diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index 5d9f967a6..8041440ce 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -14,6 +14,7 @@ public: bool isEditing() const; void setEditing(bool isEditing); void scrollToCursor(); + void reload(); /* Responder */ Toolbox * toolbox() override; @@ -29,7 +30,6 @@ public: private: bool privateHandleEvent(Ion::Events::Event event); - void cursorOrLayoutChanged(); ExpressionViewWithCursor m_expressionViewWithCursor; EditableExpressionViewDelegate * m_delegate; }; diff --git a/escher/include/escher/editable_expression_view_delegate.h b/escher/include/escher/editable_expression_view_delegate.h index 6eb66bcdd..a6728caed 100644 --- a/escher/include/escher/editable_expression_view_delegate.h +++ b/escher/include/escher/editable_expression_view_delegate.h @@ -10,9 +10,10 @@ class EditableExpressionViewDelegate { public: virtual bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; - /*virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; }; - virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) {return false;}; - virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool textHasChanged) { return returnValue; };*/ // TODO? + virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; } + virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) { return false; } + virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) { return returnValue; } + virtual void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) {} virtual Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) = 0; }; diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index 25861e61f..cd3577f19 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -23,6 +23,7 @@ public: void setAlignment(float horizontalAlignment, float verticalAlignment); KDSize minimalSizeForOptimalDisplay() const override; KDPoint drawingOrigin() const; + KDPoint absoluteDrawingOrigin() const; private: /* Warning: we do not need to delete the previous expression layout when * deleting object or setting a new expression layout. Indeed, the expression diff --git a/escher/include/escher/expression_view_with_cursor.h b/escher/include/escher/expression_view_with_cursor.h index b362bb5f3..7588769bb 100644 --- a/escher/include/escher/expression_view_with_cursor.h +++ b/escher/include/escher/expression_view_with_cursor.h @@ -10,12 +10,12 @@ class ExpressionViewWithCursor : public View { public: ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout); - Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } bool isEditing() const { return m_isEditing; } void setEditing(bool isEditing) { m_isEditing = isEditing; } void cursorPositionChanged(); KDRect cursorRect(); - const ExpressionView * expressionView() const { return &m_expressionView; } + Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } + ExpressionView * expressionView() { return &m_expressionView; } /* View */ KDSize minimalSizeForOptimalDisplay() const override; private: diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index ef3082d2c..023028d0f 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -1,4 +1,5 @@ #include +#include #include EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : @@ -28,8 +29,13 @@ Toolbox * EditableExpressionView::toolbox() { } bool EditableExpressionView::handleEvent(Ion::Events::Event event) { + KDSize previousSize = minimalSizeForOptimalDisplay(); if (privateHandleEvent(event)) { - cursorOrLayoutChanged(); + reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->editableExpressionViewDidChangeSize(this); + } return true; } return false; @@ -44,6 +50,30 @@ KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { } bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { + if (m_delegate && m_delegate->editableExpressionViewDidReceiveEvent(this, event)) { + return true; + } + if (Responder::handleEvent(event)) { + /* The only event Responder handles is 'Toolbox' displaying. In that case, + * the EditableExpressionView is forced into editing mode. */ + if (!isEditing()) { + setEditing(true); + } + return true; + } + if (isEditing() && editableExpressionViewShouldFinishEditing(event)) { + setEditing(false); + int bufferSize = TextField::maxBufferSize(); + char buffer[bufferSize]; + m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + if (m_delegate->editableExpressionViewDidFinishEditing(this, buffer, event)) { + delete m_expressionViewWithCursor.expressionView()->expressionLayout(); + Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); + m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); + } + return true; + } if (event == Ion::Events::Left) { return m_expressionViewWithCursor.cursor()->moveLeft(); } @@ -121,14 +151,22 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l if (layout == nullptr) { return; } + KDSize previousSize = minimalSizeForOptimalDisplay(); m_expressionViewWithCursor.cursor()->addLayout(layout); m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); - cursorOrLayoutChanged(); + KDSize newSize = minimalSizeForOptimalDisplay(); + reload(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->editableExpressionViewDidChangeSize(this); + } } -void EditableExpressionView::cursorOrLayoutChanged() { +void EditableExpressionView::reload() { m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); + m_expressionViewWithCursor.cursorPositionChanged(); layoutSubviews(); + scrollToCursor(); + markRectAsDirty(bounds()); } diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 0fa196d63..dfd23e3b3 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -49,8 +49,11 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const { KDPoint ExpressionView::drawingOrigin() const { KDSize expressionSize = m_expressionLayout->size(); - return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), - 0.5f*(m_frame.height() - expressionSize.height())); + return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), 0.5f*(m_frame.height() - expressionSize.height())); +} + +KDPoint ExpressionView::absoluteDrawingOrigin() const { + return drawingOrigin().translatedBy(m_frame.topLeft()); } void ExpressionView::drawRect(KDContext * ctx, KDRect rect) const { diff --git a/escher/src/expression_view_with_cursor.cpp b/escher/src/expression_view_with_cursor.cpp index b231aea65..b5889eb06 100644 --- a/escher/src/expression_view_with_cursor.cpp +++ b/escher/src/expression_view_with_cursor.cpp @@ -25,7 +25,10 @@ KDRect ExpressionViewWithCursor::cursorRect() { KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); - return KDSize(expressionViewSize.width()+1, m_expressionView.minimalSizeForOptimalDisplay().height()); // +1 for the cursor + KDSize cursorSize = isEditing() ? m_cursorView.minimalSizeForOptimalDisplay() : KDSizeZero; + KDCoordinate resultWidth = expressionViewSize.width() + cursorSize.width(); + KDCoordinate resultHeight = expressionViewSize.height() + cursorSize.height()/2; + return KDSize(resultWidth, resultHeight); } View * ExpressionViewWithCursor::subviewAtIndex(int index) { @@ -40,7 +43,7 @@ void ExpressionViewWithCursor::layoutSubviews() { } void ExpressionViewWithCursor::layoutCursorSubview() { - KDPoint expressionViewOrigin = m_expressionView.drawingOrigin(); + KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); KDPoint cursoredExpressionViewOrigin = m_cursor.pointedExpressionLayout()->absoluteOrigin(); KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); if (m_cursor.position() == ExpressionLayoutCursor::Position::Right) { From 53556ffacff9639af61b02c2248d76c010defe66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 15:17:42 +0100 Subject: [PATCH 173/459] [apps/calculation] Handle "ans" event in EditableExpressionView. Change-Id: I7761f36b5a94bb5c8190cd5b238542280666c256 --- apps/calculation/Makefile | 1 + .../edit_expression_controller.cpp | 2 +- apps/calculation/edit_expression_controller.h | 9 +++--- apps/calculation/editable_expression_view.cpp | 29 +++++++++++++++++++ apps/calculation/editable_expression_view.h | 16 ++++++++++ .../include/escher/editable_expression_view.h | 5 ++-- 6 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 apps/calculation/editable_expression_view.cpp create mode 100644 apps/calculation/editable_expression_view.h diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index c25380236..420391945 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -5,6 +5,7 @@ app_objs += $(addprefix apps/calculation/,\ app.o\ calculation.o\ calculation_store.o\ + editable_expression_view.o\ edit_expression_controller.o\ history_view_cell.o\ history_controller.o\ diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 90d8cd36d..44b118046 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -175,7 +175,7 @@ bool EditExpressionController::editableExpressionViewDidAbortEditing(::EditableE return false; } -void EditExpressionController::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) { +void EditExpressionController::editableExpressionViewDidChangeSize(::EditableExpressionView * editableExpressionView) { assert(editableExpressionView == ((ContentView *)view())->editableExpressionView()); reloadView(); } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index b9c8f4514..bf26f73e8 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -2,6 +2,7 @@ #define CALCULATION_EDIT_EXPRESSION_CONTROLLER_H #include +#include "editable_expression_view.h" #include "../shared/text_field_delegate.h" #include "../shared/editable_expression_view_delegate.h" #include "history_controller.h" @@ -27,10 +28,10 @@ public: bool textFieldDidAbortEditing(::TextField * textField, const char * text) override; /* EditableExpressionViewDelegate */ - bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; - bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override; - void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override; + bool editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + bool editableExpressionViewDidFinishEditing(::EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; + bool editableExpressionViewDidAbortEditing(::EditableExpressionView * editableExpressionView, const char * text) override; + void editableExpressionViewDidChangeSize(::EditableExpressionView * editableExpressionView) override; private: class ContentView : public View { diff --git a/apps/calculation/editable_expression_view.cpp b/apps/calculation/editable_expression_view.cpp new file mode 100644 index 000000000..fd1d30e8a --- /dev/null +++ b/apps/calculation/editable_expression_view.cpp @@ -0,0 +1,29 @@ +#include "editable_expression_view.h" + +namespace Calculation { + +bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Back) { + return false; + } + if (event == Ion::Events::Ans) { + m_expressionViewWithCursor.cursor()->insertText("ans"); + return true; + } + Poincare::ExpressionLayout * layout = m_expressionViewWithCursor.expressionView()->expressionLayout(); + bool layoutIsEmpty = layout->isEmpty() + || (layout->isHorizontal() + && layout->numberOfChildren() == 0); + if (isEditing() && layoutIsEmpty && + (event == Ion::Events::Multiplication || + event == Ion::Events::Plus || + event == Ion::Events::Power || + event == Ion::Events::Square || + event == Ion::Events::Division || + event == Ion::Events::Sto)) { + m_expressionViewWithCursor.cursor()->insertText("ans"); + } + return(::EditableExpressionView::privateHandleEvent(event)); +} + +} diff --git a/apps/calculation/editable_expression_view.h b/apps/calculation/editable_expression_view.h new file mode 100644 index 000000000..204328434 --- /dev/null +++ b/apps/calculation/editable_expression_view.h @@ -0,0 +1,16 @@ +#ifndef CALCULATION_EDITABLE_EXPRESSION_VIEW_H +#define CALCULATION_EDITABLE_EXPRESSION_VIEW_H + +#include + +namespace Calculation { + +class EditableExpressionView : public ::EditableExpressionView { + using ::EditableExpressionView::EditableExpressionView; +protected: + bool privateHandleEvent(Ion::Events::Event event) override; +}; + +} + +#endif diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index 8041440ce..456535f0a 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -28,9 +28,10 @@ public: /* View */ KDSize minimalSizeForOptimalDisplay() const override; -private: - bool privateHandleEvent(Ion::Events::Event event); +protected: + virtual bool privateHandleEvent(Ion::Events::Event event); ExpressionViewWithCursor m_expressionViewWithCursor; +private: EditableExpressionViewDelegate * m_delegate; }; From 86b29f7e2f98df919605c2c30a4d9d1746c51878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 15:25:55 +0100 Subject: [PATCH 174/459] [apps/calculation] Fix rendering bug. When powering off then on the device, the EditableExpressionView had a rendering bug on the bottom left corner. Change-Id: I1792831f949b8e646fff68b9e784c1ff573516fc --- apps/calculation/edit_expression_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 44b118046..625d25d51 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -58,7 +58,7 @@ void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rec // Draw the separator ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle); // Color the left margin - ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, k_textFieldHeight), m_textField.backgroundColor()); + ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, inputViewFrameHeight), m_textField.backgroundColor()); if (!editionIsInTextField()) { // Color the upper margin ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalMargin), m_textField.backgroundColor()); From e1235cdb4f07cfa5e10f6d02d8155a8add3904a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 15:33:57 +0100 Subject: [PATCH 175/459] [escher] EditableExpressionView: Remove the cursor when not editing. Change-Id: If333f6074bce39d71ceb89b9424f7fec26a1f0c6 --- apps/calculation/editable_expression_view.cpp | 6 ++++++ apps/calculation/editable_expression_view.h | 3 ++- escher/include/escher/expression_view_with_cursor.h | 2 +- escher/src/expression_view_with_cursor.cpp | 10 ++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/calculation/editable_expression_view.cpp b/apps/calculation/editable_expression_view.cpp index fd1d30e8a..a06287c2c 100644 --- a/apps/calculation/editable_expression_view.cpp +++ b/apps/calculation/editable_expression_view.cpp @@ -2,6 +2,12 @@ namespace Calculation { +EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : + ::EditableExpressionView(parentResponder, expressionLayout, delegate) +{ + setEditing(true); +} + bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back) { return false; diff --git a/apps/calculation/editable_expression_view.h b/apps/calculation/editable_expression_view.h index 204328434..f873e9115 100644 --- a/apps/calculation/editable_expression_view.h +++ b/apps/calculation/editable_expression_view.h @@ -6,7 +6,8 @@ namespace Calculation { class EditableExpressionView : public ::EditableExpressionView { - using ::EditableExpressionView::EditableExpressionView; +public: + EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate = nullptr); protected: bool privateHandleEvent(Ion::Events::Event event) override; }; diff --git a/escher/include/escher/expression_view_with_cursor.h b/escher/include/escher/expression_view_with_cursor.h index 7588769bb..3128d3aca 100644 --- a/escher/include/escher/expression_view_with_cursor.h +++ b/escher/include/escher/expression_view_with_cursor.h @@ -11,7 +11,7 @@ class ExpressionViewWithCursor : public View { public: ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout); bool isEditing() const { return m_isEditing; } - void setEditing(bool isEditing) { m_isEditing = isEditing; } + void setEditing(bool isEditing); void cursorPositionChanged(); KDRect cursorRect(); Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } diff --git a/escher/src/expression_view_with_cursor.cpp b/escher/src/expression_view_with_cursor.cpp index b5889eb06..f53fa5aa8 100644 --- a/escher/src/expression_view_with_cursor.cpp +++ b/escher/src/expression_view_with_cursor.cpp @@ -15,6 +15,12 @@ ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expression m_expressionView.setExpressionLayout(expressionLayout); } +void ExpressionViewWithCursor::setEditing(bool isEditing) { + m_isEditing = isEditing; + markRectAsDirty(bounds()); + layoutSubviews(); +} + void ExpressionViewWithCursor::cursorPositionChanged() { layoutCursorSubview(); } @@ -43,6 +49,10 @@ void ExpressionViewWithCursor::layoutSubviews() { } void ExpressionViewWithCursor::layoutCursorSubview() { + if (!m_isEditing) { + m_cursorView.setFrame(KDRectZero); + return; + } KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); KDPoint cursoredExpressionViewOrigin = m_cursor.pointedExpressionLayout()->absoluteOrigin(); KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); From 1d701f3305213655c6af8894e376f6b51e9e5286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:07:09 +0100 Subject: [PATCH 176/459] [apps] Handle EditableExpressionView in VariableBoxController. Change-Id: Ibd5f1b1a8999241c8aa818a075f48adb28c4032e --- ..._editable_expression_view_delegate_app.cpp | 2 +- apps/shared/text_field_delegate_app.cpp | 2 +- apps/variable_box_controller.cpp | 106 ++++++++++-------- apps/variable_box_controller.h | 14 ++- .../include/escher/editable_expression_view.h | 3 + escher/src/editable_expression_view.cpp | 5 + 6 files changed, 81 insertions(+), 51 deletions(-) diff --git a/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp b/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp index 2fd015231..516c4a466 100644 --- a/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp +++ b/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp @@ -36,7 +36,7 @@ bool TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidRec } AppsContainer * appsContainer = (AppsContainer *)editableExpressionView->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setEditableExpressionViewCaller(editableExpressionView); + variableBoxController->setEditableExpressionViewSender(editableExpressionView); editableExpressionView->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index 1678f234e..de8df6c42 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -93,7 +93,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion:: } AppsContainer * appsContainer = (AppsContainer *)textField->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setTextFieldCaller(textField); + variableBoxController->setTextFieldSender(textField); textField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 72c2b9b63..44be6b710 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -10,7 +10,7 @@ using namespace Poincare; VariableBoxController::ContentViewController::ContentViewController(Responder * parentResponder, GlobalContext * context) : ViewController(parentResponder), m_context(context), - m_textFieldCaller(nullptr), + m_sender(nullptr), m_firstSelectedRow(0), m_previousSelectedRow(0), m_currentPage(Page::RootMenu), @@ -18,14 +18,13 @@ VariableBoxController::ContentViewController::ContentViewController(Responder * { } -const char * VariableBoxController::ContentViewController::title() { - return I18n::translate(I18n::Message::Variables); -} - View * VariableBoxController::ContentViewController::view() { return &m_selectableTableView; } +const char * VariableBoxController::ContentViewController::title() { + return I18n::translate(I18n::Message::Variables); +} void VariableBoxController::ContentViewController::didBecomeFirstResponder() { m_selectableTableView.reloadData(); m_selectableTableView.scrollToCell(0,0); @@ -65,11 +64,7 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even char label[3]; putLabelAtIndexInBuffer(selectedRow(), label); const char * editedText = label; - if (!m_textFieldCaller->isEditing()) { - m_textFieldCaller->setEditing(true); - } - m_textFieldCaller->insertTextAtLocation(editedText, m_textFieldCaller->cursorLocation()); - m_textFieldCaller->setCursorLocation(m_textFieldCaller->cursorLocation() + strlen(editedText)); + m_insertTextAction(m_sender, editedText); #if MATRIX_VARIABLES m_selectableTableView.deselectTable(); m_currentPage = Page::RootMenu; @@ -202,21 +197,31 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) { return 0; } -const Expression * VariableBoxController::ContentViewController::expressionForIndex(int index) { - if (m_currentPage == Page::Scalar) { - const Symbol symbol = Symbol('A'+index); - return m_context->expressionForSymbol(&symbol); - } - if (m_currentPage == Page::Matrix) { - const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); - return m_context->expressionForSymbol(&symbol); - } -#if LIST_VARIABLES - if (m_currentPage == Page::List) { - return nullptr; - } +void VariableBoxController::ContentViewController::setTextFieldSender(TextField * textField) { + m_sender = textField; + m_insertTextAction = &insertTextInTextField; +} + +void VariableBoxController::ContentViewController::setEditableExpressionViewSender(EditableExpressionView * editableExpressionView) { + m_sender = editableExpressionView; + m_insertTextAction = &insertTextInEditableExpressionView; +} + +void VariableBoxController::ContentViewController::reloadData() { + m_selectableTableView.reloadData(); +} + +void VariableBoxController::ContentViewController::resetPage() { +#if MATRIX_VARIABLES + m_currentPage = Page::RootMenu; +#else + m_currentPage = Page::Scalar; #endif - return nullptr; +} + +void VariableBoxController::ContentViewController::viewDidDisappear() { + m_selectableTableView.deselectTable(); + ViewController::viewDidDisappear(); } VariableBoxController::ContentViewController::Page VariableBoxController::ContentViewController::pageAtIndex(int index) { @@ -257,25 +262,38 @@ I18n::Message VariableBoxController::ContentViewController::nodeLabelAtIndex(int return labels[index]; } -void VariableBoxController::ContentViewController::setTextFieldCaller(TextField * textField) { - m_textFieldCaller = textField; -} - -void VariableBoxController::ContentViewController::reloadData() { - m_selectableTableView.reloadData(); -} - -void VariableBoxController::ContentViewController::resetPage() { -#if MATRIX_VARIABLES - m_currentPage = Page::RootMenu; -#else - m_currentPage = Page::Scalar; +const Expression * VariableBoxController::ContentViewController::expressionForIndex(int index) { + if (m_currentPage == Page::Scalar) { + const Symbol symbol = Symbol('A'+index); + return m_context->expressionForSymbol(&symbol); + } + if (m_currentPage == Page::Matrix) { + const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); + return m_context->expressionForSymbol(&symbol); + } +#if LIST_VARIABLES + if (m_currentPage == Page::List) { + return nullptr; + } #endif + return nullptr; } -void VariableBoxController::ContentViewController::viewDidDisappear() { - m_selectableTableView.deselectTable(); - ViewController::viewDidDisappear(); +void VariableBoxController::ContentViewController::insertTextInTextField(void * sender, const char * textToInsert) { + TextField * textField = static_cast(sender); + if (!textField->isEditing()) { + textField->setEditing(true); + } + textField->insertTextAtLocation(textToInsert, textField->cursorLocation()); + textField->setCursorLocation(textField->cursorLocation() + strlen(textToInsert)); +} + +void VariableBoxController::ContentViewController::insertTextInEditableExpressionView(void * sender, const char * textToInsert) { + EditableExpressionView * editableExpressionView = static_cast(sender); + if (!editableExpressionView->isEditing()) { + editableExpressionView->setEditing(true); + } + editableExpressionView->insertTextAtCursor(textToInsert); } VariableBoxController::VariableBoxController(GlobalContext * context) : @@ -288,12 +306,12 @@ void VariableBoxController::didBecomeFirstResponder() { app()->setFirstResponder(&m_contentViewController); } -void VariableBoxController::setTextFieldCaller(TextField * textField) { - m_contentViewController.setTextFieldCaller(textField); +void VariableBoxController::setTextFieldSender(TextField * textField) { + m_contentViewController.setTextFieldSender(textField); } -void VariableBoxController::setEditableExpressionViewCaller(EditableExpressionView * editableExpressionView) { - //TODO +void VariableBoxController::setEditableExpressionViewSender(EditableExpressionView * editableExpressionView) { + m_contentViewController.setEditableExpressionViewSender(editableExpressionView); } void VariableBoxController::viewWillAppear() { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 1617c1a31..daa75938e 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -10,10 +10,11 @@ class VariableBoxController : public StackViewController { public: + typedef void (*Action)(void * sender, const char * text); VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; - void setTextFieldCaller(TextField * textField); - void setEditableExpressionViewCaller(EditableExpressionView * editableExpressionView); + void setTextFieldSender(TextField * textField); + void setEditableExpressionViewSender(EditableExpressionView * editableExpressionView); void viewWillAppear() override; void viewDidDisappear() override; private: @@ -32,7 +33,8 @@ private: KDCoordinate cumulatedHeightFromIndex(int j) override; int indexFromCumulatedHeight(KDCoordinate offsetY) override; int typeAtLocation(int i, int j) override; - void setTextFieldCaller(TextField * textField); + void setTextFieldSender(TextField * textField); + void setEditableExpressionViewSender(EditableExpressionView * editableExpressionView); void reloadData(); void resetPage(); void viewDidDisappear() override; @@ -56,9 +58,11 @@ private: void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); const Poincare::Expression * expressionForIndex(int index); - + static void insertTextInTextField(void * sender, const char * textToInsert); + static void insertTextInEditableExpressionView(void * sender, const char * textToInsert); Poincare::GlobalContext * m_context; - TextField * m_textFieldCaller; + Responder * m_sender; + Action m_insertTextAction; int m_firstSelectedRow; int m_previousSelectedRow; Page m_currentPage; diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index 456535f0a..b6473af4a 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -25,6 +25,9 @@ public: /* Callback for MathToolbox */ void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); + /* Callback for VariableBoxController */ + void insertTextAtCursor(const char * text); + /* View */ KDSize minimalSizeForOptimalDisplay() const override; diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 023028d0f..8f0ccb5c7 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -163,6 +163,11 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l } } +void EditableExpressionView::insertTextAtCursor(const char * text) { + m_expressionViewWithCursor.cursor()->insertText(text); + reload(); +} + void EditableExpressionView::reload() { m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); m_expressionViewWithCursor.cursorPositionChanged(); From f50391689f86a452d912b19215ffbde83de2a943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:19:26 +0100 Subject: [PATCH 177/459] [apps/calculation] Handle OK event in calculation history. Change-Id: I3e4c309a3bc031476eea0d64d433b535b1220a8f --- apps/calculation/edit_expression_controller.cpp | 14 ++++++++++---- apps/variable_box_controller.cpp | 2 +- escher/include/escher/editable_expression_view.h | 5 +---- escher/src/editable_expression_view.cpp | 10 +++++++++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 625d25d51..3bc7054b9 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -85,10 +85,16 @@ const char * EditExpressionController::textBody() { } void EditExpressionController::insertTextBody(const char * text) { - TextField * tf = ((ContentView *)view())->textField(); - tf->setEditing(true, false); - tf->insertTextAtLocation(text, tf->cursorLocation()); - tf->setCursorLocation(tf->cursorLocation() + strlen(text)); + if (((ContentView *)view())->editionIsInTextField()) { + TextField * tf = ((ContentView *)view())->textField(); + tf->setEditing(true, false); + tf->insertTextAtLocation(text, tf->cursorLocation()); + tf->setCursorLocation(tf->cursorLocation() + strlen(text)); + return; + } + EditableExpressionView * editableExpressionView = ((ContentView *)view())->editableExpressionView(); + editableExpressionView->setEditing(true); + editableExpressionView->insertLayoutFromTextAtCursor(text); } bool EditExpressionController::handleEvent(Ion::Events::Event event) { diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 44be6b710..3f14cc49c 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -293,7 +293,7 @@ void VariableBoxController::ContentViewController::insertTextInEditableExpressio if (!editableExpressionView->isEditing()) { editableExpressionView->setEditing(true); } - editableExpressionView->insertTextAtCursor(textToInsert); + editableExpressionView->insertLayoutFromTextAtCursor(textToInsert); } VariableBoxController::VariableBoxController(GlobalContext * context) : diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index b6473af4a..f4cf92423 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -22,11 +22,8 @@ public: bool editableExpressionViewShouldFinishEditing(Ion::Events::Event event); - /* Callback for MathToolbox */ void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); - - /* Callback for VariableBoxController */ - void insertTextAtCursor(const char * text); + void insertLayoutFromTextAtCursor(const char * text); /* View */ KDSize minimalSizeForOptimalDisplay() const override; diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 8f0ccb5c7..d23cf1097 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -163,7 +163,15 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l } } -void EditableExpressionView::insertTextAtCursor(const char * text) { +void EditableExpressionView::insertLayoutFromTextAtCursor(const char * text) { + Poincare::Expression * expression = Poincare::Expression::parse(text); + if (expression != nullptr) { + Poincare::ExpressionLayout * layout = expression->createLayout(); + delete expression; + insertLayoutAtCursor(layout, layout); + reload(); + return; + } m_expressionViewWithCursor.cursor()->insertText(text); reload(); } From fc2788cc794dd4cb70c27089eade02dc52ada01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:32:28 +0100 Subject: [PATCH 178/459] [apps/Makefile] Remove the ExpressionEditor app. Change-Id: I5bcb5064bf1335abda8d6e032eb00f1798463797 --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index f99c5bae4..01098023f 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= expression_editor calculation +EPSILON_APPS ?= calculation include apps/shared/Makefile include apps/home/Makefile From 62ae5840e9d3199c8a6aaac23b83a009b6ed2026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:33:03 +0100 Subject: [PATCH 179/459] [apps/poincare] Handle cursor positioning in EditableExpressionView. There cursor was not in the right place for log(), cos(), ... Change-Id: I8fe1f350f3054460204cb5d40508212642333e3e --- escher/src/editable_expression_view.cpp | 4 ---- poincare/include/poincare/expression_layout_cursor.h | 1 - poincare/src/expression_layout_cursor.cpp | 12 +++++++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index d23cf1097..40b4a30b0 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -108,10 +108,6 @@ bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { m_expressionViewWithCursor.cursor()->addEmptyExponentialLayout(); return true; } - if (event == Ion::Events::Log) { - m_expressionViewWithCursor.cursor()->addEmptyLogarithmLayout(); - return true; - } if (event == Ion::Events::Power) { m_expressionViewWithCursor.cursor()->addEmptyPowerLayout(); return true; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 3a444399f..bf3dcd900 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -42,7 +42,6 @@ public: void addLayout(ExpressionLayout * layout); void addEmptyExponentialLayout(); void addFractionLayoutAndCollapseBrothers(); - void addEmptyLogarithmLayout(); void addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); void addEmptyPowerLayout(); void addEmptySquareRootLayout(); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 86c30a923..c7ad5e9bb 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -99,11 +99,6 @@ void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { setPosition(Position::Left); } -void ExpressionLayoutCursor::addEmptyLogarithmLayout() { - insertText("log()"); - setPosition(ExpressionLayoutCursor::Position::Left); -} - void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { assert(numberOfRows > 0); assert(numberOfColumns > 0); @@ -181,9 +176,13 @@ void ExpressionLayoutCursor::insertText(const char * text) { return; } ExpressionLayout * newChild = nullptr; + ExpressionLayout * pointedChild = nullptr; for (int i = 0; i < textLength; i++) { if (text[i] == '(') { newChild = new ParenthesisLeftLayout(); + if (pointedChild == nullptr) { + pointedChild = newChild; + } } else if (text[i] == ')') { newChild = new ParenthesisRightLayout(); } else if (text[i] == '[') { @@ -197,6 +196,9 @@ void ExpressionLayoutCursor::insertText(const char * text) { m_pointedExpressionLayout = newChild; m_position = Position::Right; } + if (pointedChild != nullptr) { + m_pointedExpressionLayout = pointedChild; + } } void ExpressionLayoutCursor::performBackspace() { From 7abcfecb9c0d4168515759bbe90ebeca64785689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:37:53 +0100 Subject: [PATCH 180/459] [poincare] Change empty Power layout deletion. Change-Id: Id9b6b0c2701d70f436c3a033c23c120a41f7feda --- poincare/src/layout/vertical_offset_layout.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 2da4b08b3..6af0a64d6 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -26,9 +26,10 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { int indexInParent = m_parent->indexOfChild(this); if (base->isEmpty()) { // Case: Empty base and indice. - // Replace with the empty base layout. - m_parent->removeChildAtIndex(indexInParent - 1, false); - replaceWithAndMoveCursor(base, true, cursor); + // Remove both the base and the indice layout. + ExpressionLayout * parent = m_parent; + parent->removePointedChildAtIndexAndMoveCursor(indexInParent, true, cursor); + parent->removePointedChildAtIndexAndMoveCursor(indexInParent-1, true, cursor); return; } // Case: Empty indice only. From 24a22fb3747650e9721b95ede3ee55e9df747f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 16:54:10 +0100 Subject: [PATCH 181/459] [apps/calculation] Delete layout when unloading view. Change-Id: I7c7afc4882051266c04f28cf2823d58c803f05c0 --- apps/calculation/edit_expression_controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 3bc7054b9..93f3b906a 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -199,6 +199,7 @@ View * EditExpressionController::loadView() { } void EditExpressionController::unloadView(View * view) { + delete expressionLayout(); delete view; } From 4673358f6032a6a36ea93ff12b3d9df9ef51e22c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 17:28:49 +0100 Subject: [PATCH 182/459] [poincare] Fix RootLayout deletion. Change-Id: If9aa315299ce687e208ff3ea81346cbe29a5d03e --- poincare/src/layout/expression_layout.cpp | 11 +++-------- poincare/src/layout/horizontal_layout.cpp | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 8dfe2fb18..03a789c65 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -180,15 +180,10 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { int oldChildIndex = indexOfChild(oldChild); - assert(oldChildIndex >= 0); - if (oldChildIndex == 0) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - } else { - cursor->setPointedExpressionLayout(editableChild(oldChildIndex - 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - } + assert(indexOfChild(oldChild) >= 0); replaceChild(oldChild, newChild, deleteOldChild); + cursor->setPointedExpressionLayout(newChild); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); } void ExpressionLayout::detachChild(const ExpressionLayout * e) { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 19ee6021b..0847eabb0 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -141,7 +141,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex return; } cursor->setPointedExpressionLayout(newChild); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } From 6f8a1979d21e3fb17ad75f28681fb1b346783aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 17:29:21 +0100 Subject: [PATCH 183/459] [poincare] Remove superfluous parentheses when serializing fractions. Change-Id: I2f24d67293ed26fbe5aab3035c49ae162fdefab0 --- poincare/src/layout/fraction_layout.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 2f2d14dfe..066047caa 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -161,16 +161,10 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { int numberOfChar = 0; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - // Write the first enclosing parenthesis. - buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - // Write the content of the fraction numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, "/"); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - // Write the second enclosing parenthesis. - buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar] = 0; return numberOfChar; } From 627e96e5e3f9ce56e9189318400972b43eed23cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 17:30:55 +0100 Subject: [PATCH 184/459] [escher] Black cursor color. Change-Id: I150e4f51a1162ded51af5e6a72cdaa70b428965d --- escher/src/text_cursor_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/text_cursor_view.cpp b/escher/src/text_cursor_view.cpp index fd2ea48f1..6ef9a6ebe 100644 --- a/escher/src/text_cursor_view.cpp +++ b/escher/src/text_cursor_view.cpp @@ -2,7 +2,7 @@ void TextCursorView::drawRect(KDContext * ctx, KDRect rect) const { KDCoordinate height = bounds().height(); - ctx->fillRect(KDRect(0, 0, 1, height), KDColorRed); + ctx->fillRect(KDRect(0, 0, 1, height), KDColorBlack); } KDSize TextCursorView::minimalSizeForOptimalDisplay() const { From 51e33b69036482fd232f44f706cf268229f793a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 17:33:58 +0100 Subject: [PATCH 185/459] [apps/calculation] Fix margins. Change-Id: If799563af90c9de4ea02d3177a0ee2375d8ddbb4 --- apps/calculation/edit_expression_controller.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index bf26f73e8..a28d36a41 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -48,9 +48,9 @@ private: bool editionIsInTextField() const { return true; } //TODO static constexpr int k_bufferLength = TextField::maxBufferSize(); private: - static constexpr KDCoordinate k_textFieldHeight = 32; //37 + static constexpr KDCoordinate k_textFieldHeight = 32; static constexpr KDCoordinate k_leftMargin = 5; - static constexpr KDCoordinate k_verticalMargin = 9; + static constexpr KDCoordinate k_verticalMargin = 5; constexpr static int k_separatorThickness = 1; KDCoordinate inputViewHeight() const; KDCoordinate editableExpressionViewHeight() const; From 60127036b7a5bd2af84c3e1d82a649047c86e8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 16 Jan 2018 18:03:04 +0100 Subject: [PATCH 186/459] [poincare] Fix unused variable. Change-Id: I45cda6d12666a90d24eb4f0f03149ed083e5d68d --- poincare/src/layout/expression_layout.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 03a789c65..ec6184b1b 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -179,7 +179,6 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio } void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { - int oldChildIndex = indexOfChild(oldChild); assert(indexOfChild(oldChild) >= 0); replaceChild(oldChild, newChild, deleteOldChild); cursor->setPointedExpressionLayout(newChild); From 8ab8ef4c5f728ab708acb6e1f19abe2cf7447299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 10:38:43 +0100 Subject: [PATCH 187/459] [apps/settings] Add a setting for the edition mode (1D or 2D). Change-Id: Ia6783d3443a8b059e67a293a517bc652950aab55 --- apps/Makefile | 2 +- apps/settings/base.de.i18n | 3 ++ apps/settings/base.en.i18n | 3 ++ apps/settings/base.es.i18n | 3 ++ apps/settings/base.fr.i18n | 3 ++ apps/settings/base.pt.i18n | 3 ++ apps/settings/main_controller.cpp | 37 +++++++++++++++---------- apps/settings/main_controller.h | 6 ++-- apps/settings/sub_controller.cpp | 8 +++++- poincare/include/poincare/preferences.h | 7 +++++ poincare/src/preferences.cpp | 9 ++++++ 11 files changed, 65 insertions(+), 19 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 01098023f..4072eb811 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= calculation +EPSILON_APPS ?= calculation settings include apps/shared/Makefile include apps/home/Makefile diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 37faed397..c7a9992ab 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -2,6 +2,9 @@ SettingsApp = "Einstellungen" SettingsAppCapital = "EINSTELLUNGEN" AngleUnit = "Winkeleinheit" DisplayMode = "Zahlenformat" +EditionMode = "Editiermodus" +EditionLinear = "1D " +Edition2D = "2D " ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Start Testmodus" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 6ed3a0c64..c2188e480 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -2,6 +2,9 @@ SettingsApp = "Settings" SettingsAppCapital = "SETTINGS" AngleUnit = "Angle measure" DisplayMode = "Result format" +EditionMode = "Edition mode" +EditionLinear = "1D " +Edition2D = "2D " ComplexFormat = "Complex format" ExamMode = "Exam mode" ActivateExamMode = "Activate exam mode" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 169e8c727..a7bdaf690 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -2,6 +2,9 @@ SettingsApp = "Configuracion" SettingsAppCapital = "CONFIGURACION" AngleUnit = "Medida del angulo" DisplayMode = "Formato resultado" +EditionMode = "Modo edicion" +EditionLinear = "1D " +Edition2D = "2D " ComplexFormat = "Formato complejo" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 7f08a1732..7fffe0d16 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -2,6 +2,9 @@ SettingsApp = "Parametres" SettingsAppCapital = "PARAMETRES" AngleUnit = "Unite d'angle" DisplayMode = "Format resultat" +EditionMode = "Mode d'edition" +EditionLinear = "1D " +Edition2D = "2D " ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index fcceaadcd..788d63e85 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -2,6 +2,9 @@ SettingsApp = "Configuracao" SettingsAppCapital = "CONFIGURACAO" AngleUnit = "Valor do angulo" DisplayMode = "Formato numerico" +EditionMode = "Modo de edicao" +EditionLinear = "1D " +Edition2D = "2D " ComplexFormat = "Complexos" ExamMode = "Modo de Exame" ActivateExamMode = "Inicio modo de exame" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 37c1fb4f6..fe234ca0b 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -9,26 +9,32 @@ using namespace Poincare; namespace Settings { const SettingsMessageTree angleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)}; -const SettingsMessageTree FloatDisplayModeChildren[3] = {SettingsMessageTree(I18n::Message::Auto), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::SignificantFigures)}; +const SettingsMessageTree editionModeChildren[2] = {SettingsMessageTree(I18n::Message::EditionLinear), SettingsMessageTree(I18n::Message::Edition2D)}; +const SettingsMessageTree floatDisplayModeChildren[3] = {SettingsMessageTree(I18n::Message::Auto), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::SignificantFigures)}; const SettingsMessageTree complexFormatChildren[2] = {SettingsMessageTree(I18n::Message::Default), SettingsMessageTree(I18n::Message::Default)}; const SettingsMessageTree examChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; const SettingsMessageTree aboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; #if OS_WITH_SOFTWARE_UPDATE_PROMPT -const SettingsMessageTree menu[8] = +const SettingsMessageTree menu[9] = #else -const SettingsMessageTree menu[7] = +const SettingsMessageTree menu[8] = #endif - {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), SettingsMessageTree(I18n::Message::DisplayMode, FloatDisplayModeChildren, 3), SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), - SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), SettingsMessageTree(I18n::Message::ExamMode, examChildren, 1), + {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), + SettingsMessageTree(I18n::Message::DisplayMode, floatDisplayModeChildren, 3), + SettingsMessageTree(I18n::Message::EditionMode, editionModeChildren, 2), + SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), + SettingsMessageTree(I18n::Message::Brightness), + SettingsMessageTree(I18n::Message::Language), + SettingsMessageTree(I18n::Message::ExamMode, examChildren, 1), #if OS_WITH_SOFTWARE_UPDATE_PROMPT SettingsMessageTree(I18n::Message::UpdatePopUp), #endif SettingsMessageTree(I18n::Message::About, aboutChildren, 3)}; #if OS_WITH_SOFTWARE_UPDATE_PROMPT -const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 8); +const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 9); #else -const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 7); +const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 8); #endif MainController::MainController(Responder * parentResponder) : @@ -149,14 +155,14 @@ int MainController::reusableCellCount(int type) { } int MainController::typeAtLocation(int i, int j) { - if (j == 2) { + if (j == 3) { return 1; } - if (j == 3) { + if (j == 4) { return 2; } #if OS_WITH_SOFTWARE_UPDATE_PROMPT - if (j == 6) { + if (j == 7) { return 3; } #endif @@ -167,7 +173,7 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCell * myCell = (MessageTableCell *)cell; myCell->setMessage(m_messageTreeModel->children(index)->label()); - if (index == 2) { + if (index == 3) { if (m_complexFormatLayout) { delete m_complexFormatLayout; m_complexFormatLayout = nullptr; @@ -181,19 +187,19 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { myExpCell->setExpressionLayout(m_complexFormatLayout); return; } - if (index == 3) { + if (index == 4) { MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell; GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView(); myGauge->setLevel((float)GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()/(float)Ion::Backlight::MaxBrightness); return; } - if (index == 4) { + if (index == 5) { int index = (int)GlobalPreferences::sharedGlobalPreferences()->language()-1; static_cast(cell)->setSubtitle(I18n::LanguageNames[index]); return; } #if OS_WITH_SOFTWARE_UPDATE_PROMPT - if (index == 6) { + if (index == 7) { MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); mySwitch->setState(GlobalPreferences::sharedGlobalPreferences()->showUpdatePopUp()); @@ -208,6 +214,9 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { case 1: myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->displayMode())->label()); break; + case 2: + myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->editionMode())->label()); + break; default: myTextCell->setSubtitle(I18n::Message::Default); break; diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 4943fe3de..dd4c95eed 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -31,12 +31,12 @@ public: private: StackViewController * stackController() const; #if OS_WITH_SOFTWARE_UPDATE_PROMPT - constexpr static int k_totalNumberOfCell = 8; + constexpr static int k_totalNumberOfCell = 9; MessageTableCellWithSwitch m_updateCell; #else - constexpr static int k_totalNumberOfCell = 7; + constexpr static int k_totalNumberOfCell = 8; #endif - constexpr static int k_numberOfSimpleChevronCells = 5; + constexpr static int k_numberOfSimpleChevronCells = 6; MessageTableCellWithChevronAndMessage m_cells[k_numberOfSimpleChevronCells]; MessageTableCellWithChevronAndExpression m_complexFormatCell; MessageTableCellWithGauge m_brightnessCell; diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp index eacaededa..ff071864d 100644 --- a/apps/settings/sub_controller.cpp +++ b/apps/settings/sub_controller.cpp @@ -69,7 +69,7 @@ bool SubController::handleEvent(Ion::Events::Event event) { return true; } if (event == Ion::Events::OK || event == Ion::Events::EXE) { - /* Behavious of "Exam mode" menu*/ + /* Behaviour of "Exam mode" menu*/ if (m_messageTreeModel->label() == I18n::Message::ExamMode) { if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { return false; @@ -254,6 +254,9 @@ void SubController::setPreferenceWithValueIndex(I18n::Message message, int value if (message == I18n::Message::DisplayMode) { Preferences::sharedPreferences()->setDisplayMode((Expression::FloatDisplayMode)valueIndex); } + if (message == I18n::Message::EditionMode) { + Preferences::sharedPreferences()->setEditionMode((Preferences::EditionMode)valueIndex); + } if (message == I18n::Message::ComplexFormat) { Preferences::sharedPreferences()->setComplexFormat((Expression::ComplexFormat)valueIndex); } @@ -266,6 +269,9 @@ int SubController::valueIndexForPreference(I18n::Message message) { if (message == I18n::Message::DisplayMode) { return (int)Preferences::sharedPreferences()->displayMode(); } + if (message == I18n::Message::EditionMode) { + return (int)Preferences::sharedPreferences()->editionMode(); + } if (message == I18n::Message::ComplexFormat) { return (int)Preferences::sharedPreferences()->complexFormat(); } diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 40925dbd6..741e117bc 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -7,12 +7,18 @@ namespace Poincare { class Preferences { public: + enum class EditionMode { + Edition1D, + Edition2D + }; Preferences(); static Preferences * sharedPreferences(); Expression::AngleUnit angleUnit() const; void setAngleUnit(Expression::AngleUnit angleUnit); Expression::FloatDisplayMode displayMode() const; void setDisplayMode(Expression::FloatDisplayMode FloatDisplayMode); + EditionMode editionMode() const; + void setEditionMode(EditionMode editionMode); Expression::ComplexFormat complexFormat() const; void setComplexFormat(Expression::ComplexFormat complexFormat); char numberOfSignificantDigits() const; @@ -20,6 +26,7 @@ public: private: Expression::AngleUnit m_angleUnit; Expression::FloatDisplayMode m_displayMode; + EditionMode m_editionMode; Expression::ComplexFormat m_complexFormat; char m_numberOfSignificantDigits; }; diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index c224419fd..2a432f663 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -8,6 +8,7 @@ static Preferences s_preferences; Preferences::Preferences() : m_angleUnit(Expression::AngleUnit::Degree), m_displayMode(Expression::FloatDisplayMode::Decimal), + m_editionMode(EditionMode::Edition2D), m_complexFormat(Expression::ComplexFormat::Cartesian), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits) { @@ -33,6 +34,14 @@ void Preferences::setDisplayMode(Expression::FloatDisplayMode FloatDisplayMode) m_displayMode = FloatDisplayMode; } +Preferences::EditionMode Preferences::editionMode() const { + return m_editionMode; +} + +void Preferences::setEditionMode(Preferences::EditionMode editionMode) { + m_editionMode = editionMode; +} + Expression::ComplexFormat Preferences::complexFormat() const { return m_complexFormat; } From 05de98ea04930698f5e0ca263fd052a60fe81bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 10:39:20 +0100 Subject: [PATCH 188/459] [apps/calculation] Fetch the edition mode in the preferences. Change-Id: Iec7cfc5695907b8c410077a48749fd43efb6cc65 --- apps/calculation/edit_expression_controller.cpp | 9 +++++++-- apps/calculation/edit_expression_controller.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 93f3b906a..2a3a9ee27 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -1,7 +1,8 @@ #include "edit_expression_controller.h" -#include "../apps_container.h" -#include "ion/display.h" #include "app.h" +#include "../apps_container.h" +#include +#include #include using namespace Shared; @@ -65,6 +66,10 @@ void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rec } } +bool EditExpressionController::ContentView::editionIsInTextField() const { + return Poincare::Preferences::sharedPreferences()->editionMode() == Poincare::Preferences::EditionMode::Edition1D; +} + KDCoordinate EditExpressionController::ContentView::inputViewHeight() const { return k_verticalMargin + (editionIsInTextField() ? k_textFieldHeight : editableExpressionViewHeight()); } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index a28d36a41..54d0512da 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -45,7 +45,7 @@ private: EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } TableView * mainView() { return m_mainView; } void drawRect(KDContext * ctx, KDRect rect) const override; - bool editionIsInTextField() const { return true; } //TODO + bool editionIsInTextField() const; static constexpr int k_bufferLength = TextField::maxBufferSize(); private: static constexpr KDCoordinate k_textFieldHeight = 32; From e1811e03991839eed68a8e6c6310b2e75c1a5c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 10:55:34 +0100 Subject: [PATCH 189/459] [apps/calculation] Fix redraw bug. Change-Id: I86cf0839f4aa7f1285ed378850f6d09e811252a2 --- escher/src/editable_expression_view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 40b4a30b0..78bed4b2b 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -35,6 +35,7 @@ bool EditableExpressionView::handleEvent(Ion::Events::Event event) { KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { m_delegate->editableExpressionViewDidChangeSize(this); + reload(); } return true; } @@ -151,9 +152,8 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l m_expressionViewWithCursor.cursor()->addLayout(layout); m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); - KDSize newSize = minimalSizeForOptimalDisplay(); reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { m_delegate->editableExpressionViewDidChangeSize(this); } From cb6a526072c7c2c12602a4a92c8f1b9dcae4affa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 11:59:51 +0100 Subject: [PATCH 190/459] [poincare] Fix bug in matrix layout assert. Change-Id: I84ec8034f9f417b12b91abe84771fec5834ba8b4 --- poincare/src/layout/matrix_layout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index ff18958fc..82467984e 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -68,7 +68,7 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) { && childIsRightOfGrid(childIndex)) { // Case: Right of a child on the right of the grid. - // Remove the grey squares of the grid, then go left of the grid. + // Remove the grey squares of the grid, then go right of the grid. cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); assert(hasGreySquares()); @@ -273,8 +273,8 @@ bool MatrixLayout::hasGreySquares() const { && !lastChild->isHorizontal() && (static_cast(lastChild))->color() == EmptyVisibleLayout::Color::Grey) { - assert(isRowEmpty(m_numberOfColumns - 1)); - assert(isColumnEmpty(m_numberOfRows - 1)); + assert(isRowEmpty(m_numberOfRows - 1)); + assert(isColumnEmpty(m_numberOfColumns - 1)); return true; } return false; From d8803c610c2f51e7cbdd8f2dc8e1208a0e60f317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 12:11:28 +0100 Subject: [PATCH 191/459] [apps] "New Matrix" item in math toolbox. Change-Id: Iec01ffa96ec64f42d2cbc4b15b14eea7cfe4eaa4 --- apps/code/python_toolbox.cpp | 5 +-- apps/code/variable_box_controller.cpp | 5 +-- apps/math_toolbox.cpp | 13 +++++--- apps/shared.universal.i18n | 1 + apps/shared/toolbox_helpers.cpp | 41 ++++++++++++++++++++----- apps/shared/toolbox_helpers.h | 8 ++--- apps/toolbox.de.i18n | 1 + apps/toolbox.en.i18n | 1 + apps/toolbox.es.i18n | 1 + apps/toolbox.fr.i18n | 1 + apps/toolbox.pt.i18n | 1 + escher/src/editable_expression_view.cpp | 4 +++ poincare/src/layout/matrix_layout.h | 3 +- 13 files changed, 64 insertions(+), 21 deletions(-) diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp index c9d7d80ce..1498a58bf 100644 --- a/apps/code/python_toolbox.cpp +++ b/apps/code/python_toolbox.cpp @@ -289,8 +289,9 @@ bool PythonToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { m_selectableTableView.deselectTable(); ToolboxMessageTree * node = selectedMessageTree; const char * editedText = I18n::translate(node->insertedText()); - char strippedEditedText[strlen(editedText)+1]; - Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText); + int strippedEditedTextMaxLength = strlen(editedText)+1; + char strippedEditedText[strippedEditedTextMaxLength]; + Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength); m_action(sender(), const_cast(strippedEditedText)); app()->dismissModalViewController(); return true; diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index 657284ff2..9684642aa 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -119,8 +119,9 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl } void VariableBoxController::ContentViewController::insertTextInCaller(const char * text) { - char commandBuffer[strlen(text)+1]; - Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer); + int commandBufferMaxSize = strlen(text)+1; + char commandBuffer[commandBufferMaxSize]; + Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer, commandBufferMaxSize); if (m_textFieldCaller != nullptr) { if (!m_textFieldCaller->isEditing()) { m_textFieldCaller->setEditing(true); diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index f7a37dd10..1ce07b16e 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -36,7 +36,8 @@ const ToolboxMessageTree arithmeticChildren[4] = { ToolboxMessageTree(I18n::Message::QuoCommandWithArg, I18n::Message::Quotient, I18n::Message::QuoCommandWithArg)}; #if MATRICES_ARE_DEFINED -const ToolboxMessageTree matricesChildren[5] = { +const ToolboxMessageTree matricesChildren[6] = { + ToolboxMessageTree(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, I18n::Message::MatrixCommandWithArg), ToolboxMessageTree(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse, I18n::Message::InverseCommandWithArg), ToolboxMessageTree(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant, I18n::Message::DeterminantCommandWithArg), ToolboxMessageTree(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose, I18n::Message::TransposeCommandWithArg), @@ -88,7 +89,7 @@ const ToolboxMessageTree menu[10] = { ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), ToolboxMessageTree(I18n::Message::Arithmetic, I18n::Message::Default, I18n::Message::Default, arithmeticChildren, 4), #if MATRICES_ARE_DEFINED - ToolboxMessageTree(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 5), + ToolboxMessageTree(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 6), #endif #if LIST_ARE_DEFINED ToolboxMessageTree(I18n::Message::Lists, I18n::Message::Default, I18n::Message::Default, listesChildren, 5), @@ -119,8 +120,9 @@ void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageT EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); // Translate the message and replace the arguments with Empty chars. const char * textToInsert = I18n::translate(messageTree->insertedText()); + int strippedTextToInsertMaxLength = strlen(textToInsert); char strippedTextToInsert[strlen(textToInsert)]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert, strippedTextToInsertMaxLength); // Create the layout Expression * resultExpression = Expression::parse(strippedTextToInsert); if (resultExpression == nullptr) { @@ -156,9 +158,10 @@ void MathToolbox::actionForTextfield(void * sender, ToolboxMessageTree * message textFieldSender->setEditing(true); } const char * textToInsert = I18n::translate(messageTree->insertedText()); - char strippedTextToInsert[strlen(textToInsert)]; + int textToInsertLength = strlen(textToInsert); + char strippedTextToInsert[textToInsertLength]; // Translate the message and remove the arguments. - Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert, textToInsertLength); textFieldSender->insertTextAtLocation(strippedTextToInsert, textFieldSender->cursorLocation()); int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedTextToInsert); textFieldSender->setCursorLocation(newCursorLocation); diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 5ab160c94..1f06a778b 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -32,6 +32,7 @@ LcmCommandWithArg = "lcm(p,q)" LeftIntegralFirstLegend = "P(X≤" LeftIntegralSecondLegend = ")=" LogCommandWithArg = "log(x,a)" +MatrixCommandWithArg = "[[1,2][3,4]]" MaxCommandWithArg = "max(L)" MinCommandWithArg = "min(L)" Mu = "μ" diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index a1da1475f..268162c8d 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -1,6 +1,8 @@ #include "toolbox_helpers.h" #include +#include #include +#include namespace Shared { namespace ToolboxHelpers { @@ -10,28 +12,42 @@ int CursorIndexInCommand(const char * text) { if (text[i] == '(' || text[i] == '\'') { return i + 1; } + if (text[i] == ']') { + return (i - 1) > 0 ? i - 1 : 0; + } } return strlen(text); } -void TextToInsertForCommandMessage(I18n::Message message, char * buffer) { +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer); + TextToInsertForCommandText(messageText, buffer, bufferSize); } -void TextToInsertForCommandText(const char * command, char * buffer) { +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize) { int currentNewTextIndex = 0; + int numberOfOpenParentheses = 0; int numberOfOpenBrackets = 0; bool insideQuote = false; size_t commandLength = strlen(command); for (size_t i = 0; i < commandLength; i++) { if (command[i] == ')') { + numberOfOpenParentheses--; + } + if (command[i] == ']') { numberOfOpenBrackets--; } - if ((numberOfOpenBrackets == 0 || command[i] == ',') && (!insideQuote || command[i] == '\'')) { + if (((numberOfOpenParentheses == 0 && numberOfOpenBrackets == 0) + || command[i] == ',' + || (numberOfOpenBrackets > 0 && (command[i] == ',' || command[i] == '[' || command[i] == ']'))) + && (!insideQuote || command[i] == '\'')) { + assert(currentNewTextIndex < bufferSize); buffer[currentNewTextIndex++] = command[i]; } if (command[i] == '(') { + numberOfOpenParentheses++; + } + if (command[i] == '[') { numberOfOpenBrackets++; } if (command[i] == '\'') { @@ -41,12 +57,23 @@ void TextToInsertForCommandText(const char * command, char * buffer) { buffer[currentNewTextIndex] = 0; } -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer) { +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { + if (message == I18n::Message::MatrixCommandWithArg) { + assert(bufferSize >= 6); + // Handle a new matrix command. + buffer[0] = '['; + buffer[1] = '['; + buffer[2] = Ion::Charset::Empty; + buffer[3] = ']'; + buffer[4] = ']'; + buffer[5] = 0; + return; + } const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer); + TextToInsertForCommandText(messageText, buffer, bufferSize); size_t bufferLength = strlen(buffer); for (size_t i = 0; i < bufferLength; i++) { - if (buffer[i] == '(' || buffer[i] == ',') { + if (buffer[i] == '(' || buffer[i] == '[' || buffer[i] == ',') { // Shift the buffer to make room for the new char. Use memmove to avoid // overwritting. memmove(&buffer[i+2], &buffer[i+1], bufferLength - (i+1) + 1); diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index 98539614d..d051f5847 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -13,11 +13,11 @@ int CursorIndexInCommand(const char * text); * - The end of the text */ -void TextToInsertForCommandMessage(I18n::Message message, char * buffer); -void TextToInsertForCommandText(const char * command, char * buffer); +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize); +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize); /* Removes the arguments from a command: - * - Removes text between parentheses, except commas */ -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer); + * - Removes text between parentheses or brackets, except commas */ +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize); /* Removes the arguments from a command and replaces them with empty chars. */ } diff --git a/apps/toolbox.de.i18n b/apps/toolbox.de.i18n index a8b6fd1b6..6312f3aad 100644 --- a/apps/toolbox.de.i18n +++ b/apps/toolbox.de.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Komplexen Zahlen" Probability = "Kombinatorik" Arithmetic = "Arithmetisch" Matrices = "Matrizen" +NewMatrix = "Neue Matrix" Lists = "Listen" Approximation = "Approximation" HyperbolicTrigonometry = "Hyperbelfunktionen" diff --git a/apps/toolbox.en.i18n b/apps/toolbox.en.i18n index b1a6e3533..e8103814b 100644 --- a/apps/toolbox.en.i18n +++ b/apps/toolbox.en.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Complex numbers" Probability = "Combinatorics" Arithmetic = "Arithmetic" Matrices = "Matrix" +NewMatrix = "New matrix" Lists = "List" Approximation = "Approximation" HyperbolicTrigonometry = "Hyperbolic trigonometry" diff --git a/apps/toolbox.es.i18n b/apps/toolbox.es.i18n index 90ecf326a..a78d837d4 100644 --- a/apps/toolbox.es.i18n +++ b/apps/toolbox.es.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Numeros complejos" Probability = "Combinatoria" Arithmetic = "Aritmetica" Matrices = "Matriz" +NewMatrix = "Nueva matriz" Lists = "Listas" Approximation = "Aproximacion" HyperbolicTrigonometry = "Trigonometria hiperbolica" diff --git a/apps/toolbox.fr.i18n b/apps/toolbox.fr.i18n index d8cb4b190..d944d0415 100644 --- a/apps/toolbox.fr.i18n +++ b/apps/toolbox.fr.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Nombres complexes" Probability = "Denombrement" Arithmetic = "Arithmetique" Matrices = "Matrices" +NewMatrix = "Nouvelle matrice" Lists = "Listes" Approximation = "Approximation" HyperbolicTrigonometry = "Trigonometrie hyperbolique" diff --git a/apps/toolbox.pt.i18n b/apps/toolbox.pt.i18n index aa1ad1d81..45ade5d5e 100644 --- a/apps/toolbox.pt.i18n +++ b/apps/toolbox.pt.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Numeros complexos" Probability = "Combinatoria" Arithmetic = "Aritmetica" Matrices = "Matrizes" +NewMatrix = "Nova matriz" Lists = "Listas" Approximation = "Aproximacao" HyperbolicTrigonometry = "Funcoes hiperbolicas" diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 78bed4b2b..01159a81a 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -1,5 +1,6 @@ #include #include +#include #include EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : @@ -150,6 +151,9 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l } KDSize previousSize = minimalSizeForOptimalDisplay(); m_expressionViewWithCursor.cursor()->addLayout(layout); + if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { + static_cast(layout)->addGreySquares(); + } m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); reload(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index b931bb51b..8208d11b3 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -29,6 +29,8 @@ public: /* Special matrix method */ void newRowOrColumnAtIndex(int index); + void addGreySquares(); + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -37,7 +39,6 @@ private: void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; - void addGreySquares(); void removeGreySquares(); bool hasGreySquares() const; }; From 3154decf8ba5d5ce2560967896cf4f51781b9812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 14:10:37 +0100 Subject: [PATCH 192/459] [apps] Fixed bug in MathToolbox. When returning a MathToolbox, the textfield delegate did not set the toolbox action for textfields. Change-Id: I51f78ff5601f784be8e283cf3fb6d3462b776d9a --- apps/math_toolbox.cpp | 4 ++-- apps/math_toolbox.h | 2 +- apps/shared/text_field_delegate_app.cpp | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 1ce07b16e..3910a60c0 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -107,7 +107,7 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbo MathToolbox::MathToolbox() : Toolbox(nullptr, I18n::translate(rootModel()->label())), - m_action(actionForTextfield) + m_action(actionForTextField) { } @@ -152,7 +152,7 @@ void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageT expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); } -void MathToolbox::actionForTextfield(void * sender, ToolboxMessageTree * messageTree) { +void MathToolbox::actionForTextField(void * sender, ToolboxMessageTree * messageTree) { TextField * textFieldSender = static_cast(sender); if (!textFieldSender->isEditing()) { textFieldSender->setEditing(true); diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 6f06148d1..dbcc8e2cd 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -12,7 +12,7 @@ public: MathToolbox(); void setSenderAndAction(Responder * sender, Action action); static void actionForEditableExpressionView(void * sender, ToolboxMessageTree * messageTree); - static void actionForTextfield(void * sender, ToolboxMessageTree * messageTree); + static void actionForTextField(void * sender, ToolboxMessageTree * messageTree); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index de8df6c42..574a47e1f 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -110,7 +110,9 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion:: } Toolbox * TextFieldDelegateApp::toolboxForTextField(TextField * textField) { - return container()->mathToolbox(); + Toolbox * toolbox = container()->mathToolbox(); + static_cast(toolbox)->setSenderAndAction(textField, MathToolbox::actionForTextField); + return toolbox; } } From 169913b80008dbba99bc7f3779a82a5e701274c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 14:13:51 +0100 Subject: [PATCH 193/459] [apps/calculation] Fix background redraw bug. The margins around the textfield did not redraw themselves properly after dismissing a toolbox for instance. The textfield now takes the full height of edition zone. Change-Id: I0794b8273a880a2dc921c5f492eb0f41aef7fe97 --- apps/calculation/edit_expression_controller.cpp | 8 ++++---- apps/calculation/edit_expression_controller.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 2a3a9ee27..d1fefa9af 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -39,7 +39,7 @@ void EditExpressionController::ContentView::layoutSubviews() { KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight-k_separatorThickness); m_mainView->setFrame(mainViewFrame); if (editionIsInTextField()) { - KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight + k_verticalMargin, bounds().width()-k_leftMargin, k_textFieldHeight - k_verticalMargin); + KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight, bounds().width()-k_leftMargin, k_textFieldHeight); m_textField.setFrame(inputViewFrame); m_editableExpressionView.setFrame(KDRectZero); return; @@ -62,7 +62,7 @@ void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rec ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, inputViewFrameHeight), m_textField.backgroundColor()); if (!editionIsInTextField()) { // Color the upper margin - ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalMargin), m_textField.backgroundColor()); + ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalEditableExpressionViewMargin), m_textField.backgroundColor()); } } @@ -71,11 +71,11 @@ bool EditExpressionController::ContentView::editionIsInTextField() const { } KDCoordinate EditExpressionController::ContentView::inputViewHeight() const { - return k_verticalMargin + (editionIsInTextField() ? k_textFieldHeight : editableExpressionViewHeight()); + return editionIsInTextField() ? k_textFieldHeight : k_verticalEditableExpressionViewMargin + editableExpressionViewHeight(); } KDCoordinate EditExpressionController::ContentView::editableExpressionViewHeight() const { - return KDCoordinate(min(0.6*Ion::Display::Height, max(k_textFieldHeight, m_editableExpressionView.minimalSizeForOptimalDisplay().height()+k_verticalMargin))); + return KDCoordinate(min(0.6*Ion::Display::Height, max(k_textFieldHeight, m_editableExpressionView.minimalSizeForOptimalDisplay().height()+k_verticalEditableExpressionViewMargin))); } EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) : diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 54d0512da..9c3d3d4aa 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -48,9 +48,9 @@ private: bool editionIsInTextField() const; static constexpr int k_bufferLength = TextField::maxBufferSize(); private: - static constexpr KDCoordinate k_textFieldHeight = 32; + static constexpr KDCoordinate k_textFieldHeight = 37; static constexpr KDCoordinate k_leftMargin = 5; - static constexpr KDCoordinate k_verticalMargin = 5; + static constexpr KDCoordinate k_verticalEditableExpressionViewMargin = 5; constexpr static int k_separatorThickness = 1; KDCoordinate inputViewHeight() const; KDCoordinate editableExpressionViewHeight() const; From 613d33efbaaf066cbf80b3de16ac7e071bfbcefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 14:25:20 +0100 Subject: [PATCH 194/459] [poincare] Delete root layout if cursor left of the radicand. Change-Id: I42331f06785680053fa3cc64a95296697f207845 --- poincare/src/layout/nth_root_layout.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 77e4516ab..8c14bfe19 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -30,7 +30,15 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { && cursor->position() == ExpressionLayoutCursor::Position::Right) { // Case: Right. - // Delete the layout, keep the operand. + // Delete the layout, keep the radicand. + replaceWithAndMoveCursor(radicandLayout(), true, cursor); + return; + } + if (cursor->pointedExpressionLayout() == radicandLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + // Case: Left of the radicand. + // Delete the layout, keep the radicand. replaceWithAndMoveCursor(radicandLayout(), true, cursor); return; } From 776c4246c6948e4f90c401dd4350ff794b3e4164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 14:51:55 +0100 Subject: [PATCH 195/459] [poincare] Delete the integral when left of the integrand. And handle the cursor position. Change-Id: I573a8c7496a3a7b99385e68e8152e491f86cb66c --- poincare/src/layout/expression_layout.cpp | 4 ++- poincare/src/layout/horizontal_layout.cpp | 33 ++++++++++++++++++----- poincare/src/layout/integral_layout.cpp | 8 ++++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index ec6184b1b..6c318fb0f 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -180,9 +180,11 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { assert(indexOfChild(oldChild) >= 0); + if (!newChild->hasAncestor(oldChild)) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } replaceChild(oldChild, newChild, deleteOldChild); cursor->setPointedExpressionLayout(newChild); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); } void ExpressionLayout::detachChild(const ExpressionLayout * e) { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 0847eabb0..e0e27198d 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -68,8 +68,10 @@ void HorizontalLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChi } void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + bool oldWasAncestorOfNewLayout = false; if (newChild->hasAncestor(this)) { newChild->editableParent()->detachChild(newChild); + oldWasAncestorOfNewLayout = true; } int oldChildIndex = indexOfChild(oldChild); if (newChild->isEmpty()) { @@ -123,12 +125,28 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex if (newChild->isHorizontal()) { int indexForInsertion = indexOfChild(oldChild); if (cursor != nullptr) { - if (oldChildIndex == numberOfChildren() - 1) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + // If the old layout is not an ancestor of the new layout, or if the + // cursor was on the right of the new layout, place the cursor on the + // right of the new layout, which is left of the next brother or right of + // the parent. + if (!oldWasAncestorOfNewLayout || cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (oldChildIndex == numberOfChildren() - 1) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } else { + cursor->setPointedExpressionLayout(editableChild(oldChildIndex + 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } } else { - cursor->setPointedExpressionLayout(editableChild(oldChildIndex + 1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + // Else place the cursor on the left of the new layout, which is right + // of the previous brother or left of the parent. + if (oldChildIndex == 0) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } else { + cursor->setPointedExpressionLayout(editableChild(oldChildIndex - 1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } } } mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); @@ -136,13 +154,14 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex return; } // Else, just replace the child. + if (cursor != nullptr && !oldWasAncestorOfNewLayout) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } ExpressionLayout::replaceChild(oldChild, newChild, deleteOldChild); if (cursor == nullptr) { return; } cursor->setPointedExpressionLayout(newChild); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return; } void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 80011c669..505b14cbc 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -35,6 +35,14 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { replaceWithAndMoveCursor(integrandLayout(), true, cursor); return; } + if (cursor->pointedExpressionLayout() == integrandLayout() + && cursor->position() == ExpressionLayoutCursor::Position::Left) + { + // Case: Left of the integrand. + // Delete the layout, keep the integrand. + replaceWithAndMoveCursor(integrandLayout(), true, cursor); + return; + } ExpressionLayout::backspaceAtCursor(cursor); } From 3cda4a881d88d7cb2703b7db924ec0cb9d6b3fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 15:32:55 +0100 Subject: [PATCH 196/459] [poincare] Fix new power layout bug. There was a problem when assessing if there was a need for an empty base layout. Change-Id: I9d6f84d3cc797fc0a701395dd8289590a4ab849a --- .../poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index bf3dcd900..5cfd89e4a 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -52,6 +52,7 @@ public: private: constexpr static KDCoordinate k_cursorHeight = 18; + bool baseForNewPowerLayout(); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index c7ad5e9bb..87f5de8bb 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -121,8 +121,7 @@ void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOf void ExpressionLayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); // If there is already a base - int numberOfOpenParenthesis = 0; - if (!m_pointedExpressionLayout->isEmpty() && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) { + if (baseForNewPowerLayout()) { m_pointedExpressionLayout->addBrother(this, offsetLayout); setPointedExpressionLayout(offsetLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Left); @@ -148,8 +147,7 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { CharLayout * indiceLayout = new CharLayout('2'); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(indiceLayout, VerticalOffsetLayout::Type::Superscript, false); // If there is already a base - int numberOfOpenParenthesis = 0; - if (!m_pointedExpressionLayout->isEmpty() && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) { + if (baseForNewPowerLayout()) { m_pointedExpressionLayout->addBrother(this, offsetLayout); setPointedExpressionLayout(offsetLayout); setPosition(ExpressionLayoutCursor::Position::Right); @@ -205,5 +203,21 @@ void ExpressionLayoutCursor::performBackspace() { m_pointedExpressionLayout->backspaceAtCursor(this); } +bool ExpressionLayoutCursor::baseForNewPowerLayout() { + // Returns true if the layout on the left of the pointed layout is suitable to + // be the base of a new power layout. + int numberOfOpenParenthesis = 0; + int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); + return ((m_position == Position::Right + && !m_pointedExpressionLayout->isEmpty() + && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) + || (m_position == Position::Left + && m_pointedExpressionLayout->parent() + && m_pointedExpressionLayout->parent()->isHorizontal() + && indexInParent > 0 + && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isEmpty() + && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true))); +} + } From b70cb6dc8a8602a332a274a73f792e92d289afb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 18:06:55 +0100 Subject: [PATCH 197/459] [poincare/parser] Fix precedence bug in the parser. Change-Id: I02a36ca82729085232166d854d596154a355daae --- poincare/src/expression_parser.y | 127 +++++++++++++++++++------------ 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 0f53054f1..90d6584f9 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -70,7 +70,6 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %token UNDERSCORE %token DOT %token EE -%token ICOMPLEX %token STO %token UNDEFINED_SYMBOL @@ -92,9 +91,9 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char * one has the highest precedence. */ %nonassoc STO +%right UNARY_MINUS %left PLUS %left MINUS -%right UNARY_MINUS %left MULTIPLY %left DIVIDE %left IMPLICIT_MULTIPLY @@ -112,13 +111,20 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %nonassoc DIGITS %nonassoc DOT %nonassoc EE -%nonassoc ICOMPLEX %nonassoc UNDEFINED %nonassoc SYMBOL %nonassoc EMPTY /* The "exp" symbol uses the "expression" part of the union. */ %type final_exp; +%type term; +%type bang; +%type factor; +%type pow; +%type div; +%type mul; +%type min; +%type unmin; %type exp; %type number; %type symb; @@ -131,7 +137,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char * have some heap-allocated data that need to be discarded. */ %destructor { delete $$; } FUNCTION -%destructor { delete $$; } UNDEFINED final_exp exp number EMPTY +%destructor { delete $$; } UNDEFINED final_exp exp unmin min mul div pow factor bang term number EMPTY %destructor { delete $$; } lstData /* MATRICES_ARE_DEFINED */ %destructor { delete $$; } mtxData @@ -143,14 +149,16 @@ Root: final_exp { *expressionOutput = $1; } + ; + +lstData: exp { $$ = new Poincare::ListData($1); } + | lstData COMMA exp { $$ = $1; $$->pushExpression($3); } + ; -lstData: - exp { $$ = new Poincare::ListData($1); } - | lstData COMMA exp { $$ = $1; $$->pushExpression($3); } /* MATRICES_ARE_DEFINED */ - mtxData: - LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, false); $2->detachOperands(); delete $2; } - | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { if ($3->numberOfOperands() != $1->numberOfColumns()) { delete $1; delete $3; YYERROR; } ; $$ = $1; $$->pushListData($3, false); $3->detachOperands(); delete $3; } +mtxData: LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, false); $2->detachOperands(); delete $2; } + | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { if ($3->numberOfOperands() != $1->numberOfColumns()) { delete $1; delete $3; YYERROR; } ; $$ = $1; $$->pushListData($3, false); $3->detachOperands(); delete $3; } + ; /* When approximating expressions to double, results are bounded by 1E308 (and * 1E-308 for small numbers). We thus accept decimals whose exponents are in @@ -161,53 +169,76 @@ lstData: * of the exponent digits is above 4 (0.00...-256 times-...01E1256=1E1000 is * accepted and 1000-...256times...-0E10000 = 1E10256, 10256 does not overflow * an int32_t). */ -number: - DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); } - | DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); } - | DIGITS DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); } - | DOT DIGITS EE DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); } - | DIGITS DOT DIGITS EE DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); } - | DIGITS EE DIGITS { if ($3.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); } - | DOT DIGITS EE MINUS DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); } - | DIGITS DOT DIGITS EE MINUS DIGITS { if ($6.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $6.address, $6.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); } - | DIGITS EE MINUS DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $4.address, $4.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); } +number : DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); } + | DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); } + | DIGITS DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); } + | DOT DIGITS EE DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); } + | DIGITS DOT DIGITS EE DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); } + | DIGITS EE DIGITS { if ($3.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); } + | DOT DIGITS EE MINUS DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); } + | DIGITS DOT DIGITS EE MINUS DIGITS { if ($6.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $6.address, $6.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); } + | DIGITS EE MINUS DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $4.address, $4.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); } + ; -symb: - SYMBOL { $$ = new Poincare::Symbol($1); } +symb : SYMBOL { $$ = new Poincare::Symbol($1); } + ; -/* The rules "exp MINUS exp" and "MINUS exp" are sometimes ambiguous. We want - * to favor "exp MINUS exp" over "MINUS exp". Bison by default resolves - * reduce/reduce conflicts in favor of the first grammar rule. Thus, the order - * of the grammar rules is here paramount: "MINUS exp" should always be after - * "exp MINUS exp". */ -exp: - UNDEFINED { $$ = $1; } - | EMPTY { $$ = $1; } - | exp BANG { $$ = new Poincare::Factorial($1, false); } - | number { $$ = $1; } - | symb { $$ = $1; } - | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } - | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } - | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } - | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } - | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); } - | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } - | MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } - | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } -/* MATRICES_ARE_DEFINED */ - | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); delete $2; } - | FUNCTION UNDERSCORE LEFT_BRACE lstData RIGHT_BRACE LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; int totalNumberOfArguments = $4->numberOfOperands()+$7->numberOfOperands(); +term : EMPTY { $$ = $1; } + | symb { $$ = $1; } + | UNDEFINED { $$ = $1; } + | number { $$ = $1; } + | FUNCTION UNDERSCORE LEFT_BRACE lstData RIGHT_BRACE LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; int totalNumberOfArguments = $4->numberOfOperands()+$7->numberOfOperands(); if (!$1->hasValidNumberOfOperands(totalNumberOfArguments)) { delete $1; delete $4; delete $7; YYERROR; }; Poincare::ListData * arguments = new Poincare::ListData(); for (int i = 0; i < $4->numberOfOperands(); i++) { arguments->pushExpression($4->operands()[i]); } for (int i = 0; i < $7->numberOfOperands(); i++) { arguments->pushExpression($7->operands()[i]); } $1->setArgument(arguments, totalNumberOfArguments, false); $4->detachOperands(); delete $4; $7->detachOperands(); delete $7; arguments->detachOperands(); delete arguments;} - | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), false); $3->detachOperands(); delete $3; } + | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), false); $3->detachOperands(); delete $3; } + | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } +/* MATRICES_ARE_DEFINED */ + | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); delete $2; } + ; -final_exp: - exp { $$ = $1; } - | exp STO symb { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Store(terms, false); }; +bang : term { $$ = $1; } + | term BANG { $$ = new Poincare::Factorial($1, false); } + ; + +factor : bang { $$ = $1; } + | bang pow %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } + ; + +pow : factor { $$ = $1; } + | bang POW pow { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } + | bang POW MINUS pow { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Power(terms, false); } + ; + +div : pow { $$ = $1; } + | div DIVIDE pow { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); } + | div DIVIDE MINUS pow { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Division(terms, false); } + ; + +mul : div { $$ = $1; } + | mul MULTIPLY div { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } + | mul MULTIPLY MINUS div { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Multiplication(terms, 2, false); } + ; + +min : mul { $$ = $1; } + | mul MINUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } + | mul MINUS MINUS min { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Subtraction(terms, false); } + ; + +unmin : min { $$ = $1; } + | MINUS min %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } + ; + +exp : unmin { $$ = $1; } + | exp PLUS unmin { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } + ; + +final_exp : exp { $$ = $1; } + | exp STO symb { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Store(terms, false); } + ; %% void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, const char * msg) { From 7770f92df88b118e39aeabfe6c2d16ce1ebe6f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 18 Jan 2018 10:26:38 +0100 Subject: [PATCH 198/459] [poincare] canBeOmittedMultiplicationLeft/RightFactor for layouts. Change-Id: I059226e95cb8d931ee65062965a888f4a06e67db --- poincare/include/poincare/expression_layout.h | 7 +++++++ poincare/src/layout/expression_layout.cpp | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 3cfd319a6..28cf1f1e2 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -95,6 +95,13 @@ public: virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a brother fraction: should the layout be * inserted in the numerator (or denominator)? */ + bool canBeOmittedMultiplicationLeftFactor() const; + bool canBeOmittedMultiplicationRightFactor() const; + /* canBeOmittedMultiplicationLeftFactor and RightFactor return true if the + * layout, next to another layout, might be the factor of a multiplication + * with an omitted multiplication sign. For instance, an absolute value layout + * returns true, because |3|2 means |3|*2. A '+' CharLayout returns false, + * because +'something' nevers means +*'something'. */ virtual bool mustHaveLeftBrother() const { return false; } virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 6c318fb0f..ffec0e9b8 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -282,6 +282,23 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor) { return moveInside(VerticalDirection::Down, cursor); } +bool ExpressionLayout::canBeOmittedMultiplicationLeftFactor() const { + // WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + // isCollapsable is true too. If isCollapsable changes, it might not be the + // case anymore so make sure to modify this function if needed. + int numberOfOpenParentheses = 0; + return isCollapsable(&numberOfOpenParentheses, true); +} + +bool ExpressionLayout::canBeOmittedMultiplicationRightFactor() const { + // WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + // isCollapsable is true and mustHaveLeftBrother is false. If one of these + // functions changes, , it might not be the case anymore so make sure to + // modify canBeOmittedMultiplicationRightFactor if needed. + int numberOfOpenParentheses = 0; + return isCollapsable(&numberOfOpenParentheses, false) && !mustHaveLeftBrother(); +} + void ExpressionLayout::detachChildAtIndex(int i) { ExpressionLayout ** op = const_cast(children()); if (op[i] != nullptr && op[i]->parent() == this) { From 8ffac8f69f33b9b67524125482f636dbeecd5b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 18:07:49 +0100 Subject: [PATCH 199/459] [poincare] Fixed fraction serialization. There was a problem with omitted multiplications: 1/2 3 would be computed as 1/(2*3). Change-Id: Ic8e7ebfaa525c8bbf910d7c93fb7a3ca770a2e44 --- poincare/src/layout/fraction_layout.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 066047caa..4b112cfb7 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -2,6 +2,7 @@ #include "empty_visible_layout.h" #include "horizontal_layout.h" #include +#include #include #include #include @@ -161,10 +162,27 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { int numberOfChar = 0; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + int indexInParent = -1; + if (m_parent) { + indexInParent = m_parent->indexOfChild(this); + } + + // Add a multiplication if omitted. + if (indexInParent > 0 && m_parent->isHorizontal() && m_parent->child(indexInParent - 1)->canBeOmittedMultiplicationLeftFactor()) { + buffer[numberOfChar++] = Ion::Charset::MiddleDot; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + // Write the content of the fraction numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, "/"); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Add a multiplication if omitted. + if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->canBeOmittedMultiplicationRightFactor()) { + buffer[numberOfChar++] = Ion::Charset::MiddleDot; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + buffer[numberOfChar] = 0; return numberOfChar; } From 65666dc35f3a8855c66f27ef00856ed3d58dd8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 17 Jan 2018 18:09:04 +0100 Subject: [PATCH 200/459] [poincare] Fixed vertical offset layout serialization. There was a problem with omitted multiplications: 1^2 3 would be computed as 1^(2*3). Change-Id: Ifc4b0e0bd61fad1b752e1415c6dd0cf3b3b1f3a6 --- poincare/src/layout/vertical_offset_layout.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 6af0a64d6..7f3fac07c 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -1,5 +1,6 @@ #include "vertical_offset_layout.h" #include "empty_visible_layout.h" +#include #include #include #include @@ -206,7 +207,19 @@ int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const } assert(m_type == Type::Superscript); // If the layout is a superscript, write "^(indice)" - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); + int numberOfChar = LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); + + // Add a multiplication if omitted. + int indexInParent = -1; + if (m_parent) { + indexInParent = m_parent->indexOfChild(this); + } + if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->canBeOmittedMultiplicationRightFactor()) { + buffer[numberOfChar++] = Ion::Charset::MiddleDot; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + buffer[numberOfChar] = 0; + return numberOfChar; } ExpressionLayout * VerticalOffsetLayout::indiceLayout() { From 5363eac1489b44b12f71ab66fb5ece2e219fa066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 18 Jan 2018 09:40:24 +0100 Subject: [PATCH 201/459] [poincare] Fixed function operands order in parser. Change-Id: Ieff07d664827a82bdd6fbdda821a4b61feabd795 --- poincare/src/expression_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 90d6584f9..e617edf6a 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -190,8 +190,8 @@ term : EMPTY { $$ = $1; } | FUNCTION UNDERSCORE LEFT_BRACE lstData RIGHT_BRACE LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; int totalNumberOfArguments = $4->numberOfOperands()+$7->numberOfOperands(); if (!$1->hasValidNumberOfOperands(totalNumberOfArguments)) { delete $1; delete $4; delete $7; YYERROR; }; Poincare::ListData * arguments = new Poincare::ListData(); -for (int i = 0; i < $4->numberOfOperands(); i++) { arguments->pushExpression($4->operands()[i]); } for (int i = 0; i < $7->numberOfOperands(); i++) { arguments->pushExpression($7->operands()[i]); } +for (int i = 0; i < $4->numberOfOperands(); i++) { arguments->pushExpression($4->operands()[i]); } $1->setArgument(arguments, totalNumberOfArguments, false); $4->detachOperands(); delete $4; $7->detachOperands(); delete $7; arguments->detachOperands(); delete arguments;} | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), false); $3->detachOperands(); delete $3; } From 440709dace4dfff9f78b737175c4ff134671dd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 18 Jan 2018 10:26:04 +0100 Subject: [PATCH 202/459] [poincare] Better comment for isCollapsable in ExpressionLayout. Change-Id: I944ec90a52b3b69e90c7a75163716c885ef256b4 --- poincare/include/poincare/expression_layout.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 28cf1f1e2..43992af35 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -94,7 +94,9 @@ public: /* Other */ virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a brother fraction: should the layout be - * inserted in the numerator (or denominator)? */ + * inserted in the numerator (or denominator)? For instance, 1+2|3-4 should + * become 1+ 2/3 - 4 when pressing "Divide": a CharLayout is collapsable if + * its char is not +, -, or *. */ bool canBeOmittedMultiplicationLeftFactor() const; bool canBeOmittedMultiplicationRightFactor() const; /* canBeOmittedMultiplicationLeftFactor and RightFactor return true if the From 1ad4e6e74471e96f4e9dceb5d9991dc6189a4cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 18 Jan 2018 17:55:16 +0100 Subject: [PATCH 203/459] [escher/poincare] Remove unneeded layout computation. When moving a cursor in an EditableExpressionView, do not recompute the layout, unless specified otherwise (for instance when entering or exiting a MatrixLayout). Change-Id: Ic2471095d6f6a08014a79f1d9d8fb7d39a1a6864 --- .../include/escher/editable_expression_view.h | 1 + escher/src/editable_expression_view.cpp | 63 ++++++++++++------- poincare/include/poincare/expression_layout.h | 25 ++++---- .../poincare/expression_layout_cursor.h | 8 +-- poincare/src/expression_layout_cursor.cpp | 16 ++--- .../layout/binomial_coefficient_layout.cpp | 20 +++--- .../src/layout/binomial_coefficient_layout.h | 8 +-- poincare/src/layout/bracket_layout.cpp | 8 +-- poincare/src/layout/bracket_layout.h | 4 +- .../src/layout/bracket_left_right_layout.cpp | 8 +-- .../src/layout/bracket_left_right_layout.h | 4 +- poincare/src/layout/char_layout.cpp | 8 +-- poincare/src/layout/char_layout.h | 4 +- poincare/src/layout/condensed_sum_layout.cpp | 28 ++++----- poincare/src/layout/condensed_sum_layout.h | 8 +-- poincare/src/layout/conjugate_layout.cpp | 8 +-- poincare/src/layout/conjugate_layout.h | 4 +- poincare/src/layout/empty_visible_layout.cpp | 8 +-- poincare/src/layout/empty_visible_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 23 +++---- poincare/src/layout/fraction_layout.cpp | 24 +++---- poincare/src/layout/fraction_layout.h | 8 +-- poincare/src/layout/grid_layout.cpp | 20 +++--- poincare/src/layout/grid_layout.h | 8 +-- poincare/src/layout/horizontal_layout.cpp | 46 +++++++------- poincare/src/layout/horizontal_layout.h | 10 +-- poincare/src/layout/integral_layout.cpp | 24 +++---- poincare/src/layout/integral_layout.h | 8 +-- poincare/src/layout/matrix_layout.cpp | 22 ++++--- poincare/src/layout/matrix_layout.h | 8 +-- poincare/src/layout/nth_root_layout.cpp | 16 ++--- poincare/src/layout/nth_root_layout.h | 8 +-- .../layout/parenthesis_left_right_layout.cpp | 8 +-- .../layout/parenthesis_left_right_layout.h | 4 +- poincare/src/layout/sequence_layout.cpp | 24 +++---- poincare/src/layout/sequence_layout.h | 8 +-- .../src/layout/vertical_offset_layout.cpp | 16 ++--- poincare/src/layout/vertical_offset_layout.h | 8 +-- 38 files changed, 280 insertions(+), 250 deletions(-) diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index f4cf92423..84dcd8d9b 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -30,6 +30,7 @@ public: protected: virtual bool privateHandleEvent(Ion::Events::Event event); + bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); ExpressionViewWithCursor m_expressionViewWithCursor; private: EditableExpressionViewDelegate * m_delegate; diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 01159a81a..acc66f38d 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -31,6 +31,21 @@ Toolbox * EditableExpressionView::toolbox() { bool EditableExpressionView::handleEvent(Ion::Events::Event event) { KDSize previousSize = minimalSizeForOptimalDisplay(); + bool shouldRecomputeLayout = false; + if (privateHandleMoveEvent(event, &shouldRecomputeLayout)) { + if (!shouldRecomputeLayout) { + m_expressionViewWithCursor.cursorPositionChanged(); + scrollToCursor(); + return true; + } + reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->editableExpressionViewDidChangeSize(this); + reload(); + } + return true; + } if (privateHandleEvent(event)) { reload(); KDSize newSize = minimalSizeForOptimalDisplay(); @@ -51,6 +66,32 @@ KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); } +bool EditableExpressionView::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { + if (event == Ion::Events::Left) { + return m_expressionViewWithCursor.cursor()->moveLeft(shouldRecomputeLayout); + } + if (event == Ion::Events::Right) { + return m_expressionViewWithCursor.cursor()->moveRight(shouldRecomputeLayout); + } + if (event == Ion::Events::Up) { + return m_expressionViewWithCursor.cursor()->moveUp(shouldRecomputeLayout); + } + if (event == Ion::Events::Down) { + return m_expressionViewWithCursor.cursor()->moveDown(shouldRecomputeLayout); + } + if (event == Ion::Events::ShiftLeft) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); + return true; + } + if (event == Ion::Events::ShiftRight) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + return true; + } + return false; +} + bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { if (m_delegate && m_delegate->editableExpressionViewDidReceiveEvent(this, event)) { return true; @@ -76,28 +117,6 @@ bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { } return true; } - if (event == Ion::Events::Left) { - return m_expressionViewWithCursor.cursor()->moveLeft(); - } - if (event == Ion::Events::Right) { - return m_expressionViewWithCursor.cursor()->moveRight(); - } - if (event == Ion::Events::Up) { - return m_expressionViewWithCursor.cursor()->moveUp(); - } - if (event == Ion::Events::Down) { - return m_expressionViewWithCursor.cursor()->moveDown(); - } - if (event == Ion::Events::ShiftLeft) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); - return true; - } - if (event == Ion::Events::ShiftRight) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - return true; - } if (event == Ion::Events::Division) { m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); return true; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 43992af35..580f89273 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -75,18 +75,20 @@ public: virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ - virtual bool moveLeft(ExpressionLayoutCursor * cursor) = 0; - virtual bool moveRight(ExpressionLayoutCursor * cursor) = 0; + virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) = 0; + virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) = 0; virtual bool moveUp( ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); virtual bool moveDown( ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); - virtual bool moveUpInside(ExpressionLayoutCursor * cursor); - virtual bool moveDownInside(ExpressionLayoutCursor * cursor); + virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr); + virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; @@ -119,6 +121,13 @@ protected: virtual KDSize computeSize() = 0; virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; + virtual void moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultScore); ExpressionLayout * m_parent; KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to @@ -129,13 +138,7 @@ protected: bool m_positioned; private: void detachChildAtIndex(int i); - bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor); - void moveCursorInsideAtDirection ( - VerticalDirection direction, - ExpressionLayoutCursor * cursor, - ExpressionLayout ** childResult, - void * resultPosition, - int * resultScore); + bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; }; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 5cfd89e4a..7145d3c81 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -33,10 +33,10 @@ public: KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position); /* Move */ - bool moveLeft(); - bool moveRight(); - bool moveUp(); - bool moveDown(); + bool moveLeft(bool * shouldRecomputeLayout = nullptr); + bool moveRight(bool * shouldRecomputeLayout); + bool moveUp(bool * shouldRecomputeLayout); + bool moveDown(bool * shouldRecomputeLayout); /* Edition */ void addLayout(ExpressionLayout * layout); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 87f5de8bb..0923f888e 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -25,20 +25,20 @@ KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expre return KDPoint(layoutOrigin.x() + expressionLayout->size().width(), y); } -bool ExpressionLayoutCursor::moveLeft() { - return m_pointedExpressionLayout->moveLeft(this); +bool ExpressionLayoutCursor::moveLeft(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->moveLeft(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveRight() { - return m_pointedExpressionLayout->moveRight(this); +bool ExpressionLayoutCursor::moveRight(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->moveRight(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveUp() { - return m_pointedExpressionLayout->moveUp(this); +bool ExpressionLayoutCursor::moveUp(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->moveUp(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveDown() { - return m_pointedExpressionLayout->moveDown(this); +bool ExpressionLayoutCursor::moveDown(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->moveDown(this, shouldRecomputeLayout); } void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index aec65fd20..93867456a 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -18,7 +18,7 @@ ExpressionLayout * BinomialCoefficientLayout::clone() const { return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); } -bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the children. // Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Left @@ -43,12 +43,12 @@ bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the children. // Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Right @@ -71,27 +71,27 @@ bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Case: kLayout. // Move to nLayout. if (previousLayout == kLayout()) { - return nLayout()->moveUpInside(cursor); + return nLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Case: nLayout. // Move to kLayout. if (previousLayout == nLayout()) { - return kLayout()->moveDownInside(cursor); + return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 30dc3da69..8cfa19323 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -10,10 +10,10 @@ class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "binomial"); } diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 38fd0b400..9fe511f88 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -25,7 +25,7 @@ void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. // Go Left of the brackets. if (operandLayout() @@ -47,12 +47,12 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the brackets. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the operand. // Go Right of the brackets. if (operandLayout() @@ -75,7 +75,7 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. cursor->setPointedExpressionLayout(this); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 94b63398f..b9a746f36 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -10,8 +10,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: ExpressionLayout * operandLayout(); diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_left_right_layout.cpp index f39263fff..540a4ce89 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_left_right_layout.cpp @@ -18,7 +18,7 @@ void BracketLeftRightLayout::invalidAllSizesPositionsAndBaselines() { ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -30,12 +30,12 @@ bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -47,7 +47,7 @@ bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 98cf4e875..7dfc9708a 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -9,8 +9,8 @@ class BracketLeftRightLayout : public StaticLayoutHierarchy<0> { public: BracketLeftRightLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; protected: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index b4e67dc52..0dde197c6 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -18,7 +18,7 @@ ExpressionLayout * CharLayout::clone() const { return layout; } -bool CharLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool CharLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -29,12 +29,12 @@ bool CharLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool CharLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool CharLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -45,7 +45,7 @@ bool CharLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index cbdb775b8..37ebd3692 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -17,8 +17,8 @@ public: char character() { return m_char; } KDText::FontSize fontSize() const { return m_fontSize; } - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index a7a511e9e..33058438e 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -10,7 +10,7 @@ ExpressionLayout * CondensedSumLayout::clone() const { return layout; } -bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the bounds. // Go Left of the sum. if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) @@ -37,18 +37,18 @@ bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(baseLayout()); cursor->setPointedExpressionLayout(baseLayout()); - return baseLayout()->moveLeft(cursor); + return baseLayout()->moveLeft(cursor, shouldRecomputeLayout); } // Case: Left. // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the bounds. // Go Left of the operand. if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) @@ -69,7 +69,7 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } @@ -85,16 +85,16 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the subscript layout, move it to the superscript. if (subscriptLayout() && previousLayout == subscriptLayout()) { assert(superscriptLayout() != nullptr); - return superscriptLayout()->moveUpInside(cursor); + return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the superscript. if (baseLayout() @@ -102,16 +102,16 @@ bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayou && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(superscriptLayout() != nullptr); - return superscriptLayout()->moveUpInside(cursor); + return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the superscript layout, move it to the subscript. if (superscriptLayout() && previousLayout == superscriptLayout()) { assert(subscriptLayout() != nullptr); - return subscriptLayout()->moveUpInside(cursor); + return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the subscript. if (baseLayout() @@ -119,9 +119,9 @@ bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLay && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(subscriptLayout() != nullptr); - return subscriptLayout()->moveUpInside(cursor); + return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 2647474cd..d7a236e4e 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -10,10 +10,10 @@ class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "sum"); } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 7323e1fd7..15e90362d 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -27,7 +27,7 @@ void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. // Move Left. if (operandLayout() @@ -49,12 +49,12 @@ bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the operand. // Move Right. if (operandLayout() @@ -76,7 +76,7 @@ bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index f4846619f..896e777a0 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -11,8 +11,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index bddbda688..5e8517611 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -40,7 +40,7 @@ void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } } -bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -51,12 +51,12 @@ bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -67,7 +67,7 @@ bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 4d454d97b..0bab3e9ff 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -16,8 +16,8 @@ public: ExpressionLayout * clone() const override; void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index ffec0e9b8..936c7c9fd 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -260,26 +260,26 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (m_parent) { - return m_parent->moveUp(cursor, this, previousLayout); + return m_parent->moveUp(cursor, shouldRecomputeLayout, this, previousLayout); } return false; } -bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor) { - return moveInside(VerticalDirection::Up, cursor); +bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + return moveInside(VerticalDirection::Up, cursor, shouldRecomputeLayout); } -bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (m_parent) { - return m_parent->moveDown(cursor, this, previousLayout); + return m_parent->moveDown(cursor, shouldRecomputeLayout, this, previousLayout); } return false; } -bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor) { - return moveInside(VerticalDirection::Down, cursor); +bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); } bool ExpressionLayout::canBeOmittedMultiplicationLeftFactor() const { @@ -310,7 +310,7 @@ void ExpressionLayout::detachChildAtIndex(int i) { m_baselined = false; } -bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor) { +bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; @@ -318,7 +318,7 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC // than this initial value of score. int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; - moveCursorInsideAtDirection(direction, cursor, childResultPtr, &resultPosition, &resultScore); + moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResultPtr, &resultPosition, &resultScore); // If there is a valid result if (*childResultPtr == nullptr) { @@ -332,6 +332,7 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC void ExpressionLayout::moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout, ExpressionLayout ** childResult, void * resultPosition, int * resultScore) @@ -361,7 +362,7 @@ void ExpressionLayout::moveCursorInsideAtDirection ( if (layoutIsUnderOrAbove || layoutContains) { int childIndex = 0; while (child(childIndex++)) { - editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, childResult, castedResultPosition, resultScore); + editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); } } } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 4b112cfb7..82e6956ff 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -72,7 +72,7 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the numerator or the denominator. // Go Left of the fraction. if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) @@ -94,12 +94,12 @@ bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the numerator or the denominator. // Go Right of the fraction. if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) @@ -121,37 +121,37 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside denominator, move it to the numerator. if (denominatorLayout() && previousLayout == denominatorLayout()) { assert(numeratorLayout() != nullptr); - return numeratorLayout()->moveUpInside(cursor); + return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the numerator. if (cursor->pointedExpressionLayout() == this){ assert(numeratorLayout() != nullptr); - return numeratorLayout()->moveUpInside(cursor); + return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside numerator, move it to the denominator. if (numeratorLayout() && previousLayout == numeratorLayout()) { assert(denominatorLayout() != nullptr); - return denominatorLayout()->moveDownInside(cursor); + return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the denominator. if (cursor->pointedExpressionLayout() == this){ assert(denominatorLayout() != nullptr); - return denominatorLayout()->moveDownInside(cursor); + return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 7c551df14..2eb341453 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -11,10 +11,10 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index e7af88579..b5d9f9934 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -21,7 +21,7 @@ ExpressionLayout * GridLayout::clone() const { return layout; } -bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right. // Go to the last entry. if (cursor->pointedExpressionLayout() == this @@ -52,12 +52,12 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool GridLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left. // Go to the first entry. if (cursor->pointedExpressionLayout() == this @@ -89,29 +89,29 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is child that is not on the top row, move it inside the upper // neighbourg. int childIndex = indexOfChild(previousLayout); if (childIndex >- 1 && !childIsTopOfGrid(childIndex)) { - return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor); + return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is child that is not on the bottom row, move it inside the // lower neighbourg. int childIndex = indexOfChild(previousLayout); if (childIndex >- 1 && !childIsBottomOfGrid(childIndex)) { - return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor); + return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index d7e2915f6..ad80b8f49 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -13,10 +13,10 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index e0e27198d..baf038e23 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -177,13 +177,13 @@ void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, addChildAtIndex(eL, newIndex); } -bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left. // Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } @@ -194,14 +194,14 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } ExpressionLayout * lastChild = editableChild(numberOfChildren()-1); assert(lastChild != nullptr); cursor->setPointedExpressionLayout(lastChild); - return lastChild->moveLeft(cursor); + return lastChild->moveLeft(cursor, shouldRecomputeLayout); } // Case: The cursor is Left of a child. @@ -213,7 +213,7 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Ask the parent. if (m_parent) { cursor->setPointedExpressionLayout(this); - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } @@ -221,16 +221,16 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Go to its left brother and move Left. cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return editableChild(childIndex-1)->moveLeft(cursor); + return editableChild(childIndex-1)->moveLeft(cursor, shouldRecomputeLayout); } -bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right. // Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } @@ -241,14 +241,14 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); cursor->setPointedExpressionLayout(firstChild); - return firstChild->moveRight(cursor); + return firstChild->moveRight(cursor, shouldRecomputeLayout); } // Case: The cursor is Right of a child. @@ -260,7 +260,7 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. if (m_parent) { cursor->setPointedExpressionLayout(this); - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } @@ -268,15 +268,15 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor) { // Go to its right brother and move Right. cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return editableChild(childIndex+1)->moveRight(cursor); + return editableChild(childIndex+1)->moveRight(cursor, shouldRecomputeLayout); } -bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - return moveVertically(ExpressionLayout::VerticalDirection::Up, cursor, previousLayout, previousPreviousLayout); +bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + return moveVertically(ExpressionLayout::VerticalDirection::Up, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, previousLayout, previousPreviousLayout); +bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { @@ -341,14 +341,14 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Prevent looping fom child to parent if (previousPreviousLayout == this) { if (direction == ExpressionLayout::VerticalDirection::Up) { - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } assert(direction == ExpressionLayout::VerticalDirection::Down); - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } // If the cursor Left or Right of a child, try moving it up from its brother. int previousLayoutIndex = indexOfChild(previousLayout); @@ -368,10 +368,10 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct ExpressionLayoutCursor::Position previousPosition = cursor->position(); cursor->setPointedExpressionLayout(brother); cursor->setPosition(newPosition); - if (direction == ExpressionLayout::VerticalDirection::Up && brother->moveUp(cursor, this, previousLayout)) { + if (direction == ExpressionLayout::VerticalDirection::Up && brother->moveUp(cursor, shouldRecomputeLayout, this, previousLayout)) { return true; } - if (direction == ExpressionLayout::VerticalDirection::Down && brother->moveDown(cursor, this, previousLayout)) { + if (direction == ExpressionLayout::VerticalDirection::Down && brother->moveDown(cursor, shouldRecomputeLayout, this, previousLayout)) { return true; } cursor->setPointedExpressionLayout(previousPointedLayout); @@ -379,10 +379,10 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct } } if (direction == ExpressionLayout::VerticalDirection::Up) { - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } assert(direction == ExpressionLayout::VerticalDirection::Down); - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 8516fa977..f6185545f 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -22,10 +22,10 @@ public: void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; @@ -45,7 +45,7 @@ protected: void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); + bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); }; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 505b14cbc..48941a195 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -46,7 +46,7 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left the upper or lower bound. // Go Left of the integral. if (((upperBoundLayout() @@ -81,12 +81,12 @@ bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left of the brackets. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right the upper or lower bound. // Go Left of the integrand. if (((upperBoundLayout() @@ -121,16 +121,16 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor); + return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() @@ -138,16 +138,16 @@ bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor); + return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && previousLayout == upperBoundLayout()) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor); + return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() @@ -155,9 +155,9 @@ bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor); + return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 35e9769df..56cb14999 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -17,10 +17,10 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 82467984e..753b3e7b4 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -17,7 +17,7 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } -bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { int childIndex = indexOfChild(cursor->pointedExpressionLayout()); if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Left @@ -27,6 +27,7 @@ bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Remove the grey squares of the grid, then go left of the grid. assert(hasGreySquares()); removeGreySquares(); + *shouldRecomputeLayout = true; cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; @@ -39,15 +40,16 @@ bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor) { { assert(!hasGreySquares()); addGreySquares(); + *shouldRecomputeLayout = true; ExpressionLayout * lastChild = editableChild((m_numberOfColumns-1)*(m_numberOfRows-1)); assert(lastChild != nullptr); cursor->setPointedExpressionLayout(lastChild); return true; } - return GridLayout::moveLeft(cursor); + return GridLayout::moveLeft(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left. // Add the grey squares to the matrix,, then go to the first entry. if (cursor->pointedExpressionLayout() == this @@ -55,6 +57,7 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) { { assert(!hasGreySquares()); addGreySquares(); + *shouldRecomputeLayout = true; assert(m_numberOfColumns*m_numberOfRows >= 1); ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); @@ -73,25 +76,28 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); assert(hasGreySquares()); removeGreySquares(); + *shouldRecomputeLayout = true; return true; } - return GridLayout::moveRight(cursor); + return GridLayout::moveRight(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor) { - bool result = GridLayout::moveUpInside(cursor); +bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + bool result = GridLayout::moveUpInside(cursor, shouldRecomputeLayout); if (result) { assert(!hasGreySquares()); addGreySquares(); + *shouldRecomputeLayout = true; } return result; } -bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor) { - bool result = GridLayout::moveDownInside(cursor); +bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + bool result = GridLayout::moveDownInside(cursor, shouldRecomputeLayout); if (result) { assert(!hasGreySquares()); addGreySquares(); + *shouldRecomputeLayout = true; } return result; } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 8208d11b3..2a4633b6d 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -11,10 +11,10 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUpInside(ExpressionLayoutCursor * cursor) override; - bool moveDownInside(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 8c14bfe19..291171463 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -45,7 +45,7 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the radicand. // Go the index if there is one, else go Left of the root. if (radicandLayout() @@ -81,12 +81,12 @@ bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the radicand. // Go the Right of the root. if (radicandLayout() @@ -123,12 +123,12 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() @@ -148,10 +148,10 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * p cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { if (indexLayout() && previousLayout == indexLayout()) { // If the cursor is Right of the index, move it to the radicand. if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { @@ -167,7 +167,7 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * return true; } } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } static_assert('\x90' == Ion::Charset::Root, "Unicode error"); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 86a840b55..e97d05595 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -17,10 +17,10 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 060596fac..b7d8f819e 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -18,7 +18,7 @@ void ParenthesisLeftRightLayout::invalidAllSizesPositionsAndBaselines() { ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -30,12 +30,12 @@ bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -47,7 +47,7 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 8596d219b..0dc125452 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -9,8 +9,8 @@ class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLeftRightLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index b9a91e85b..94a64aa37 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -20,7 +20,7 @@ void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the bounds. // Go Left of the sequence. if (cursor->position() == ExpressionLayoutCursor::Position::Left @@ -55,12 +55,12 @@ bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Case: Left. // Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the bounds. // Go Left of the argument. if (cursor->position() == ExpressionLayoutCursor::Position::Right @@ -96,40 +96,40 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor) { // Case: Right. // Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor); + return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the upper bound. if (argumentLayout() && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor); + return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && previousLayout == upperBoundLayout()) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor); + return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor); + return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } char SequenceLayout::XNTChar() const { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index ef92f3f68..f7c77d5b2 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -11,10 +11,10 @@ public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; char XNTChar() const override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 7f3fac07c..89b25fb24 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -57,7 +57,7 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::backspaceAtCursor(cursor); } -bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor) { +bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the indice. // Go Left. if (indiceLayout() @@ -81,12 +81,12 @@ bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor); + return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } -bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor) { +bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the indice. // Go Right. if (indiceLayout() @@ -109,12 +109,12 @@ bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor) { // Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor); + return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; } -bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Case: Superscript. if (m_type == VerticalOffsetLayout::Type::Superscript) { // Case: Right. @@ -145,10 +145,10 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, ExpressionLay cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveUp(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Case: Subscript. if (m_type == VerticalOffsetLayout::Type::Subscript) { // Case: Right. @@ -178,7 +178,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, ExpressionL cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveDown(cursor, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index bf3242cb7..75ca9f1e3 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -14,10 +14,10 @@ public: VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor) override; - bool moveRight(ExpressionLayoutCursor * cursor) override; - bool moveUp(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; bool mustHaveLeftBrother() const override { return true; } protected: From 865060e2e910f0e7d2e447f96808e6cf628e4dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 09:58:59 +0100 Subject: [PATCH 204/459] [poincare] Add asserts in removePointedChildAtIndexAndMoveCursor. Change-Id: Ifc49b79f18ad53a96a4675d1c6edad69e1c6258f --- poincare/src/layout/conjugate_layout.cpp | 1 + poincare/src/layout/dynamic_layout_hierarchy.cpp | 2 +- poincare/src/layout/expression_layout.cpp | 1 + poincare/src/layout/matrix_layout.cpp | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 15e90362d..e9c3fda59 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -95,6 +95,7 @@ void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChil void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); + assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 8a54de8b3..3ed6dd802 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -116,7 +116,7 @@ void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemov void DynamicLayoutHierarchy::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert(cursor->pointedExpressionLayout() == child(index)); + assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); if (numberOfChildren() == 1) { if (m_parent) { if (!deleteAfterRemoval) { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 936c7c9fd..9faf5b7e0 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -205,6 +205,7 @@ void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); + assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); removeChildAtIndex(index, deleteAfterRemoval); if (index < numberOfChildren()) { cursor->setPointedExpressionLayout(editableChild(index)); diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 753b3e7b4..273fd1d3c 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -125,6 +125,7 @@ void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); + assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); } From 511d9e3adaa5f7bc6aa9f5318a5fe3924055d491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 10:00:06 +0100 Subject: [PATCH 205/459] [poincare] Better handling of grey squares in MatrixLayout. Add/remove grey squares when the cursor enters or leaves the matrix on modeUp or moveDown. Recompute the layout if the cursor enters or leaves a matrix: adding or removing grey squares changes the layout of the expression. Change-Id: I356f660cbf96883bd5bf1c4bd2cd160a921a29e7 --- poincare/src/layout/matrix_layout.cpp | 58 ++++++++++++++++++++++++++- poincare/src/layout/matrix_layout.h | 9 +++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 273fd1d3c..fbec5bd3a 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -82,9 +82,43 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom return GridLayout::moveRight(cursor, shouldRecomputeLayout); } +bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + bool shouldRemoveGreySquares = false; + int childIndex = indexOfChild(previousLayout); + if (childIndex >- 1 && childIsTopOfGrid(childIndex)) { + // The cursor is leaving the matrix, so remove the grey squares. + shouldRemoveGreySquares = true; + } + bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + if (returnValue && shouldRemoveGreySquares) { + assert(hasGreySquares()); + removeGreySquares(); + *shouldRecomputeLayout = true; + } + return returnValue; +} + +bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + bool shouldRemoveGreySquares = false; + int childIndex = indexOfChild(previousLayout); + if (childIndex >- 1 && childIsBottomOfGrid(childIndex)) { + // The cursor is leaving the matrix, so remove the grey squares. + shouldRemoveGreySquares = true; + } + bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + if (returnValue && shouldRemoveGreySquares) { + assert(hasGreySquares()); + removeGreySquares(); + *shouldRecomputeLayout = true; + } + return returnValue; +} + bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool result = GridLayout::moveUpInside(cursor, shouldRecomputeLayout); - if (result) { + if (result && cursor->pointedExpressionLayout() != this) { + // Add the grey squares if the cursor is pointing at a matrix descendant, + // not at the matrix itself. assert(!hasGreySquares()); addGreySquares(); *shouldRecomputeLayout = true; @@ -94,7 +128,9 @@ bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRe bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool result = GridLayout::moveDownInside(cursor, shouldRecomputeLayout); - if (result) { + if (result && cursor->pointedExpressionLayout() != this) { + // Add the grey squares if the cursor is pointing at a matrix descendant, + // not at the matrix itself. assert(!hasGreySquares()); addGreySquares(); *shouldRecomputeLayout = true; @@ -239,6 +275,24 @@ ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, return GridLayout::positionOfChild(child).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); } +void MatrixLayout::moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultScore) +{ + GridLayout::moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResult, resultPosition, resultScore); + if (*childResult != this) { + // Add the grey squares if the cursor is pointing at a matrix descendant, + // not at the matrix itself. + assert(!hasGreySquares()); + addGreySquares(); + *shouldRecomputeLayout = true; + } +} + bool MatrixLayout::isRowEmpty(int index) const { assert(index >= 0 && index < m_numberOfRows); for (int i = index * m_numberOfColumns; i < (index+1) * m_numberOfColumns; i++) { diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 2a4633b6d..78139be13 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -13,6 +13,8 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; @@ -36,6 +38,13 @@ protected: KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: + void moveCursorInsideAtDirection ( + VerticalDirection direction, + ExpressionLayoutCursor * cursor, + bool * shouldRecomputeLayout, + ExpressionLayout ** childResult, + void * resultPosition, + int * resultScore) override; void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; From 7094bcef75c409ea56fac5efc1cc75b2bb2a5664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 15:38:49 +0100 Subject: [PATCH 206/459] [escher] EditableExpressionView handles Paste events. Change-Id: Ie23fe49a4b300592ffb77c5548305d1c50279dd1 --- escher/src/editable_expression_view.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index acc66f38d..a4de32044 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -161,6 +162,13 @@ bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { m_expressionViewWithCursor.cursor()->performBackspace(); return true; } + if (event == Ion::Events::Paste) { + if (!isEditing()) { + setEditing(true); + } + insertLayoutFromTextAtCursor(Clipboard::sharedClipboard()->storedText()); + return true; + } return false; } From a6f93478cde61f0fe2b229e63afd3fe19c18c135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 15:58:07 +0100 Subject: [PATCH 207/459] [poincare] Fix 1/2 3/4 serialization bug. The omitted multiplication fix that serialized "1 2/3 4" into "1*2/3*4" caused a bug and serialized "1/2 3/4" into "1/2**3/4", as well as "1^2 3/4" into "1^(2)**3/4". Change-Id: I59b55a2f13e6eceee68c7e52169c14918391f235 --- poincare/include/poincare/expression_layout.h | 4 ++-- poincare/src/layout/fraction_layout.h | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 580f89273..38ef59c82 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -100,12 +100,12 @@ public: * become 1+ 2/3 - 4 when pressing "Divide": a CharLayout is collapsable if * its char is not +, -, or *. */ bool canBeOmittedMultiplicationLeftFactor() const; - bool canBeOmittedMultiplicationRightFactor() const; + virtual bool canBeOmittedMultiplicationRightFactor() const; /* canBeOmittedMultiplicationLeftFactor and RightFactor return true if the * layout, next to another layout, might be the factor of a multiplication * with an omitted multiplication sign. For instance, an absolute value layout * returns true, because |3|2 means |3|*2. A '+' CharLayout returns false, - * because +'something' nevers means +*'something'. */ + * because +'something' nevers means +*'something'. */ virtual bool mustHaveLeftBrother() const { return false; } virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 2eb341453..02562db82 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -16,6 +16,12 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + bool canBeOmittedMultiplicationRightFactor() const override { return false; } + /* WARNING: We need to override this function, else 1/2 3/4 would be + * serialized as 1/2**3/4, as the two Fraction layouts think their brother is + * an omitted multiplication layout factor. We have the same problem with + * 2^3 1/2 being serialized as 2^3**1/2, so must override the Right version + * and not canBeOmittedMultiplicationLeftFactor. */ protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; From 2cb895666509e758f87b5947c2264298be789cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 16:18:55 +0100 Subject: [PATCH 208/459] [apps/math_toolbox] Remove the pointedPath from ToolboxMessageTree. Change-Id: I2deb6564321da13ea27975216aa949b68298533c --- apps/math_toolbox.cpp | 10 ++-------- escher/include/escher/toolbox_message_tree.h | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 3910a60c0..6a82fc083 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -73,7 +73,6 @@ const ToolboxMessageTree predictionChildren[3] = { ToolboxMessageTree(I18n::Message::PredictionCommandWithArg, I18n::Message::Prediction, I18n::Message::PredictionCommandWithArg), ToolboxMessageTree(I18n::Message::ConfidenceCommandWithArg, I18n::Message::Confidence, I18n::Message::ConfidenceCommandWithArg)}; -const int pointedLayoutPathLog[] = {3,0}; #if LIST_ARE_DEFINED const ToolboxMessageTree menu[12] = { #elif MATRICES_ARE_DEFINED @@ -83,7 +82,7 @@ const ToolboxMessageTree menu[10] = { #endif ToolboxMessageTree(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue, I18n::Message::AbsCommandWithArg), ToolboxMessageTree(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot, I18n::Message::RootCommandWithArg), - ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg, nullptr, 0, const_cast(&pointedLayoutPathLog[0]), 2), + ToolboxMessageTree(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm, I18n::Message::LogCommandWithArg), ToolboxMessageTree(I18n::Message::Calculation, I18n::Message::Default, I18n::Message::Default, calculChildren, 4), ToolboxMessageTree(I18n::Message::ComplexNumber, I18n::Message::Default, I18n::Message::Default, complexChildren, 5), ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), @@ -131,12 +130,7 @@ void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageT ExpressionLayout * resultLayout = resultExpression->createLayout(); // Find the pointed layout. ExpressionLayout * pointedLayout = resultLayout; - if (messageTree->pointedPath() != nullptr) { - for (int i = 0; i < messageTree->pointedPathLength(); i++) { - assert(messageTree->pointedPath()[i] < pointedLayout->numberOfChildren()); - pointedLayout = pointedLayout->editableChild(messageTree->pointedPath()[i]); - } - } else if (resultLayout->isHorizontal()) { + if (resultLayout->isHorizontal()) { // If the layout is horizontal, pick the first open parenthesis. for (int i = 0; i < resultLayout->numberOfChildren(); i++) { if (resultLayout->editableChild(i)->isLeftParenthesis()) { diff --git a/escher/include/escher/toolbox_message_tree.h b/escher/include/escher/toolbox_message_tree.h index 062271417..48d027403 100644 --- a/escher/include/escher/toolbox_message_tree.h +++ b/escher/include/escher/toolbox_message_tree.h @@ -6,26 +6,20 @@ class ToolboxMessageTree : public MessageTree { public: - constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0, int * pointedLayoutPath = nullptr, int pointedLayoutPathLength = 0) : + constexpr ToolboxMessageTree(I18n::Message label = (I18n::Message)0, I18n::Message text = (I18n::Message)0, I18n::Message insertedText = (I18n::Message)0, const ToolboxMessageTree * children = nullptr, int numberOfChildren = 0) : MessageTree(label, numberOfChildren), m_children(children), m_text(text), - m_insertedText(insertedText), - m_pointedLayoutPath(pointedLayoutPath), - m_pointedLayoutPathLength(pointedLayoutPathLength) + m_insertedText(insertedText) { }; const MessageTree * children(int index) const override { return &m_children[index]; } I18n::Message text() const { return m_text; } I18n::Message insertedText() const { return m_insertedText; } - int * pointedPath() const { return m_pointedLayoutPath; } - int pointedPathLength() const { return m_pointedLayoutPathLength; } private: const ToolboxMessageTree * m_children; I18n::Message m_text; I18n::Message m_insertedText; - int * m_pointedLayoutPath; - int m_pointedLayoutPathLength; }; #endif From f3e6b104107b86007c101197371696f97cccdc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 16:24:05 +0100 Subject: [PATCH 209/459] [apps/math_toolbox] Handle const char * when selecting a leaf. Else, there would be a problem with sequence_toolbox, where not all toolbox leaves are message trees. Change-Id: Ib4968aad37f6a835b1ea4d77efac2ae1bd19c7ce --- apps/code/app.cpp | 4 ++-- apps/code/variable_box_controller.cpp | 4 ++-- apps/math_toolbox.cpp | 28 +++++++++++++-------------- apps/math_toolbox.h | 6 +++--- apps/shared/toolbox_helpers.cpp | 14 ++++++++------ apps/shared/toolbox_helpers.h | 5 +++-- 6 files changed, 31 insertions(+), 30 deletions(-) diff --git a/apps/code/app.cpp b/apps/code/app.cpp index f59b1b285..9b9d6402a 100644 --- a/apps/code/app.cpp +++ b/apps/code/app.cpp @@ -47,7 +47,7 @@ App::App(Container * container, Snapshot * snapshot) : // insertText() also moves the cursor. We need to re-move it to the // position we want (which is after the first parenthesis or before the // first point). - int deltaCursorLocation = - textArea->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(text); + int deltaCursorLocation = - textArea->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommandText(text); // WARNING: This is a dirty and only works because the cursor location we // want is always on the first line of the text we insert. Because of the // auto indentation, it would be difficult to compute the wanted cursor @@ -59,7 +59,7 @@ App::App(Container * container, Snapshot * snapshot) : if (!textField->isEditing()) { textField->setEditing(true); } - int newCursorLocation = textField->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(text); + int newCursorLocation = textField->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommandText(text); if (textField->insertTextAtLocation(text, textField->cursorLocation())) { textField->setCursorLocation(newCursorLocation); }}), diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index 9684642aa..81127b78e 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -128,13 +128,13 @@ void VariableBoxController::ContentViewController::insertTextInCaller(const char } int previousCursorLocation = m_textFieldCaller->cursorLocation(); m_textFieldCaller->insertTextAtLocation(commandBuffer, previousCursorLocation); - m_textFieldCaller->setCursorLocation(previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(commandBuffer)); + m_textFieldCaller->setCursorLocation(previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommandText(commandBuffer)); return; } if (m_textAreaCaller != nullptr) { int previousCursorLocation = m_textAreaCaller->cursorLocation(); m_textAreaCaller->insertText(commandBuffer); - int deltaCursorLocation = - m_textAreaCaller->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(commandBuffer); + int deltaCursorLocation = - m_textAreaCaller->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommandText(commandBuffer); m_textAreaCaller->moveCursor(deltaCursorLocation); } } diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 6a82fc083..dc11829a7 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -115,15 +115,14 @@ void MathToolbox::setSenderAndAction(Responder * sender, Action action) { m_action = action; } -void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageTree * messageTree) { +void MathToolbox::actionForEditableExpressionView(void * sender, const char * text) { EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); - // Translate the message and replace the arguments with Empty chars. - const char * textToInsert = I18n::translate(messageTree->insertedText()); - int strippedTextToInsertMaxLength = strlen(textToInsert); - char strippedTextToInsert[strlen(textToInsert)]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert, strippedTextToInsertMaxLength); + // Replace the arguments with Empty chars. + int textToInsertMaxLength = strlen(text); + char textToInsert[textToInsertMaxLength]; + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandText(text, textToInsert, textToInsertMaxLength); // Create the layout - Expression * resultExpression = Expression::parse(strippedTextToInsert); + Expression * resultExpression = Expression::parse(textToInsert); if (resultExpression == nullptr) { return; } @@ -146,25 +145,24 @@ void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageT expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); } -void MathToolbox::actionForTextField(void * sender, ToolboxMessageTree * messageTree) { +void MathToolbox::actionForTextField(void * sender, const char * text) { TextField * textFieldSender = static_cast(sender); if (!textFieldSender->isEditing()) { textFieldSender->setEditing(true); } - const char * textToInsert = I18n::translate(messageTree->insertedText()); - int textToInsertLength = strlen(textToInsert); - char strippedTextToInsert[textToInsertLength]; + int maxTextToInsertLength = strlen(text); + char textToInsert[maxTextToInsertLength]; // Translate the message and remove the arguments. - Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert, textToInsertLength); - textFieldSender->insertTextAtLocation(strippedTextToInsert, textFieldSender->cursorLocation()); - int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedTextToInsert); + Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength); + textFieldSender->insertTextAtLocation(textToInsert, textFieldSender->cursorLocation()); + int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommandText(text); textFieldSender->setCursorLocation(newCursorLocation); } bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { ToolboxMessageTree * messageTree = selectedMessageTree; m_selectableTableView.deselectTable(); - m_action(sender(), messageTree); + m_action(sender(), I18n::translate(messageTree->insertedText())); app()->dismissModalViewController(); return true; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index dbcc8e2cd..2f607863c 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -8,11 +8,11 @@ class MathToolbox : public Toolbox { public: - typedef void (*Action)(void * sender, ToolboxMessageTree * messageTree); + typedef void (*Action)(void * sender, const char * text); MathToolbox(); void setSenderAndAction(Responder * sender, Action action); - static void actionForEditableExpressionView(void * sender, ToolboxMessageTree * messageTree); - static void actionForTextField(void * sender, ToolboxMessageTree * messageTree); + static void actionForEditableExpressionView(void * sender, const char * text); + static void actionForTextField(void * sender, const char * text); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index 268162c8d..6186dce33 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -7,7 +7,7 @@ namespace Shared { namespace ToolboxHelpers { -int CursorIndexInCommand(const char * text) { +int CursorIndexInCommandText(const char * text) { for (size_t i = 0; i < strlen(text); i++) { if (text[i] == '(' || text[i] == '\'') { return i + 1; @@ -20,8 +20,7 @@ int CursorIndexInCommand(const char * text) { } void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { - const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer, bufferSize); + TextToInsertForCommandText(I18n::translate(message), buffer, bufferSize); } void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize) { @@ -58,7 +57,11 @@ void TextToInsertForCommandText(const char * command, char * buffer, int bufferS } void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { - if (message == I18n::Message::MatrixCommandWithArg) { + TextToParseIntoLayoutForCommandText(I18n::translate(message), buffer, bufferSize); +} + +void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize) { + if (command == I18n::translate(I18n::Message::MatrixCommandWithArg)) { assert(bufferSize >= 6); // Handle a new matrix command. buffer[0] = '['; @@ -69,8 +72,7 @@ void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer buffer[5] = 0; return; } - const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer, bufferSize); + TextToInsertForCommandText(command, buffer, bufferSize); size_t bufferLength = strlen(buffer); for (size_t i = 0; i < bufferLength; i++) { if (buffer[i] == '(' || buffer[i] == '[' || buffer[i] == ',') { diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index d051f5847..0065993a2 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -6,8 +6,8 @@ namespace Shared { namespace ToolboxHelpers { -int CursorIndexInCommand(const char * text); -/* Returns the index of the cursor position in a Command, which is the smallest +int CursorIndexInCommandText(const char * text); +/* Returns the index of the cursor position in a command, which is the smallest * index between : * - After the first open parenthesis * - The end of the text */ @@ -18,6 +18,7 @@ void TextToInsertForCommandText(const char * command, char * buffer, int bufferS /* Removes the arguments from a command: * - Removes text between parentheses or brackets, except commas */ void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize); +void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize); /* Removes the arguments from a command and replaces them with empty chars. */ } From 251c4d01afe1c3447b3e2d2c330307aa09cfed30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 16:42:05 +0100 Subject: [PATCH 210/459] [apps/sequence] Fix math_toolbox wrong functions calls. Change-Id: I0b7871e87ea64ef9fbd008d9fb3e6d4cce2e97ca --- apps/math_toolbox.h | 2 +- apps/sequence/list/sequence_toolbox.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 2f607863c..02be3effa 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -20,8 +20,8 @@ protected: MessageTableCellWithChevron* nodeCellAtIndex(int index) override; int maxNumberOfDisplayedRows() override; constexpr static int k_maxNumberOfDisplayedRows = 6; // = 240/40 -private: Action m_action; +private: MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows]; }; diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index fddc7d061..f4346311d 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -114,9 +114,8 @@ void SequenceToolbox::setExtraCells(const char * sequenceName, int recurrenceDep bool SequenceToolbox::selectAddedCell(int selectedRow){ int bufferSize = 10; char buffer[bufferSize]; - int currentChar = m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); - textFieldSender()->insertTextAtLocation(buffer, textFieldSender()->cursorLocation()); - textFieldSender()->setCursorLocation(textFieldSender()->cursorLocation()+currentChar); + m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); + m_action(sender(), buffer); app()->dismissModalViewController(); return true; } From 64efb45c2487b7fa299d593168fd471784dca5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 17:30:47 +0100 Subject: [PATCH 211/459] [apps/math_toolbox] Cleaner matrix layout insertion. Change-Id: I5c51eb353ac848334626e6ffcaf71f3b94534b2e --- apps/math_toolbox.cpp | 2 +- apps/shared.universal.i18n | 1 + apps/shared/toolbox_helpers.cpp | 15 ++------------- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index dc11829a7..a91e93daf 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -37,7 +37,7 @@ const ToolboxMessageTree arithmeticChildren[4] = { #if MATRICES_ARE_DEFINED const ToolboxMessageTree matricesChildren[6] = { - ToolboxMessageTree(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, I18n::Message::MatrixCommandWithArg), + ToolboxMessageTree(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, I18n::Message::MatrixCommand), ToolboxMessageTree(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse, I18n::Message::InverseCommandWithArg), ToolboxMessageTree(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant, I18n::Message::DeterminantCommandWithArg), ToolboxMessageTree(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose, I18n::Message::TransposeCommandWithArg), diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 1f06a778b..d8147eaf0 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -32,6 +32,7 @@ LcmCommandWithArg = "lcm(p,q)" LeftIntegralFirstLegend = "P(X≤" LeftIntegralSecondLegend = ")=" LogCommandWithArg = "log(x,a)" +MatrixCommand = "[[]]" MatrixCommandWithArg = "[[1,2][3,4]]" MaxCommandWithArg = "max(L)" MinCommandWithArg = "min(L)" diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index 6186dce33..33c7b4461 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -13,7 +13,7 @@ int CursorIndexInCommandText(const char * text) { return i + 1; } if (text[i] == ']') { - return (i - 1) > 0 ? i - 1 : 0; + return i; } } return strlen(text); @@ -61,21 +61,10 @@ void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer } void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize) { - if (command == I18n::translate(I18n::Message::MatrixCommandWithArg)) { - assert(bufferSize >= 6); - // Handle a new matrix command. - buffer[0] = '['; - buffer[1] = '['; - buffer[2] = Ion::Charset::Empty; - buffer[3] = ']'; - buffer[4] = ']'; - buffer[5] = 0; - return; - } TextToInsertForCommandText(command, buffer, bufferSize); size_t bufferLength = strlen(buffer); for (size_t i = 0; i < bufferLength; i++) { - if (buffer[i] == '(' || buffer[i] == '[' || buffer[i] == ',') { + if (buffer[i] == '(' || buffer[i] == ',' || (i < bufferLength - 1 && buffer[i] == '[' && buffer[i+1] == ']')) { // Shift the buffer to make room for the new char. Use memmove to avoid // overwritting. memmove(&buffer[i+2], &buffer[i+1], bufferLength - (i+1) + 1); From e29691e1f17a9210f172c19152e5ab92a1799b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 17:31:37 +0100 Subject: [PATCH 212/459] [apps/sequence] Fix the insertion of sequence terms in text fields. For instance, the serialization of the V_n layout is "v_{n}", which is what we want to insert in an EditableExpressionView, but not in a Text Field for which we want "v(n)". Change-Id: Iab38058d982322891b530b3afd2d303a266643f9 --- apps/math_toolbox.cpp | 41 ++++++++++++++++--------- apps/math_toolbox.h | 6 ++-- apps/sequence/list/sequence_toolbox.cpp | 21 ++++++++++++- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index a91e93daf..a083d5747 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -115,14 +115,19 @@ void MathToolbox::setSenderAndAction(Responder * sender, Action action) { m_action = action; } -void MathToolbox::actionForEditableExpressionView(void * sender, const char * text) { +void MathToolbox::actionForEditableExpressionView(void * sender, const char * text, bool removeArguments) { EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); - // Replace the arguments with Empty chars. - int textToInsertMaxLength = strlen(text); - char textToInsert[textToInsertMaxLength]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandText(text, textToInsert, textToInsertMaxLength); - // Create the layout - Expression * resultExpression = Expression::parse(textToInsert); + Expression * resultExpression = nullptr; + if (removeArguments) { + // Replace the arguments with Empty chars. + int textToInsertMaxLength = strlen(text); + char textToInsert[textToInsertMaxLength]; + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandText(text, textToInsert, textToInsertMaxLength); + // Create the layout + resultExpression = Expression::parse(textToInsert); + } else { + resultExpression = Expression::parse(text); + } if (resultExpression == nullptr) { return; } @@ -145,24 +150,30 @@ void MathToolbox::actionForEditableExpressionView(void * sender, const char * te expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); } -void MathToolbox::actionForTextField(void * sender, const char * text) { +void MathToolbox::actionForTextField(void * sender, const char * text, bool removeArguments) { TextField * textFieldSender = static_cast(sender); if (!textFieldSender->isEditing()) { textFieldSender->setEditing(true); } - int maxTextToInsertLength = strlen(text); - char textToInsert[maxTextToInsertLength]; - // Translate the message and remove the arguments. - Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength); - textFieldSender->insertTextAtLocation(textToInsert, textFieldSender->cursorLocation()); - int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommandText(text); + int newCursorLocation = textFieldSender->cursorLocation(); + if (removeArguments) { + int maxTextToInsertLength = strlen(text); + char textToInsert[maxTextToInsertLength]; + // Translate the message and remove the arguments. + Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength); + textFieldSender->insertTextAtLocation(textToInsert, textFieldSender->cursorLocation()); + newCursorLocation+= Shared::ToolboxHelpers::CursorIndexInCommandText(textToInsert); + } else { + textFieldSender->insertTextAtLocation(text, textFieldSender->cursorLocation()); + newCursorLocation+= Shared::ToolboxHelpers::CursorIndexInCommandText(text); + } textFieldSender->setCursorLocation(newCursorLocation); } bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { ToolboxMessageTree * messageTree = selectedMessageTree; m_selectableTableView.deselectTable(); - m_action(sender(), I18n::translate(messageTree->insertedText())); + m_action(sender(), I18n::translate(messageTree->insertedText()), true); app()->dismissModalViewController(); return true; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 02be3effa..913706611 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -8,11 +8,11 @@ class MathToolbox : public Toolbox { public: - typedef void (*Action)(void * sender, const char * text); + typedef void (*Action)(void * sender, const char * text, bool removeArguments); MathToolbox(); void setSenderAndAction(Responder * sender, Action action); - static void actionForEditableExpressionView(void * sender, const char * text); - static void actionForTextField(void * sender, const char * text); + static void actionForEditableExpressionView(void * sender, const char * text, bool removeArguments = true); + static void actionForTextField(void * sender, const char * text, bool removeArguments = true); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index f4346311d..3772521c5 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -115,7 +115,26 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){ int bufferSize = 10; char buffer[bufferSize]; m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); - m_action(sender(), buffer); + if (m_action == MathToolbox::actionForTextField) { + // DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout, + // which serializes into "_{}", but we want parentheses for text fields. We + // thus need to remove any underscores, and changes brackets into + // parentheses. + for (int i = 0; i < bufferSize; i++) { + if (buffer[i] == '{') { + buffer[i] = '('; + } + if (buffer[i] == '}') { + buffer[i] = ')'; + } + if (buffer[i] == '_') { + memmove(&buffer[i], &buffer[i+1], bufferSize - (i+1) + 1); + bufferSize--; + i--; + } + } + } + m_action(sender(), buffer, false); app()->dismissModalViewController(); return true; } From 17cbcd0ab52fa0f90fd606cb0c2b28019966de85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 19 Jan 2018 17:36:01 +0100 Subject: [PATCH 213/459] [apps/Makefile] Put all the apps back. Change-Id: Ic88eee0e64c4b17364a08a4d4e5bb99fd0481914 --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index 4072eb811..7e5d367ab 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= calculation settings +EPSILON_APPS ?= calculation graph sequence settings statistics probability regression code include apps/shared/Makefile include apps/home/Makefile From 4d778b5d9fdccd1a7d780ef7afcd9dd4f9e07a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 22 Jan 2018 17:38:02 +0100 Subject: [PATCH 214/459] [apps/escher/poincare] Use 2D Edition in Sequence and Graph apps. EditableExpressionView is renamed ScrollableViewWithCursor. EditableExpressionView is now a View that displays either a TextField or a ScrollableViewWithCursor, depending on Poincare::Preferences. Change-Id: Id44ddcd9a83f5fd17d65753ca4c94c5c7cda9b8a --- apps/calculation/Makefile | 3 +- apps/calculation/app.cpp | 12 +- apps/calculation/app.h | 4 +- .../edit_expression_controller.cpp | 166 ++++------ apps/calculation/edit_expression_controller.h | 43 +-- apps/calculation/editable_expression_view.cpp | 18 +- apps/calculation/editable_expression_view.h | 4 +- apps/calculation/text_field.cpp | 33 -- apps/calculation/text_field.h | 16 - apps/graph/app.cpp | 2 +- apps/math_toolbox.cpp | 4 +- apps/math_toolbox.h | 2 +- apps/sequence/app.cpp | 2 +- apps/sequence/list/list_controller.cpp | 4 + apps/sequence/list/list_controller.h | 8 +- apps/shared/Makefile | 4 +- .../editable_expression_view_delegate.cpp | 35 -- .../editable_expression_view_delegate.h | 24 -- .../editable_expression_view_delegate_app.cpp | 56 ++++ .../editable_expression_view_delegate_app.h | 21 ++ apps/shared/function_app.cpp | 4 +- apps/shared/function_app.h | 4 +- ...e_expression_view_with_cursor_delegate.cpp | 31 ++ ...ble_expression_view_with_cursor_delegate.h | 23 ++ ..._editable_expression_view_delegate_app.cpp | 52 --- ...nd_editable_expression_view_delegate_app.h | 21 -- apps/variable_box_controller.cpp | 20 +- apps/variable_box_controller.h | 6 +- escher/Makefile | 1 + escher/include/escher.h | 3 +- .../include/escher/editable_expression_view.h | 58 ++-- .../editable_expression_view_delegate.h | 20 -- escher/include/escher/input_view_controller.h | 52 +-- escher/include/escher/modal_view_controller.h | 3 + .../scrollable_expression_view_with_cursor.h | 40 +++ ...ble_expression_view_with_cursor_delegate.h | 19 ++ escher/src/editable_expression_view.cpp | 299 +++++++----------- escher/src/input_view_controller.cpp | 125 ++++---- escher/src/modal_view_controller.cpp | 9 + ...scrollable_expression_view_with_cursor.cpp | 225 +++++++++++++ poincare/include/poincare/expression_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 6 + 42 files changed, 793 insertions(+), 690 deletions(-) delete mode 100644 apps/calculation/text_field.cpp delete mode 100644 apps/calculation/text_field.h delete mode 100644 apps/shared/editable_expression_view_delegate.cpp delete mode 100644 apps/shared/editable_expression_view_delegate.h create mode 100644 apps/shared/editable_expression_view_delegate_app.cpp create mode 100644 apps/shared/editable_expression_view_delegate_app.h create mode 100644 apps/shared/scrollable_expression_view_with_cursor_delegate.cpp create mode 100644 apps/shared/scrollable_expression_view_with_cursor_delegate.h delete mode 100644 apps/shared/text_field_and_editable_expression_view_delegate_app.cpp delete mode 100644 apps/shared/text_field_and_editable_expression_view_delegate_app.h delete mode 100644 escher/include/escher/editable_expression_view_delegate.h create mode 100644 escher/include/escher/scrollable_expression_view_with_cursor.h create mode 100644 escher/include/escher/scrollable_expression_view_with_cursor_delegate.h create mode 100644 escher/src/scrollable_expression_view_with_cursor.cpp diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index 420391945..226945971 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -5,8 +5,8 @@ app_objs += $(addprefix apps/calculation/,\ app.o\ calculation.o\ calculation_store.o\ - editable_expression_view.o\ edit_expression_controller.o\ + editable_expression_view.o\ history_view_cell.o\ history_controller.o\ local_context.o\ @@ -14,7 +14,6 @@ app_objs += $(addprefix apps/calculation/,\ scrollable_expression_view.o\ scrollable_output_expressions_view.o\ selectable_table_view.o\ - text_field.o\ ) i18n_files += $(addprefix apps/calculation/,\ diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 21056ddb4..f4bb63e6a 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -43,7 +43,7 @@ void App::Snapshot::tidy() { } App::App(Container * container, Snapshot * snapshot) : - TextFieldAndEditableExpressionViewDelegateApp(container, snapshot, &m_editExpressionController), + EditableExpressionViewDelegateApp(container, snapshot, &m_editExpressionController), m_localContext((GlobalContext *)((AppsContainer *)container)->globalContext(), snapshot->calculationStore()), m_historyController(&m_editExpressionController, snapshot->calculationStore()), m_editExpressionController(&m_modalViewController, &m_historyController, snapshot->calculationStore()) @@ -80,21 +80,21 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e return false; } -bool App::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - if ((event == Ion::Events::Var || event == Ion::Events::XNT) && TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidReceiveEvent(editableExpressionView, event)) { +bool App::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event)) { return true; } /* Here, we check that the expression entered by the user can be printed with * less than k_printedExpressionLength characters. Otherwise, we prevent the * user from adding this expression to the calculation store. */ - if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event)) { + if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event)) { int bufferLength = TextField::maxBufferSize(); char bufferForParsing[bufferLength]; - Poincare::ExpressionLayout * expressionLayout = editableExpressionView->expressionViewWithCursor()->expressionView()->expressionLayout(); + Poincare::ExpressionLayout * expressionLayout = scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout(); expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); Expression * exp = Expression::parse(bufferForParsing); if (exp == nullptr) { - editableExpressionView->app()->displayWarning(I18n::Message::SyntaxError); + scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); return true; } char buffer[Calculation::k_printedExpressionSize]; diff --git a/apps/calculation/app.h b/apps/calculation/app.h index 4ec807891..56d404178 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -10,7 +10,7 @@ namespace Calculation { -class App : public Shared::TextFieldAndEditableExpressionViewDelegateApp { +class App : public Shared::EditableExpressionViewDelegateApp { public: class Descriptor : public ::App::Descriptor { public: @@ -30,7 +30,7 @@ public: }; Poincare::Context * localContext() override; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; - bool editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; const char * XNT() override; private: App(Container * container, Snapshot * snapshot); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index d1fefa9af..45d9c2474 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -9,17 +9,11 @@ using namespace Shared; namespace Calculation { -EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate) : +EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : View(), m_mainView(subview), - m_textField(parentResponder, m_textBody, TextField::maxBufferSize(), textFieldDelegate), - m_editableExpressionView(parentResponder, new Poincare::HorizontalLayout(), editableExpressionViewDelegate) + m_editableExpressionView(parentResponder, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) { - m_textBody[0] = 0; -} - -int EditExpressionController::ContentView::numberOfSubviews() const { - return 2; } View * EditExpressionController::ContentView::subviewAtIndex(int index) { @@ -28,25 +22,15 @@ View * EditExpressionController::ContentView::subviewAtIndex(int index) { return m_mainView; } assert(index == 1); - if (editionIsInTextField()) { - return &m_textField; - } return &m_editableExpressionView; } void EditExpressionController::ContentView::layoutSubviews() { - KDCoordinate inputViewFrameHeight = inputViewHeight(); - KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight-k_separatorThickness); + KDCoordinate inputViewFrameHeight = m_editableExpressionView.minimalSizeForOptimalDisplay().height(); + KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight); m_mainView->setFrame(mainViewFrame); - if (editionIsInTextField()) { - KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight, bounds().width()-k_leftMargin, k_textFieldHeight); - m_textField.setFrame(inputViewFrame); - m_editableExpressionView.setFrame(KDRectZero); - return; - } - KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight, bounds().width() - k_leftMargin, inputViewFrameHeight); + KDRect inputViewFrame(0, bounds().height() - inputViewFrameHeight, bounds().width(), inputViewFrameHeight); m_editableExpressionView.setFrame(inputViewFrame); - m_textField.setFrame(KDRectZero); } void EditExpressionController::ContentView::reload() { @@ -54,30 +38,6 @@ void EditExpressionController::ContentView::reload() { markRectAsDirty(bounds()); } -void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { - KDCoordinate inputViewFrameHeight = inputViewHeight(); - // Draw the separator - ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle); - // Color the left margin - ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, inputViewFrameHeight), m_textField.backgroundColor()); - if (!editionIsInTextField()) { - // Color the upper margin - ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalEditableExpressionViewMargin), m_textField.backgroundColor()); - } -} - -bool EditExpressionController::ContentView::editionIsInTextField() const { - return Poincare::Preferences::sharedPreferences()->editionMode() == Poincare::Preferences::EditionMode::Edition1D; -} - -KDCoordinate EditExpressionController::ContentView::inputViewHeight() const { - return editionIsInTextField() ? k_textFieldHeight : k_verticalEditableExpressionViewMargin + editableExpressionViewHeight(); -} - -KDCoordinate EditExpressionController::ContentView::editableExpressionViewHeight() const { - return KDCoordinate(min(0.6*Ion::Display::Height, max(k_textFieldHeight, m_editableExpressionView.minimalSizeForOptimalDisplay().height()+k_verticalEditableExpressionViewMargin))); -} - EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) : DynamicViewController(parentResponder), m_historyController(historyController), @@ -86,31 +46,18 @@ EditExpressionController::EditExpressionController(Responder * parentResponder, } const char * EditExpressionController::textBody() { - return ((ContentView *)view())->textField()->text(); + return ((ContentView *)view())->editableExpressionView()->text(); } void EditExpressionController::insertTextBody(const char * text) { - if (((ContentView *)view())->editionIsInTextField()) { - TextField * tf = ((ContentView *)view())->textField(); - tf->setEditing(true, false); - tf->insertTextAtLocation(text, tf->cursorLocation()); - tf->setCursorLocation(tf->cursorLocation() + strlen(text)); - return; - } - EditableExpressionView * editableExpressionView = ((ContentView *)view())->editableExpressionView(); - editableExpressionView->setEditing(true); - editableExpressionView->insertLayoutFromTextAtCursor(text); + ((ContentView *)view())->editableExpressionView()->insertText(text); } bool EditExpressionController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Up) { if (m_calculationStore->numberOfCalculations() > 0) { - if (((ContentView *)view())->editionIsInTextField()) { - ((ContentView *)view())->textField()->setEditing(false, false); - } else { - ((ContentView *)view())->editableExpressionView()->setEditing(false); - } - app()->setFirstResponder(m_historyController); + ((ContentView *)view())->editableExpressionView()->setEditing(false, false); + app()->setFirstResponder(m_historyController); } return true; } @@ -120,74 +67,48 @@ bool EditExpressionController::handleEvent(Ion::Events::Event event) { void EditExpressionController::didBecomeFirstResponder() { int lastRow = m_calculationStore->numberOfCalculations() > 0 ? m_calculationStore->numberOfCalculations()-1 : 0; m_historyController->scrollToCell(0, lastRow); - if (((ContentView *)view())->editionIsInTextField()) { - ((ContentView *)view())->textField()->setEditing(true, false); - app()->setFirstResponder(((ContentView *)view())->textField()); - return; - } - ((ContentView *)view())->editableExpressionView()->setEditing(true); + ((ContentView *)view())->editableExpressionView()->setEditing(true, false); app()->setFirstResponder(((ContentView *)view())->editableExpressionView()); } bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { + assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); if (textField->isEditing() && textField->textFieldShouldFinishEditing(event) && textField->draftTextLength() == 0 && m_calculationStore->numberOfCalculations() > 0) { - App * calculationApp = (App *)app(); - const char * lastTextBody = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1)->inputText(); - m_calculationStore->push(lastTextBody, calculationApp->localContext()); - m_historyController->reload(); - ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); - return true; + return inputViewDidReceiveEvent(event); } return textFieldDelegateApp()->textFieldDidReceiveEvent(textField, event); } bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) { - App * calculationApp = (App *)app(); - m_calculationStore->push(textBody(), calculationApp->localContext()); - m_historyController->reload(); - ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); - ((ContentView *)view())->textField()->setEditing(true); - ((ContentView *)view())->textField()->setText(""); - return true; + assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); + return inputViewDidFinishEditing(text, event); } bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField, const char * text) { - ((ContentView *)view())->textField()->setEditing(true); - ((ContentView *)view())->textField()->setText(text); - return false; + assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); + return inputViewDidAbortEditing(text); } -bool EditExpressionController::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - bool layoutIsEmpty = expressionLayout()->isHorizontal() && expressionLayout()->numberOfChildren() == 0; - if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event) && layoutIsEmpty && m_calculationStore->numberOfCalculations() > 0) { - App * calculationApp = (App *)app(); - const char * lastTextBody = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1)->inputText(); - m_calculationStore->push(lastTextBody, calculationApp->localContext()); - m_historyController->reload(); - ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); - return true; +bool EditExpressionController::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); + if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event) && !expressionLayout()->hasText() && m_calculationStore->numberOfCalculations() > 0) { + return inputViewDidReceiveEvent(event); } - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event); + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); } -bool EditExpressionController::editableExpressionViewDidFinishEditing(::EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { - App * calculationApp = (App *)app(); - expressionLayout()->writeTextInBuffer(const_cast(textBody()), ContentView::k_bufferLength); - m_calculationStore->push(textBody(), calculationApp->localContext()); - (const_cast(((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()))->setExpressionLayout(new Poincare::HorizontalLayout()); - reloadView(); - ((ContentView *)view())->editableExpressionView()->setEditing(true); - return true; +bool EditExpressionController::scrollableExpressionViewWithCursorDidFinishEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { + assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); + return inputViewDidFinishEditing(text, event); } -bool EditExpressionController::editableExpressionViewDidAbortEditing(::EditableExpressionView * editableExpressionView, const char * text) { - ((ContentView *)view())->editableExpressionView()->setEditing(true); - //TODO ((ContentView *)view())->editableExpressionView()->editableExpressionView()->expressionViewWithCursor()->expressionView()->setLayout(; - return false; +bool EditExpressionController::scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { + assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); + return inputViewDidAbortEditing(text); } -void EditExpressionController::editableExpressionViewDidChangeSize(::EditableExpressionView * editableExpressionView) { - assert(editableExpressionView == ((ContentView *)view())->editableExpressionView()); +void EditExpressionController::scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); reloadView(); } @@ -195,7 +116,7 @@ TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() { return (App *)app(); } -TextFieldAndEditableExpressionViewDelegateApp * EditExpressionController::textFieldAndEditableExpressionViewDelegateApp() { +EditableExpressionViewDelegateApp * EditExpressionController::editableExpressionViewDelegateApp() { return (App *)app(); } @@ -216,13 +137,38 @@ void EditExpressionController::reloadView() { } } +bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event) { + App * calculationApp = (App *)app(); + const char * lastTextBody = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1)->inputText(); + m_calculationStore->push(lastTextBody, calculationApp->localContext()); + m_historyController->reload(); + ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); + return true; +} + +bool EditExpressionController::inputViewDidFinishEditing(const char * text, Ion::Events::Event event) { + App * calculationApp = (App *)app(); + m_calculationStore->push(textBody(), calculationApp->localContext()); + m_historyController->reload(); + ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); + ((ContentView *)view())->editableExpressionView()->setEditing(true, true); + ((ContentView *)view())->editableExpressionView()->setText(""); + return true; +} + +bool EditExpressionController::inputViewDidAbortEditing(const char * text) { + ((ContentView *)view())->editableExpressionView()->setEditing(true, true); + ((ContentView *)view())->editableExpressionView()->setText(text); + return false; +} + void EditExpressionController::viewDidDisappear() { DynamicViewController::viewDidDisappear(); m_historyController->viewDidDisappear(); } Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { - return ((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()->expressionLayout(); + return ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()->expressionViewWithCursor()->expressionView()->expressionLayout(); } } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 9c3d3d4aa..a2b64b951 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -4,16 +4,15 @@ #include #include "editable_expression_view.h" #include "../shared/text_field_delegate.h" -#include "../shared/editable_expression_view_delegate.h" +#include "../shared/scrollable_expression_view_with_cursor_delegate.h" #include "history_controller.h" #include "calculation_store.h" -#include "text_field.h" namespace Calculation { class HistoryController; /* TODO: implement a split view */ -class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::EditableExpressionViewDelegate { +class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::ScrollableExpressionViewWithCursorDelegate { public: EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore); void didBecomeFirstResponder() override; @@ -27,43 +26,35 @@ public: bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(::TextField * textField, const char * text) override; - /* EditableExpressionViewDelegate */ - bool editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - bool editableExpressionViewDidFinishEditing(::EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; - bool editableExpressionViewDidAbortEditing(::EditableExpressionView * editableExpressionView, const char * text) override; - void editableExpressionViewDidChangeSize(::EditableExpressionView * editableExpressionView) override; + /* ScrollableExpressionViewWithCursorDelegate */ + bool scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidFinishEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + void scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; private: class ContentView : public View { public: - ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate); - int numberOfSubviews() const override; + ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + void reload(); + TableView * mainView() { return m_mainView; } + EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } + /* View */ + int numberOfSubviews() const override { return 2; } View * subviewAtIndex(int index) override; void layoutSubviews() override; - void reload(); - TextField * textField() { return &m_textField; } - EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } - TableView * mainView() { return m_mainView; } - void drawRect(KDContext * ctx, KDRect rect) const override; - bool editionIsInTextField() const; - static constexpr int k_bufferLength = TextField::maxBufferSize(); private: - static constexpr KDCoordinate k_textFieldHeight = 37; - static constexpr KDCoordinate k_leftMargin = 5; - static constexpr KDCoordinate k_verticalEditableExpressionViewMargin = 5; - constexpr static int k_separatorThickness = 1; - KDCoordinate inputViewHeight() const; - KDCoordinate editableExpressionViewHeight() const; TableView * m_mainView; - TextField m_textField; EditableExpressionView m_editableExpressionView; - char m_textBody[k_bufferLength]; }; View * loadView() override; void unloadView(View * view) override; void reloadView(); + bool inputViewDidReceiveEvent(Ion::Events::Event event); + bool inputViewDidFinishEditing(const char * text, Ion::Events::Event event); + bool inputViewDidAbortEditing(const char * text); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; - Shared::TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() override; + Shared::EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() override; Poincare::ExpressionLayout * expressionLayout(); HistoryController * m_historyController; CalculationStore * m_calculationStore; diff --git a/apps/calculation/editable_expression_view.cpp b/apps/calculation/editable_expression_view.cpp index a06287c2c..ac9b2000d 100644 --- a/apps/calculation/editable_expression_view.cpp +++ b/apps/calculation/editable_expression_view.cpp @@ -2,34 +2,30 @@ namespace Calculation { -EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : - ::EditableExpressionView(parentResponder, expressionLayout, delegate) +EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : + ::EditableExpressionView(parentResponder, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) { setEditing(true); } -bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { +bool EditableExpressionView::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back) { return false; } if (event == Ion::Events::Ans) { - m_expressionViewWithCursor.cursor()->insertText("ans"); + insertText("ans"); return true; } - Poincare::ExpressionLayout * layout = m_expressionViewWithCursor.expressionView()->expressionLayout(); - bool layoutIsEmpty = layout->isEmpty() - || (layout->isHorizontal() - && layout->numberOfChildren() == 0); - if (isEditing() && layoutIsEmpty && + if (isEditing() && isEmpty() && (event == Ion::Events::Multiplication || event == Ion::Events::Plus || event == Ion::Events::Power || event == Ion::Events::Square || event == Ion::Events::Division || event == Ion::Events::Sto)) { - m_expressionViewWithCursor.cursor()->insertText("ans"); + insertText("ans"); } - return(::EditableExpressionView::privateHandleEvent(event)); + return(::EditableExpressionView::handleEvent(event)); } } diff --git a/apps/calculation/editable_expression_view.h b/apps/calculation/editable_expression_view.h index f873e9115..52a1faad3 100644 --- a/apps/calculation/editable_expression_view.h +++ b/apps/calculation/editable_expression_view.h @@ -7,9 +7,9 @@ namespace Calculation { class EditableExpressionView : public ::EditableExpressionView { public: - EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate = nullptr); + EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); protected: - bool privateHandleEvent(Ion::Events::Event event) override; + bool handleEvent(Ion::Events::Event event) override; }; } diff --git a/apps/calculation/text_field.cpp b/apps/calculation/text_field.cpp deleted file mode 100644 index e9349c201..000000000 --- a/apps/calculation/text_field.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "text_field.h" - -namespace Calculation { - -TextField::TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate) : - ::TextField(parentResponder, textBuffer, textBuffer, textBufferSize, delegate, false) -{ - setEditing(true); -} - -bool TextField::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::Back) { - return false; - } - if (event == Ion::Events::Ans) { - insertTextAtLocation("ans", cursorLocation()); - setCursorLocation(cursorLocation() + strlen("ans")); - return true; - } - if (isEditing() && draftTextLength() == 0 && - (event == Ion::Events::Multiplication || - event == Ion::Events::Plus || - event == Ion::Events::Power || - event == Ion::Events::Square || - event == Ion::Events::Division || - event == Ion::Events::Sto)) { - insertTextAtLocation("ans", cursorLocation()); - setCursorLocation(cursorLocation() + strlen("ans")); - } - return(::TextField::handleEvent(event)); -} - -} diff --git a/apps/calculation/text_field.h b/apps/calculation/text_field.h deleted file mode 100644 index 6d2f12392..000000000 --- a/apps/calculation/text_field.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CALCULATION_TEXT_FIELD_H -#define CALCULATION_TEXT_FIELD_H - -#include - -namespace Calculation { - -class TextField : public ::TextField { -public: - TextField(Responder * parentResponder, char * textBuffer, size_t textBufferSize, TextFieldDelegate * delegate); - bool handleEvent(Ion::Events::Event event) override; -}; - -} - -#endif diff --git a/apps/graph/app.cpp b/apps/graph/app.cpp index 581877d5f..c1b3d7a0e 100644 --- a/apps/graph/app.cpp +++ b/apps/graph/app.cpp @@ -70,7 +70,7 @@ App::App(Container * container, Snapshot * snapshot) : m_valuesHeader(&m_valuesStackViewController, &m_valuesAlternateEmptyViewController, &m_valuesController), m_valuesStackViewController(&m_tabViewController, &m_valuesHeader), m_tabViewController(&m_inputViewController, snapshot, &m_listStackViewController, &m_graphStackViewController, &m_valuesStackViewController), - m_inputViewController(&m_modalViewController, &m_tabViewController, this) + m_inputViewController(&m_modalViewController, &m_tabViewController, this, this) { } diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index a083d5747..63639f81f 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -115,8 +115,8 @@ void MathToolbox::setSenderAndAction(Responder * sender, Action action) { m_action = action; } -void MathToolbox::actionForEditableExpressionView(void * sender, const char * text, bool removeArguments) { - EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); +void MathToolbox::actionForScrollableExpressionViewWithCursor(void * sender, const char * text, bool removeArguments) { + ScrollableExpressionViewWithCursor * expressionLayoutEditorSender = static_cast(sender); Expression * resultExpression = nullptr; if (removeArguments) { // Replace the arguments with Empty chars. diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 913706611..68f38e3e9 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -11,7 +11,7 @@ public: typedef void (*Action)(void * sender, const char * text, bool removeArguments); MathToolbox(); void setSenderAndAction(Responder * sender, Action action); - static void actionForEditableExpressionView(void * sender, const char * text, bool removeArguments = true); + static void actionForScrollableExpressionViewWithCursor(void * sender, const char * text, bool removeArguments = true); static void actionForTextField(void * sender, const char * text, bool removeArguments = true); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; diff --git a/apps/sequence/app.cpp b/apps/sequence/app.cpp index de681f165..8c9194f5c 100644 --- a/apps/sequence/app.cpp +++ b/apps/sequence/app.cpp @@ -72,7 +72,7 @@ App::App(Container * container, Snapshot * snapshot) : m_valuesHeader(nullptr, &m_valuesAlternateEmptyViewController, &m_valuesController), m_valuesStackViewController(&m_tabViewController, &m_valuesHeader), m_tabViewController(&m_inputViewController, snapshot, &m_listStackViewController, &m_graphStackViewController, &m_valuesStackViewController), - m_inputViewController(&m_modalViewController, &m_tabViewController, &m_listController) + m_inputViewController(&m_modalViewController, &m_tabViewController, &m_listController, &m_listController) { } diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index c3a8e6031..b8cc8cdeb 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -38,6 +38,10 @@ TextFieldDelegateApp * ListController::textFieldDelegateApp() { return (App *)app(); } +EditableExpressionViewDelegateApp * ListController::editableExpressionViewDelegateApp() { + return (App *)app(); +} + int ListController::numberOfRows() { int numberOfRows = 0; for (int i = 0; i < m_sequenceStore->numberOfFunctions(); i++) { diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 2fd3f0f35..a8f34882f 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -5,16 +5,17 @@ #include "../sequence_title_cell.h" #include "../sequence_store.h" #include "../../shared/function_expression_cell.h" -#include "type_parameter_controller.h" -#include "../../shared/new_function_cell.h" #include "../../shared/list_controller.h" +#include "../../shared/new_function_cell.h" +#include "../../shared/scrollable_expression_view_with_cursor_delegate.h" #include "../../shared/text_field_delegate.h" #include "list_parameter_controller.h" #include "sequence_toolbox.h" +#include "type_parameter_controller.h" namespace Sequence { -class ListController : public Shared::ListController, public Shared::TextFieldDelegate { +class ListController : public Shared::ListController, public Shared::TextFieldDelegate, public Shared::ScrollableExpressionViewWithCursorDelegate { public: ListController(Responder * parentResponder, SequenceStore * sequenceStore, ButtonRowController * header, ButtonRowController * footer); const char * title() override; @@ -25,6 +26,7 @@ public: void selectPreviousNewSequenceCell(); private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override; + Shared::EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() override; void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event); ListParameterController * parameterController() override; int maxNumberOfRows() override; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 40c3a475c..11e481683 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -6,7 +6,7 @@ app_objs += $(addprefix apps/shared/,\ curve_view_cursor.o\ curve_view_range.o\ editable_cell_table_view_controller.o\ - editable_expression_view_delegate.o\ + editable_expression_view_delegate_app.o\ float_pair_store.o\ float_parameter_controller.o\ function.o\ @@ -35,10 +35,10 @@ app_objs += $(addprefix apps/shared/,\ parameter_text_field_delegate.o\ range_parameter_controller.o\ regular_table_view_data_source.o\ + scrollable_expression_view_with_cursor_delegate.o\ store_controller.o\ store_parameter_controller.o\ tab_table_controller.o\ - text_field_and_editable_expression_view_delegate_app.o\ text_field_delegate.o\ text_field_delegate_app.o\ toolbox_helpers.o\ diff --git a/apps/shared/editable_expression_view_delegate.cpp b/apps/shared/editable_expression_view_delegate.cpp deleted file mode 100644 index ff7542ed4..000000000 --- a/apps/shared/editable_expression_view_delegate.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "editable_expression_view_delegate.h" - -using namespace Poincare; - -namespace Shared { - -bool EditableExpressionViewDelegate::editableExpressionViewShouldFinishEditing(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewShouldFinishEditing(editableExpressionView, event); -} - -bool EditableExpressionViewDelegate::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event); -} - -bool EditableExpressionViewDelegate::editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidFinishEditing(editableExpressionView, text, event); -} - -bool EditableExpressionViewDelegate::editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidAbortEditing(editableExpressionView, text); -} - -bool EditableExpressionViewDelegate::editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidHandleEvent(editableExpressionView, event, returnValue, expressionHasChanged); -} - -void EditableExpressionViewDelegate::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) { - return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidChangeSize(editableExpressionView); -} - -Toolbox * EditableExpressionViewDelegate::toolboxForEditableExpressionView(::EditableExpressionView * editableExpressionView) { - return textFieldAndEditableExpressionViewDelegateApp()->toolboxForEditableExpressionView(editableExpressionView); -} - -} diff --git a/apps/shared/editable_expression_view_delegate.h b/apps/shared/editable_expression_view_delegate.h deleted file mode 100644 index 9c779b642..000000000 --- a/apps/shared/editable_expression_view_delegate.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_H -#define SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_H - -#include -#include "text_field_and_editable_expression_view_delegate_app.h" - -namespace Shared { - -class EditableExpressionViewDelegate : public ::EditableExpressionViewDelegate { -public: - bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override; - bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override; - bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) override; - void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override; - Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override; -private: - virtual TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() = 0; -}; - -} - -#endif diff --git a/apps/shared/editable_expression_view_delegate_app.cpp b/apps/shared/editable_expression_view_delegate_app.cpp new file mode 100644 index 000000000..3ce1f53cb --- /dev/null +++ b/apps/shared/editable_expression_view_delegate_app.cpp @@ -0,0 +1,56 @@ +#include "editable_expression_view_delegate_app.h" +#include "../i18n.h" +#include "../apps_container.h" + +using namespace Poincare; + +namespace Shared { + +EditableExpressionViewDelegateApp::EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : + TextFieldDelegateApp(container, snapshot, rootViewController), + ScrollableExpressionViewWithCursorDelegate() +{ +} + +bool EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + return event == Ion::Events::OK || event == Ion::Events::EXE; +} + +bool EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event)) { + if (!scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout()->hasText()) { + scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); + return true; + } + int bufferSize = 256; + char buffer[bufferSize]; + scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + Expression * exp = Expression::parse(buffer); + if (exp != nullptr) { + delete exp; + } + if (exp == nullptr) { + scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); + return true; + } + } + if (event == Ion::Events::Var) { + if (!scrollableExpressionViewWithCursor->isEditing()) { + scrollableExpressionViewWithCursor->setEditing(true); + } + AppsContainer * appsContainer = (AppsContainer *)scrollableExpressionViewWithCursor->app()->container(); + VariableBoxController * variableBoxController = appsContainer->variableBoxController(); + variableBoxController->setScrollableExpressionViewWithCursorSender(scrollableExpressionViewWithCursor); + scrollableExpressionViewWithCursor->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + return true; + } + return false; +} + +Toolbox * EditableExpressionViewDelegateApp::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + Toolbox * toolbox = container()->mathToolbox(); + static_cast(toolbox)->setSenderAndAction(scrollableExpressionViewWithCursor, MathToolbox::actionForScrollableExpressionViewWithCursor); + return toolbox; +} + +} diff --git a/apps/shared/editable_expression_view_delegate_app.h b/apps/shared/editable_expression_view_delegate_app.h new file mode 100644 index 000000000..626b3fac7 --- /dev/null +++ b/apps/shared/editable_expression_view_delegate_app.h @@ -0,0 +1,21 @@ +#ifndef SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H +#define SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H + +#include "text_field_delegate_app.h" +#include + +namespace Shared { + +class EditableExpressionViewDelegateApp : public TextFieldDelegateApp, public ScrollableExpressionViewWithCursorDelegate { +public: + virtual ~EditableExpressionViewDelegateApp() = default; + bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + virtual bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; +protected: + EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); +}; + +} + +#endif diff --git a/apps/shared/function_app.cpp b/apps/shared/function_app.cpp index 4e01d51d4..f805efe48 100644 --- a/apps/shared/function_app.cpp +++ b/apps/shared/function_app.cpp @@ -47,7 +47,7 @@ void FunctionApp::Snapshot::reset() { } FunctionApp::FunctionApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : - TextFieldDelegateApp(container, snapshot, rootViewController) + EditableExpressionViewDelegateApp(container, snapshot, rootViewController) { } @@ -56,7 +56,7 @@ void FunctionApp::willBecomeInactive() { m_modalViewController.dismissModalViewController(); } if (inputViewController()->isDisplayingModal()) { - inputViewController()->abortTextFieldEditionAndDismiss(); + inputViewController()->abortEditionAndDismiss(); } ::App::willBecomeInactive(); } diff --git a/apps/shared/function_app.h b/apps/shared/function_app.h index 0c73d582f..b4b59503d 100644 --- a/apps/shared/function_app.h +++ b/apps/shared/function_app.h @@ -2,7 +2,7 @@ #define SHARED_FUNCTION_APP_H #include -#include "text_field_delegate_app.h" +#include "editable_expression_view_delegate_app.h" #include "curve_view_cursor.h" #include "interval.h" @@ -10,7 +10,7 @@ class AppsContainer; namespace Shared { -class FunctionApp : public TextFieldDelegateApp { +class FunctionApp : public EditableExpressionViewDelegateApp { public: class Snapshot : public ::App::Snapshot, public TabViewDataSource { public: diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp b/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp new file mode 100644 index 000000000..5174721ff --- /dev/null +++ b/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp @@ -0,0 +1,31 @@ +#include "scrollable_expression_view_with_cursor_delegate.h" + +using namespace Poincare; + +namespace Shared { + +bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorShouldFinishEditing(scrollableExpressionViewWithCursor, event); +} + +bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); +} + +bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidFinishEditing(scrollableExpressionViewWithCursor, text, event); +} + +bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidAbortEditing(scrollableExpressionViewWithCursor, text); +} + +void ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidChangeSize(scrollableExpressionViewWithCursor); +} + +Toolbox * ScrollableExpressionViewWithCursorDelegate::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + return editableExpressionViewDelegateApp()->toolboxForScrollableExpressionViewWithCursor(scrollableExpressionViewWithCursor); +} + +} diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.h b/apps/shared/scrollable_expression_view_with_cursor_delegate.h new file mode 100644 index 000000000..589f6a8db --- /dev/null +++ b/apps/shared/scrollable_expression_view_with_cursor_delegate.h @@ -0,0 +1,23 @@ +#ifndef SHARED_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H +#define SHARED_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H + +#include +#include "editable_expression_view_delegate_app.h" + +namespace Shared { + +class ScrollableExpressionViewWithCursorDelegate : public ::ScrollableExpressionViewWithCursorDelegate { +public: + bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; +private: + virtual EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() = 0; +}; + +} + +#endif diff --git a/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp b/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp deleted file mode 100644 index 516c4a466..000000000 --- a/apps/shared/text_field_and_editable_expression_view_delegate_app.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "text_field_and_editable_expression_view_delegate_app.h" -#include "../i18n.h" -#include "../apps_container.h" - -using namespace Poincare; - -namespace Shared { - -TextFieldAndEditableExpressionViewDelegateApp::TextFieldAndEditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : - TextFieldDelegateApp(container, snapshot, rootViewController), - EditableExpressionViewDelegate() -{ -} - -bool TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - return event == Ion::Events::OK || event == Ion::Events::EXE; -} - -bool TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) { - if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event)) { - int bufferSize = 256; - char buffer[bufferSize]; - editableExpressionView->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); - Expression * exp = Expression::parse(buffer); - if (exp != nullptr) { - delete exp; - } - if (exp == nullptr) { - editableExpressionView->app()->displayWarning(I18n::Message::SyntaxError); - return true; - } - } - if (event == Ion::Events::Var) { - if (!editableExpressionView->isEditing()) { - editableExpressionView->setEditing(true); - } - AppsContainer * appsContainer = (AppsContainer *)editableExpressionView->app()->container(); - VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setEditableExpressionViewSender(editableExpressionView); - editableExpressionView->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); - return true; - } - return false; -} - -Toolbox * TextFieldAndEditableExpressionViewDelegateApp::toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) { - Toolbox * toolbox = container()->mathToolbox(); - static_cast(toolbox)->setSenderAndAction(editableExpressionView, MathToolbox::actionForEditableExpressionView); - return toolbox; -} - -} diff --git a/apps/shared/text_field_and_editable_expression_view_delegate_app.h b/apps/shared/text_field_and_editable_expression_view_delegate_app.h deleted file mode 100644 index 85bc85fc2..000000000 --- a/apps/shared/text_field_and_editable_expression_view_delegate_app.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHARED_TEXT_FIELD_AND_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H -#define SHARED_TEXT_FIELD_AND_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H - -#include "text_field_delegate_app.h" -#include - -namespace Shared { - -class TextFieldAndEditableExpressionViewDelegateApp : public TextFieldDelegateApp, public EditableExpressionViewDelegate { -public: - virtual ~TextFieldAndEditableExpressionViewDelegateApp() = default; - bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override; - Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override; -protected: - TextFieldAndEditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); -}; - -} - -#endif diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 3f14cc49c..253a38ea9 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -202,9 +202,9 @@ void VariableBoxController::ContentViewController::setTextFieldSender(TextField m_insertTextAction = &insertTextInTextField; } -void VariableBoxController::ContentViewController::setEditableExpressionViewSender(EditableExpressionView * editableExpressionView) { - m_sender = editableExpressionView; - m_insertTextAction = &insertTextInEditableExpressionView; +void VariableBoxController::ContentViewController::setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + m_sender = scrollableExpressionViewWithCursor; + m_insertTextAction = &insertTextInScrollableExpressionViewWithCursor; } void VariableBoxController::ContentViewController::reloadData() { @@ -288,12 +288,12 @@ void VariableBoxController::ContentViewController::insertTextInTextField(void * textField->setCursorLocation(textField->cursorLocation() + strlen(textToInsert)); } -void VariableBoxController::ContentViewController::insertTextInEditableExpressionView(void * sender, const char * textToInsert) { - EditableExpressionView * editableExpressionView = static_cast(sender); - if (!editableExpressionView->isEditing()) { - editableExpressionView->setEditing(true); +void VariableBoxController::ContentViewController::insertTextInScrollableExpressionViewWithCursor(void * sender, const char * textToInsert) { + ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor = static_cast(sender); + if (!scrollableExpressionViewWithCursor->isEditing()) { + scrollableExpressionViewWithCursor->setEditing(true); } - editableExpressionView->insertLayoutFromTextAtCursor(textToInsert); + scrollableExpressionViewWithCursor->insertLayoutFromTextAtCursor(textToInsert); } VariableBoxController::VariableBoxController(GlobalContext * context) : @@ -310,8 +310,8 @@ void VariableBoxController::setTextFieldSender(TextField * textField) { m_contentViewController.setTextFieldSender(textField); } -void VariableBoxController::setEditableExpressionViewSender(EditableExpressionView * editableExpressionView) { - m_contentViewController.setEditableExpressionViewSender(editableExpressionView); +void VariableBoxController::setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + m_contentViewController.setScrollableExpressionViewWithCursorSender(scrollableExpressionViewWithCursor); } void VariableBoxController::viewWillAppear() { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index daa75938e..512ef2798 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -14,7 +14,7 @@ public: VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; void setTextFieldSender(TextField * textField); - void setEditableExpressionViewSender(EditableExpressionView * editableExpressionView); + void setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor); void viewWillAppear() override; void viewDidDisappear() override; private: @@ -34,7 +34,7 @@ private: int indexFromCumulatedHeight(KDCoordinate offsetY) override; int typeAtLocation(int i, int j) override; void setTextFieldSender(TextField * textField); - void setEditableExpressionViewSender(EditableExpressionView * editableExpressionView); + void setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor); void reloadData(); void resetPage(); void viewDidDisappear() override; @@ -59,7 +59,7 @@ private: I18n::Message nodeLabelAtIndex(int index); const Poincare::Expression * expressionForIndex(int index); static void insertTextInTextField(void * sender, const char * textToInsert); - static void insertTextInEditableExpressionView(void * sender, const char * textToInsert); + static void insertTextInScrollableExpressionViewWithCursor(void * sender, const char * textToInsert); Poincare::GlobalContext * m_context; Responder * m_sender; Action m_insertTextAction; diff --git a/escher/Makefile b/escher/Makefile index bf54220fe..274900e46 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -49,6 +49,7 @@ objs += $(addprefix escher/src/,\ scroll_view_data_source.o\ scroll_view_indicator.o\ scrollable_view.o\ + scrollable_expression_view_with_cursor.o\ selectable_table_view.o\ selectable_table_view_data_source.o\ selectable_table_view_delegate.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 50dc65933..9db562c60 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -53,6 +52,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index 84dcd8d9b..d0c6e88b8 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -1,39 +1,49 @@ #ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_H #define ESCHER_EDITABLE_EXPRESSION_VIEW_H -#include -#include -#include -#include +#include +#include +#include +#include -class EditableExpressionView : public ScrollableView, public ScrollViewDataSource { +class EditableExpressionView : public Responder, public View { public: - EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate = nullptr); - void setDelegate(EditableExpressionViewDelegate * delegate) { m_delegate = delegate; } - ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } + EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + + void setEditing(bool isEditing, bool reinitDraftBuffer = true); bool isEditing() const; - void setEditing(bool isEditing); - void scrollToCursor(); + const char * text(); + void setText(const char * text); + void insertText(const char * text); void reload(); - - /* Responder */ - Toolbox * toolbox() override; - bool handleEvent(Ion::Events::Event event) override; - - bool editableExpressionViewShouldFinishEditing(Ion::Events::Event event); - - void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); - void insertLayoutFromTextAtCursor(const char * text); + TextField * textField() { return &m_textField; } + ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } + bool editionIsInTextField() const; + bool isEmpty() const; + bool heightIsMaximal() const; /* View */ + int numberOfSubviews() const override { return 1; } + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + void drawRect(KDContext * ctx, KDRect rect) const override; KDSize minimalSizeForOptimalDisplay() const override; -protected: - virtual bool privateHandleEvent(Ion::Events::Event event); - bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); - ExpressionViewWithCursor m_expressionViewWithCursor; + /* Responder */ + void didBecomeFirstResponder() override; + bool handleEvent(Ion::Events::Event event) override; + + static constexpr int k_bufferLength = TextField::maxBufferSize(); private: - EditableExpressionViewDelegate * m_delegate; + static constexpr KDCoordinate k_textFieldHeight = 37; + static constexpr KDCoordinate k_leftMargin = 5; + static constexpr KDCoordinate k_verticalExpressionViewMargin = 5; + constexpr static int k_separatorThickness = 1; + KDCoordinate inputViewHeight() const; + KDCoordinate maximalHeight() const; + TextField m_textField; + ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; + char m_textBody[k_bufferLength]; }; #endif diff --git a/escher/include/escher/editable_expression_view_delegate.h b/escher/include/escher/editable_expression_view_delegate.h deleted file mode 100644 index a6728caed..000000000 --- a/escher/include/escher/editable_expression_view_delegate.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_DELEGATE_H -#define ESCHER_EDITABLE_EXPRESSION_VIEW_DELEGATE_H - -#include -#include - -class EditableExpressionView; - -class EditableExpressionViewDelegate { -public: - virtual bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; - virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0; - virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; } - virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) { return false; } - virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) { return returnValue; } - virtual void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) {} - virtual Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) = 0; -}; - -#endif diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 52169e9b6..a2f037758 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -1,53 +1,53 @@ #ifndef ESCHER_INPUT_VIEW_CONTROLLER_H #define ESCHER_INPUT_VIEW_CONTROLLER_H +#include +#include #include #include #include #include -class InputViewController : public ModalViewController, TextFieldDelegate { +class InputViewController : public ModalViewController, TextFieldDelegate, ScrollableExpressionViewWithCursorDelegate { public: - InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate); + InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); void edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction); const char * textBody(); + void abortEditionAndDismiss(); + + /* TextFieldDelegate */ bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; - void abortTextFieldEditionAndDismiss(); bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(TextField * textField, const char * text) override; Toolbox * toolboxForTextField(TextField * textFied) override; + + /* ScrollableExpressionViewWithCursorDelegate */ + bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + private: - class TextFieldController : public ViewController { + class EditableExpressionViewController : public ViewController { public: - TextFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate); + EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); void didBecomeFirstResponder() override; - View * view() override; - TextField * textField(); + View * view() override { return &m_editableExpressionView; } + EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } private: - class ContentView : public Responder, public View { - public: - ContentView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate); - void didBecomeFirstResponder() override; - TextField * textField(); - void drawRect(KDContext * ctx, KDRect rect) const override; - KDSize minimalSizeForOptimalDisplay() const override; - private: - View * subviewAtIndex(int index) override; - int numberOfSubviews() const override; - void layoutSubviews() override; - constexpr static KDCoordinate k_inputHeight = 37; - constexpr static KDCoordinate k_separatorThickness = 1; - constexpr static KDCoordinate k_textMargin = 5; - TextField m_textField; - char m_textBody[TextField::maxBufferSize()]; - }; - ContentView m_view; + EditableExpressionView m_editableExpressionView; }; - TextFieldController m_textFieldController; + bool inputViewDidFinishEditing(); + bool inputViewDidAbortEditing(); + EditableExpressionViewController m_editableExpressionViewController; Invocation m_successAction; Invocation m_failureAction; TextFieldDelegate * m_textFieldDelegate; + ScrollableExpressionViewWithCursorDelegate * m_scrollableExpressionViewWithCursorDelegate; + bool m_inputViewHeightIsMaximal; }; #endif diff --git a/escher/include/escher/modal_view_controller.h b/escher/include/escher/modal_view_controller.h index ae466b820..3a326a12d 100644 --- a/escher/include/escher/modal_view_controller.h +++ b/escher/include/escher/modal_view_controller.h @@ -17,6 +17,8 @@ public: bool isDisplayingModal(); void viewWillAppear() override; void viewDidDisappear() override; +protected: + void reloadView(); private: class ContentView : public View { public: @@ -29,6 +31,7 @@ private: KDCoordinate topMargin, KDCoordinate leftMargin, KDCoordinate bottomMargin, KDCoordinate rightMargin); void dismissModalView(); bool isDisplayingModal() const; + void reload(); private: KDRect frame() const; View * m_regularView; diff --git a/escher/include/escher/scrollable_expression_view_with_cursor.h b/escher/include/escher/scrollable_expression_view_with_cursor.h new file mode 100644 index 000000000..7983e0ab7 --- /dev/null +++ b/escher/include/escher/scrollable_expression_view_with_cursor.h @@ -0,0 +1,40 @@ +#ifndef ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H +#define ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H + +#include +#include +#include +#include + +class ScrollableExpressionViewWithCursor : public ScrollableView, public ScrollViewDataSource { +public: + ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ScrollableExpressionViewWithCursorDelegate * delegate = nullptr); + void setDelegate(ScrollableExpressionViewWithCursorDelegate * delegate) { m_delegate = delegate; } + ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } + bool isEditing() const; + void setEditing(bool isEditing); + void clearLayout(); + void scrollToCursor(); + void reload(); + + /* Responder */ + Toolbox * toolbox() override; + bool handleEvent(Ion::Events::Event event) override; + + bool scrollableExpressionViewWithCursorShouldFinishEditing(Ion::Events::Event event); + + void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); + void insertLayoutFromTextAtCursor(const char * text); + + /* View */ + KDSize minimalSizeForOptimalDisplay() const override; + +protected: + virtual bool privateHandleEvent(Ion::Events::Event event); + bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); + ExpressionViewWithCursor m_expressionViewWithCursor; +private: + ScrollableExpressionViewWithCursorDelegate * m_delegate; +}; + +#endif diff --git a/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h b/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h new file mode 100644 index 000000000..56b22b337 --- /dev/null +++ b/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h @@ -0,0 +1,19 @@ +#ifndef ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H +#define ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H + +#include +#include + +class ScrollableExpressionViewWithCursor; + +class ScrollableExpressionViewWithCursorDelegate { +public: + virtual bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; + virtual bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; + virtual bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { return false; } + virtual bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { return false; } + virtual void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) {} + virtual Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) = 0; +}; + +#endif diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index a4de32044..359d129cf 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -1,212 +1,137 @@ #include -#include -#include -#include +#include #include -EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : - ScrollableView(parentResponder, &m_expressionViewWithCursor, this), - m_expressionViewWithCursor(expressionLayout), - m_delegate(delegate) +EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : + Responder(parentResponder), + View(), + m_textField(parentResponder, m_textBody, m_textBody, k_bufferLength, textFieldDelegate, false), + m_scrollableExpressionViewWithCursor(parentResponder, new Poincare::HorizontalLayout(), scrollableExpressionViewWithCursorDelegate) { + m_textBody[0] = 0; +} + +void EditableExpressionView::setEditing(bool isEditing, bool reinitDraftBuffer) { + if (editionIsInTextField()) { + m_textField.setEditing(isEditing, reinitDraftBuffer); + } + if (reinitDraftBuffer) { + m_scrollableExpressionViewWithCursor.clearLayout(); + } + m_scrollableExpressionViewWithCursor.setEditing(isEditing); } bool EditableExpressionView::isEditing() const { - return m_expressionViewWithCursor.isEditing(); + return editionIsInTextField() ? m_textField.isEditing() : m_scrollableExpressionViewWithCursor.isEditing(); } -void EditableExpressionView::setEditing(bool isEditing) { - m_expressionViewWithCursor.setEditing(isEditing); +const char * EditableExpressionView::text() { + if (!editionIsInTextField()) { + m_scrollableExpressionViewWithCursor.expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(m_textBody, k_bufferLength); + } + return m_textBody; } -void EditableExpressionView::scrollToCursor() { - scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); +void EditableExpressionView::setText(const char * text) { + if (editionIsInTextField()) { + m_textField.setText(text); + } + m_scrollableExpressionViewWithCursor.clearLayout(); + if (strlen(text) > 0) { + m_scrollableExpressionViewWithCursor.insertLayoutFromTextAtCursor(text); + } } -Toolbox * EditableExpressionView::toolbox() { - if (m_delegate) { - return m_delegate->toolboxForEditableExpressionView(this); - } - return nullptr; -} - -bool EditableExpressionView::handleEvent(Ion::Events::Event event) { - KDSize previousSize = minimalSizeForOptimalDisplay(); - bool shouldRecomputeLayout = false; - if (privateHandleMoveEvent(event, &shouldRecomputeLayout)) { - if (!shouldRecomputeLayout) { - m_expressionViewWithCursor.cursorPositionChanged(); - scrollToCursor(); - return true; - } - reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->editableExpressionViewDidChangeSize(this); - reload(); - } - return true; - } - if (privateHandleEvent(event)) { - reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->editableExpressionViewDidChangeSize(this); - reload(); - } - return true; - } - return false; -} - -bool EditableExpressionView::editableExpressionViewShouldFinishEditing(Ion::Events::Event event) { - return m_delegate->editableExpressionViewShouldFinishEditing(this, event); -} - -KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { - return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); -} - -bool EditableExpressionView::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { - if (event == Ion::Events::Left) { - return m_expressionViewWithCursor.cursor()->moveLeft(shouldRecomputeLayout); - } - if (event == Ion::Events::Right) { - return m_expressionViewWithCursor.cursor()->moveRight(shouldRecomputeLayout); - } - if (event == Ion::Events::Up) { - return m_expressionViewWithCursor.cursor()->moveUp(shouldRecomputeLayout); - } - if (event == Ion::Events::Down) { - return m_expressionViewWithCursor.cursor()->moveDown(shouldRecomputeLayout); - } - if (event == Ion::Events::ShiftLeft) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); - return true; - } - if (event == Ion::Events::ShiftRight) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - return true; - } - return false; -} - -bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) { - if (m_delegate && m_delegate->editableExpressionViewDidReceiveEvent(this, event)) { - return true; - } - if (Responder::handleEvent(event)) { - /* The only event Responder handles is 'Toolbox' displaying. In that case, - * the EditableExpressionView is forced into editing mode. */ - if (!isEditing()) { - setEditing(true); - } - return true; - } - if (isEditing() && editableExpressionViewShouldFinishEditing(event)) { - setEditing(false); - int bufferSize = TextField::maxBufferSize(); - char buffer[bufferSize]; - m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); - if (m_delegate->editableExpressionViewDidFinishEditing(this, buffer, event)) { - delete m_expressionViewWithCursor.expressionView()->expressionLayout(); - Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); - m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); - } - return true; - } - if (event == Ion::Events::Division) { - m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); - return true; - } - if (event == Ion::Events::XNT) { - m_expressionViewWithCursor.cursor()->addXNTCharLayout(); - return true; - } - if (event == Ion::Events::Exp) { - m_expressionViewWithCursor.cursor()->addEmptyExponentialLayout(); - return true; - } - if (event == Ion::Events::Power) { - m_expressionViewWithCursor.cursor()->addEmptyPowerLayout(); - return true; - } - if (event == Ion::Events::Sqrt) { - m_expressionViewWithCursor.cursor()->addEmptySquareRootLayout(); - return true; - } - if (event == Ion::Events::Square) { - m_expressionViewWithCursor.cursor()->addEmptySquarePowerLayout(); - return true; - } - if (event.hasText()) { - const char * textToInsert = event.text(); - if (textToInsert[1] == 0) { - if (textToInsert[0] == Ion::Charset::MultiplicationSign) { - const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - m_expressionViewWithCursor.cursor()->insertText(middleDotString); - return true; - } - if (textToInsert[0] == '[' || textToInsert[0] == ']') { - m_expressionViewWithCursor.cursor()->addEmptyMatrixLayout(); - return true; - } - } - m_expressionViewWithCursor.cursor()->insertText(textToInsert); - return true; - } - if (event == Ion::Events::Backspace) { - m_expressionViewWithCursor.cursor()->performBackspace(); - return true; - } - if (event == Ion::Events::Paste) { - if (!isEditing()) { - setEditing(true); - } - insertLayoutFromTextAtCursor(Clipboard::sharedClipboard()->storedText()); - return true; - } - return false; -} - -void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout) { - if (layout == nullptr) { +void EditableExpressionView::insertText(const char * text) { + if (editionIsInTextField()) { + m_textField.setEditing(true, false); + m_textField.insertTextAtLocation(text, m_textField.cursorLocation()); + m_textField.setCursorLocation(m_textField.cursorLocation() + strlen(text)); return; } - KDSize previousSize = minimalSizeForOptimalDisplay(); - m_expressionViewWithCursor.cursor()->addLayout(layout); - if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { - static_cast(layout)->addGreySquares(); - } - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->editableExpressionViewDidChangeSize(this); - } + m_scrollableExpressionViewWithCursor.setEditing(true); + m_scrollableExpressionViewWithCursor.insertLayoutFromTextAtCursor(text); } -void EditableExpressionView::insertLayoutFromTextAtCursor(const char * text) { - Poincare::Expression * expression = Poincare::Expression::parse(text); - if (expression != nullptr) { - Poincare::ExpressionLayout * layout = expression->createLayout(); - delete expression; - insertLayoutAtCursor(layout, layout); - reload(); +View * EditableExpressionView::subviewAtIndex(int index) { + assert(index == 0); + if (editionIsInTextField()) { + return &m_textField; + } + return &m_scrollableExpressionViewWithCursor; +} + +void EditableExpressionView::layoutSubviews() { + KDRect inputViewFrame(k_leftMargin, k_separatorThickness, bounds().width() - k_leftMargin, bounds().height() - k_separatorThickness); + if (editionIsInTextField()) { + m_textField.setFrame(inputViewFrame); + m_scrollableExpressionViewWithCursor.setFrame(KDRectZero); return; } - m_expressionViewWithCursor.cursor()->insertText(text); - reload(); + m_scrollableExpressionViewWithCursor.setFrame(inputViewFrame); + m_textField.setFrame(KDRectZero); } void EditableExpressionView::reload() { - m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); - m_expressionViewWithCursor.cursorPositionChanged(); layoutSubviews(); - scrollToCursor(); markRectAsDirty(bounds()); } + +void EditableExpressionView::drawRect(KDContext * ctx, KDRect rect) const { + // Draw the separator + ctx->fillRect(KDRect(0, 0, bounds().width(), k_separatorThickness), Palette::GreyMiddle); + // Color the left margin + ctx->fillRect(KDRect(0, k_separatorThickness, k_leftMargin, bounds().height() - k_separatorThickness), m_textField.backgroundColor()); + if (!editionIsInTextField()) { + // Color the upper margin + ctx->fillRect(KDRect(0, k_separatorThickness, bounds().width(), k_verticalExpressionViewMargin), m_textField.backgroundColor()); + } +} + +void EditableExpressionView::didBecomeFirstResponder() { + if (editionIsInTextField()) { + app()->setFirstResponder(&m_textField); + return; + } + app()->setFirstResponder(&m_scrollableExpressionViewWithCursor); +} + +bool EditableExpressionView::handleEvent(Ion::Events::Event event) { + return editionIsInTextField() ? m_textField.handleEvent(event) : m_scrollableExpressionViewWithCursor.handleEvent(event); +} + +KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { + return KDSize(0, inputViewHeight()); +} + +bool EditableExpressionView::editionIsInTextField() const { + return Poincare::Preferences::sharedPreferences()->editionMode() == Poincare::Preferences::EditionMode::Edition1D; +} + +bool EditableExpressionView::isEmpty() const { + if (editionIsInTextField()) { + return m_textField.draftTextLength() == 0; + } + Poincare::ExpressionLayout * layout = const_cast(&m_scrollableExpressionViewWithCursor)->expressionViewWithCursor()->expressionView()->expressionLayout(); + return !layout->hasText(); +} + +bool EditableExpressionView::heightIsMaximal() const { + return inputViewHeight() == k_separatorThickness + k_verticalExpressionViewMargin + maximalHeight(); +} + +KDCoordinate EditableExpressionView::inputViewHeight() const { + if (editionIsInTextField()) { + return k_separatorThickness + k_textFieldHeight; + } + return k_separatorThickness + + k_verticalExpressionViewMargin + + min(maximalHeight(), + max(k_textFieldHeight, + m_scrollableExpressionViewWithCursor.minimalSizeForOptimalDisplay().height() + + k_verticalExpressionViewMargin)); +} + +KDCoordinate EditableExpressionView::maximalHeight() const { + return 0.6*Ion::Display::Height; +} diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 22fd62fa1..fb89c3d62 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -1,89 +1,47 @@ #include #include #include +#include #include -InputViewController::TextFieldController::ContentView::ContentView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate) : - Responder(parentResponder), - View(), - m_textField(this, m_textBody, m_textBody, TextField::maxBufferSize(), textFieldDelegate, false) -{ - m_textBody[0] = 0; -} - -void InputViewController::TextFieldController::ContentView::didBecomeFirstResponder() { - app()->setFirstResponder(&m_textField); -} - -TextField * InputViewController::TextFieldController::ContentView::textField() { - return &m_textField; -} - -void InputViewController::TextFieldController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect(KDRect(0, 0, bounds().width(), k_separatorThickness), Palette::GreyMiddle); - ctx->fillRect(KDRect(0, k_separatorThickness, k_textMargin, bounds().height()-k_separatorThickness), m_textField.backgroundColor()); -} - -KDSize InputViewController::TextFieldController::ContentView::minimalSizeForOptimalDisplay() const { - return KDSize(0, k_inputHeight); -} - -int InputViewController::TextFieldController::ContentView::numberOfSubviews() const { - return 1; -} - -View * InputViewController::TextFieldController::ContentView::subviewAtIndex(int index) { - return &m_textField; -} - -void InputViewController::TextFieldController::ContentView::layoutSubviews() { - m_textField.setFrame(KDRect(k_textMargin, k_separatorThickness, bounds().width()-k_textMargin, bounds().height())); -} - -InputViewController::TextFieldController::TextFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate) : +InputViewController::EditableExpressionViewController::EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : ViewController(parentResponder), - m_view(this, textFieldDelegate) + m_editableExpressionView(this, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) { } -View * InputViewController::TextFieldController::view() { - return &m_view; +void InputViewController::EditableExpressionViewController::didBecomeFirstResponder() { + app()->setFirstResponder(&m_editableExpressionView); } -void InputViewController::TextFieldController::didBecomeFirstResponder() { - app()->setFirstResponder(&m_view); -} - -TextField * InputViewController::TextFieldController::textField() { - return m_view.textField(); -} - -InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate) : +InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : ModalViewController(parentResponder, child), - m_textFieldController(this, this), + m_editableExpressionViewController(this, this, this), m_successAction(Invocation(nullptr, nullptr)), m_failureAction(Invocation(nullptr, nullptr)), - m_textFieldDelegate(textFieldDelegate) + m_textFieldDelegate(textFieldDelegate), + m_scrollableExpressionViewWithCursorDelegate(scrollableExpressionViewWithCursorDelegate), + m_inputViewHeightIsMaximal(false) { } const char * InputViewController::textBody() { - return m_textFieldController.textField()->text(); + return m_editableExpressionViewController.editableExpressionView()->text(); } void InputViewController::edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction) { m_successAction = Invocation(successAction, context); m_failureAction = Invocation(failureAction, context); - displayModalViewController(&m_textFieldController, 1.0f, 1.0f); - m_textFieldController.textField()->handleEvent(event); + displayModalViewController(&m_editableExpressionViewController, 1.0f, 1.0f); if (initialText != nullptr) { - m_textFieldController.textField()->insertTextAtLocation(initialText, 0); - m_textFieldController.textField()->setCursorLocation(strlen(initialText)); + m_editableExpressionViewController.editableExpressionView()->setText(initialText); + //TODO is the editableExpressionView always clean before we set the text? Otherwise, problem if there is no initial text. } + m_editableExpressionViewController.editableExpressionView()->handleEvent(event); } -void InputViewController::abortTextFieldEditionAndDismiss() { - m_textFieldController.textField()->setEditing(false); +void InputViewController::abortEditionAndDismiss() { + m_editableExpressionViewController.editableExpressionView()->setEditing(false); dismissModalViewController(); } @@ -92,15 +50,11 @@ bool InputViewController::textFieldShouldFinishEditing(TextField * textField, Io } bool InputViewController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { - m_successAction.perform(this); - dismissModalViewController(); - return true; + return inputViewDidFinishEditing(); } bool InputViewController::textFieldDidAbortEditing(TextField * textField, const char * text) { - m_failureAction.perform(this); - dismissModalViewController(); - return true; + return inputViewDidAbortEditing(); } bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) { @@ -110,3 +64,44 @@ bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::E Toolbox * InputViewController::toolboxForTextField(TextField * textField) { return m_textFieldDelegate->toolboxForTextField(textField); } +bool InputViewController::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + return event == Ion::Events::OK || event == Ion::Events::EXE; +} + +bool InputViewController::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { + return m_scrollableExpressionViewWithCursorDelegate->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); +} + +bool InputViewController::scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { + return inputViewDidFinishEditing(); +} + +bool InputViewController::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { + return inputViewDidAbortEditing(); +} + +void InputViewController::scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + // Reload the view only if the EditableExpressionView height actually changes, + // i.e. not if the height is already maximal and stays maximal. + bool newInputViewHeightIsMaximal = m_editableExpressionViewController.editableExpressionView()->heightIsMaximal(); + if (!m_inputViewHeightIsMaximal || !newInputViewHeightIsMaximal) { + m_inputViewHeightIsMaximal = newInputViewHeightIsMaximal; + reloadView(); + } +} + +Toolbox * InputViewController::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + return m_scrollableExpressionViewWithCursorDelegate->toolboxForScrollableExpressionViewWithCursor(scrollableExpressionViewWithCursor); +} + +bool InputViewController::inputViewDidFinishEditing() { + m_successAction.perform(this); + dismissModalViewController(); + return true; +} + +bool InputViewController::inputViewDidAbortEditing() { + m_failureAction.perform(this); + dismissModalViewController(); + return true; +} diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index 5780b448f..1f7aaed18 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -95,6 +95,11 @@ bool ModalViewController::ContentView::isDisplayingModal() const { return m_isDisplayingModal; } +void ModalViewController::ContentView::reload() { + markRectAsDirty(frame()); + layoutSubviews(); +} + ModalViewController::ModalViewController(Responder * parentResponder, ViewController * child) : ViewController(parentResponder), m_contentView(), @@ -162,3 +167,7 @@ void ModalViewController::viewDidDisappear() { } m_regularViewController->viewDidDisappear(); } + +void ModalViewController::reloadView() { + m_contentView.reload(); +} diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp new file mode 100644 index 000000000..4ce4d5c6a --- /dev/null +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +ScrollableExpressionViewWithCursor::ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ScrollableExpressionViewWithCursorDelegate * delegate) : + ScrollableView(parentResponder, &m_expressionViewWithCursor, this), + m_expressionViewWithCursor(expressionLayout), + m_delegate(delegate) +{ +} + +bool ScrollableExpressionViewWithCursor::isEditing() const { + return m_expressionViewWithCursor.isEditing(); +} + +void ScrollableExpressionViewWithCursor::setEditing(bool isEditing) { + m_expressionViewWithCursor.setEditing(isEditing); +} + +void ScrollableExpressionViewWithCursor::clearLayout() { + delete m_expressionViewWithCursor.expressionView()->expressionLayout(); + Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); + m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); +} + +void ScrollableExpressionViewWithCursor::scrollToCursor() { + scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); +} + +Toolbox * ScrollableExpressionViewWithCursor::toolbox() { + if (m_delegate) { + return m_delegate->toolboxForScrollableExpressionViewWithCursor(this); + } + return nullptr; +} + +bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { + KDSize previousSize = minimalSizeForOptimalDisplay(); + bool shouldRecomputeLayout = false; + if (privateHandleMoveEvent(event, &shouldRecomputeLayout)) { + if (!shouldRecomputeLayout) { + m_expressionViewWithCursor.cursorPositionChanged(); + scrollToCursor(); + return true; + } + reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + reload(); + } + return true; + } + if (privateHandleEvent(event)) { + reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + reload(); + } + return true; + } + return false; +} + +bool ScrollableExpressionViewWithCursor::scrollableExpressionViewWithCursorShouldFinishEditing(Ion::Events::Event event) { + return m_delegate->scrollableExpressionViewWithCursorShouldFinishEditing(this, event); +} + +KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { + return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); +} + +bool ScrollableExpressionViewWithCursor::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { + if (event == Ion::Events::Left) { + return m_expressionViewWithCursor.cursor()->moveLeft(shouldRecomputeLayout); + } + if (event == Ion::Events::Right) { + return m_expressionViewWithCursor.cursor()->moveRight(shouldRecomputeLayout); + } + if (event == Ion::Events::Up) { + return m_expressionViewWithCursor.cursor()->moveUp(shouldRecomputeLayout); + } + if (event == Ion::Events::Down) { + return m_expressionViewWithCursor.cursor()->moveDown(shouldRecomputeLayout); + } + if (event == Ion::Events::ShiftLeft) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); + return true; + } + if (event == Ion::Events::ShiftRight) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + return true; + } + return false; +} + +bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event event) { + if (m_delegate && m_delegate->scrollableExpressionViewWithCursorDidReceiveEvent(this, event)) { + return true; + } + if (Responder::handleEvent(event)) { + /* The only event Responder handles is 'Toolbox' displaying. In that case, + * the ScrollableExpressionViewWithCursor is forced into editing mode. */ + if (!isEditing()) { + setEditing(true); + } + return true; + } + if (isEditing() && scrollableExpressionViewWithCursorShouldFinishEditing(event)) { + setEditing(false); + int bufferSize = TextField::maxBufferSize(); + char buffer[bufferSize]; + m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + if (m_delegate->scrollableExpressionViewWithCursorDidFinishEditing(this, buffer, event)) { + delete m_expressionViewWithCursor.expressionView()->expressionLayout(); + Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); + m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); + } + return true; + } + if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { + setEditing(true); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + return true; + } + if (event == Ion::Events::Division) { + m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); + return true; + } + if (event == Ion::Events::XNT) { + m_expressionViewWithCursor.cursor()->addXNTCharLayout(); + return true; + } + if (event == Ion::Events::Exp) { + m_expressionViewWithCursor.cursor()->addEmptyExponentialLayout(); + return true; + } + if (event == Ion::Events::Power) { + m_expressionViewWithCursor.cursor()->addEmptyPowerLayout(); + return true; + } + if (event == Ion::Events::Sqrt) { + m_expressionViewWithCursor.cursor()->addEmptySquareRootLayout(); + return true; + } + if (event == Ion::Events::Square) { + m_expressionViewWithCursor.cursor()->addEmptySquarePowerLayout(); + return true; + } + if (event.hasText()) { + const char * textToInsert = event.text(); + if (textToInsert[1] == 0) { + if (textToInsert[0] == Ion::Charset::MultiplicationSign) { + const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; + m_expressionViewWithCursor.cursor()->insertText(middleDotString); + return true; + } + if (textToInsert[0] == '[' || textToInsert[0] == ']') { + m_expressionViewWithCursor.cursor()->addEmptyMatrixLayout(); + return true; + } + } + m_expressionViewWithCursor.cursor()->insertText(textToInsert); + return true; + } + if (event == Ion::Events::Backspace) { + m_expressionViewWithCursor.cursor()->performBackspace(); + return true; + } + if (event == Ion::Events::Paste) { + if (!isEditing()) { + setEditing(true); + } + insertLayoutFromTextAtCursor(Clipboard::sharedClipboard()->storedText()); + return true; + } + return false; +} + +void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout) { + if (layout == nullptr) { + return; + } + KDSize previousSize = minimalSizeForOptimalDisplay(); + m_expressionViewWithCursor.cursor()->addLayout(layout); + if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { + static_cast(layout)->addGreySquares(); + } + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + reload(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + } +} + +void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char * text) { + Poincare::Expression * expression = Poincare::Expression::parse(text); + if (expression != nullptr) { + Poincare::ExpressionLayout * layout = expression->createLayout(); + delete expression; + insertLayoutAtCursor(layout, layout); + reload(); + return; + } + m_expressionViewWithCursor.cursor()->insertText(text); + reload(); +} + +void ScrollableExpressionViewWithCursor::reload() { + m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); + m_expressionViewWithCursor.cursorPositionChanged(); + layoutSubviews(); + scrollToCursor(); + markRectAsDirty(bounds()); +} diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 38ef59c82..e97f4e73d 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -94,6 +94,7 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Other */ + bool hasText() const; virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a brother fraction: should the layout be * inserted in the numerator (or denominator)? For instance, 1+2|3-4 should diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 9faf5b7e0..1b22d51b7 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -283,6 +283,12 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * sh return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); } +bool ExpressionLayout::hasText() const { + // A layout has text if it is not empty and it is not an horizontal layout + // with no child or with one child with no text. + return !isEmpty() && !(isHorizontal() && (numberOfChildren() == 0 || (numberOfChildren() == 1 && !child(0)->hasText()))); +} + bool ExpressionLayout::canBeOmittedMultiplicationLeftFactor() const { // WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when // isCollapsable is true too. If isCollapsable changes, it might not be the From a2c0eaa20ba439d60d16b8f7516c2249d1a8993f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 23 Jan 2018 09:53:17 +0100 Subject: [PATCH 215/459] [apps/escher] Remove textFieldDidAbortEditing const char * argument. Also removed the same argument in scrollableExpressionViewWithCursorDidAbortEditing. Change-Id: Iadc6b708cfc0fab44b9fd4edb980cb759d41e8d0 --- apps/calculation/edit_expression_controller.cpp | 14 ++++++++------ apps/calculation/edit_expression_controller.h | 4 ++-- apps/code/console_controller.cpp | 2 +- apps/code/console_controller.h | 2 +- apps/code/menu_controller.cpp | 4 ++-- apps/code/menu_controller.h | 2 +- ...llable_expression_view_with_cursor_delegate.cpp | 4 ++-- ...rollable_expression_view_with_cursor_delegate.h | 2 +- escher/include/escher/input_view_controller.h | 4 ++-- ...rollable_expression_view_with_cursor_delegate.h | 2 +- escher/include/escher/text_field_delegate.h | 2 +- escher/src/input_view_controller.cpp | 4 ++-- escher/src/text_field.cpp | 2 +- 13 files changed, 25 insertions(+), 23 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 45d9c2474..68667378e 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -84,9 +84,9 @@ bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField return inputViewDidFinishEditing(text, event); } -bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField, const char * text) { +bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) { assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); - return inputViewDidAbortEditing(text); + return inputViewDidAbortEditing(textField->text()); } bool EditExpressionController::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { @@ -102,9 +102,9 @@ bool EditExpressionController::scrollableExpressionViewWithCursorDidFinishEditin return inputViewDidFinishEditing(text, event); } -bool EditExpressionController::scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { +bool EditExpressionController::scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); - return inputViewDidAbortEditing(text); + return inputViewDidAbortEditing(nullptr); } void EditExpressionController::scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { @@ -157,8 +157,10 @@ bool EditExpressionController::inputViewDidFinishEditing(const char * text, Ion: } bool EditExpressionController::inputViewDidAbortEditing(const char * text) { - ((ContentView *)view())->editableExpressionView()->setEditing(true, true); - ((ContentView *)view())->editableExpressionView()->setText(text); + if (text != nullptr) { + ((ContentView *)view())->editableExpressionView()->setEditing(true, true); + ((ContentView *)view())->editableExpressionView()->setText(text); + } return false; } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index a2b64b951..864b53aba 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -24,12 +24,12 @@ public: /* TextFieldDelegate */ bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(::TextField * textField, const char * text) override; + bool textFieldDidAbortEditing(::TextField * textField) override; /* ScrollableExpressionViewWithCursorDelegate */ bool scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; bool scrollableExpressionViewWithCursorDidFinishEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; void scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; private: diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index eba0b1396..8d12b0e0c 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -252,7 +252,7 @@ bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const c return true; } -bool ConsoleController::textFieldDidAbortEditing(TextField * textField, const char * text) { +bool ConsoleController::textFieldDidAbortEditing(TextField * textField) { stackViewController()->pop(); return true; } diff --git a/apps/code/console_controller.h b/apps/code/console_controller.h index 1037ca76e..78d3a4705 100644 --- a/apps/code/console_controller.h +++ b/apps/code/console_controller.h @@ -56,7 +56,7 @@ public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(TextField * textField, const char * text) override; + bool textFieldDidAbortEditing(TextField * textField) override; Toolbox * toolboxForTextField(TextField * textField) override; // MicroPython::ExecutionEnvironment diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 5c3444d19..c65fd7657 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -307,8 +307,8 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char return false; } -bool MenuController::textFieldDidAbortEditing(TextField * textField, const char * text) { - if (strlen(text) <= strlen(ScriptStore::k_scriptExtension)) { +bool MenuController::textFieldDidAbortEditing(TextField * textField) { + if (strlen(textField->text()) <= strlen(ScriptStore::k_scriptExtension)) { // The previous text was an empty name. Use a numbered default script name. char numberedDefaultName[k_defaultScriptNameMaxSize]; numberedDefaultScriptName(numberedDefaultName); diff --git a/apps/code/menu_controller.h b/apps/code/menu_controller.h index af4441f80..89c5c6f4f 100644 --- a/apps/code/menu_controller.h +++ b/apps/code/menu_controller.h @@ -52,7 +52,7 @@ public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(TextField * textField, const char * text) override; + bool textFieldDidAbortEditing(TextField * textField) override; bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) override; Toolbox * toolboxForTextField(TextField * textField) override { return nullptr; } diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp b/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp index 5174721ff..84a29933c 100644 --- a/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp +++ b/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp @@ -16,8 +16,8 @@ bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCur return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidFinishEditing(scrollableExpressionViewWithCursor, text, event); } -bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidAbortEditing(scrollableExpressionViewWithCursor, text); +bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidAbortEditing(scrollableExpressionViewWithCursor); } void ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.h b/apps/shared/scrollable_expression_view_with_cursor_delegate.h index 589f6a8db..093cecf71 100644 --- a/apps/shared/scrollable_expression_view_with_cursor_delegate.h +++ b/apps/shared/scrollable_expression_view_with_cursor_delegate.h @@ -11,7 +11,7 @@ public: bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; private: diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index a2f037758..090b6bce1 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -19,14 +19,14 @@ public: bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(TextField * textField, const char * text) override; + bool textFieldDidAbortEditing(TextField * textField) override; Toolbox * toolboxForTextField(TextField * textFied) override; /* ScrollableExpressionViewWithCursorDelegate */ bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) override; + bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; diff --git a/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h b/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h index 56b22b337..c2bf5fe96 100644 --- a/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h +++ b/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h @@ -11,7 +11,7 @@ public: virtual bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; virtual bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; virtual bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { return false; } - virtual bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { return false; } + virtual bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { return false; } virtual void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) {} virtual Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) = 0; }; diff --git a/escher/include/escher/text_field_delegate.h b/escher/include/escher/text_field_delegate.h index ad2300e93..349555402 100644 --- a/escher/include/escher/text_field_delegate.h +++ b/escher/include/escher/text_field_delegate.h @@ -8,7 +8,7 @@ public: virtual bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) = 0; virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) = 0; virtual bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { return false; }; - virtual bool textFieldDidAbortEditing(TextField * textField, const char * text) {return false;}; + virtual bool textFieldDidAbortEditing(TextField * textField) {return false;}; virtual bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) { return returnValue; }; virtual Toolbox * toolboxForTextField(TextField * textField) = 0; }; diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index fb89c3d62..ac5fa9956 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -53,7 +53,7 @@ bool InputViewController::textFieldDidFinishEditing(TextField * textField, const return inputViewDidFinishEditing(); } -bool InputViewController::textFieldDidAbortEditing(TextField * textField, const char * text) { +bool InputViewController::textFieldDidAbortEditing(TextField * textField) { return inputViewDidAbortEditing(); } @@ -76,7 +76,7 @@ bool InputViewController::scrollableExpressionViewWithCursorDidFinishEditing(Scr return inputViewDidFinishEditing(); } -bool InputViewController::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text) { +bool InputViewController::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { return inputViewDidAbortEditing(); } diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index f448fbf11..62abe0330 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -361,7 +361,7 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back && isEditing()) { setEditing(false); reloadScroll(); - m_delegate->textFieldDidAbortEditing(this, text()); + m_delegate->textFieldDidAbortEditing(this); return true; } if (event == Ion::Events::Clear && isEditing()) { From bea0d208c193e98c5ea79af4c8c24651da921fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 23 Jan 2018 09:57:30 +0100 Subject: [PATCH 216/459] [escher] ScrollableExpressionViewWithCursor handles Back event. Change-Id: I8d98040e34740b48ee8285e5356ea94cd48f2e98 --- escher/src/scrollable_expression_view_with_cursor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 4ce4d5c6a..7a14de953 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -131,6 +131,11 @@ bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event e m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); return true; } + if (event == Ion::Events::Back && isEditing()) { + setEditing(false); + m_delegate->scrollableExpressionViewWithCursorDidAbortEditing(this); + return true; + } if (event == Ion::Events::Division) { m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); return true; From 2929409d3e931e03b58f83f36bfd93075f583544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 23 Jan 2018 10:24:38 +0100 Subject: [PATCH 217/459] [escher] Comment about implementing a split view for InputViewController Change-Id: I46b50bac50f958fad956696a02d334a690b0a2b2 --- escher/include/escher/input_view_controller.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 090b6bce1..f8bc02bd5 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -8,6 +8,9 @@ #include #include +/* TODO Implement a split view. Because we use a modal view, the main view is + * redrawn underneath the modal view, which is visible and ugly. */ + class InputViewController : public ModalViewController, TextFieldDelegate, ScrollableExpressionViewWithCursorDelegate { public: InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); From 71263285c5d7bcc8f3afbb1393462552a50bfe4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 23 Jan 2018 16:57:16 +0100 Subject: [PATCH 218/459] [poincare] Fixed serialization bug of empty Horizontal layouts. Change-Id: I6a71eb34ae1f734ed86590cadaf086e1c3a1bd44 --- poincare/src/layout/horizontal_layout.cpp | 11 +++++++++++ poincare/src/layout/horizontal_layout.h | 4 +--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index baf038e23..d41889f05 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -289,6 +289,17 @@ void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); } +int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize) const { + if (numberOfChildren() == 0) { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; + } + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); +} + bool HorizontalLayout::isEmpty() const { if (m_numberOfChildren == 1 && child(0)->isEmpty()) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index f6185545f..39b38d82d 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -31,9 +31,7 @@ public: void removeChildAtIndex(int index, bool deleteAfterRemoval) override; /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); - } + int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Other */ bool isHorizontal() const override { return true; } From b3c5b93d2169b71a885c9c6fcb10f730effb012a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 23 Jan 2018 17:13:58 +0100 Subject: [PATCH 219/459] [escher] Fix invalid pointer access. A layout might be deleted after calling addLayout: for instance, if the layout is horizontal and added as a child to another horizontal layout, its children are stolen and it is deleted. Change-Id: Icc2c344dd7878d7df2ec72f014a98dd0d27dc258 --- escher/src/scrollable_expression_view_with_cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 7a14de953..3f1f11a4f 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -195,10 +195,10 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi return; } KDSize previousSize = minimalSizeForOptimalDisplay(); - m_expressionViewWithCursor.cursor()->addLayout(layout); if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } + m_expressionViewWithCursor.cursor()->addLayout(layout); m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); reload(); From b9a7973961c955ce21422546a63e44c0619fa9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 24 Jan 2018 10:15:16 +0100 Subject: [PATCH 220/459] [escher/poincare] Move the cursor when inserting a layout (if wanted). The new pointed layout can be specified. If not, the cursor will be on the right of the new layout. Change-Id: I5e0c37cf6365447f8eaf354dc5e86a24c6981034 --- apps/math_toolbox.cpp | 6 +- ...scrollable_expression_view_with_cursor.cpp | 12 ++-- poincare/include/poincare/expression_layout.h | 4 +- .../poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 4 ++ poincare/src/layout/empty_visible_layout.cpp | 26 ++++---- poincare/src/layout/empty_visible_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 65 ++++++++++--------- poincare/src/layout/horizontal_layout.cpp | 25 +++++++ poincare/src/layout/horizontal_layout.h | 1 + 10 files changed, 98 insertions(+), 48 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 63639f81f..d42924e17 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -133,9 +133,10 @@ void MathToolbox::actionForScrollableExpressionViewWithCursor(void * sender, con } ExpressionLayout * resultLayout = resultExpression->createLayout(); // Find the pointed layout. - ExpressionLayout * pointedLayout = resultLayout; + ExpressionLayout * pointedLayout = nullptr; if (resultLayout->isHorizontal()) { // If the layout is horizontal, pick the first open parenthesis. + // For now, all horizontal layouts in MathToolbox have parentheses. for (int i = 0; i < resultLayout->numberOfChildren(); i++) { if (resultLayout->editableChild(i)->isLeftParenthesis()) { pointedLayout = resultLayout->editableChild(i); @@ -146,7 +147,8 @@ void MathToolbox::actionForScrollableExpressionViewWithCursor(void * sender, con // Else, if the layout has children, pick the first one. pointedLayout = resultLayout->editableChild(0); } - // Insert the layout + // Insert the layout. If pointedLayout is nullptr, the cursor will be on the + // right of the inserted layout. expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); } diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 3f1f11a4f..89eb1d303 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -198,9 +198,13 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } - m_expressionViewWithCursor.cursor()->addLayout(layout); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + if (pointedLayout != nullptr) { + m_expressionViewWithCursor.cursor()->addLayout(layout); + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + } else { + m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); + } reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { @@ -213,7 +217,7 @@ void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char if (expression != nullptr) { Poincare::ExpressionLayout * layout = expression->createLayout(); delete expression; - insertLayoutAtCursor(layout, layout); + insertLayoutAtCursor(layout, nullptr); reload(); return; } diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index e97f4e73d..60bfeea85 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -50,7 +50,8 @@ public: // Add virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } - virtual void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + void addBrotherAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); // Replace virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace); @@ -129,6 +130,7 @@ protected: ExpressionLayout ** childResult, void * resultPosition, int * resultScore); + virtual void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor); ExpressionLayout * m_parent; KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 7145d3c81..7657d5e18 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -40,6 +40,7 @@ public: /* Edition */ void addLayout(ExpressionLayout * layout); + void addLayoutAndMoveCursor(ExpressionLayout * layout); void addEmptyExponentialLayout(); void addFractionLayoutAndCollapseBrothers(); void addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 0923f888e..947dfedf9 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -45,6 +45,10 @@ void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { pointedExpressionLayout()->addBrother(this, layout); } +void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { + pointedExpressionLayout()->addBrotherAndMoveCursor(this, layout); +} + void ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index 5e8517611..244b8d48a 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -17,17 +17,6 @@ ExpressionLayout * EmptyVisibleLayout::clone() const { return layout; } -void EmptyVisibleLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - Color currentColor = m_color; - int indexInParent = m_parent->indexOfChild(this); - ExpressionLayout * parent = m_parent; - replaceWith(brother, true); - if (currentColor == Color::Grey) { - // The parent is a MatrixLayout. - static_cast(parent)->newRowOrColumnAtIndex(indexInParent); - } -} - void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { @@ -95,4 +84,19 @@ void EmptyVisibleLayout::computeBaseline() { m_baselined = true; } +void EmptyVisibleLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { + Color currentColor = m_color; + int indexInParent = m_parent->indexOfChild(this); + ExpressionLayout * parent = m_parent; + replaceWith(brother, true); + if (moveCursor) { + cursor->setPointedExpressionLayout(brother); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + if (currentColor == Color::Grey) { + // The parent is a MatrixLayout. + static_cast(parent)->newRowOrColumnAtIndex(indexInParent); + } +} + } diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 0bab3e9ff..8731a3f55 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -14,7 +14,6 @@ public: }; EmptyVisibleLayout(Color color = Color::Yellow); ExpressionLayout * clone() const override; - void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; @@ -30,6 +29,7 @@ protected: assert(false); return KDPointZero; } + void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; private: constexpr static KDCoordinate k_width = 7; constexpr static KDCoordinate k_height = 13; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 1b22d51b7..958edf102 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -107,36 +107,11 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { } void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - // First, assess the special case when the layout is horizontal. - // If so, add the "brother" as a child. - if (isHorizontal()) { - // If there is only one empty child, remove it before adding the layout. - if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { - removeChildAtIndex(0, true); - } - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - addChildAtIndex(brother, 0); - return; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - addChildAtIndex(brother, numberOfChildren()); - return; - } + privateAddBrother(cursor, brother, false); +} - // If the layout is not horizontal, it must have a parent. - assert(m_parent); - int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; - if (m_parent->isHorizontal()) { - static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex, true); - return; - } - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - replaceWithJuxtapositionOf(brother, this, false); - return; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - replaceWithJuxtapositionOf(this, brother, false); - return; +void ExpressionLayout::addBrotherAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { + privateAddBrother(cursor, brother, true); } ExpressionLayout * ExpressionLayout::replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace) { @@ -374,8 +349,40 @@ void ExpressionLayout::moveCursorInsideAtDirection ( } } +void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { + // The layout must have a parent, because HorizontalLayout overrides + // privateAddBrother and only an HorizontalLayout can be the root layout. + assert(m_parent); + if (m_parent->isHorizontal()) { + int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; + if (moveCursor) { + if (brotherIndex < m_parent->numberOfChildren()) { + cursor->setPointedExpressionLayout(m_parent->editableChild(brotherIndex)); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); + } else { + cursor->setPointedExpressionLayout(m_parent); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + } + static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex, true); + return; + } + ExpressionLayout * juxtapositionLayout = nullptr; + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + juxtapositionLayout = replaceWithJuxtapositionOf(brother, this, false); + } else { + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + juxtapositionLayout = replaceWithJuxtapositionOf(this, brother, false); + } + if (moveCursor) { + cursor->setPointedExpressionLayout(juxtapositionLayout); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } +} + ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace) { assert(m_parent != nullptr); + assert(!m_parent->isHorizontal()); /* One of the children to juxtapose might be "this", so we first have to * replace "this" with an horizontal layout, then add "this" to the layout. */ ExpressionLayout * layout = new HorizontalLayout(); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index d41889f05..815161b80 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -352,6 +352,31 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } +void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { + // Add the "brother" as a child. + // If there is only one empty child, remove it before adding the layout. + if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { + removeChildAtIndex(0, true); + } + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (moveCursor) { + if (numberOfChildren() > 0) { + cursor->setPointedExpressionLayout(editableChild(0)); + } else { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); + } + } + addChildAtIndex(brother, 0); + return; + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + addChildAtIndex(brother, numberOfChildren()); + if (moveCursor) { + cursor->setPointedExpressionLayout(this); + } +} + bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { // Prevent looping fom child to parent if (previousPreviousLayout == this) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 39b38d82d..a0d7bdfaa 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -42,6 +42,7 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; + void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); From f38bbff447e33e38d346abe63d2c0dfe2d383d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 24 Jan 2018 10:20:09 +0100 Subject: [PATCH 221/459] [escher] Fix responder order bug. EditableExpressionView cannot pass the first responder state to one of its children, otherwise Calculation::EditableExpressionView's overriden handleEvent method is never called. Change-Id: Id2b56b9501e67431e860573cf4c62a16651c3958 --- escher/include/escher/editable_expression_view.h | 1 - escher/src/editable_expression_view.cpp | 8 -------- 2 files changed, 9 deletions(-) diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index d0c6e88b8..44d5f867e 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -30,7 +30,6 @@ public: KDSize minimalSizeForOptimalDisplay() const override; /* Responder */ - void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; static constexpr int k_bufferLength = TextField::maxBufferSize(); diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 359d129cf..cc557b04e 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -88,14 +88,6 @@ void EditableExpressionView::drawRect(KDContext * ctx, KDRect rect) const { } } -void EditableExpressionView::didBecomeFirstResponder() { - if (editionIsInTextField()) { - app()->setFirstResponder(&m_textField); - return; - } - app()->setFirstResponder(&m_scrollableExpressionViewWithCursor); -} - bool EditableExpressionView::handleEvent(Ion::Events::Event event) { return editionIsInTextField() ? m_textField.handleEvent(event) : m_scrollableExpressionViewWithCursor.handleEvent(event); } From 4b79175fa8eb5c5f5848df405f69b6d144324a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 25 Jan 2018 17:29:00 +0100 Subject: [PATCH 222/459] [escher] Handle Clear event in ScrollableExpressionViewWithCursor. Change-Id: I8a71a3f866420cd62514a7431f89a468580ff4eb --- escher/src/scrollable_expression_view_with_cursor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 89eb1d303..fd0f07a1b 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -187,6 +187,10 @@ bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event e insertLayoutFromTextAtCursor(Clipboard::sharedClipboard()->storedText()); return true; } + if (event == Ion::Events::Clear && isEditing()) { + clearLayout(); + return true; + } return false; } From 093131302cf38bace834adaf075365515818a743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 11:00:06 +0100 Subject: [PATCH 223/459] [expression_editor] Delete this app. Change-Id: I4c010ce1948f4c04dff526218d6d85a6d34d109e --- apps/expression_editor/Makefile | 23 --- apps/expression_editor/app.cpp | 29 --- apps/expression_editor/app.h | 38 ---- apps/expression_editor/base.universal.i18n | 2 - apps/expression_editor/controller.cpp | 191 ------------------ apps/expression_editor/controller.h | 45 ----- .../expression_and_layout.cpp | 54 ----- .../expression_editor/expression_and_layout.h | 26 --- .../expression_editor_view.cpp | 55 ----- .../expression_editor_view.h | 30 --- .../expression_view_with_cursor.cpp | 49 ----- .../expression_view_with_cursor.h | 35 ---- ...scrollable_expression_view_with_cursor.cpp | 21 -- .../scrollable_expression_view_with_cursor.h | 25 --- apps/expression_editor/test/dummy_test.cpp | 6 - apps/math_toolbox.h | 1 - 16 files changed, 630 deletions(-) delete mode 100644 apps/expression_editor/Makefile delete mode 100644 apps/expression_editor/app.cpp delete mode 100644 apps/expression_editor/app.h delete mode 100644 apps/expression_editor/base.universal.i18n delete mode 100644 apps/expression_editor/controller.cpp delete mode 100644 apps/expression_editor/controller.h delete mode 100644 apps/expression_editor/expression_and_layout.cpp delete mode 100644 apps/expression_editor/expression_and_layout.h delete mode 100644 apps/expression_editor/expression_editor_view.cpp delete mode 100644 apps/expression_editor/expression_editor_view.h delete mode 100644 apps/expression_editor/expression_view_with_cursor.cpp delete mode 100644 apps/expression_editor/expression_view_with_cursor.h delete mode 100644 apps/expression_editor/scrollable_expression_view_with_cursor.cpp delete mode 100644 apps/expression_editor/scrollable_expression_view_with_cursor.h delete mode 100644 apps/expression_editor/test/dummy_test.cpp diff --git a/apps/expression_editor/Makefile b/apps/expression_editor/Makefile deleted file mode 100644 index 137280e8a..000000000 --- a/apps/expression_editor/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -snapshots += ExpressionEditor::App::Snapshot -snapshot_headers += apps/expression_editor/app.h - -app_objs += $(addprefix apps/expression_editor/,\ - app.o\ - controller.o\ - expression_and_layout.o\ - expression_editor_view.o\ - expression_view_with_cursor.o\ - scrollable_expression_view_with_cursor.o\ -) - -i18n_files += $(addprefix apps/expression_editor/,\ - base.universal.i18n\ -) - -tests += $(addprefix apps/expression_editor/test/,\ - dummy_test.cpp\ -) - -test_objs += $(addprefix apps/expression_editor/,\ - expression_view_with_cursor.o\ -) diff --git a/apps/expression_editor/app.cpp b/apps/expression_editor/app.cpp deleted file mode 100644 index 5ef392b9c..000000000 --- a/apps/expression_editor/app.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "app.h" -#include "../i18n.h" - -namespace ExpressionEditor { - -I18n::Message App::Descriptor::name() { - return I18n::Message::ExpressionEditorApp; -} - -I18n::Message App::Descriptor::upperName() { - return I18n::Message::ExpressionEditorAppCapital; -} - -App * App::Snapshot::unpack(Container * container) { - return new App(container, this); -} - -App::Descriptor * App::Snapshot::descriptor() { - static Descriptor descriptor; - return &descriptor; -} - -App::App(Container * container, Snapshot * snapshot) : - ::App(container, snapshot, &m_controller), - m_controller(&m_modalViewController, snapshot->expressionAndLayout()->expressionLayout()) -{ -} - -} diff --git a/apps/expression_editor/app.h b/apps/expression_editor/app.h deleted file mode 100644 index 84b537833..000000000 --- a/apps/expression_editor/app.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef EXPRESSION_EDITOR_APP_H -#define EXPRESSION_EDITOR_APP_H - -#include -#include -#include "controller.h" -#include "expression_and_layout.h" - -namespace ExpressionEditor { - -/* TODO This app is used for creating ExpressionLayout edition. It should be - * removed when the development is finished. */ - -class App : public ::App { -public: - class Descriptor : public ::App::Descriptor { - public: - I18n::Message name() override; - I18n::Message upperName() override; - }; - class Snapshot : public ::App::Snapshot, public SelectableTableViewDataSource { - public: - App * unpack(Container * container) override; - Descriptor * descriptor() override; - ExpressionAndLayout * expressionAndLayout() { return &m_expressionAndLayout; } - private: - ExpressionAndLayout m_expressionAndLayout; - }; - MathToolbox * mathToolbox() { return &m_toolbox; } -private: - App(Container * container, Snapshot * snapshot); - Controller m_controller; - MathToolbox m_toolbox; -}; - -} - -#endif diff --git a/apps/expression_editor/base.universal.i18n b/apps/expression_editor/base.universal.i18n deleted file mode 100644 index 01a156f37..000000000 --- a/apps/expression_editor/base.universal.i18n +++ /dev/null @@ -1,2 +0,0 @@ -ExpressionEditorApp = "ExpressionEdit" -ExpressionEditorAppCapital = "EXPRESSION EDITOR" diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp deleted file mode 100644 index 69ca7ac66..000000000 --- a/apps/expression_editor/controller.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "controller.h" -#include -#include -#include - -using namespace Poincare; - -namespace ExpressionEditor { - -Controller::Controller(Responder * parentResponder, ExpressionLayout * expressionLayout) : - ViewController(parentResponder), - m_view(parentResponder, expressionLayout, &m_cursor), - m_expressionLayout(expressionLayout), - m_resultLayout(nullptr) -{ - m_cursor.setPointedExpressionLayout(expressionLayout); -} - -void Controller::didBecomeFirstResponder() { - m_view.layoutSubviews(); - /* TODO We need the layout to be done in order to scroll to the cursor. We - * thus made ExpressionViewWithCursor's layoutSubviews() public, which is the - * solution used in ModalViewController for instance. A cleaner solution would - * be to split viewWillAppear into loadViewIfNeeded() and viewWillAppear(), in - * order to change App::didBecomeActive to: - * m_modalViewController.loadViewIfNeeded(); - * window->setContentView(view); - * m_modalViewController.viewWillAppear(); - * The scrolling could then be done in viewWillAppear(), without calling - * layoutSubviews() manually. */ - m_view.scrollableExpressionViewWithCursor()->scrollToCursor(); -} - -bool Controller::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::EXE) { - serializeLayout(); - computeResult(); - return true; - } - if (privateHandleEvent(event)) { - m_view.cursorPositionChanged(); - return true; - } - return Responder::handleEvent(event); -} - -Toolbox * Controller::toolbox() { - ExpressionEditor::App * expressionEditorApp = static_cast(app()); - return expressionEditorApp->mathToolbox(); -} - -void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayout * pointedLayout) { - if (layout == nullptr) { - return; - } - m_cursor.addLayout(layout); - m_cursor.setPointedExpressionLayout(pointedLayout); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - m_expressionLayout->invalidAllSizesPositionsAndBaselines(); - m_view.cursorPositionChanged(); -} - -bool Controller::privateHandleEvent(Ion::Events::Event event) { - if (handleMoveEvent(event)) { - m_expressionLayout->invalidAllSizesPositionsAndBaselines(); - m_view.layoutSubviews(); - return true; - } - if (handleAddEvent(event)) { - m_expressionLayout->invalidAllSizesPositionsAndBaselines(); - m_view.layoutSubviews(); - return true; - } - if (handleDeleteEvent(event)) { - m_expressionLayout->invalidAllSizesPositionsAndBaselines(); - m_view.layoutSubviews(); - return true; - } - return false; -} - -bool Controller::handleMoveEvent(Ion::Events::Event event) { - if (event == Ion::Events::Left) { - return m_cursor.moveLeft(); - } - if (event == Ion::Events::Right) { - return m_cursor.moveRight(); - } - if (event == Ion::Events::Up) { - return m_cursor.moveUp(); - } - if (event == Ion::Events::Down) { - return m_cursor.moveDown(); - } - if (event == Ion::Events::ShiftLeft) { - // The cursor should never point to the main HorizontalLayout. - m_cursor.setPointedExpressionLayout(m_expressionLayout); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - if (event == Ion::Events::ShiftRight) { - m_cursor.setPointedExpressionLayout(m_expressionLayout); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - return false; -} - -bool Controller::handleAddEvent(Ion::Events::Event event) { - if (event == Ion::Events::Division) { - m_cursor.addFractionLayoutAndCollapseBrothers(); - return true; - } - if (event == Ion::Events::XNT) { - m_cursor.addXNTCharLayout(); - return true; - } - if (event == Ion::Events::Exp) { - m_cursor.addEmptyExponentialLayout(); - return true; - } - if (event == Ion::Events::Log) { - m_cursor.addEmptyLogarithmLayout(); - return true; - } - if (event == Ion::Events::Power) { - m_cursor.addEmptyPowerLayout(); - return true; - } - if (event == Ion::Events::Sqrt) { - m_cursor.addEmptySquareRootLayout(); - return true; - } - if (event == Ion::Events::Square) { - m_cursor.addEmptySquarePowerLayout(); - return true; - } - if (event.hasText()) { - const char * textToInsert = event.text(); - if (textToInsert[1] == 0) { - if (textToInsert[0] == Ion::Charset::MultiplicationSign) { - const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - m_cursor.insertText(middleDotString); - return true; - } - if (textToInsert[0] == '[' || textToInsert[0] == ']') { - m_cursor.addEmptyMatrixLayout(); - return true; - } - } - m_cursor.insertText(textToInsert); - return true; - } - return false; -} - -bool Controller::handleDeleteEvent(Ion::Events::Event event) { - if (event == Ion::Events::Backspace) { - m_cursor.performBackspace(); - return true; - } - return false; -} - -void Controller::serializeLayout() { - m_expressionLayout->writeTextInBuffer(m_buffer, k_bufferSize); - m_view.setText(const_cast(m_buffer)); -} - -void Controller::computeResult() { - m_expressionLayout->writeTextInBuffer(m_buffer, k_bufferSize); - Expression * result = Expression::parse(m_buffer); - Expression * approxResult = nullptr; - if (result != nullptr) { - Expression::Simplify(&result,*(((AppsContainer *)(app()->container()))->globalContext())); - approxResult = result->approximate(*(((AppsContainer *)(app()->container()))->globalContext())); - delete m_resultLayout; - } else { - approxResult = new Undefined(); - } - m_resultLayout = approxResult->createLayout(); - m_view.setResult(m_resultLayout); - if (result != nullptr) { - delete result; - } - if (approxResult != nullptr) { - delete approxResult; - } -} - -} diff --git a/apps/expression_editor/controller.h b/apps/expression_editor/controller.h deleted file mode 100644 index 546d00680..000000000 --- a/apps/expression_editor/controller.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef EXPRESSION_EDITOR_CONTROLLER_H -#define EXPRESSION_EDITOR_CONTROLLER_H - -#include -#include -#include "expression_and_layout.h" -#include "expression_editor_view.h" -extern "C" { -#include -} - -namespace ExpressionEditor { - -class Controller : public ViewController { -public: - Controller(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout); - View * view() override { return &m_view; } - void didBecomeFirstResponder() override; - bool handleEvent(Ion::Events::Event event) override; - - /* Responder */ - Toolbox * toolbox() override; - - /* Callback for Toolbox */ - void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); - -private: - bool privateHandleEvent(Ion::Events::Event event); - bool handleMoveEvent(Ion::Events::Event event); - bool handleAddEvent(Ion::Events::Event event); - bool handleDeleteEvent(Ion::Events::Event event); - void serializeLayout(); - void computeResult(); - ExpressionEditorView m_view; - Poincare::ExpressionLayout * m_expressionLayout; - Poincare::ExpressionLayoutCursor m_cursor; - static constexpr int k_bufferSize = 256; - char m_buffer[k_bufferSize]; - Poincare::ExpressionLayout * m_resultLayout; - //Poincare::Context m_context; -}; - -} - -#endif diff --git a/apps/expression_editor/expression_and_layout.cpp b/apps/expression_editor/expression_and_layout.cpp deleted file mode 100644 index 24e0f3df4..000000000 --- a/apps/expression_editor/expression_and_layout.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "expression_and_layout.h" -#include -#include - -namespace ExpressionEditor { - -ExpressionAndLayout::ExpressionAndLayout() { - const char * expression = "1"; - //const char * expression = "1+2/(3+4)"; - //const char * expression = "1+2/3+5+8"; - //const char * expression = "[[1+5,2,3][4,5,6]]"; - //const char * expression = "1+2/(7+5/3/467777777)/3+8"; - //const char * expression = "1+2/7467777777"; - //const char * expression = "2385658/(7+5/46)"; - //const char * expression = "1+conj(100)+2"; - //const char * expression = "1+abs(100)+2"; - //const char * expression = "1+root(100,41)+2"; - //const char * expression = "ln(36)"; - //const char * expression = "1+floor(36)+2"; - //const char * expression = "ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988)"; - //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+(1111111)/(2/3+4/5)"; - //const char * expression = "2385658/(int(5/46*7/8,3,45))"; - //const char * expression = "1+binomial(6,88)+1"; - //const char * expression = "[[1+5,2,3][4,5,int(5/46+1,3,4)]]"; - //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; - //const char * expression = "1/2+[[1,2,3][4,5,6]]+1"; - //const char * expression = "1+(3+4)+1"; - //const char * expression = "1+product(23,46,123)+[[2,3][5,6]]+1/4"; - //const char * expression = "2385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; - //const char * expression = "7/78+int(5/46*7/8,3,45)+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]"; - //const char * expression = "1+conj(39)+abs(3)+root(6000,23)"; - //const char * expression = "1.5+3.4"; - //const char * expression = "abs(5)+int(5/46*7/8,3,4544444)+conj(4)+int(333,4,5)"; - //const char * expression = "conj(int(5/46*7/8,3,45))+conj(4)"; - //const char * expression = "abs(1+conj(conj(4))+(23)+conj(42))+abs(1+2)"; - //const char * expression = "13+(23)"; - //const char * expression = "1+sum(12,3,4)+product(12,3,4)+2"; - //const char * expression = "(1+2^3)-385658/(7/78+int(5/46*7/8,3,45))+sum(12,3,4)+[[1+5,2,3][4/2,5,6]]/123+ln(36)+root(542,52)+sum(12,3,4)+int(22,3,4)+conj(988+2)+abs(conj(345))+conj(conj(conj(3)))+floor(48)+binomial(6,88)+product(23,46,123)+log(10,565)-0.03"; - - m_expression = Poincare::Expression::parse(expression); - m_expressionLayout = new Poincare::HorizontalLayout(); -} -ExpressionAndLayout::~ExpressionAndLayout() { - if (m_expressionLayout) { - delete m_expressionLayout; - m_expressionLayout = nullptr; - } - if (m_expression) { - delete m_expression; - m_expression = nullptr; - } -} - -} diff --git a/apps/expression_editor/expression_and_layout.h b/apps/expression_editor/expression_and_layout.h deleted file mode 100644 index a1ef237fc..000000000 --- a/apps/expression_editor/expression_and_layout.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef EXPRESSION_EDITOR_EXPRESSION_AND_LAYOUT_H -#define EXPRESSION_EDITOR_EXPRESSION_AND_LAYOUT_H - -#include - -namespace ExpressionEditor { - -class ExpressionAndLayout { -public: - ExpressionAndLayout(); - ~ExpressionAndLayout(); - ExpressionAndLayout(const ExpressionAndLayout& other) = delete; - ExpressionAndLayout(ExpressionAndLayout&& other) = delete; - ExpressionAndLayout operator=(const ExpressionAndLayout& other) = delete; - ExpressionAndLayout& operator=(ExpressionAndLayout&& other) = delete; - - Poincare::Expression * expression() { return m_expression; } - Poincare::ExpressionLayout * expressionLayout() { return m_expressionLayout; } -private: - Poincare::Expression * m_expression; - Poincare::ExpressionLayout * m_expressionLayout; -}; - -} - -#endif diff --git a/apps/expression_editor/expression_editor_view.cpp b/apps/expression_editor/expression_editor_view.cpp deleted file mode 100644 index 7fc386c89..000000000 --- a/apps/expression_editor/expression_editor_view.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "expression_editor_view.h" -#include - -namespace ExpressionEditor { - -ExpressionEditorView::ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor) : - SolidColorView(KDColorWhite), - m_scrollableExpressionViewWithCursor(parentResponder, expressionLayout, cursor), - m_resultExpressionView() -{ - m_serializerTextView.setText("Hello"); -} - -void ExpressionEditorView::cursorPositionChanged() { - m_scrollableExpressionViewWithCursor.expressionViewWithCursor()->cursorPositionChanged(); - m_scrollableExpressionViewWithCursor.scrollToCursor(); -} - -void ExpressionEditorView::setText(const char * text) { - m_serializerTextView.setText(text); -} - -void ExpressionEditorView::setResult(Poincare::ExpressionLayout * eL) { - m_resultExpressionView.setExpressionLayout(eL); -} - -View * ExpressionEditorView::subviewAtIndex(int index) { - assert(index >= 0 && index < 3); - if (index == 0) { - return &m_scrollableExpressionViewWithCursor; - } - if (index == 1) { - return &m_resultExpressionView; - } - return &m_serializerTextView; -} - -void ExpressionEditorView::layoutSubviews() { - m_serializerTextView.setFrame(KDRect(0, 0, bounds().width(), 20)); - m_resultExpressionView.setFrame(KDRect(20, k_margin, bounds().width() - 2 * k_margin, 50)); - m_scrollableExpressionViewWithCursor.setFrame(KDRect( - k_margin, - 50+k_margin, - bounds().width() - 2 * k_margin, - bounds().height() - 2 * k_margin)); - markRectAsDirty(bounds()); -} - -KDSize ExpressionEditorView::minimalSizeForOptimalDisplay() const { - return KDSize(300, 220); -} - - -} - diff --git a/apps/expression_editor/expression_editor_view.h b/apps/expression_editor/expression_editor_view.h deleted file mode 100644 index 2d0116b35..000000000 --- a/apps/expression_editor/expression_editor_view.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef EXPRESSION_EDITOR_EXPRESSION_EDITOR_VIEW_H -#define EXPRESSION_EDITOR_EXPRESSION_EDITOR_VIEW_H - -#include -#include "expression_and_layout.h" -#include "scrollable_expression_view_with_cursor.h" - -namespace ExpressionEditor { - -class ExpressionEditorView : public SolidColorView { -public: - ExpressionEditorView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); - void cursorPositionChanged(); - void setText(const char * text); - void setResult(Poincare::ExpressionLayout * result); - int numberOfSubviews() const override { return 3; } - ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - KDSize minimalSizeForOptimalDisplay() const override; -private: - constexpr static KDCoordinate k_margin = 10; - ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; - ExpressionView m_resultExpressionView; - BufferTextView m_serializerTextView; -}; - -} - -#endif diff --git a/apps/expression_editor/expression_view_with_cursor.cpp b/apps/expression_editor/expression_view_with_cursor.cpp deleted file mode 100644 index 716d23492..000000000 --- a/apps/expression_editor/expression_view_with_cursor.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "expression_view_with_cursor.h" -#include - -using namespace Poincare; - -namespace ExpressionEditor { - -ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expressionLayout, ExpressionLayoutCursor * cursor) : - m_cursor(cursor) -{ - m_expressionView.setExpressionLayout(expressionLayout); -} - -void ExpressionViewWithCursor::cursorPositionChanged() { - layoutCursorSubview(); -} - -KDRect ExpressionViewWithCursor::cursorRect() { - return m_cursorView.frame(); -} - -KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { - KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); - return KDSize(expressionViewSize.width()+1, m_expressionView.minimalSizeForOptimalDisplay().height()); // +1 for the cursor -} - -View * ExpressionViewWithCursor::subviewAtIndex(int index) { - assert(index >= 0 && index < 2); - View * m_views[] = {&m_expressionView, &m_cursorView}; - return m_views[index]; -} - -void ExpressionViewWithCursor::layoutSubviews() { - m_expressionView.setFrame(bounds()); - layoutCursorSubview(); -} - -void ExpressionViewWithCursor::layoutCursorSubview() { - KDPoint expressionViewOrigin = m_expressionView.drawingOrigin(); - KDPoint cursoredExpressionViewOrigin = m_cursor->pointedExpressionLayout()->absoluteOrigin(); - KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); - if (m_cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursorX += m_cursor->pointedExpressionLayout()->size().width(); - } - KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor->pointedExpressionLayout()->baseline()-m_cursor->cursorHeight()/2); - m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor->cursorHeight())); -} - -} diff --git a/apps/expression_editor/expression_view_with_cursor.h b/apps/expression_editor/expression_view_with_cursor.h deleted file mode 100644 index 79353173c..000000000 --- a/apps/expression_editor/expression_view_with_cursor.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef EXPRESSION_EDITOR_EXPRESSION_VIEW_WITH_CURSOR_H -#define EXPRESSION_EDITOR_EXPRESSION_VIEW_WITH_CURSOR_H - -#include -#include -#include -#include - -namespace ExpressionEditor { - -class ExpressionViewWithCursor : public View { -public: - ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); - void cursorPositionChanged(); - KDRect cursorRect(); - const ExpressionView * expressionView() const { return &m_expressionView; } - /* View */ - KDSize minimalSizeForOptimalDisplay() const override; -private: - enum class Position { - Top, - Bottom - }; - int numberOfSubviews() const override { return 2; } - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - void layoutCursorSubview(); - Poincare::ExpressionLayoutCursor * m_cursor; - ExpressionView m_expressionView; - TextCursorView m_cursorView; -}; - -} - -#endif diff --git a/apps/expression_editor/scrollable_expression_view_with_cursor.cpp b/apps/expression_editor/scrollable_expression_view_with_cursor.cpp deleted file mode 100644 index 60b5c1733..000000000 --- a/apps/expression_editor/scrollable_expression_view_with_cursor.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "scrollable_expression_view_with_cursor.h" -#include - -namespace ExpressionEditor { - -ScrollableExpressionViewWithCursor::ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor) : - ScrollableView(parentResponder, &m_expressionViewWithCursor, this), - m_expressionViewWithCursor(expressionLayout, cursor) -{ -} - -KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { - return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); -} - -void ScrollableExpressionViewWithCursor::scrollToCursor() { - scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); -} - -} - diff --git a/apps/expression_editor/scrollable_expression_view_with_cursor.h b/apps/expression_editor/scrollable_expression_view_with_cursor.h deleted file mode 100644 index 7083f1153..000000000 --- a/apps/expression_editor/scrollable_expression_view_with_cursor.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EXPRESSION_EDITOR_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H -#define EXPRESSION_EDITOR_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H - -#include -#include -#include -#include "expression_view_with_cursor.h" - -namespace ExpressionEditor { - -class ScrollableExpressionViewWithCursor : public ScrollableView, public ScrollViewDataSource { -public: - ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, Poincare::ExpressionLayoutCursor * cursor); - KDSize minimalSizeForOptimalDisplay() const override; - ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } - void scrollToCursor(); - /* ScrollableView */ - bool handleEvent(Ion::Events::Event event) override { return false; } -private: - ExpressionViewWithCursor m_expressionViewWithCursor; -}; - -} - -#endif diff --git a/apps/expression_editor/test/dummy_test.cpp b/apps/expression_editor/test/dummy_test.cpp deleted file mode 100644 index 18e40f6c0..000000000 --- a/apps/expression_editor/test/dummy_test.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - -QUIZ_CASE() { - assert(true); -} diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 68f38e3e9..2e5b0131a 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -4,7 +4,6 @@ #define MATRICES_ARE_DEFINED 1 #include #include -#include class MathToolbox : public Toolbox { public: From ab8140c1c3a0f56c349e608240b4e3cf1d6b8df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 11:36:34 +0100 Subject: [PATCH 224/459] [poincare] Pointer shouldRecomputeLayout mandatory for layout navigation This fixes a bug. Change-Id: I9bb5ff3a3f365865d85f89efcd970e3ac5096536 --- poincare/include/poincare/expression_layout.h | 8 ++++---- poincare/include/poincare/expression_layout_cursor.h | 2 +- poincare/src/layout/binomial_coefficient_layout.h | 4 ++-- poincare/src/layout/bracket_layout.h | 4 ++-- poincare/src/layout/bracket_left_right_layout.h | 4 ++-- poincare/src/layout/char_layout.h | 4 ++-- poincare/src/layout/condensed_sum_layout.h | 4 ++-- poincare/src/layout/conjugate_layout.h | 4 ++-- poincare/src/layout/empty_visible_layout.h | 4 ++-- poincare/src/layout/expression_layout.cpp | 3 ++- poincare/src/layout/fraction_layout.h | 4 ++-- poincare/src/layout/grid_layout.h | 4 ++-- poincare/src/layout/horizontal_layout.h | 4 ++-- poincare/src/layout/integral_layout.h | 4 ++-- poincare/src/layout/matrix_layout.h | 8 ++++---- poincare/src/layout/nth_root_layout.h | 4 ++-- poincare/src/layout/parenthesis_left_right_layout.h | 4 ++-- poincare/src/layout/sequence_layout.h | 4 ++-- poincare/src/layout/vertical_offset_layout.h | 4 ++-- 19 files changed, 41 insertions(+), 40 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 60bfeea85..2a7da4542 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -76,8 +76,8 @@ public: virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ - virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) = 0; - virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) = 0; + virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; + virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; virtual bool moveUp( ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, @@ -88,8 +88,8 @@ public: bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr); - virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr); - virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr); + virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 7657d5e18..2d6791e9a 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -33,7 +33,7 @@ public: KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position); /* Move */ - bool moveLeft(bool * shouldRecomputeLayout = nullptr); + bool moveLeft(bool * shouldRecomputeLayout); bool moveRight(bool * shouldRecomputeLayout); bool moveUp(bool * shouldRecomputeLayout); bool moveDown(bool * shouldRecomputeLayout); diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 8cfa19323..a77b9426b 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -10,8 +10,8 @@ class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index b9a746f36..9c9deaf66 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -10,8 +10,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; protected: ExpressionLayout * operandLayout(); diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_left_right_layout.h index 7dfc9708a..9791e18c4 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_left_right_layout.h @@ -9,8 +9,8 @@ class BracketLeftRightLayout : public StaticLayoutHierarchy<0> { public: BracketLeftRightLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; protected: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 37ebd3692..48a7590c2 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -17,8 +17,8 @@ public: char character() { return m_char; } KDText::FontSize fontSize() const { return m_fontSize; } - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index d7a236e4e..3026ef0b5 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -10,8 +10,8 @@ class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 896e777a0..5b1f2097e 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -11,8 +11,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize) const override { diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index 8731a3f55..c554a9188 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -15,8 +15,8 @@ public: EmptyVisibleLayout(Color color = Color::Yellow); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 958edf102..c318adfc3 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -205,7 +205,8 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // Case: The pointed layout is a child. // Move Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - cursor->moveLeft(); + bool shouldRecomputeLayout = false; + cursor->moveLeft(&shouldRecomputeLayout); return; } assert(cursor->pointedExpressionLayout() == this); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 02562db82..044d60158 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -11,8 +11,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index ad80b8f49..9bd6b467e 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -13,8 +13,8 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index a0d7bdfaa..89e79e592 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -22,8 +22,8 @@ public: void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 56cb14999..6241c756d 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -17,8 +17,8 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 78139be13..767686e37 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -11,12 +11,12 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; - bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index e97d05595..db5eec064 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -17,8 +17,8 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 0dc125452..b40f2536d 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -9,8 +9,8 @@ class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLeftRightLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index f7c77d5b2..7299ca914 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -11,8 +11,8 @@ public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; char XNTChar() const override; diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 75ca9f1e3..bfceadee1 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -14,8 +14,8 @@ public: VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr) override; + bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize) const override; From 95f859ce80eab99276a9a7d1020f50500e180690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 11:55:04 +0100 Subject: [PATCH 225/459] [apps/sequence] Set sender for sequence toolbox. Change-Id: I3fe78127273083fb4f8f680ea3e6394f99913a12 --- apps/sequence/list/list_controller.cpp | 25 ++++++++++++++++++------- apps/sequence/list/list_controller.h | 2 ++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index b8cc8cdeb..e03f0e821 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -24,13 +24,14 @@ const char * ListController::title() { } Toolbox * ListController::toolboxForTextField(TextField * textField) { - int recurrenceDepth = -1; - int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow())); - if (sequenceDefinition == 0) { - recurrenceDepth = sequence->numberOfElements()-1; - } - m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth); + setToolboxExtraCells(); + m_sequenceToolbox.setSenderAndAction(textField, MathToolbox::actionForTextField); + return &m_sequenceToolbox; +} + +Toolbox * ListController::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { + setToolboxExtraCells(); + m_sequenceToolbox.setSenderAndAction(scrollableExpressionViewWithCursor, MathToolbox::actionForScrollableExpressionViewWithCursor); return &m_sequenceToolbox; } @@ -308,4 +309,14 @@ void ListController::unloadView(View * view) { Shared::ListController::unloadView(view); } +void ListController::setToolboxExtraCells() { + int recurrenceDepth = -1; + int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); + Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow())); + if (sequenceDefinition == 0) { + recurrenceDepth = sequence->numberOfElements()-1; + } + m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth); +} + } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index a8f34882f..78ae667a0 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -23,6 +23,7 @@ public: virtual KDCoordinate rowHeight(int j) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; Toolbox * toolboxForTextField(TextField * textField) override; + Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; void selectPreviousNewSequenceCell(); private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override; @@ -43,6 +44,7 @@ private: void reinitExpression(Shared::Function * function) override; View * loadView() override; void unloadView(View * view) override; + void setToolboxExtraCells(); static constexpr KDCoordinate k_emptySubRowHeight = 30; constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences; SequenceStore * m_sequenceStore; From 30ac81db284c28f984db71c37ecb35165cadd0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 12:03:19 +0100 Subject: [PATCH 226/459] [poincare/lexer] Add rules to recognize symbols such as "u_{n}". Change-Id: Ib6976e3b02357a975241ef5314a5999f967d6a45 --- poincare/src/expression_lexer.l | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 57ed5769a..d8753a6c1 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -89,6 +89,10 @@ u\(n\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::un; retu u\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::un1; return SYMBOL; } v\(n\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn; return SYMBOL; } v\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn1; return SYMBOL; } +u\_\{n\} { poincare_expression_yylval.character = Symbol::SpecialSymbols::un; return SYMBOL; } +u\_\{n\+1\} { poincare_expression_yylval.character = Symbol::SpecialSymbols::un1; return SYMBOL; } +v\_\{n\} { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn; return SYMBOL; } +v\_\{n\+1\} { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn1; return SYMBOL; } acos { poincare_expression_yylval.expression = new ArcCosine(); return FUNCTION; } acosh { poincare_expression_yylval.expression = new HyperbolicArcCosine(); return FUNCTION; } abs { poincare_expression_yylval.expression = new AbsoluteValue(); return FUNCTION; } From acf8fe25ff7d5a64c056241b0bd26a6832b5546b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 14:20:08 +0100 Subject: [PATCH 227/459] [escher] Fix text field bug when editing a sequence. The InputViewController inserted the text to edit in the TextField then set the edition to true, which deleted the text. Change-Id: Id77e740c0b615066e647512a19731214a435a2f0 --- escher/src/input_view_controller.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index ac5fa9956..d04c5edcb 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -33,11 +33,10 @@ void InputViewController::edit(Responder * caller, Ion::Events::Event event, voi m_successAction = Invocation(successAction, context); m_failureAction = Invocation(failureAction, context); displayModalViewController(&m_editableExpressionViewController, 1.0f, 1.0f); + m_editableExpressionViewController.editableExpressionView()->handleEvent(event); if (initialText != nullptr) { m_editableExpressionViewController.editableExpressionView()->setText(initialText); - //TODO is the editableExpressionView always clean before we set the text? Otherwise, problem if there is no initial text. } - m_editableExpressionViewController.editableExpressionView()->handleEvent(event); } void InputViewController::abortEditionAndDismiss() { From bc21aa919f1124323dbdd501da3ae5abb68269f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 14:27:45 +0100 Subject: [PATCH 228/459] [escher] Missing return statement. Change-Id: I96feaeac32a8a01098b5446e9bc11321442b1022 --- escher/src/editable_expression_view.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index cc557b04e..8881f48f4 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -35,6 +35,7 @@ const char * EditableExpressionView::text() { void EditableExpressionView::setText(const char * text) { if (editionIsInTextField()) { m_textField.setText(text); + return; } m_scrollableExpressionViewWithCursor.clearLayout(); if (strlen(text) > 0) { From 2c79071d0764317416cc9bae39e8ae3dfd0d84f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 14:44:39 +0100 Subject: [PATCH 229/459] [poincare] Fix bug in HorizontalLayout. Adding a brother should add it has a child, or merge it if the "brother" is an horizontal layout! Change-Id: I77e993ef2270fd1bf61599d688f3835feb8c0971 --- poincare/src/layout/horizontal_layout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 815161b80..e9285e151 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -367,11 +367,11 @@ void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres cursor->setPosition(ExpressionLayoutCursor::Position::Right); } } - addChildAtIndex(brother, 0); + addOrMergeChildAtIndex(brother, 0, false); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - addChildAtIndex(brother, numberOfChildren()); + addOrMergeChildAtIndex(brother, numberOfChildren(), false); if (moveCursor) { cursor->setPointedExpressionLayout(this); } From 8f17807fc16617d5648d2965119c35d19a8833bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 14:54:35 +0100 Subject: [PATCH 230/459] [poincare] Fixed power layout insertion bug. The method to determine if an empty base layout should also be inserted had a bug. Change-Id: I6c5e0de033eaee8a21a39f3eaffa18b259865a6e --- poincare/src/expression_layout_cursor.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 947dfedf9..11e25ea3f 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -211,16 +211,24 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { // Returns true if the layout on the left of the pointed layout is suitable to // be the base of a new power layout. int numberOfOpenParenthesis = 0; - int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); - return ((m_position == Position::Right - && !m_pointedExpressionLayout->isEmpty() - && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) - || (m_position == Position::Left - && m_pointedExpressionLayout->parent() + if (m_position == Position::Right + && !m_pointedExpressionLayout->isEmpty() + && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) + { + return true; + } + if (m_pointedExpressionLayout->parent() != nullptr) { + int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); + if (m_position == Position::Left && m_pointedExpressionLayout->parent()->isHorizontal() && indexInParent > 0 && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isEmpty() - && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true))); + && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true)) + { + return true; + } + } + return false; } } From fa1dcbf434df0fc9466b3216b4e34b8fea93f99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 15:03:47 +0100 Subject: [PATCH 231/459] [poincare] Fix SquareRoot layout creation. Change-Id: I9985735a5a00b1acf14993996f63be5dc91d9c14 --- poincare/src/square_root.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index ccb695d2d..37cf805a0 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -52,7 +52,7 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), nullptr, false); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } } From d217832ba12d9482dde692319de36a0b17c345df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 17:32:56 +0100 Subject: [PATCH 232/459] [poincare] Fix bug when inserting a fraction between base and indice. Change-Id: I4e3f6a5b6aee251a99e580dde7cb65b753f99ac5 --- poincare/src/expression_layout_cursor.cpp | 11 ++++++++--- poincare/src/layout/char_layout.cpp | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 11e25ea3f..805b6bb65 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -76,11 +76,16 @@ void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { // Collapse the brothers on the right int numberOfOpenParenthesis = 0; - while (fractionIndexInParent < numberOfBrothers - 1) { - ExpressionLayout * rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); + bool canCollapseOnRight = true; + if (fractionIndexInParent < numberOfBrothers - 1) { + canCollapseOnRight = !(newChild->editableParent()->editableChild(fractionIndexInParent+1)->mustHaveLeftBrother()); + } + ExpressionLayout * rightBrother = nullptr; + while (canCollapseOnRight && fractionIndexInParent < numberOfBrothers - 1) { + rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); if (rightBrother->isCollapsable(&numberOfOpenParenthesis, false)) { newChild->editableParent()->removeChildAtIndex(fractionIndexInParent+1, false); - child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), true); + child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), false); numberOfBrothers--; } else { break; diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index 0dde197c6..2a86c61f2 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -56,7 +56,8 @@ bool CharLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) co || m_char == '-' || m_char == '*' || m_char == Ion::Charset::MultiplicationSign - || m_char == Ion::Charset::MiddleDot)) + || m_char == Ion::Charset::MiddleDot + || m_char == ',')) { return false; } From d5a24bd71ca65589881aaeb368b92af7e60e1a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 26 Jan 2018 18:14:06 +0100 Subject: [PATCH 233/459] [To remove] Change-Id: Ifbd887c0ddbdec71c8495eca10354352ffa1418e --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index 7e5d367ab..01af17fff 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,5 +1,5 @@ EPSILON_I18N_LANGUAGES ?= en fr es de pt -EPSILON_APPS ?= calculation graph sequence settings statistics probability regression code +EPSILON_APPS ?= calculation graph sequence settings include apps/shared/Makefile include apps/home/Makefile From eb03b713c332a1daac1aad1a3c5c4f4648993259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 13:32:54 +0100 Subject: [PATCH 234/459] [poincare] Fix bug when layouting a left parenthesis. When the parenthesis is the base of a vertical offset superscript, its height and baseline should be default values, else it creates an infinite loop because the parenthesis needs the superscript position, which needs the parenthesis position. Change-Id: Ib5f7d7cbd1cb48b5de8251cdda64b271e50f216f --- .../src/layout/parenthesis_left_layout.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index aaa91ede0..2ed96c93a 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -67,9 +67,18 @@ void ParenthesisLeftLayout::computeOperandHeight() { m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; KDCoordinate max_under_baseline = 0; KDCoordinate max_above_baseline = 0; + int indexInParent = m_parent->indexOfChild(this); int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + if (indexInParent < numberOfBrothers - 1 + && m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) + { + // If the parenthesis is the base of a superscript layout, it should have a + // default height, else it creates an infinite loop because the parenthesis + // needs the superscript height, which needs the parenthesis height. + return; + } + for (int i = indexInParent + 1; i < numberOfBrothers; i++) { ExpressionLayout * brother = m_parent->editableChild(i); if (brother->isRightParenthesis()) { currentNumberOfOpenParentheses--; @@ -107,6 +116,16 @@ void ParenthesisLeftLayout::computeBaseline() { m_baselined = true; return; } + if (m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) { + // If the parenthesis is the base of a superscript layout, it should have a + // default baseline, else it creates an infinite loop because the + // parenthesis needs the superscript height, which needs the parenthesis + // baseline. + m_baseline = operandHeight()/2; + m_baselined = true; + return; + } + m_baseline = 0; for (int i = indexInParent + 1; i < numberOfBrothers; i++) { ExpressionLayout * brother = m_parent->editableChild(i); From e375e571adbd34b83b449819f9abf7b7527bba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 14:00:40 +0100 Subject: [PATCH 235/459] [poincare] Remove empty child when inserting in HorizontalLayout Change-Id: I393469cc28c83e6ab28d73a524ec62fab8165696 --- poincare/src/layout/horizontal_layout.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index e9285e151..27bff6bb9 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -354,11 +354,11 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { // Add the "brother" as a child. - // If there is only one empty child, remove it before adding the layout. - if (numberOfChildren() == 1 && editableChild(0)->isEmpty()) { - removeChildAtIndex(0, true); - } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + // If the first child is empty, remove it before adding the layout. + if (numberOfChildren() > 0 && editableChild(0)->isEmpty()) { + removeChildAtIndex(0, true); + } if (moveCursor) { if (numberOfChildren() > 0) { cursor->setPointedExpressionLayout(editableChild(0)); @@ -371,7 +371,12 @@ void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - addOrMergeChildAtIndex(brother, numberOfChildren(), false); + // If the first child is empty, remove it before adding the layout. + int childrenCount = numberOfChildren(); + if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty()) { + removeChildAtIndex(childrenCount - 1, true); + } + addOrMergeChildAtIndex(brother, childrenCount, false); if (moveCursor) { cursor->setPointedExpressionLayout(this); } From 40ef1d1caa755c16b232f5ca1d72f0992558c98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 14:10:38 +0100 Subject: [PATCH 236/459] [poincare] Fix cursor position bug when deleting VerticalOffsetLayout. Change-Id: Ie53030e5bff6876c75a785a61f6c43604bee2b05 --- poincare/src/layout/vertical_offset_layout.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 89b25fb24..b5e58b3dc 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -29,6 +29,8 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // Case: Empty base and indice. // Remove both the base and the indice layout. ExpressionLayout * parent = m_parent; + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); parent->removePointedChildAtIndexAndMoveCursor(indexInParent, true, cursor); parent->removePointedChildAtIndexAndMoveCursor(indexInParent-1, true, cursor); return; From 8d62aa90f8302b1171c88a67e2e8b01f46769d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 15:29:58 +0100 Subject: [PATCH 237/459] [poincare] Better removal of empty child in HorizontalLayout Change-Id: I126af718ec8a983b22f07ab49fd3298b8b416ea5 --- poincare/src/layout/horizontal_layout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 27bff6bb9..fe6dcd92b 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -166,7 +166,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { int newIndex = index; - if (numberOfChildren() > 0 && child(0)->isEmpty()) { + if (numberOfChildren() > 0 && child(0)->isEmpty() && (numberOfChildren() < 1 || !child(1)->mustHaveLeftBrother())) { removeChildAtIndex(0, true); newIndex = index == 0 ? 0 : index - 1; } @@ -371,12 +371,12 @@ void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // If the first child is empty, remove it before adding the layout. + // If the last child is empty, remove it before adding the layout. int childrenCount = numberOfChildren(); if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty()) { removeChildAtIndex(childrenCount - 1, true); } - addOrMergeChildAtIndex(brother, childrenCount, false); + addOrMergeChildAtIndex(brother, numberOfChildren(), false); if (moveCursor) { cursor->setPointedExpressionLayout(this); } From 7e1e811082fe7b4414f11c09bbc91859438220a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 15:31:21 +0100 Subject: [PATCH 238/459] [poincare] Fix bug when deleting an empty VerticalOffsetLayout. Change-Id: Ic2d2248c783a718521c65b7cc2e15406926a8e94 --- poincare/src/layout/vertical_offset_layout.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index b5e58b3dc..5180c986f 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -32,6 +32,8 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); parent->removePointedChildAtIndexAndMoveCursor(indexInParent, true, cursor); + cursor->setPointedExpressionLayout(parent->editableChild(indexInParent-1)); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); parent->removePointedChildAtIndexAndMoveCursor(indexInParent-1, true, cursor); return; } From 7fd3b965eb9c90e5b39e0b9655073a8f243b8adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 16:11:06 +0100 Subject: [PATCH 239/459] [poincare] Fixed HorizontalLayout empty child removal. Change-Id: Ic956a98b2637dafeda7c6e7476caa789ce398321 --- .../poincare/dynamic_layout_hierarchy.h | 4 +- poincare/src/expression_layout_cursor.cpp | 1 - poincare/src/layout/empty_visible_layout.cpp | 13 ++-- poincare/src/layout/horizontal_layout.cpp | 67 ++++++++++++++----- poincare/src/layout/horizontal_layout.h | 5 ++ 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 499f09cef..43dbb606e 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -25,11 +25,11 @@ public: int numberOfChildren() const override { return m_numberOfChildren; } const ExpressionLayout * const * children() const override { return m_children; }; - void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren); + virtual void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren); bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; - void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. + virtual void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. protected: const ExpressionLayout ** m_children; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 805b6bb65..90b0aaabb 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -217,7 +217,6 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { // be the base of a new power layout. int numberOfOpenParenthesis = 0; if (m_position == Position::Right - && !m_pointedExpressionLayout->isEmpty() && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) { return true; diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index 244b8d48a..bcc59d66c 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -88,10 +88,15 @@ void EmptyVisibleLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expr Color currentColor = m_color; int indexInParent = m_parent->indexOfChild(this); ExpressionLayout * parent = m_parent; - replaceWith(brother, true); - if (moveCursor) { - cursor->setPointedExpressionLayout(brother); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + if (brother->mustHaveLeftBrother()) { + m_color = Color::Yellow; + ExpressionLayout::privateAddBrother(cursor, brother, moveCursor); + } else { + if (moveCursor) { + replaceWithAndMoveCursor(brother, true, cursor); + } else { + replaceWith(brother, true); + } } if (currentColor == Color::Grey) { // The parent is a MatrixLayout. diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index fe6dcd92b..63bd346c5 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -149,8 +149,11 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex } } } + bool oldChildRemovedAtMerge = oldChild->isEmpty(); mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); - removeChildAtIndex(indexForInsertion, deleteOldChild); + if (!oldChildRemovedAtMerge) { + removeChildAtIndex(indexForInsertion, deleteOldChild); + } return; } // Else, just replace the child. @@ -165,16 +168,11 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex } void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { - int newIndex = index; - if (numberOfChildren() > 0 && child(0)->isEmpty() && (numberOfChildren() < 1 || !child(1)->mustHaveLeftBrother())) { - removeChildAtIndex(0, true); - newIndex = index == 0 ? 0 : index - 1; - } if (eL->isHorizontal()) { - mergeChildrenAtIndex(static_cast(eL), newIndex, removeEmptyChildren); + mergeChildrenAtIndex(static_cast(eL), index, removeEmptyChildren); return; } - addChildAtIndex(eL, newIndex); + addChildAtIndex(eL, index); } bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { @@ -279,14 +277,25 @@ bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRe return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } + +void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { + int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, operands[0]->mustHaveLeftBrother()); + DynamicLayoutHierarchy::addChildrenAtIndex(operands, numberOfOperands, newIndex, removeEmptyChildren); +} + +bool HorizontalLayout::addChildAtIndex(ExpressionLayout * operand, int index) { + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, operand->mustHaveLeftBrother()); + return DynamicLayoutHierarchy::addChildAtIndex(operand, newIndex); +} + void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { - // If the child to remove is at index 0 and its right brother must have a left - // brother (e.g. it is a VerticalOffsetLayout), replace the child with an - // EmptyVisibleLayout instead of removing it. - if (index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { - addChildAtIndex(new EmptyVisibleLayout(), index + 1); - } - DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); + privateRemoveChildAtIndex(index, deleteAfterRemoval, false); +} + +void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { + bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? eL->child(0)->mustHaveLeftBrother() : true; + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); + DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); } int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize) const { @@ -426,4 +435,32 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } +void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { + // If the child to remove is at index 0 and its right brother must have a left + // brother (e.g. it is a VerticalOffsetLayout), replace the child with an + // EmptyVisibleLayout instead of removing it. + if ( !forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { + addChildAtIndex(new EmptyVisibleLayout(), index + 1); + } + DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); +} + +int HorizontalLayout::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { + int newIndex = index; + // If empty, remove the child that would be on the right of the inserted + // layout. + if (newIndex < numberOfChildren() + && child(newIndex)->isEmpty()) + { + privateRemoveChildAtIndex(newIndex, true, true); + } + // If empty, remove the child that would be on the left of the inserted + // layout. + if ( shouldRemoveOnLeft && newIndex - 1 > 0 && newIndex - 1 < numberOfChildren() -1 && child(newIndex - 1)->isEmpty()) { + privateRemoveChildAtIndex(newIndex-1, true, true); + newIndex = index - 1; + } + return newIndex; +} + } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 89e79e592..5d3c6d9d7 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -28,7 +28,10 @@ public: bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Dynamic layout */ + void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) override; + bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; + void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize) const override; @@ -46,6 +49,8 @@ protected: private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); + void privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove); + int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); }; } From 214e490112ba848030050868655fa40a2b7a03b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 29 Jan 2018 17:58:11 +0100 Subject: [PATCH 240/459] [poincare] Fixed grey squares bug when moving up in nested matrices. Before, too many grey squares were added. Change-Id: I0694dc943f82006fe3367dea9750d2feb83071ad --- poincare/include/poincare/expression_layout.h | 3 ++- poincare/src/layout/expression_layout.cpp | 14 ++++++++++++++ poincare/src/layout/matrix_layout.cpp | 18 ------------------ poincare/src/layout/matrix_layout.h | 7 ------- 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 2a7da4542..8de6d3878 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -95,6 +95,7 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Other */ + bool addGreySquaresToAllMatrixAncestors(); bool hasText() const; virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a brother fraction: should the layout be @@ -123,7 +124,7 @@ protected: virtual KDSize computeSize() = 0; virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; - virtual void moveCursorInsideAtDirection ( + void moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index c318adfc3..8d9feb31c 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -259,6 +259,19 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * sh return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); } +bool ExpressionLayout::addGreySquaresToAllMatrixAncestors() { + bool addedSquares = false; + ExpressionLayout * currentAncestor = m_parent; + while (currentAncestor != nullptr) { + if (currentAncestor->isMatrix()) { + static_cast(currentAncestor)->addGreySquares(); + addedSquares = true; + } + currentAncestor = currentAncestor->editableParent(); + } + return addedSquares; +} + bool ExpressionLayout::hasText() const { // A layout has text if it is not empty and it is not an horizontal layout // with no child or with one child with no text. @@ -309,6 +322,7 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC } cursor->setPointedExpressionLayout(*childResultPtr); cursor->setPosition(resultPosition); + *shouldRecomputeLayout = (*childResultPtr)->addGreySquaresToAllMatrixAncestors(); return true; } diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index fbec5bd3a..282e99081 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -275,24 +275,6 @@ ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, return GridLayout::positionOfChild(child).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); } -void MatrixLayout::moveCursorInsideAtDirection ( - VerticalDirection direction, - ExpressionLayoutCursor * cursor, - bool * shouldRecomputeLayout, - ExpressionLayout ** childResult, - void * resultPosition, - int * resultScore) -{ - GridLayout::moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResult, resultPosition, resultScore); - if (*childResult != this) { - // Add the grey squares if the cursor is pointing at a matrix descendant, - // not at the matrix itself. - assert(!hasGreySquares()); - addGreySquares(); - *shouldRecomputeLayout = true; - } -} - bool MatrixLayout::isRowEmpty(int index) const { assert(index >= 0 && index < m_numberOfRows); for (int i = index * m_numberOfColumns; i < (index+1) * m_numberOfColumns; i++) { diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 767686e37..0c595d32d 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -38,13 +38,6 @@ protected: KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - void moveCursorInsideAtDirection ( - VerticalDirection direction, - ExpressionLayoutCursor * cursor, - bool * shouldRecomputeLayout, - ExpressionLayout ** childResult, - void * resultPosition, - int * resultScore) override; void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; From 90068b5cc764f7b7199dfd2e1394b79e5badafd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 31 Jan 2018 10:32:07 +0100 Subject: [PATCH 241/459] [poincare] Fix Matrix copy bug. When selecting a matrix in the calculation history and pressing 'OK', in the apps Calculation, there was a nullptr bug. Change-Id: I8f05771b76bcb3c68b51cf8ca33a49011144abf9 --- escher/src/scrollable_expression_view_with_cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index fd0f07a1b..c80e887a8 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -199,7 +199,7 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi return; } KDSize previousSize = minimalSizeForOptimalDisplay(); - if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { + if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } if (pointedLayout != nullptr) { From ac84a2e045a492ecb10fce43304c1190d8fecb80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 17:26:49 +0200 Subject: [PATCH 242/459] [poincare] Fix EmptyExpression. Change-Id: I317bbb546af5a42de3c896b2e9a92a8040a95d22 --- poincare/include/poincare/empty_expression.h | 5 +++-- poincare/src/empty_expression.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index e56ecc47a..09d1cbb9d 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -14,9 +14,10 @@ public: return Type::EmptyExpression; } Expression * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override;private: + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; +private: /* Layout */ - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index b9d7ae2fd..455e26b59 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -13,11 +13,11 @@ Expression * EmptyExpression::clone() const { return new EmptyExpression(); } -int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize) const { +int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, Ion::Charset::Empty); } -ExpressionLayout * EmptyExpression::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { +ExpressionLayout * EmptyExpression::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { return new EmptyVisibleLayout(); } From f504b52dac235c711a45b214a9e65e3bf9a6cbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 17:27:10 +0200 Subject: [PATCH 243/459] [poincare] Remove un-needed function typedef. Change-Id: I36b17a1978f03e51064c8e11768dcc9fad5b9b35 --- poincare/include/poincare/layout_engine.h | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 1be9c9f08..818f38e82 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -18,7 +18,6 @@ public: static ExpressionLayout * createLogLayout(ExpressionLayout * argument, ExpressionLayout * index); /* Expression to Text */ - typedef bool (*OperandNeedsParenthesis)(const Expression * e); static int writeInfixExpressionTextInBuffer( const Expression * expression, char * buffer, From 9f9692b009897a8d9a79c3b580fff8a75a977f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 17:49:51 +0200 Subject: [PATCH 244/459] [poincare] Add numberOfSignificantDigits arguent in writetextInBuffer Change-Id: I1bef3462dbdfd94bff0af0e9d569d0ecf63d157c --- poincare/include/poincare/expression_layout.h | 3 ++- poincare/include/poincare/integer.h | 3 ++- poincare/src/layout/absolute_value_layout.h | 5 +++-- poincare/src/layout/binomial_coefficient_layout.h | 5 +++-- poincare/src/layout/bracket_layout.cpp | 2 +- poincare/src/layout/bracket_layout.h | 3 ++- poincare/src/layout/bracket_left_layout.h | 2 +- poincare/src/layout/bracket_right_layout.h | 2 +- poincare/src/layout/ceiling_layout.h | 4 ++-- poincare/src/layout/char_layout.h | 2 +- poincare/src/layout/condensed_sum_layout.h | 4 ++-- poincare/src/layout/conjugate_layout.h | 4 ++-- poincare/src/layout/empty_visible_layout.cpp | 2 +- poincare/src/layout/empty_visible_layout.h | 2 +- poincare/src/layout/floor_layout.h | 4 ++-- poincare/src/layout/fraction_layout.cpp | 4 ++-- poincare/src/layout/fraction_layout.h | 2 +- poincare/src/layout/grid_layout.h | 2 +- poincare/src/layout/horizontal_layout.cpp | 4 ++-- poincare/src/layout/horizontal_layout.h | 2 +- poincare/src/layout/integral_layout.cpp | 8 ++++---- poincare/src/layout/integral_layout.h | 2 +- poincare/src/layout/matrix_layout.cpp | 4 ++-- poincare/src/layout/matrix_layout.h | 2 +- poincare/src/layout/nth_root_layout.cpp | 8 ++++---- poincare/src/layout/nth_root_layout.h | 2 +- poincare/src/layout/parenthesis_left_layout.h | 2 +- poincare/src/layout/parenthesis_right_layout.h | 2 +- poincare/src/layout/product_layout.cpp | 4 ++-- poincare/src/layout/product_layout.h | 2 +- poincare/src/layout/sequence_layout.cpp | 8 ++++---- poincare/src/layout/sequence_layout.h | 2 +- poincare/src/layout/sum_layout.cpp | 4 ++-- poincare/src/layout/sum_layout.h | 2 +- poincare/src/layout/vertical_offset_layout.cpp | 6 +++--- poincare/src/layout/vertical_offset_layout.h | 2 +- 36 files changed, 63 insertions(+), 58 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 8de6d3878..ec5bc978c 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -2,6 +2,7 @@ #define POINCARE_EXPRESSION_LAYOUT_H #include +#include namespace Poincare { @@ -92,7 +93,7 @@ public: virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); /* Expression Engine */ - virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; + virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; /* Other */ bool addGreySquaresToAllMatrixAncestors(); diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 3889d28c2..659e446e6 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -3,10 +3,11 @@ #include #include -#include namespace Poincare { +class ExpressionLayout; + /* All algorithm should be improved with: * Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */ diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index 0be2b78a8..eddb3ad55 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -3,6 +3,7 @@ #include "bracket_layout.h" #include +#include namespace Poincare { @@ -10,8 +11,8 @@ class AbsoluteValueLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "abs"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "abs"); } protected: KDCoordinate widthMargin() const override { return 2; } diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index a77b9426b..5ba22a114 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -14,8 +15,8 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "binomial"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 9fe511f88..5544e628c 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -80,7 +80,7 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldReco return false; } -int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 9c9deaf66..6ddb363b7 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -2,6 +2,7 @@ #define POINCARE_BRACKET_LAYOUT_H #include +#include namespace Poincare { @@ -12,7 +13,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: ExpressionLayout * operandLayout(); KDCoordinate externWidthMargin() const { return 2; } diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index 77f9f00bb..9db160521 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -11,7 +11,7 @@ class BracketLeftLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '['); } bool isLeftBracket() const override { return true; } diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index 726d23694..1b303c0d2 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -11,7 +11,7 @@ class BracketRightLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ']'); } bool isRightBracket() const override { return true; } diff --git a/poincare/src/layout/ceiling_layout.h b/poincare/src/layout/ceiling_layout.h index b09c99f5a..1d60673d4 100644 --- a/poincare/src/layout/ceiling_layout.h +++ b/poincare/src/layout/ceiling_layout.h @@ -10,8 +10,8 @@ class CeilingLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "ceil"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "ceil"); } protected: bool renderBottomBar() const override { return false; } diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 48a7590c2..90b7de8bb 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -11,7 +11,7 @@ class CharLayout : public StaticLayoutHierarchy<0> { public: CharLayout(char c, KDText::FontSize fontSize = KDText::FontSize::Large); ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 3026ef0b5..aa76d39d9 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -14,8 +14,8 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "sum"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 5b1f2097e..52b7f321e 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -15,8 +15,8 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "conj"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "conj"); } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index bcc59d66c..770ef69a5 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -61,7 +61,7 @@ bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul return false; } -int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index c554a9188..c9d0aa123 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -17,7 +17,7 @@ public: void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } void setColor(Color color) { m_color = color; } diff --git a/poincare/src/layout/floor_layout.h b/poincare/src/layout/floor_layout.h index 5e5a9785b..8d8d65227 100644 --- a/poincare/src/layout/floor_layout.h +++ b/poincare/src/layout/floor_layout.h @@ -10,8 +10,8 @@ class FloorLayout : public BracketLayout { public: using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "floor"); + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "floor"); } protected: bool renderTopBar() const override { return false; } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 82e6956ff..173394484 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -154,7 +154,7 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { if (bufferSize == 0) { return -1; } @@ -174,7 +174,7 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } // Write the content of the fraction - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, "/"); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits "/"); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Add a multiplication if omitted. diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 044d60158..c71dd5ef9 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -15,7 +15,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } /* WARNING: We need to override this function, else 1/2 3/4 would be * serialized as 1/2**3/4, as the two Fraction layouts think their brother is diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 9bd6b467e..b0e981ae4 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -24,7 +24,7 @@ public: // grid's children, do not call this function. /* Expression engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return 0; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 63bd346c5..adbb8a68d 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -298,7 +298,7 @@ void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int ind DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); } -int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { if (numberOfChildren() == 0) { if (bufferSize == 0) { return -1; @@ -306,7 +306,7 @@ int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[0] = 0; return 0; } - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, ""); + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); } bool HorizontalLayout::isEmpty() const { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 5d3c6d9d7..e714e73a9 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -34,7 +34,7 @@ public: void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) override; /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Other */ bool isHorizontal() const override { return true; } diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 48941a195..2184a1cd3 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -160,7 +160,7 @@ bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } @@ -179,7 +179,7 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { } // Write the argument - numberOfChar += const_cast(this)->integrandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->integrandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma @@ -187,7 +187,7 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the lower bound - numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma @@ -195,7 +195,7 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize) const { if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the upper bound - numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the closing parenthesis diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 6241c756d..a5866df1b 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -23,7 +23,7 @@ public: bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 282e99081..209d3455f 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -165,7 +165,7 @@ void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool delete replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); } -int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { // The grid is a matrix. if (bufferSize == 0) { return -1; @@ -183,7 +183,7 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[numberOfChar++] = '['; if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + maxColumnIndex); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits, ",", i*m_numberOfColumns, i* m_numberOfColumns + maxColumnIndex); buffer[numberOfChar++] = ']'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 0c595d32d..f18cba8aa 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -24,7 +24,7 @@ public: void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; /* Expression engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Other */ bool isMatrix() const override { return true; } diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 291171463..80ce7f0cc 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -171,17 +171,17 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecom } static_assert('\x90' == Ion::Charset::Root, "Unicode error"); -int NthRootLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int NthRootLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { // Case: root(x,n) if (numberOfChildren() == 2 && (const_cast(this))->indexLayout() && !(const_cast(this))->indexLayout()->isEmpty()) { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "root"); + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "root"); } // Case: squareRoot(x) if (numberOfChildren() == 1) { - return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "\x90"); + return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "\x90"); } // Case: root(x,empty) // Write "'SquareRootSymbol'('radicandLayout')". @@ -202,7 +202,7 @@ int NthRootLayout::writeTextInBuffer(char * buffer, int bufferSize) const { return bufferSize-1; } - numberOfChar += (const_cast(this))->radicandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += (const_cast(this))->radicandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ')'; diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index db5eec064..c46ccbe86 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -23,7 +23,7 @@ public: bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Expression Engine */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 468385383..99c070fe4 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -12,7 +12,7 @@ class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '('); } bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index fb372b06c..edf361dfb 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -12,7 +12,7 @@ class ParenthesisRightLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ')'); } bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp index 2b9120db7..f850b8860 100644 --- a/poincare/src/layout/product_layout.cpp +++ b/poincare/src/layout/product_layout.cpp @@ -9,8 +9,8 @@ ExpressionLayout * ProductLayout::clone() const { return layout; } -int ProductLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - return SequenceLayout::writeDerivedClassInBuffer("product", buffer, bufferSize); +int ProductLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return SequenceLayout::writeDerivedClassInBuffer("product", buffer, bufferSize, numberOfSignificantDigits); } void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/product_layout.h b/poincare/src/layout/product_layout.h index 72750ebbb..090aab63d 100644 --- a/poincare/src/layout/product_layout.h +++ b/poincare/src/layout/product_layout.h @@ -10,7 +10,7 @@ class ProductLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; private: diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 94a64aa37..dd1066051 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -136,7 +136,7 @@ char SequenceLayout::XNTChar() const { return 'n'; } -int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize) const { +int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits) const { assert(operatorName != nullptr); if (bufferSize == 0) { return -1; @@ -152,7 +152,7 @@ int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the argument - numberOfChar += const_cast(this)->argumentLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->argumentLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma @@ -160,7 +160,7 @@ int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the lower bound - numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the comma @@ -168,7 +168,7 @@ int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the upper bound - numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the closing parenthesis diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 7299ca914..164ead79d 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -19,7 +19,7 @@ public: protected: constexpr static KDCoordinate k_boundHeightMargin = 2; constexpr static KDCoordinate k_argumentWidthMargin = 2; - int writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize) const; + int writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; ExpressionLayout * lowerBoundLayout(); ExpressionLayout * upperBoundLayout(); ExpressionLayout * argumentLayout(); diff --git a/poincare/src/layout/sum_layout.cpp b/poincare/src/layout/sum_layout.cpp index a38117c97..41c274556 100644 --- a/poincare/src/layout/sum_layout.cpp +++ b/poincare/src/layout/sum_layout.cpp @@ -27,8 +27,8 @@ ExpressionLayout * SumLayout::clone() const { return layout; } -int SumLayout::writeTextInBuffer(char * buffer, int bufferSize) const { - return SequenceLayout::writeDerivedClassInBuffer("sum", buffer, bufferSize); +int SumLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return SequenceLayout::writeDerivedClassInBuffer("sum", buffer, bufferSize, numberOfSignificantDigits); } void SumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/sum_layout.h b/poincare/src/layout/sum_layout.h index 4f8228921..205ee0831 100644 --- a/poincare/src/layout/sum_layout.h +++ b/poincare/src/layout/sum_layout.h @@ -10,7 +10,7 @@ class SumLayout : public SequenceLayout { public: using SequenceLayout::SequenceLayout; ExpressionLayout * clone() const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; private: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; }; diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 5180c986f..0448502f2 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -185,7 +185,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shou return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const { +int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (m_type == Type::Subscript) { if (bufferSize == 0) { return -1; @@ -201,7 +201,7 @@ int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '{'); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - numberOfChar += const_cast(this)->indiceLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->indiceLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '}'); @@ -211,7 +211,7 @@ int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize) const } assert(m_type == Type::Superscript); // If the layout is a superscript, write "^(indice)" - int numberOfChar = LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, "^"); + int numberOfChar = LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "^"); // Add a multiplication if omitted. int indexInParent = -1; diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index bfceadee1..d63ca2e9c 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -18,7 +18,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftBrother() const override { return true; } protected: ExpressionLayout * indiceLayout(); From 6044ca8493732cb5bed482040c5d0813653e6c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 17:55:31 +0200 Subject: [PATCH 245/459] [poincare] Fix too many arguments problem Change-Id: Ie3018b2b82f0c87b1551ab2bcd9c80bb41212ecb --- poincare/src/layout_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index dd0a6c68b..9b2e43ddb 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -87,7 +87,7 @@ int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expressio } int LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis) { - return writeInfixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, numberOfDigits, operatorName, firstChildIndex, lastChildIndex, [](const Expression * e) { return true; }, childNeedsParenthesis); + return writeInfixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, numberOfDigits, operatorName, firstChildIndex, lastChildIndex, childNeedsParenthesis); } int LayoutEngine::writePrefixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, bool writeFirstChild) { From 0e67cc6b11b7f0e10de5645521526d5e98e8a587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 17:56:13 +0200 Subject: [PATCH 246/459] [poincare] Add missing header Change-Id: Ic0a90940b16a3d4c30c85e22fba9ab5d4f1006c8 --- poincare/src/symbol.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 545a64217..abcb886f2 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include From 1c6e8119b3b6b5147376bb9d6d0ed93a4e0e5070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 18:03:19 +0200 Subject: [PATCH 247/459] [apps] Remove use of StringLayout Change-Id: I4b8cac2fa778ebddb3e2b1f3f0f75182deb45a61 --- apps/shared/sum_graph_controller.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 0f162a333..52f351b61 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -1,8 +1,7 @@ #include "sum_graph_controller.h" #include "../apps_container.h" +#include #include "../../poincare/src/layout/condensed_sum_layout.h" -#include "../../poincare/src/layout/string_layout.h" -#include "../../poincare/src/layout/horizontal_layout.h" #include #include @@ -245,23 +244,23 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl } const char sigma[] = {' ', m_sumSymbol}; if (step == Step::FirstParameter) { - m_sumLayout = new StringLayout(sigma, sizeof(sigma)); + m_sumLayout = LayoutEngine::createStringLayout(sigma, sizeof(sigma)); } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); + m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); } else { char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - ExpressionLayout * start = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + ExpressionLayout * start = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); PrintFloat::convertFloatToText(end, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - ExpressionLayout * end = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); - m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, sizeof(sigma)), start, end); + ExpressionLayout * end = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), start, end); ExpressionLayout * childrenLayouts[3]; strlcpy(buffer, "= ", 3); PrintFloat::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); - childrenLayouts[2] = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + childrenLayouts[2] = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); childrenLayouts[1] = functionLayout; childrenLayouts[0] = m_sumLayout; m_sumLayout = new HorizontalLayout(childrenLayouts, 3); From a6e6416e09ca3d1bf9b37b98a4f7ba9baac2e8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 18:03:40 +0200 Subject: [PATCH 248/459] [poincare] Fix code typos Change-Id: I02143e1b99d3cf2f4ced6954bf2e612542c01642 --- poincare/src/layout/fraction_layout.cpp | 4 ++-- poincare/src/layout/horizontal_layout.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 173394484..7702cad28 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -154,7 +154,7 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } -int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { +int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } @@ -174,7 +174,7 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO } // Write the content of the fraction - numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits "/"); + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits, "/"); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Add a multiplication if omitted. diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index adbb8a68d..7c454e760 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -298,7 +298,7 @@ void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int ind DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); } -int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { +int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (numberOfChildren() == 0) { if (bufferSize == 0) { return -1; From 7991c5376fb7f4de17861b99f68df6f27f4f7680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Apr 2018 18:14:55 +0200 Subject: [PATCH 249/459] [apps] Fix typos Change-Id: I650d0d98daab5959e9efab79b78905533316b85d --- apps/shared/sum_graph_controller.cpp | 4 ++-- apps/shared/sum_graph_controller.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 52f351b61..f646a4029 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -144,7 +144,7 @@ bool SumGraphController::textFieldDidFinishEditing(TextField * textField, const return false; } -bool SumGraphController::textFieldDidAbortEditing(TextField * textField, const char * text) { +bool SumGraphController::textFieldDidAbortEditing(TextField * textField) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; double parameter = NAN; switch(m_step) { @@ -265,7 +265,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl childrenLayouts[0] = m_sumLayout; m_sumLayout = new HorizontalLayout(childrenLayouts, 3); } - m_sum.setExpression(m_sumLayout); + m_sum.setExpressionLayout(m_sumLayout); if (step == Step::Result) { m_sum.setAlignment(0.5f, 0.5f); } else { diff --git a/apps/shared/sum_graph_controller.h b/apps/shared/sum_graph_controller.h index 4915de927..98a110957 100644 --- a/apps/shared/sum_graph_controller.h +++ b/apps/shared/sum_graph_controller.h @@ -20,7 +20,7 @@ public: bool handleEvent(Ion::Events::Event event) override; void setFunction(Function * function); bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - bool textFieldDidAbortEditing(TextField * textField, const char * text) override; + bool textFieldDidAbortEditing(TextField * textField) override; bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; protected: virtual bool moveCursorHorizontallyToPosition(double position); From 6d3c67e9db47ed8cf34ac480f9d513cfc8f1daa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 10:21:25 +0200 Subject: [PATCH 250/459] [apps] Merge apps/sequence/graph/term_sum_controller.cpp Change-Id: I9cbcbb73f4f475590762e29ab98999bd42906e74 --- apps/sequence/graph/term_sum_controller.cpp | 113 +------------------- 1 file changed, 5 insertions(+), 108 deletions(-) diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index 1cdf439c8..4d0574fae 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -2,9 +2,7 @@ #include "../../shared/text_field_delegate.h" #include "../app.h" -#include #include "../../../poincare/src/layout/char_layout.h" -#include "../../../poincare/src/layout/condensed_sum_layout.h" #include "../../../poincare/src/layout/horizontal_layout.h" #include "../../../poincare/src/layout/vertical_offset_layout.h" @@ -52,115 +50,14 @@ double TermSumController::cursorNextStep(double x, int direction) { return std::round(m_cursor->x()+delta); } -<<<<<<< HEAD ExpressionLayout * TermSumController::createFunctionLayout(const char * functionName) { - return new BaselineRelativeLayout(new StringLayout(functionName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); -======= -/* Legend View */ - -TermSumController::LegendView::LegendView() : - m_sum(0.0f, 0.5f, KDColorBlack, Palette::GreyBright), - m_sumLayout(nullptr), - m_legend(KDText::FontSize::Small, I18n::Message::Default, 0.0f, 0.5f, KDColorBlack, Palette::GreyBright) -{ -} - -TermSumController::LegendView::~LegendView() { - if (m_sumLayout != nullptr) { - delete m_sumLayout; - m_sumLayout = nullptr; - } -} - -void TermSumController::LegendView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect(KDRect(0, bounds().height() - k_legendHeight, bounds().width(), k_legendHeight), Palette::GreyMiddle); -} - -KDSize TermSumController::LegendView::minimalSizeForOptimalDisplay() const { - return KDSize(0, k_legendHeight); -} - -void TermSumController::LegendView::setLegendMessage(I18n::Message message) { - m_legend.setMessage(message); - layoutSubviews(); -} - -void TermSumController::LegendView::setSumSubscript(float start) { - if (m_sumLayout) { - delete m_sumLayout; - m_sumLayout = nullptr; - } - const char sigma[] = {' ', Ion::Charset::CapitalSigma}; - char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - m_sumLayout = new CondensedSumLayout( - LayoutEngine::createStringLayout(sigma, sizeof(sigma), KDText::FontSize::Large), - LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), - nullptr, - false); - m_sum.setExpressionLayout(m_sumLayout); - m_sum.setAlignment(0.0f, 0.5f); -} - -void TermSumController::LegendView::setSumSuperscript(float start, float end) { - if (m_sumLayout) { - delete m_sumLayout; - m_sumLayout = nullptr; - } - const char sigma[] = {' ', Ion::Charset::CapitalSigma}; - char bufferStart[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(start, bufferStart, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - char bufferEnd[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - m_sumLayout = new CondensedSumLayout( - LayoutEngine::createStringLayout(sigma, sizeof(sigma), KDText::FontSize::Large), - LayoutEngine::createStringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), - LayoutEngine::createStringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small), - false); - m_sum.setExpressionLayout(m_sumLayout); - m_sum.setAlignment(0.0f, 0.5f); -} - -void TermSumController::LegendView::setSumResult(const char * sequenceName, double result) { - char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - strlcpy(buffer, "= ", 3); - Complex::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); - m_sumLayout = new HorizontalLayout( - m_sumLayout, - new HorizontalLayout( - new CharLayout(sequenceName[0], KDText::FontSize::Small), - new VerticalOffsetLayout(new CharLayout('n', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), + return new HorizontalLayout( + new CharLayout(functionName[0], KDText::FontSize::Small), + new VerticalOffsetLayout( + new CharLayout('n', KDText::FontSize::Small), + VerticalOffsetLayout::Type::Subscript, false), - LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), false); - m_sum.setExpressionLayout(m_sumLayout); - m_sum.setAlignment(0.5f, 0.5f); -} - -int TermSumController::LegendView::numberOfSubviews() const { - return 2; -} - -View * TermSumController::LegendView::subviewAtIndex(int index) { - assert(index >= 0 && index < 2); - if (index == 0) { - return &m_sum; - } - return &m_legend; -} - -void TermSumController::LegendView::layoutSubviews() { - KDCoordinate width = bounds().width(); - KDCoordinate heigth = bounds().height(); - KDSize legendSize = m_legend.minimalSizeForOptimalDisplay(); - if (legendSize.width() > 0) { - m_sum.setFrame(KDRect(0, 0, width-legendSize.width(), heigth)); - m_legend.setFrame(KDRect(width-legendSize.width(), 0, legendSize.width(), heigth)); - return; - } - m_sum.setFrame(bounds()); - m_legend.setFrame(KDRectZero); ->>>>>>> SaisieJolieRebase1201 } } From 2146dd6422083315204e9cb99f0b89d5f734523d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 10:40:06 +0200 Subject: [PATCH 251/459] [apps] Fix wrong method call Change-Id: I2695d7c659f18edb1839cdf7c8282cc69862a4e5 --- apps/calculation/edit_expression_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index bcaa408da..37cd3c772 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -158,8 +158,8 @@ bool EditExpressionController::inputViewDidFinishEditing(const char * text, Ion: m_calculationStore->push(textBody(), calculationApp->localContext()); m_historyController->reload(); ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); - ((ContentView *)view())->textField()->setEditing(true); - ((ContentView *)view())->textField()->setText(""); + ((ContentView *)view())->editableExpressionView()->setEditing(true); + ((ContentView *)view())->editableExpressionView()->setText(""); return true; } From cbaba85daae76668f614ad8ce9778224f37a316e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 10:41:28 +0200 Subject: [PATCH 252/459] [apps] Fix missing arguments in layout creation. Change-Id: If819c6f8d067b80d5672774ca303b68e21cf0d7a --- apps/shared/sum_graph_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index f646a4029..27c9f6f56 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -248,7 +248,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); + m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr, false); } else { char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); @@ -263,7 +263,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl childrenLayouts[2] = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); childrenLayouts[1] = functionLayout; childrenLayouts[0] = m_sumLayout; - m_sumLayout = new HorizontalLayout(childrenLayouts, 3); + m_sumLayout = new HorizontalLayout(childrenLayouts, 3, false); } m_sum.setExpressionLayout(m_sumLayout); if (step == Step::Result) { From 44e8eb1285c549c920df4f9f281b31740d945059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 10:42:20 +0200 Subject: [PATCH 253/459] [escher] EditableExpressionView, fix setEditing It should only apply to the TextField or ScrollableExpressionViewWithCursor depending on the edition mode. Change-Id: I2ae4a3a4e956dc1d51729c9497642b9c236f9069 --- escher/src/editable_expression_view.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index add967f2d..00c98bd13 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -14,11 +14,12 @@ EditableExpressionView::EditableExpressionView(Responder * parentResponder, Text void EditableExpressionView::setEditing(bool isEditing, bool reinitDraftBuffer) { if (editionIsInTextField()) { m_textField.setEditing(isEditing, reinitDraftBuffer); + } else { + if (reinitDraftBuffer) { + m_scrollableExpressionViewWithCursor.clearLayout(); + } + m_scrollableExpressionViewWithCursor.setEditing(isEditing); } - if (reinitDraftBuffer) { - m_scrollableExpressionViewWithCursor.clearLayout(); - } - m_scrollableExpressionViewWithCursor.setEditing(isEditing); } bool EditableExpressionView::isEditing() const { From 5984b24107f339ba085734e24d8892f3095d14ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 16:53:38 +0200 Subject: [PATCH 254/459] [apps] Remove obsolete StringLayout. Change-Id: Ib8ef9f6b89ead2674b3bc1f19131afdd73f0e823 --- apps/graph/graph/integral_graph_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/graph/graph/integral_graph_controller.cpp b/apps/graph/graph/integral_graph_controller.cpp index 49fd032fc..c83d43113 100644 --- a/apps/graph/graph/integral_graph_controller.cpp +++ b/apps/graph/graph/integral_graph_controller.cpp @@ -1,6 +1,6 @@ #include "integral_graph_controller.h" #include "../../shared/text_field_delegate.h" -#include "../../../poincare/src/layout/string_layout.h" +#include #include "../app.h" #include @@ -39,7 +39,7 @@ double IntegralGraphController::cursorNextStep(double x, int direction) { ExpressionLayout * IntegralGraphController::createFunctionLayout(const char * functionName) { char buffer[7] = "0(x)dx"; buffer[0] = functionName[0]; - return new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + return LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); } } From 749c93e1af9925819bfedc521b49134d01dbb94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 16:56:35 +0200 Subject: [PATCH 255/459] [apps/sequence] Fix obsolete code. Change-Id: I4f6c1792ac245c072a3d70108a55518473c3fe80 --- apps/sequence/list/list_controller.cpp | 2 +- apps/sequence/list/sequence_toolbox.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 9c3207232..3a4a7f185 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -25,7 +25,7 @@ const char * ListController::title() { Toolbox * ListController::toolboxForTextInput(TextInput * textInput) { setToolboxExtraCells(); - m_sequenceToolbox.setSenderAndAction(textField, MathToolbox::actionForTextInput); + m_sequenceToolbox.setSenderAndAction(textInput, MathToolbox::actionForTextInput); return &m_sequenceToolbox; } diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index 9d321a4cb..04509ceb0 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -106,7 +106,7 @@ void SequenceToolbox::setExtraCells(const char * sequenceName, int recurrenceDep false); } for (int index = 0; index < k_maxNumberOfDisplayedRows; index++) { - m_addedCells[index].setExpression(m_addedCellLayout[index]); + m_addedCells[index].setExpressionLayout(m_addedCellLayout[index]); } } @@ -114,7 +114,7 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){ int bufferSize = 10; char buffer[bufferSize]; m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); - if (m_action == MathToolbox::actionForTextField) { + if (m_action == MathToolbox::actionForTextInput) { // DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout, // which serializes into "_{}", but we want parentheses for text fields. We // thus need to remove any underscores, and changes brackets into From 88aaab64ba7543000c4d452df59f541b44f6a3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 17:10:09 +0200 Subject: [PATCH 256/459] [apps] Fix obsolete code in Code and Shared Change-Id: Ie6ce0f753bf05cb5f6dd5ed974db2a715b21624e --- apps/code/menu_controller.cpp | 2 +- apps/shared/sum_graph_controller.cpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index d85139c24..11338bc88 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -55,7 +55,7 @@ void MenuController::willExitResponderChain(Responder * nextFirstResponder) { TextField * tf = static_cast(m_selectableTableView.selectedCell())->editableTextCell()->textField(); if (tf->isEditing()) { tf->setEditing(false); - textFieldDidAbortEditing(tf, tf->text()); + textFieldDidAbortEditing(tf); } } } diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 27c9f6f56..5244263a7 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -248,15 +248,22 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr, false); + m_sumLayout = new CondensedSumLayout( + LayoutEngine::createStringLayout(sigma, sizeof(sigma)), + LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), + nullptr, + false); } else { char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); ExpressionLayout * start = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); PrintFloat::convertFloatToText(end, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); ExpressionLayout * end = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); - m_sumLayout = new CondensedSumLayout(LayoutEngine::createStringLayout(sigma, sizeof(sigma)), start, end); - + m_sumLayout = new CondensedSumLayout( + LayoutEngine::createStringLayout(sigma, sizeof(sigma)), + start, + end, + false); ExpressionLayout * childrenLayouts[3]; strlcpy(buffer, "= ", 3); PrintFloat::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); From 0fcd2a90f6680e37242be07404a6c3b1c5b02f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Apr 2018 17:11:05 +0200 Subject: [PATCH 257/459] [apps] Fix comment aesthetics Change-Id: I3e91391f0751515efe50ec4e4335a2421f2acbee --- apps/sequence/list/sequence_toolbox.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index 04509ceb0..08d67f4fd 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -115,10 +115,10 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){ char buffer[bufferSize]; m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); if (m_action == MathToolbox::actionForTextInput) { - // DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout, - // which serializes into "_{}", but we want parentheses for text fields. We - // thus need to remove any underscores, and changes brackets into - // parentheses. + /* DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout, + * which serializes into "_{}", but we want parentheses for text fields. We + * thus need to remove any underscores, and changes brackets into + * parentheses. */ for (int i = 0; i < bufferSize; i++) { if (buffer[i] == '{') { buffer[i] = '('; From e60cf7cea359d62401ae71c247e2fdf5528dbfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 11:19:30 +0200 Subject: [PATCH 258/459] [escher] Clean code. Change-Id: I081aa2ac6b1be4df034aeac0e274379e9daa2afd --- .../src/scrollable_expression_view_with_cursor.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index c80e887a8..3860ea167 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -40,21 +40,18 @@ Toolbox * ScrollableExpressionViewWithCursor::toolbox() { bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { KDSize previousSize = minimalSizeForOptimalDisplay(); bool shouldRecomputeLayout = false; + bool didHandleEvent = false; if (privateHandleMoveEvent(event, &shouldRecomputeLayout)) { if (!shouldRecomputeLayout) { m_expressionViewWithCursor.cursorPositionChanged(); scrollToCursor(); return true; } - reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); - reload(); - } - return true; + didHandleEvent = true; + } else if (privateHandleEvent(event)) { + didHandleEvent = true; } - if (privateHandleEvent(event)) { + if (didHandleEvent) { reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { From 34f6729e357489df27c79d9c77c82161012bbc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 11:20:15 +0200 Subject: [PATCH 259/459] [escher] Add initial text before handling event in editableEV It seems more logical. Change-Id: I72432221ba567b0f7b0d46946a397e4d1b53c8d0 --- escher/src/input_view_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 2eec8b207..bd8e71d36 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -33,10 +33,10 @@ void InputViewController::edit(Responder * caller, Ion::Events::Event event, voi m_successAction = Invocation(successAction, context); m_failureAction = Invocation(failureAction, context); displayModalViewController(&m_editableExpressionViewController, 1.0f, 1.0f); - m_editableExpressionViewController.editableExpressionView()->handleEvent(event); if (initialText != nullptr) { m_editableExpressionViewController.editableExpressionView()->setText(initialText); } + m_editableExpressionViewController.editableExpressionView()->handleEvent(event); } void InputViewController::abortEditionAndDismiss() { From 8ced0d68399bdc1c8b925a354500e7a3adb2f35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 11:21:46 +0200 Subject: [PATCH 260/459] [poincare] HorizontalLayout is not collapsable. This fixes a bug when pressing (^2) on an empty function definition in Graph. Change-Id: If9c07218d3aa7fe8a67b32c6f20d2e52800877b9 --- poincare/src/layout/horizontal_layout.h | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index e714e73a9..bd26b71a2 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -39,6 +39,7 @@ public: /* Other */ bool isHorizontal() const override { return true; } bool isEmpty() const override; + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return false; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; From 042bdf3477be01acddd3f84aac0b2b329a9217d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 11:38:14 +0200 Subject: [PATCH 261/459] [escher] setEditing(true) when handling event in ScrollableEVWithCursor Change-Id: I24760d7050fffd3ba5c38393450c4545354a7769 --- escher/src/scrollable_expression_view_with_cursor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 3860ea167..5a882acc1 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -52,6 +52,9 @@ bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { didHandleEvent = true; } if (didHandleEvent) { + if (!isEditing()) { + setEditing(true); + } reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { From c97c1b6231389dfde9d11988aaf77edd2f998e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 11:42:32 +0200 Subject: [PATCH 262/459] Remove debug comment. Change-Id: I2bd6731e8045606fb0132d29e2aea353f0518380 --- escher/src/text_area.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index 61892a169..7512d6bac 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -344,7 +344,7 @@ void TextArea::setText(char * textBuffer, size_t textBufferSize) { bool TextArea::insertTextWithIndentation(const char * textBuffer, int location) { int indentation = indentationBeforeCursor(); - char spaceString[indentation+1]; // WOUHOU + char spaceString[indentation+1]; for (int i = 0; i < indentation; i++) { spaceString[i] = ' '; } From ca53df8166767e40ba69af5658a5d6f0d6765f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 12:00:23 +0200 Subject: [PATCH 263/459] [poincare] Fix fraction to a power bug. 2/345 ^6 would give 2/(345^6) Change-Id: I1eb0144f511b80ce98cb247de8497fb33153e94b --- poincare/src/layout/fraction_layout.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 7702cad28..f71761b68 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -173,10 +173,24 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO if (numberOfChar >= bufferSize-1) { return bufferSize-1;} } + bool addParenthesis = false; + if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) { + addParenthesis = true; + // Add parenthesis + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + // Write the content of the fraction numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits, "/"); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + if (addParenthesis) { + // Add parenthesis + buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + // Add a multiplication if omitted. if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->canBeOmittedMultiplicationRightFactor()) { buffer[numberOfChar++] = Ion::Charset::MiddleDot; From 3cdec1ccfecf02313a65953d93bf09c617fe2047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 12:01:34 +0200 Subject: [PATCH 264/459] [poincare] Change Horizontal Layout collapsability. canBeOmittedMultiplicationLeft/RightFactor depends on isCollapsable() so it should not be changed too much. Change-Id: Iad7dab5cf751863b392bbd81976c66ebf849f048 --- poincare/src/layout/horizontal_layout.cpp | 8 ++++++++ poincare/src/layout/horizontal_layout.h | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 7c454e760..80fc0cd6d 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -317,6 +317,14 @@ bool HorizontalLayout::isEmpty() const { return false; } +bool HorizontalLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (m_numberOfChildren == 0) { + return false; + } else { + return true; + } +} + void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index bd26b71a2..f194d5376 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -39,8 +39,7 @@ public: /* Other */ bool isHorizontal() const override { return true; } bool isEmpty() const override; - bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return false; } - + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; From a1da582573e5f7ff52e125a91dee4f2aa19e7467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 12:16:55 +0200 Subject: [PATCH 265/459] [poincare] Fix power insertion Example: 12|3 and the cursor is on the left of the 3 Addig a power also adds an empty base, because of a mistake in baseForNewPowerLayout(). Change-Id: I12de33baca7fa03fb5d34b6a928a85b11a1d389f --- poincare/src/expression_layout_cursor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 90b0aaabb..35d534575 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -226,8 +226,8 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { if (m_position == Position::Left && m_pointedExpressionLayout->parent()->isHorizontal() && indexInParent > 0 - && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isEmpty() - && !m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true)) + && (m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isEmpty() + || m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true))) { return true; } From 7e1fd151147107c2b898c979b619a4274592da11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 14:23:17 +0200 Subject: [PATCH 266/459] [poincare] Fix the removal of empty layouts when copy-pasting. Example case problem: copy a value, enter '1' and '/', then paste. Before, the empty layout was not removed. Change-Id: I1df050a2ac144a05578462e58700959a090ed839 --- poincare/src/layout/horizontal_layout.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 80fc0cd6d..af9875390 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -277,7 +277,6 @@ bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRe return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } - void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, operands[0]->mustHaveLeftBrother()); DynamicLayoutHierarchy::addChildrenAtIndex(operands, numberOfOperands, newIndex, removeEmptyChildren); @@ -293,7 +292,10 @@ void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { } void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { - bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? eL->child(0)->mustHaveLeftBrother() : true; + /* If the layout to insert starts with a vertical offset layout, the child + * empty layout on the left of the inserted layout (if there is one) shoul not + * be reomved, as it wil be the base for the VerticalOffsetLayout. */ + bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? !(eL->child(0)->mustHaveLeftBrother()) : true; int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); } @@ -447,7 +449,7 @@ void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemo // If the child to remove is at index 0 and its right brother must have a left // brother (e.g. it is a VerticalOffsetLayout), replace the child with an // EmptyVisibleLayout instead of removing it. - if ( !forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { + if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { addChildAtIndex(new EmptyVisibleLayout(), index + 1); } DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); @@ -464,7 +466,11 @@ int HorizontalLayout::removeEmptyChildBeforeInsertionAtIndex(int index, bool sho } // If empty, remove the child that would be on the left of the inserted // layout. - if ( shouldRemoveOnLeft && newIndex - 1 > 0 && newIndex - 1 < numberOfChildren() -1 && child(newIndex - 1)->isEmpty()) { + if (shouldRemoveOnLeft + && newIndex - 1 >= 0 + && newIndex - 1 <= numberOfChildren() -1 + && child(newIndex - 1)->isEmpty()) + { privateRemoveChildAtIndex(newIndex-1, true, true); newIndex = index - 1; } From fd72bb450d711a7ad6fa076d192ed69e2304156a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 14:36:19 +0200 Subject: [PATCH 267/459] [poincare] Align exponent and nth root indexes layouts Change-Id: I4806d9c3338ad7b3bfd2fd4e6781b87f9956c463 --- poincare/src/layout/nth_root_layout.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index c46ccbe86..67935c06d 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -33,7 +33,7 @@ protected: private: constexpr static KDCoordinate k_rightRadixHeight = 2; constexpr static KDCoordinate k_radixHorizontalOverflow = 2; - constexpr static KDCoordinate k_indexHeight = 5; + constexpr static KDCoordinate k_indexHeight = 4; constexpr static KDCoordinate k_heightMargin = 2; constexpr static KDCoordinate k_widthMargin = 1; constexpr static KDCoordinate k_radixLineThickness = 1; From 51312f8af184b1c6ed2572354522850b5c27c40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 15:25:03 +0200 Subject: [PATCH 268/459] [poincare] Add right margin to superscript layout. Otherwise, in 2D edition, the indexes of a root and an exponential merge visually into one index: e^(123)root(1,456) displays "123456". Change-Id: I9bda14350e624181af2de66653481f3fc7ff0982 --- poincare/src/layout/vertical_offset_layout.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 0448502f2..640be9a01 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -243,6 +243,9 @@ void VerticalOffsetLayout::render(KDContext * ctx, KDPoint p, KDColor expression KDSize VerticalOffsetLayout::computeSize() { KDSize indiceSize = indiceLayout()->size(); KDCoordinate width = indiceSize.width(); + if (m_type == Type::Superscript) { + width += 5; + } KDCoordinate height = 0; if (m_type == Type::Subscript) { height = positionOfChild(indiceLayout()).y()+ indiceLayout()->size().height(); From 9b22175877bb1536d1778e3b19fbc1d796a483e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 17:23:49 +0200 Subject: [PATCH 269/459] [poincare] Hide EmptyLayout when the cursor is next to it. Change-Id: I487b99105229451d033999a12e510b3370e63093 --- ...scrollable_expression_view_with_cursor.cpp | 22 +++++++++---- .../poincare/expression_layout_cursor.h | 3 ++ poincare/src/expression_layout_cursor.cpp | 20 ++++++++++++ poincare/src/layout/empty_visible_layout.cpp | 32 +++++++------------ poincare/src/layout/empty_visible_layout.h | 5 ++- poincare/src/layout/expression_layout.cpp | 1 - 6 files changed, 54 insertions(+), 29 deletions(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 5a882acc1..57dbb5660 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -39,22 +39,26 @@ Toolbox * ScrollableExpressionViewWithCursor::toolbox() { bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { KDSize previousSize = minimalSizeForOptimalDisplay(); - bool shouldRecomputeLayout = false; bool didHandleEvent = false; - if (privateHandleMoveEvent(event, &shouldRecomputeLayout)) { - if (!shouldRecomputeLayout) { - m_expressionViewWithCursor.cursorPositionChanged(); - scrollToCursor(); - return true; - } + bool shouldRecomputeLayout = m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); + bool moveEventChangedLayout = false; + if (privateHandleMoveEvent(event, &moveEventChangedLayout)) { + shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout; didHandleEvent = true; } else if (privateHandleEvent(event)) { + shouldRecomputeLayout = true; didHandleEvent = true; } if (didHandleEvent) { if (!isEditing()) { setEditing(true); } + shouldRecomputeLayout = m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; + if (!shouldRecomputeLayout) { + m_expressionViewWithCursor.cursorPositionChanged(); + scrollToCursor(); + return true; + } reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { @@ -198,6 +202,7 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi if (layout == nullptr) { return; } + m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); KDSize previousSize = minimalSizeForOptimalDisplay(); if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); @@ -209,6 +214,7 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi } else { m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); } + m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { @@ -225,7 +231,9 @@ void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char reload(); return; } + m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); m_expressionViewWithCursor.cursor()->insertText(text); + m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); reload(); } diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 2d6791e9a..290368888 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -50,10 +50,13 @@ public: void addXNTCharLayout(); void insertText(const char * text); void performBackspace(); + bool showEmptyLayoutIfNeeded(); + bool hideEmptyLayoutIfNeeded(); private: constexpr static KDCoordinate k_cursorHeight = 18; bool baseForNewPowerLayout(); + bool privateShowHideEmptyLayoutIfNeeded(bool show); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 35d534575..748c8425c 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -212,6 +212,26 @@ void ExpressionLayoutCursor::performBackspace() { m_pointedExpressionLayout->backspaceAtCursor(this); } +bool ExpressionLayoutCursor::showEmptyLayoutIfNeeded() { + return privateShowHideEmptyLayoutIfNeeded(true); +} + +bool ExpressionLayoutCursor::hideEmptyLayoutIfNeeded() { + return privateShowHideEmptyLayoutIfNeeded(false); +} + +bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { + if (m_pointedExpressionLayout->isEmpty()) { + if (m_pointedExpressionLayout->isHorizontal()) { + static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); + } else { + static_cast(m_pointedExpressionLayout)->setVisible(show); + } + return true; + } + return false; +} + bool ExpressionLayoutCursor::baseForNewPowerLayout() { // Returns true if the layout on the left of the pointed layout is suitable to // be the base of a new power layout. diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_visible_layout.cpp index 770ef69a5..6317e0f0b 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_visible_layout.cpp @@ -6,14 +6,15 @@ namespace Poincare { -EmptyVisibleLayout::EmptyVisibleLayout(Color color) : +EmptyVisibleLayout::EmptyVisibleLayout(Color color, bool visible) : StaticLayoutHierarchy(), + m_isVisible(visible), m_color(color) { } ExpressionLayout * EmptyVisibleLayout::clone() const { - EmptyVisibleLayout * layout = new EmptyVisibleLayout(); + EmptyVisibleLayout * layout = new EmptyVisibleLayout(m_color, m_isVisible); return layout; } @@ -31,15 +32,9 @@ void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Left. // Ask the parent. if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Left); return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; @@ -47,15 +42,9 @@ bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * should bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; - } - // Case: Right. // Ask the parent. if (m_parent) { + cursor->setPosition(ExpressionLayoutCursor::Position::Right); return m_parent->moveRight(cursor, shouldRecomputeLayout); } return false; @@ -70,13 +59,16 @@ int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize, int num } void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); + if (m_isVisible) { + KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); + ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); + } } KDSize EmptyVisibleLayout::computeSize() { - return KDSize(k_width + 2*k_marginWidth, k_height + 2*k_marginHeight); + KDCoordinate width = m_isVisible ? k_width + 2*k_marginWidth : 0; + return KDSize(width, k_height + 2*k_marginHeight); } void EmptyVisibleLayout::computeBaseline() { diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_visible_layout.h index c9d0aa123..d96735c44 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_visible_layout.h @@ -12,7 +12,7 @@ public: Yellow, Grey }; - EmptyVisibleLayout(Color color = Color::Yellow); + EmptyVisibleLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -21,6 +21,8 @@ public: bool isEmpty() const override { return true; } Color color() const { return m_color; } void setColor(Color color) { m_color = color; } + bool isVisible() const { return m_isVisible; } + void setVisible(bool visible) { m_isVisible = visible; } protected: virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; virtual KDSize computeSize() override; @@ -36,6 +38,7 @@ private: constexpr static KDCoordinate k_marginWidth = 1; constexpr static KDCoordinate k_marginHeight = 2; constexpr static KDCoordinate k_lineThickness = 1; + bool m_isVisible; Color m_color; }; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 8d9feb31c..c0ac161bc 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -64,7 +64,6 @@ KDCoordinate ExpressionLayout::baseline() { return m_baseline; } - void ExpressionLayout::invalidAllSizesPositionsAndBaselines() { m_sized = false; m_positioned = false; From 1342c0f2db371eaca7520287c37cc6677981a256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 17:41:56 +0200 Subject: [PATCH 270/459] [poincare] Fix empty layout that stayed When typing 1|23 then pressing / and poing up. Change-Id: I15752919914af526b35483b2abf2a027cddc4e7b --- poincare/src/expression_layout_cursor.cpp | 2 +- poincare/src/layout/horizontal_layout.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 748c8425c..18ae81332 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -85,7 +85,7 @@ void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); if (rightBrother->isCollapsable(&numberOfOpenParenthesis, false)) { newChild->editableParent()->removeChildAtIndex(fractionIndexInParent+1, false); - child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), false); + child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), true); numberOfBrothers--; } else { break; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index af9875390..43a7fae89 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -278,12 +278,12 @@ bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRe } void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { - int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, operands[0]->mustHaveLeftBrother()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, !operands[0]->mustHaveLeftBrother()); DynamicLayoutHierarchy::addChildrenAtIndex(operands, numberOfOperands, newIndex, removeEmptyChildren); } bool HorizontalLayout::addChildAtIndex(ExpressionLayout * operand, int index) { - int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, operand->mustHaveLeftBrother()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, !operand->mustHaveLeftBrother()); return DynamicLayoutHierarchy::addChildAtIndex(operand, newIndex); } From ba97e635802c082594d3f6c56a6df45e592203fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 16 Apr 2018 17:45:49 +0200 Subject: [PATCH 271/459] [poincare] EmptyVisibleLayout becomes EmptyLayout. Change-Id: I2e33cf32ced72e47c72d2793fcc6cd98aac4eb4d --- poincare/Makefile | 2 +- poincare/include/poincare_layouts.h | 2 +- poincare/src/empty_expression.cpp | 4 +-- poincare/src/expression_layout_cursor.cpp | 22 +++++++-------- .../layout/binomial_coefficient_layout.cpp | 2 +- poincare/src/layout/conjugate_layout.cpp | 4 +-- .../src/layout/dynamic_layout_hierarchy.cpp | 2 +- ...ty_visible_layout.cpp => empty_layout.cpp} | 24 ++++++++-------- ...{empty_visible_layout.h => empty_layout.h} | 8 +++--- poincare/src/layout/expression_layout.cpp | 4 +-- poincare/src/layout/fraction_layout.cpp | 4 +-- poincare/src/layout/grid_layout.cpp | 10 +++---- poincare/src/layout/grid_layout.h | 8 +++--- poincare/src/layout/horizontal_layout.cpp | 6 ++-- poincare/src/layout/matrix_layout.cpp | 28 +++++++++---------- .../src/layout/vertical_offset_layout.cpp | 2 +- 16 files changed, 66 insertions(+), 66 deletions(-) rename poincare/src/layout/{empty_visible_layout.cpp => empty_layout.cpp} (70%) rename poincare/src/layout/{empty_visible_layout.h => empty_layout.h} (88%) diff --git a/poincare/Makefile b/poincare/Makefile index 1ace1408d..6d900aa72 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -100,7 +100,7 @@ objs += $(addprefix poincare/src/layout/,\ condensed_sum_layout.o\ conjugate_layout.o\ dynamic_layout_hierarchy.o\ - empty_visible_layout.o\ + empty_layout.o\ expression_layout.o\ floor_layout.o\ fraction_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 818351031..28e742db7 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index 455e26b59..9e416269c 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include extern "C" { @@ -18,7 +18,7 @@ int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize, int number } ExpressionLayout * EmptyExpression::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return new EmptyVisibleLayout(); + return new EmptyLayout(); } template Complex * EmptyExpression::templatedApproximate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 18ae81332..418fc85f3 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -51,7 +51,7 @@ void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { void ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyLayout(), VerticalOffsetLayout::Type::Superscript, false); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); pointedExpressionLayout()->addBrother(this, newChild); setPointedExpressionLayout(offsetLayout->editableChild(0)); @@ -60,8 +60,8 @@ void ExpressionLayoutCursor::addEmptyExponentialLayout() { void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { // Add a new FractionLayout - HorizontalLayout * child1 = new HorizontalLayout(new EmptyVisibleLayout(), false); - HorizontalLayout * child2 = new HorizontalLayout(new EmptyVisibleLayout(), false); + HorizontalLayout * child1 = new HorizontalLayout(new EmptyLayout(), false); + HorizontalLayout * child2 = new HorizontalLayout(new EmptyLayout(), false); FractionLayout * newChild = new FractionLayout(child1, child2, false); pointedExpressionLayout()->addBrother(this, newChild); @@ -115,9 +115,9 @@ void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOf for (int i = 0; i < numberOfRows + 1; i++) { for (int j = 0; j < numberOfColumns + 1; j++) { if (i < numberOfRows && j < numberOfColumns) { - children[i*(numberOfColumns+1)+j] = new EmptyVisibleLayout(EmptyVisibleLayout::Color::Yellow); + children[i*(numberOfColumns+1)+j] = new EmptyLayout(EmptyLayout::Color::Yellow); } else { - children[i*(numberOfColumns+1)+j] = new EmptyVisibleLayout(EmptyVisibleLayout::Color::Grey); + children[i*(numberOfColumns+1)+j] = new EmptyLayout(EmptyLayout::Color::Grey); } } } @@ -128,7 +128,7 @@ void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOf } void ExpressionLayoutCursor::addEmptyPowerLayout() { - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyVisibleLayout(), VerticalOffsetLayout::Type::Superscript, false); + VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyLayout(), VerticalOffsetLayout::Type::Superscript, false); // If there is already a base if (baseForNewPowerLayout()) { m_pointedExpressionLayout->addBrother(this, offsetLayout); @@ -137,7 +137,7 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { return; } // Else, add an empty base - EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyLayout * child1 = new EmptyLayout(); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); @@ -145,7 +145,7 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { } void ExpressionLayoutCursor::addEmptySquareRootLayout() { - EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyLayout * child1 = new EmptyLayout(); NthRootLayout * newChild = new NthRootLayout(child1, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); @@ -163,7 +163,7 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { return; } // Else, add an empty base - EmptyVisibleLayout * child1 = new EmptyVisibleLayout(); + EmptyLayout * child1 = new EmptyLayout(); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); m_pointedExpressionLayout->addBrother(this, newChild); setPointedExpressionLayout(child1); @@ -223,9 +223,9 @@ bool ExpressionLayoutCursor::hideEmptyLayoutIfNeeded() { bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { if (m_pointedExpressionLayout->isEmpty()) { if (m_pointedExpressionLayout->isHorizontal()) { - static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); + static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); } else { - static_cast(m_pointedExpressionLayout)->setVisible(show); + static_cast(m_pointedExpressionLayout)->setVisible(show); } return true; } diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 93867456a..300ccf0b2 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -1,5 +1,5 @@ #include "binomial_coefficient_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include "grid_layout.h" #include "horizontal_layout.h" #include "parenthesis_left_layout.h" diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index e9c3fda59..68783c34e 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -1,5 +1,5 @@ #include "conjugate_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include #include extern "C" { @@ -96,7 +96,7 @@ void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChil void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); - replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); + replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); } void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 3ed6dd802..15cf10b5b 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -1,5 +1,5 @@ #include -#include "empty_visible_layout.h" +#include "empty_layout.h" #include extern "C" { #include diff --git a/poincare/src/layout/empty_visible_layout.cpp b/poincare/src/layout/empty_layout.cpp similarity index 70% rename from poincare/src/layout/empty_visible_layout.cpp rename to poincare/src/layout/empty_layout.cpp index 6317e0f0b..8c759d011 100644 --- a/poincare/src/layout/empty_visible_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -1,4 +1,4 @@ -#include "empty_visible_layout.h" +#include "empty_layout.h" #include "matrix_layout.h" #include #include @@ -6,19 +6,19 @@ namespace Poincare { -EmptyVisibleLayout::EmptyVisibleLayout(Color color, bool visible) : +EmptyLayout::EmptyLayout(Color color, bool visible) : StaticLayoutHierarchy(), m_isVisible(visible), m_color(color) { } -ExpressionLayout * EmptyVisibleLayout::clone() const { - EmptyVisibleLayout * layout = new EmptyVisibleLayout(m_color, m_isVisible); +ExpressionLayout * EmptyLayout::clone() const { + EmptyLayout * layout = new EmptyLayout(m_color, m_isVisible); return layout; } -void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void EmptyLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); @@ -30,7 +30,7 @@ void EmptyVisibleLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } } -bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool EmptyLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { @@ -40,7 +40,7 @@ bool EmptyVisibleLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * should return false; } -bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool EmptyLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { @@ -50,7 +50,7 @@ bool EmptyVisibleLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul return false; } -int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { +int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } @@ -58,7 +58,7 @@ int EmptyVisibleLayout::writeTextInBuffer(char * buffer, int bufferSize, int num return 0; } -void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void EmptyLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { if (m_isVisible) { KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); @@ -66,17 +66,17 @@ void EmptyVisibleLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCo } } -KDSize EmptyVisibleLayout::computeSize() { +KDSize EmptyLayout::computeSize() { KDCoordinate width = m_isVisible ? k_width + 2*k_marginWidth : 0; return KDSize(width, k_height + 2*k_marginHeight); } -void EmptyVisibleLayout::computeBaseline() { +void EmptyLayout::computeBaseline() { m_baseline = k_marginHeight + k_height/2; m_baselined = true; } -void EmptyVisibleLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { +void EmptyLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { Color currentColor = m_color; int indexInParent = m_parent->indexOfChild(this); ExpressionLayout * parent = m_parent; diff --git a/poincare/src/layout/empty_visible_layout.h b/poincare/src/layout/empty_layout.h similarity index 88% rename from poincare/src/layout/empty_visible_layout.h rename to poincare/src/layout/empty_layout.h index d96735c44..4003da2c1 100644 --- a/poincare/src/layout/empty_visible_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -1,18 +1,18 @@ -#ifndef POINCARE_EMPTY_VISIBLE_LAYOUT_H -#define POINCARE_EMPTY_VISIBLE_LAYOUT_H +#ifndef POINCARE_empty_layout_H +#define POINCARE_empty_layout_H #include #include namespace Poincare { -class EmptyVisibleLayout : public StaticLayoutHierarchy<0> { +class EmptyLayout : public StaticLayoutHierarchy<0> { public: enum class Color { Yellow, Grey }; - EmptyVisibleLayout(Color color = Color::Yellow, bool visible = true); + EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index c0ac161bc..646a07f10 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -1,5 +1,5 @@ #include -#include "empty_visible_layout.h" +#include "empty_layout.h" #include "horizontal_layout.h" #include "matrix_layout.h" #include @@ -174,7 +174,7 @@ void ExpressionLayout::detachChildren() { void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { assert(index >= 0 && index < numberOfChildren()); - replaceChild(editableChild(index), new EmptyVisibleLayout(), deleteAfterRemoval); + replaceChild(editableChild(index), new EmptyLayout(), deleteAfterRemoval); } void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index f71761b68..151f70481 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -1,5 +1,5 @@ #include "fraction_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include "horizontal_layout.h" #include #include @@ -23,7 +23,7 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { // Case: Numerator and denominator are empty. // Move the cursor then replace the fraction with an empty layout. - replaceWithAndMoveCursor(new EmptyVisibleLayout(), true, cursor); + replaceWithAndMoveCursor(new EmptyLayout(), true, cursor); return; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index b5d9f9934..2ac10b22c 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -1,5 +1,5 @@ #include "grid_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include #include extern "C" { @@ -199,20 +199,20 @@ KDPoint GridLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -void GridLayout::addEmptyRow(EmptyVisibleLayout::Color color) { +void GridLayout::addEmptyRow(EmptyLayout::Color color) { ExpressionLayout * newChildren[m_numberOfColumns]; for (int i = 0; i < m_numberOfColumns; i++) { - newChildren[i] = new EmptyVisibleLayout(color); + newChildren[i] = new EmptyLayout(color); } addChildrenAtIndex(const_cast(const_cast(newChildren)), m_numberOfColumns, numberOfChildren(), false); m_numberOfRows++; invalidAllSizesPositionsAndBaselines(); } -void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) { +void GridLayout::addEmptyColumn(EmptyLayout::Color color) { m_numberOfColumns++; for (int i = 0; i < m_numberOfRows; i++) { - addChildAtIndex(new EmptyVisibleLayout(color), i*m_numberOfColumns + m_numberOfColumns-1); + addChildAtIndex(new EmptyLayout(color), i*m_numberOfColumns + m_numberOfColumns-1); } invalidAllSizesPositionsAndBaselines(); } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index b0e981ae4..15cf34725 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -2,7 +2,7 @@ #define POINCARE_GRID_LAYOUT_H #include -#include "empty_visible_layout.h" +#include "empty_layout.h" namespace Poincare { @@ -20,7 +20,7 @@ public: /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; - // This function replaces the child with an EmptyVisibleLayout. To delete the + // This function replaces the child with an EmptyLayout. To delete the // grid's children, do not call this function. /* Expression engine */ @@ -31,8 +31,8 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - void addEmptyRow(EmptyVisibleLayout::Color color); - void addEmptyColumn(EmptyVisibleLayout::Color color); + void addEmptyRow(EmptyLayout::Color color); + void addEmptyColumn(EmptyLayout::Color color); void deleteRowAtIndex(int index); void deleteColumnAtIndex(int index); bool childIsRightOfGrid(int index) const; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 43a7fae89..29be089e5 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,5 +1,5 @@ #include "horizontal_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include extern "C" { #include @@ -448,9 +448,9 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { // If the child to remove is at index 0 and its right brother must have a left // brother (e.g. it is a VerticalOffsetLayout), replace the child with an - // EmptyVisibleLayout instead of removing it. + // EmptyLayout instead of removing it. if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { - addChildAtIndex(new EmptyVisibleLayout(), index + 1); + addChildAtIndex(new EmptyLayout(), index + 1); } DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); } diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 209d3455f..35be32544 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -1,5 +1,5 @@ #include "matrix_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include "horizontal_layout.h" #include "bracket_left_layout.h" #include "bracket_right_layout.h" @@ -162,7 +162,7 @@ void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); - replaceChildAndMoveCursor(child(index), new EmptyVisibleLayout(), deleteAfterRemoval, cursor); + replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); } int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { @@ -200,27 +200,27 @@ void MatrixLayout::newRowOrColumnAtIndex(int index) { // We need to compute this bool before modifying the layout.:w // if (GridLayout::childIsRightOfGrid(index)) { - // Color the grey EmptyVisibleLayouts of the column in yellow. + // Color the grey EmptyLayouts of the column in yellow. int correspondingColumn = m_numberOfColumns - 1; for (int i = 0; i < m_numberOfRows - 1; i++) { ExpressionLayout * lastLayoutOfRow = editableChild(i*m_numberOfColumns+correspondingColumn); if (lastLayoutOfRow->isEmpty()) { - static_cast(lastLayoutOfRow)->setColor(EmptyVisibleLayout::Color::Yellow); + static_cast(lastLayoutOfRow)->setColor(EmptyLayout::Color::Yellow); } } - // Add a column of grey EmptyVisibleLayouts on the right. - addEmptyColumn(EmptyVisibleLayout::Color::Grey); + // Add a column of grey EmptyLayouts on the right. + addEmptyColumn(EmptyLayout::Color::Grey); } if (shouldAddNewRow) { - // Color the grey EmptyVisibleLayouts of the row in yellow. + // Color the grey EmptyLayouts of the row in yellow. for (int i = 0; i < m_numberOfColumns - 1; i++) { ExpressionLayout * lastLayoutOfColumn = editableChild(correspondingRow*m_numberOfColumns+i); if (lastLayoutOfColumn->isEmpty()) { - static_cast(lastLayoutOfColumn)->setColor(EmptyVisibleLayout::Color::Yellow); + static_cast(lastLayoutOfColumn)->setColor(EmptyLayout::Color::Yellow); } } - // Add a row of grey EmptyVisibleLayouts at the bottom. - addEmptyRow(EmptyVisibleLayout::Color::Grey); + // Add a row of grey EmptyLayouts at the bottom. + addEmptyRow(EmptyLayout::Color::Grey); } } @@ -242,7 +242,7 @@ void MatrixLayout::childWasReplacedAtIndex(int index) { && (childIsRightOfGrid(index) || childIsBottomOfGrid(index))) { - static_cast(newChild)->setColor(EmptyVisibleLayout::Color::Grey); + static_cast(newChild)->setColor(EmptyLayout::Color::Grey); } } } @@ -297,8 +297,8 @@ bool MatrixLayout::isColumnEmpty(int index) const { void MatrixLayout::addGreySquares() { if (!hasGreySquares()) { - addEmptyRow(EmptyVisibleLayout::Color::Grey); - addEmptyColumn(EmptyVisibleLayout::Color::Grey); + addEmptyRow(EmptyLayout::Color::Grey); + addEmptyColumn(EmptyLayout::Color::Grey); } } @@ -314,7 +314,7 @@ bool MatrixLayout::hasGreySquares() const { const ExpressionLayout * lastChild = child(m_numberOfRows * m_numberOfColumns - 1); if (lastChild->isEmpty() && !lastChild->isHorizontal() - && (static_cast(lastChild))->color() == EmptyVisibleLayout::Color::Grey) + && (static_cast(lastChild))->color() == EmptyLayout::Color::Grey) { assert(isRowEmpty(m_numberOfRows - 1)); assert(isColumnEmpty(m_numberOfColumns - 1)); diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 640be9a01..16d1bd1ae 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -1,5 +1,5 @@ #include "vertical_offset_layout.h" -#include "empty_visible_layout.h" +#include "empty_layout.h" #include #include #include From 3abb619283cfa58cd41e66d682b88ccbd3e9f9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 10:06:14 +0200 Subject: [PATCH 272/459] [poincare] Hiding/Show EmptyLayouts: check pointed layout's neighbour Change-Id: I5f6977de5c14e409b40f7f371d5dfa390f2dca37 --- poincare/src/expression_layout_cursor.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 418fc85f3..a1763ed02 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -221,13 +221,36 @@ bool ExpressionLayoutCursor::hideEmptyLayoutIfNeeded() { } bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { + /* Find Empty layouts adjacent to the cursor: Check the pointed layout and its + * neighbour in an Horizontal layout */ + + // Check the pointed layout if (m_pointedExpressionLayout->isEmpty()) { + /* An empty layout is either an EmptyLayout or an HorizontalLayout with one + * child only, and this child is an EmptyLayout. */ if (m_pointedExpressionLayout->isHorizontal()) { static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); } else { static_cast(m_pointedExpressionLayout)->setVisible(show); } return true; + } else if (m_pointedExpressionLayout->parent() != nullptr + && m_pointedExpressionLayout->parent()->isHorizontal()) + { + // Check the neighbour of the pointed layout in an HorizontalLayout + int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); + int indexToCheck = m_position == Position::Right ? indexInParent + 1 : indexInParent - 1; + if (indexToCheck >=0 + && indexToCheck < m_pointedExpressionLayout->parent()->numberOfChildren() + && m_pointedExpressionLayout->parent()->child(indexToCheck)->isEmpty()) + { + if (m_pointedExpressionLayout->isHorizontal()) { + static_cast(m_pointedExpressionLayout->editableParent()->editableChild(indexToCheck)->editableChild(0))->setVisible(show); + } else { + static_cast(m_pointedExpressionLayout->editableParent()->editableChild(indexToCheck))->setVisible(show); + } + return true; + } } return false; } From b4be993d2f3ebe6b11bba1283db5933e18a89fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 10:59:06 +0200 Subject: [PATCH 273/459] [poincare] Check children when moving vertically in HorizontalLayout Change-Id: Ib0fa5ef58b605c16079e46040a28c96695dcf3d5 --- poincare/src/layout/horizontal_layout.cpp | 36 ++++++++++++++++------- poincare/src/layout/horizontal_layout.h | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 29be089e5..aa0a30053 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,6 +1,5 @@ #include "horizontal_layout.h" #include "empty_layout.h" -#include extern "C" { #include #include @@ -424,18 +423,17 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct newPosition = ExpressionLayoutCursor::Position::Left; } if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { - ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); - ExpressionLayoutCursor::Position previousPosition = cursor->position(); - cursor->setPointedExpressionLayout(brother); - cursor->setPosition(newPosition); - if (direction == ExpressionLayout::VerticalDirection::Up && brother->moveUp(cursor, shouldRecomputeLayout, this, previousLayout)) { + if (tryMoveVerticallyFromAnotherLayout(brother, newPosition, direction, cursor, shouldRecomputeLayout, previousLayout)) { return true; } - if (direction == ExpressionLayout::VerticalDirection::Down && brother->moveDown(cursor, shouldRecomputeLayout, this, previousLayout)) { - return true; - } - cursor->setPointedExpressionLayout(previousPointedLayout); - cursor->setPosition(previousPosition); + } + } + /* If the cursor is Lefit or Right of the HorizontalLayout, try moving it up + * from its extremal child. */ + if (cursor->pointedExpressionLayout() == this && previousLayout == nullptr) { + int indexOfChildToCheck = cursor->position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1; + if (tryMoveVerticallyFromAnotherLayout(editableChild(indexOfChildToCheck), cursor->position(), direction, cursor, shouldRecomputeLayout, previousLayout)) { + return true; } } if (direction == ExpressionLayout::VerticalDirection::Up) { @@ -445,6 +443,22 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } +bool HorizontalLayout::tryMoveVerticallyFromAnotherLayout(ExpressionLayout * otherLayout, ExpressionLayoutCursor::Position otherPosition, ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout) { + ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); + ExpressionLayoutCursor::Position previousPosition = cursor->position(); + cursor->setPointedExpressionLayout(otherLayout); + cursor->setPosition(otherPosition); + if (direction == ExpressionLayout::VerticalDirection::Up && otherLayout->moveUp(cursor, shouldRecomputeLayout, this, previousLayout)) { + return true; + } + if (direction == ExpressionLayout::VerticalDirection::Down && otherLayout->moveDown(cursor, shouldRecomputeLayout, this, previousLayout)) { + return true; + } + cursor->setPointedExpressionLayout(previousPointedLayout); + cursor->setPosition(previousPosition); + return false; +} + void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { // If the child to remove is at index 0 and its right brother must have a left // brother (e.g. it is a VerticalOffsetLayout), replace the child with an diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index f194d5376..d69cd0daf 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -48,6 +49,7 @@ protected: void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); + bool tryMoveVerticallyFromAnotherLayout(ExpressionLayout * otherLayout, ExpressionLayoutCursor::Position otherPosition, ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout); void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); void privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove); int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); From 8d5b40c351b92c4abab797db6af6d3d3e8b7b492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 11:50:01 +0200 Subject: [PATCH 274/459] [poincare] Add collapseBrothers method on ExpressionLayout. Change-Id: Ia4be10b42ae8db300ce1ce7029175a92a667c808 --- poincare/include/poincare/expression_layout.h | 4 ++ poincare/src/expression_layout_cursor.cpp | 40 +------------------ poincare/src/layout/expression_layout.cpp | 40 +++++++++++++++++++ poincare/src/layout/fraction_layout.cpp | 5 +++ poincare/src/layout/fraction_layout.h | 1 + 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index ec5bc978c..5ed835743 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -49,6 +49,9 @@ public: /* Dynamic Layout */ + // Collapse + virtual void collapseBrothers() {} + // Add virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); @@ -133,6 +136,7 @@ protected: void * resultPosition, int * resultScore); virtual void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor); + void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); ExpressionLayout * m_parent; KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index a1763ed02..90a566bae 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -64,45 +64,7 @@ void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { HorizontalLayout * child2 = new HorizontalLayout(new EmptyLayout(), false); FractionLayout * newChild = new FractionLayout(child1, child2, false); pointedExpressionLayout()->addBrother(this, newChild); - - if (!newChild->parent()->isHorizontal()) { - setPointedExpressionLayout(child2->editableChild(0)); - setPosition(Position::Left); - return; - } - - int fractionIndexInParent = newChild->parent()->indexOfChild(newChild); - int numberOfBrothers = newChild->parent()->numberOfChildren(); - - // Collapse the brothers on the right - int numberOfOpenParenthesis = 0; - bool canCollapseOnRight = true; - if (fractionIndexInParent < numberOfBrothers - 1) { - canCollapseOnRight = !(newChild->editableParent()->editableChild(fractionIndexInParent+1)->mustHaveLeftBrother()); - } - ExpressionLayout * rightBrother = nullptr; - while (canCollapseOnRight && fractionIndexInParent < numberOfBrothers - 1) { - rightBrother = newChild->editableParent()->editableChild(fractionIndexInParent+1); - if (rightBrother->isCollapsable(&numberOfOpenParenthesis, false)) { - newChild->editableParent()->removeChildAtIndex(fractionIndexInParent+1, false); - child2->addOrMergeChildAtIndex(rightBrother, child2->numberOfChildren(), true); - numberOfBrothers--; - } else { - break; - } - } - // Collapse the brothers on the left - numberOfOpenParenthesis = 0; - while (fractionIndexInParent > 0) { - ExpressionLayout * leftBrother = newChild->editableParent()->editableChild(fractionIndexInParent-1); - if (leftBrother->isCollapsable(&numberOfOpenParenthesis, true)) { - newChild->editableParent()->removeChildAtIndex(fractionIndexInParent-1, false); - child1->addOrMergeChildAtIndex(leftBrother, 0, true); - fractionIndexInParent--; - } else { - break; - } - } + newChild->collapseBrothers(); // Set the cursor position setPointedExpressionLayout(child2->editableChild(0)); setPosition(Position::Left); diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 646a07f10..8ab2ae2b3 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -394,6 +394,46 @@ void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres } } +void ExpressionLayout::collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex) { + if (!parent() || !parent()->isHorizontal()) { + return; + } + int indexInParent = parent()->indexOfChild(this); + int numberOfBrothers = parent()->numberOfChildren(); + int numberOfOpenParenthesis = 0; + bool canCollapse = true; + ExpressionLayout * absorbingChild = editableChild(absorbingChildIndex); + if (!absorbingChild || !absorbingChild->isHorizontal()) { + return; + } + HorizontalLayout * horizontalAbsorbingChild = static_cast(absorbingChild); + if (direction == HorizontalDirection::Right && indexInParent < numberOfBrothers - 1) { + canCollapse = !(editableParent()->editableChild(indexInParent+1)->mustHaveLeftBrother()); + } + ExpressionLayout * brother = nullptr; + while (canCollapse) { + if (direction == HorizontalDirection::Right && indexInParent == numberOfBrothers - 1) { + break; + } + if (direction == HorizontalDirection::Left && indexInParent == 0) { + break; + } + int brotherIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; + brother = editableParent()->editableChild(brotherIndex); + if (brother->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left)) { + editableParent()->removeChildAtIndex(brotherIndex, false); + int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; + horizontalAbsorbingChild->addOrMergeChildAtIndex(brother, newIndex, true); + numberOfBrothers--; + if (direction == HorizontalDirection::Left) { + indexInParent--; + } + } else { + break; + } + } +} + ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace) { assert(m_parent != nullptr); assert(!m_parent->isHorizontal()); diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 151f70481..3324f7ecd 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -14,6 +14,11 @@ ExpressionLayout * FractionLayout::clone() const { return layout; } +void FractionLayout::collapseBrothers() { + ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 1); + ExpressionLayout::collapseOnDirection(HorizontalDirection::Left, 0); +} + void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { // Case: Left of the denominator. // Replace the fraction with a horizontal juxtaposition of the numerator and diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index c71dd5ef9..9491fb81a 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -10,6 +10,7 @@ class FractionLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void collapseBrothers() override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; From 9f0755a330277ab1b96a53d4522b84d3e281361f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 11:50:33 +0200 Subject: [PATCH 275/459] [poincare] NthRootLayoutcan collapse its brothers on the right. Change-Id: Iba3c6c197029036adf3dce20b6c6bd5173e448ce --- poincare/src/expression_layout_cursor.cpp | 5 +++-- poincare/src/layout/nth_root_layout.cpp | 4 ++++ poincare/src/layout/nth_root_layout.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 90a566bae..45e71ca10 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -107,11 +107,12 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { } void ExpressionLayoutCursor::addEmptySquareRootLayout() { - EmptyLayout * child1 = new EmptyLayout(); + HorizontalLayout * child1 = new HorizontalLayout(new EmptyLayout(), false); NthRootLayout * newChild = new NthRootLayout(child1, false); m_pointedExpressionLayout->addBrother(this, newChild); + newChild->collapseBrothers(); setPointedExpressionLayout(child1); - setPosition(ExpressionLayoutCursor::Position::Right); + setPosition(ExpressionLayoutCursor::Position::Left); } void ExpressionLayoutCursor::addEmptySquarePowerLayout() { diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 80ce7f0cc..8b270cb1b 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -25,6 +25,10 @@ ExpressionLayout * NthRootLayout::clone() const { return new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); } +void NthRootLayout::collapseBrothers() { + ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); +} + void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 67935c06d..c8a15dc9e 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -14,6 +14,7 @@ public: ExpressionLayout * clone() const override; /* Dynamic Layout*/ + void collapseBrothers() override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ From 42e15d6a15b9bb5f5cd20a2928213bbf11ef3eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 12:26:19 +0200 Subject: [PATCH 276/459] [poincare] Move the cursor when collapsing a layout Change-Id: I28a80ac19310214044bad653a6f887956d1fdacc --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/expression_layout_cursor.cpp | 9 ++------- poincare/src/layout/expression_layout.cpp | 5 +++++ poincare/src/layout/fraction_layout.cpp | 4 +++- poincare/src/layout/fraction_layout.h | 2 +- poincare/src/layout/nth_root_layout.cpp | 4 +++- poincare/src/layout/nth_root_layout.h | 2 +- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 5ed835743..1064f7488 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -50,7 +50,7 @@ public: /* Dynamic Layout */ // Collapse - virtual void collapseBrothers() {} + virtual void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor); // Add virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 45e71ca10..a5e33e4e1 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -64,10 +64,7 @@ void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { HorizontalLayout * child2 = new HorizontalLayout(new EmptyLayout(), false); FractionLayout * newChild = new FractionLayout(child1, child2, false); pointedExpressionLayout()->addBrother(this, newChild); - newChild->collapseBrothers(); - // Set the cursor position - setPointedExpressionLayout(child2->editableChild(0)); - setPosition(Position::Left); + newChild->collapseBrothersAndMoveCursor(this); } void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { @@ -110,9 +107,7 @@ void ExpressionLayoutCursor::addEmptySquareRootLayout() { HorizontalLayout * child1 = new HorizontalLayout(new EmptyLayout(), false); NthRootLayout * newChild = new NthRootLayout(child1, false); m_pointedExpressionLayout->addBrother(this, newChild); - newChild->collapseBrothers(); - setPointedExpressionLayout(child1); - setPosition(ExpressionLayoutCursor::Position::Left); + newChild->collapseBrothersAndMoveCursor(this); } void ExpressionLayoutCursor::addEmptySquarePowerLayout() { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 8ab2ae2b3..119631668 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -105,6 +105,11 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { return m_parent->hasAncestor(e); } +void ExpressionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { + cursor->setPointedExpressionLayout(this); + cursor->setPosition(ExpressionLayoutCursor::Position::Right); +} + void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { privateAddBrother(cursor, brother, false); } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 3324f7ecd..659da4265 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -14,9 +14,11 @@ ExpressionLayout * FractionLayout::clone() const { return layout; } -void FractionLayout::collapseBrothers() { +void FractionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 1); ExpressionLayout::collapseOnDirection(HorizontalDirection::Left, 0); + cursor->setPointedExpressionLayout(denominatorLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); } void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 9491fb81a..65ab4251f 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -10,7 +10,7 @@ class FractionLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - void collapseBrothers() override; + void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 8b270cb1b..2eddf12d6 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -25,8 +25,10 @@ ExpressionLayout * NthRootLayout::clone() const { return new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); } -void NthRootLayout::collapseBrothers() { +void NthRootLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); + cursor->setPointedExpressionLayout(radicandLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); } void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index c8a15dc9e..f5d31c723 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -14,7 +14,7 @@ public: ExpressionLayout * clone() const override; /* Dynamic Layout*/ - void collapseBrothers() override; + void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ From e327c0bbf19332a81b72422d0d4bd9e25dd56e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 12:27:07 +0200 Subject: [PATCH 277/459] [poincare] Create Horizontal child layouts when collapsing. Change-Id: I174aee72997c6ba895e7a17906802f6bd5e939d2 --- poincare/src/layout/fraction_layout.cpp | 10 ++++++++++ poincare/src/layout/nth_root_layout.cpp | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 659da4265..cb680d6d0 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -15,6 +15,16 @@ ExpressionLayout * FractionLayout::clone() const { } void FractionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { + /* If the numerator or denominator layouts are not HorizontalLayouts, replace + * them with one. */ + if (!numeratorLayout()->isHorizontal()) { + HorizontalLayout * horizontalNumeratorLayout = new HorizontalLayout(numeratorLayout(), false); + replaceChild(numeratorLayout(), horizontalNumeratorLayout, false); + } + if (!denominatorLayout()->isHorizontal()) { + HorizontalLayout * horizontalDenominatorLayout = new HorizontalLayout(denominatorLayout(), false); + replaceChild(denominatorLayout(), horizontalDenominatorLayout, false); + } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 1); ExpressionLayout::collapseOnDirection(HorizontalDirection::Left, 0); cursor->setPointedExpressionLayout(denominatorLayout()); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 2eddf12d6..e365e68d7 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -1,4 +1,5 @@ #include "nth_root_layout.h" +#include "horizontal_layout.h" #include #include #include @@ -26,6 +27,11 @@ ExpressionLayout * NthRootLayout::clone() const { } void NthRootLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { + // If the radicand layout is not an HorizontalLayout, replace it with one. + if (!radicandLayout()->isHorizontal()) { + HorizontalLayout * horizontalRadicandLayout = new HorizontalLayout(radicandLayout(), false); + replaceChild(radicandLayout(), horizontalRadicandLayout, false); + } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); cursor->setPointedExpressionLayout(radicandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); From 1fd6705f9d4e239f9501f773b57beee5f8506df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 13:29:01 +0200 Subject: [PATCH 278/459] [poincare] Fix HorizontalLayout vertical navigation. Change-Id: Ia8fd862f24a99bcd6d0f5085b008f572ba859f69 --- poincare/src/layout/horizontal_layout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index aa0a30053..e7597ed68 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -428,9 +428,9 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct } } } - /* If the cursor is Lefit or Right of the HorizontalLayout, try moving it up + /* If the cursor is Left or Right of the HorizontalLayout, try moving it up * from its extremal child. */ - if (cursor->pointedExpressionLayout() == this && previousLayout == nullptr) { + if (cursor->pointedExpressionLayout() == this && previousLayout == nullptr && numberOfChildren() > 0) { int indexOfChildToCheck = cursor->position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1; if (tryMoveVerticallyFromAnotherLayout(editableChild(indexOfChildToCheck), cursor->position(), direction, cursor, shouldRecomputeLayout, previousLayout)) { return true; From 3c010b3269cbc60c9e25a6e9d4aea32925dda870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 13:49:19 +0200 Subject: [PATCH 279/459] [poincare] Collapse BracketLayouts. Change-Id: I9ea87155228483cfd5aec6189e39543ad0ccfbbb --- poincare/src/layout/bracket_layout.cpp | 12 ++++++++++++ poincare/src/layout/bracket_layout.h | 1 + 2 files changed, 13 insertions(+) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 5544e628c..d6cf73c42 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -1,4 +1,5 @@ #include "bracket_layout.h" +#include "horizontal_layout.h" #include #include extern "C" { @@ -13,6 +14,17 @@ ExpressionLayout * BracketLayout::clone() const { return layout; } +void BracketLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { + // If the operand layouts is not HorizontalLayouts, replace it with one. + if (!operandLayout()->isHorizontal()) { + HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); + replaceChild(operandLayout(), horizontalOperandLayout, false); + } + ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); + cursor->setPointedExpressionLayout(operandLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); +} + void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 6ddb363b7..a55f6f8fe 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -10,6 +10,7 @@ class BracketLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; From 65876c012338a166fd8963cdd9da073a4bbdd610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 13:49:43 +0200 Subject: [PATCH 280/459] [poincare] Collapse ConjugateLayouts. Change-Id: Icdf875b6e55e942858324a055890d974c23bba33 --- poincare/src/layout/conjugate_layout.cpp | 12 ++++++++++++ poincare/src/layout/conjugate_layout.h | 1 + 2 files changed, 13 insertions(+) diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 68783c34e..e6d2038ba 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -1,5 +1,6 @@ #include "conjugate_layout.h" #include "empty_layout.h" +#include "horizontal_layout.h" #include #include extern "C" { @@ -14,6 +15,17 @@ ExpressionLayout * ConjugateLayout::clone() const { return layout; } +void ConjugateLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { + // If the operand layouts is not HorizontalLayouts, replace it with one. + if (!operandLayout()->isHorizontal()) { + HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); + replaceChild(operandLayout(), horizontalOperandLayout, false); + } + ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); + cursor->setPointedExpressionLayout(operandLayout()); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); +} + void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 52b7f321e..265c911bd 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -10,6 +10,7 @@ class ConjugateLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; From 20935db3d52c0cde714d82d20ac212f5b9af7829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 13:50:57 +0200 Subject: [PATCH 281/459] [poincare] Collapse after inserting layout. Change-Id: I6251d4603e3adb883ffc64b1659cae889c349227 --- poincare/src/expression_layout_cursor.cpp | 4 ++++ poincare/src/layout/expression_layout.cpp | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index a5e33e4e1..12d8fc056 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -46,7 +46,11 @@ void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { } void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { + bool layoutWillBeMerged = layout->isHorizontal(); pointedExpressionLayout()->addBrotherAndMoveCursor(this, layout); + if (!layoutWillBeMerged) { + layout->collapseBrothersAndMoveCursor(this); + } } void ExpressionLayoutCursor::addEmptyExponentialLayout() { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 119631668..280d30eb2 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -106,8 +106,6 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { } void ExpressionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); } void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { From bf43ad4d22826fea9ccfac4c7026a922fa3b763d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 14:17:49 +0200 Subject: [PATCH 282/459] [apps/settings] Change "Edition mode" labels. Change-Id: I5475749c05c2103000e3a0da914936c5a28c2aa3 --- apps/settings/base.de.i18n | 6 +++--- apps/settings/base.en.i18n | 6 +++--- apps/settings/base.es.i18n | 6 +++--- apps/settings/base.fr.i18n | 6 +++--- apps/settings/base.pt.i18n | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index c7a9992ab..8a166a47d 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -2,9 +2,9 @@ SettingsApp = "Einstellungen" SettingsAppCapital = "EINSTELLUNGEN" AngleUnit = "Winkeleinheit" DisplayMode = "Zahlenformat" -EditionMode = "Editiermodus" -EditionLinear = "1D " -Edition2D = "2D " +EditionMode = "Eintrag" +EditionLinear = "In Zeilen " +Edition2D = "Natürliche " ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Start Testmodus" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index c2188e480..ee51a6f23 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -2,9 +2,9 @@ SettingsApp = "Settings" SettingsAppCapital = "SETTINGS" AngleUnit = "Angle measure" DisplayMode = "Result format" -EditionMode = "Edition mode" -EditionLinear = "1D " -Edition2D = "2D " +EditionMode = "Writing format" +EditionLinear = "Linear " +Edition2D = "Natural " ComplexFormat = "Complex format" ExamMode = "Exam mode" ActivateExamMode = "Activate exam mode" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index a7bdaf690..d4b6a3907 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -2,9 +2,9 @@ SettingsApp = "Configuracion" SettingsAppCapital = "CONFIGURACION" AngleUnit = "Medida del angulo" DisplayMode = "Formato resultado" -EditionMode = "Modo edicion" -EditionLinear = "1D " -Edition2D = "2D " +EditionMode = "Formato escritura" +EditionLinear = "En línea " +Edition2D = "Natural " ComplexFormat = "Formato complejo" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 7fffe0d16..fc2922fa3 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -2,9 +2,9 @@ SettingsApp = "Parametres" SettingsAppCapital = "PARAMETRES" AngleUnit = "Unite d'angle" DisplayMode = "Format resultat" -EditionMode = "Mode d'edition" -EditionLinear = "1D " -Edition2D = "2D " +EditionMode = "Format écriture" +EditionLinear = "En ligne " +Edition2D = "Naturelle " ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 788d63e85..a7443e5f6 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -2,9 +2,9 @@ SettingsApp = "Configuracao" SettingsAppCapital = "CONFIGURACAO" AngleUnit = "Valor do angulo" DisplayMode = "Formato numerico" -EditionMode = "Modo de edicao" -EditionLinear = "1D " -Edition2D = "2D " +EditionMode = "Formato escrita " +EditionLinear = "Em linha " +Edition2D = "Natural " ComplexFormat = "Complexos" ExamMode = "Modo de Exame" ActivateExamMode = "Inicio modo de exame" From 193aefd5a66afe316dff740bd1a4eaf723405c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 15:33:40 +0200 Subject: [PATCH 283/459] [poincare] Each leayout gives the layoutToPointWhenInserting Change-Id: I5f054643decd27731e77d0f1cf2e6874cf6ff8d5 --- apps/math_toolbox.cpp | 3 --- escher/src/scrollable_expression_view_with_cursor.cpp | 9 +++++++-- poincare/include/poincare/expression_layout.h | 1 + poincare/src/layout/condensed_sum_layout.cpp | 5 +++++ poincare/src/layout/condensed_sum_layout.h | 1 + poincare/src/layout/expression_layout.cpp | 7 +++++++ poincare/src/layout/fraction_layout.cpp | 10 ++++++++++ poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/integral_layout.cpp | 5 +++++ poincare/src/layout/integral_layout.h | 2 ++ poincare/src/layout/sequence_layout.cpp | 5 +++++ poincare/src/layout/sequence_layout.h | 1 + 12 files changed, 45 insertions(+), 5 deletions(-) diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index e8f126b18..61b5ca479 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -146,9 +146,6 @@ void MathToolbox::actionForScrollableExpressionViewWithCursor(void * sender, con break; } } - } else if (resultLayout->numberOfChildren() > 0) { - // Else, if the layout has children, pick the first one. - pointedLayout = resultLayout->editableChild(0); } // Insert the layout. If pointedLayout is nullptr, the cursor will be on the // right of the inserted layout. diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 57dbb5660..654c7c450 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -207,9 +207,14 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } - if (pointedLayout != nullptr) { + bool layoutWillBeMerged = layout->isHorizontal(); + if (!layoutWillBeMerged) { m_expressionViewWithCursor.cursor()->addLayout(layout); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + if (pointedLayout != nullptr) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + } else { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); + } m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } else { m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 1064f7488..2286410af 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -99,6 +99,7 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; /* Other */ + virtual ExpressionLayout * layoutToPointWhenInserting(); bool addGreySquaresToAllMatrixAncestors(); bool hasText() const; virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 33058438e..32e7dbb30 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -124,6 +124,11 @@ bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * should return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } +ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { + assert(subscriptLayout() != nullptr); + return subscriptLayout(); +} + void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Nothing to draw } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index aa76d39d9..ec506a839 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -17,6 +17,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } + ExpressionLayout * layoutToPointWhenInserting() override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 280d30eb2..c7c4d4bf0 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -261,6 +261,13 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * sh return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); } +ExpressionLayout * ExpressionLayout::layoutToPointWhenInserting() { + if (numberOfChildren() > 0) { + return editableChild(0); + } + return this; +} + bool ExpressionLayout::addGreySquaresToAllMatrixAncestors() { bool addedSquares = false; ExpressionLayout * currentAncestor = m_parent; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index cb680d6d0..4e9dd3a95 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -218,6 +218,16 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO return numberOfChar; } +ExpressionLayout * FractionLayout::layoutToPointWhenInserting() { + if (numeratorLayout()->isEmpty()){ + return numeratorLayout(); + } + if (denominatorLayout()->isEmpty()){ + return denominatorLayout(); + } + return this; +} + void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + numeratorLayout()->size().height() + k_fractionLineMargin; ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, size().width()-2*Metric::FractionAndConjugateHorizontalMargin, 1), expressionColor); diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 65ab4251f..1ed0becba 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -17,6 +17,7 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } /* WARNING: We need to override this function, else 1/2 3/4 would be * serialized as 1/2**3/4, as the two Fraction layouts think their brother is diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 2184a1cd3..e3042631b 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -204,6 +204,11 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO return numberOfChar; } +ExpressionLayout * IntegralLayout::layoutToPointWhenInserting() { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout(); +} + void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = integrandLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index a5866df1b..c165c6395 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -25,6 +25,8 @@ public: /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + /* Other */ + ExpressionLayout * layoutToPointWhenInserting() override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index dd1066051..2194214cb 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -132,6 +132,11 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } +ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout(); +} + char SequenceLayout::XNTChar() const { return 'n'; } diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 164ead79d..37fc29b02 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -15,6 +15,7 @@ public: bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + ExpressionLayout * layoutToPointWhenInserting() override; char XNTChar() const override; protected: constexpr static KDCoordinate k_boundHeightMargin = 2; From 0fee6685fef16baaa20a7f2d8f6c1006e149ec8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 15:36:46 +0200 Subject: [PATCH 284/459] [escher] Hide and show empty layouts Change-Id: I3a54848108e1168dfdecf76a562381c7bd1dd65d --- escher/src/scrollable_expression_view_with_cursor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 654c7c450..81bfc71f3 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -232,7 +232,9 @@ void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char if (expression != nullptr) { Poincare::ExpressionLayout * layout = expression->createLayout(); delete expression; + m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); insertLayoutAtCursor(layout, nullptr); + m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); reload(); return; } From f07127b68bcf249b6dca4c1628aaf84542e83524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 15:42:07 +0200 Subject: [PATCH 285/459] [escher/poincare] Remove duplicate function Change-Id: Ie7ab03d1f2716d751f85a9f9747b064892a9b19e --- .../scrollable_expression_view_with_cursor.cpp | 15 ++++++--------- .../include/poincare/expression_layout_cursor.h | 1 - poincare/src/expression_layout_cursor.cpp | 4 ---- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 81bfc71f3..64cfca73a 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -208,16 +208,13 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi static_cast(layout)->addGreySquares(); } bool layoutWillBeMerged = layout->isHorizontal(); - if (!layoutWillBeMerged) { - m_expressionViewWithCursor.cursor()->addLayout(layout); - if (pointedLayout != nullptr) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); - } else { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); - } + m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); + if (pointedLayout != nullptr) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); + m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + } else if (!layoutWillBeMerged) { + m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - } else { - m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); } m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); reload(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 290368888..ee4ec84c6 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -39,7 +39,6 @@ public: bool moveDown(bool * shouldRecomputeLayout); /* Edition */ - void addLayout(ExpressionLayout * layout); void addLayoutAndMoveCursor(ExpressionLayout * layout); void addEmptyExponentialLayout(); void addFractionLayoutAndCollapseBrothers(); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 12d8fc056..2fefcf2f9 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -41,10 +41,6 @@ bool ExpressionLayoutCursor::moveDown(bool * shouldRecomputeLayout) { return m_pointedExpressionLayout->moveDown(this, shouldRecomputeLayout); } -void ExpressionLayoutCursor::addLayout(ExpressionLayout * layout) { - pointedExpressionLayout()->addBrother(this, layout); -} - void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { bool layoutWillBeMerged = layout->isHorizontal(); pointedExpressionLayout()->addBrotherAndMoveCursor(this, layout); From a9d10cc3c47ad5a5cb20d56a8b96e4edda6c7025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 15:45:13 +0200 Subject: [PATCH 286/459] [poincare] EmptyLayout backspace acts as if the cursor is on the Left Change-Id: I3bae2c830972be74b0eb99fe3f26c755031cb6de --- poincare/src/layout/empty_layout.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 8c759d011..55da8f382 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -19,12 +19,7 @@ ExpressionLayout * EmptyLayout::clone() const { } void EmptyLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - assert(cursor->pointedExpressionLayout() == this); - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return; - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->backspaceAtCursor(cursor); } From ef83756cd4a83df0b265b45d9413584813664d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 16:08:22 +0200 Subject: [PATCH 287/459] [escher] Reload did not work properly when inserting a high layout Change-Id: I17d0be33bed325107e183598374f6399427ae9a1 --- escher/src/scrollable_expression_view_with_cursor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 64cfca73a..b62b69646 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -243,8 +243,9 @@ void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char void ScrollableExpressionViewWithCursor::reload() { m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); - m_expressionViewWithCursor.cursorPositionChanged(); layoutSubviews(); + m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); scrollToCursor(); + m_expressionViewWithCursor.cursorPositionChanged(); markRectAsDirty(bounds()); } From 90ad955fe4beeec708eaf875381e76e7df5f9385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 16:24:22 +0200 Subject: [PATCH 288/459] [poincare] Coding style for comments. Change-Id: Ib1855b34ba79b17a0b839db7cc290e7e9ecd072f --- poincare/src/layout/expression_layout.cpp | 38 +++++----- poincare/src/layout/horizontal_layout.cpp | 87 +++++++++++------------ 2 files changed, 57 insertions(+), 68 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index c7c4d4bf0..e26c85d08 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -204,8 +204,7 @@ bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, Express void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { - // Case: The pointed layout is a child. - // Move Left. + // Case: The pointed layout is a child. Move Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); bool shouldRecomputeLayout = false; cursor->moveLeft(&shouldRecomputeLayout); @@ -214,21 +213,18 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { assert(cursor->pointedExpressionLayout() == this); // Case: this is the pointed layout. if (m_parent == nullptr) { - // Case: No parent. - // Return. + // Case: No parent. Return. return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { m_parent->backspaceAtCursor(cursor); } return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Delete the layout. + // Case: Right. Delete the layout. m_parent->removePointedChildAtIndexAndMoveCursor(m_parent->indexOfChild(this), true, cursor); } @@ -282,24 +278,24 @@ bool ExpressionLayout::addGreySquaresToAllMatrixAncestors() { } bool ExpressionLayout::hasText() const { - // A layout has text if it is not empty and it is not an horizontal layout - // with no child or with one child with no text. + /* A layout has text if it is not empty and it is not an horizontal layout + * with no child or with one child with no text. */ return !isEmpty() && !(isHorizontal() && (numberOfChildren() == 0 || (numberOfChildren() == 1 && !child(0)->hasText()))); } bool ExpressionLayout::canBeOmittedMultiplicationLeftFactor() const { - // WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when - // isCollapsable is true too. If isCollapsable changes, it might not be the - // case anymore so make sure to modify this function if needed. + /* WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + * isCollapsable is true too. If isCollapsable changes, it might not be the + * case anymore so make sure to modify this function if needed. */ int numberOfOpenParentheses = 0; return isCollapsable(&numberOfOpenParentheses, true); } bool ExpressionLayout::canBeOmittedMultiplicationRightFactor() const { - // WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when - // isCollapsable is true and mustHaveLeftBrother is false. If one of these - // functions changes, , it might not be the case anymore so make sure to - // modify canBeOmittedMultiplicationRightFactor if needed. + /* WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + * isCollapsable is true and mustHaveLeftBrother is false. If one of these + * functions changes, it might not be the case anymore so make sure to modify + * canBeOmittedMultiplicationRightFactor if needed. */ int numberOfOpenParentheses = 0; return isCollapsable(&numberOfOpenParentheses, false) && !mustHaveLeftBrother(); } @@ -319,8 +315,8 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; - // The distance between the cursor and its next position cannot be greater - // than this initial value of score. + /* The distance between the cursor and its next position cannot be greater + * than this initial value of score. */ int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResultPtr, &resultPosition, &resultScore); @@ -374,8 +370,8 @@ void ExpressionLayout::moveCursorInsideAtDirection ( } void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { - // The layout must have a parent, because HorizontalLayout overrides - // privateAddBrother and only an HorizontalLayout can be the root layout. + /* The layout must have a parent, because HorizontalLayout overrides + * privateAddBrother and only an HorizontalLayout can be the root layout. */ assert(m_parent); if (m_parent->isHorizontal()) { int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index e7597ed68..e84002647 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -18,8 +18,7 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { && cursor->position() == ExpressionLayoutCursor::Position::Left && m_parent == nullptr) { - // Case: Left and this is the main layout. - // Return. + // Case: Left and this is the main layout. Return. return; } if (cursor->pointedExpressionLayout() == this @@ -27,16 +26,15 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { && m_parent == nullptr && numberOfChildren() == 0) { - // Case: Right and this is the main layout with no children. - // Return. + // Case: Right and this is the main layout with no children. Return. return; } if (cursor->position() == ExpressionLayoutCursor::Position::Left) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { - // Case: Left of a child. - // Point Right of the previous child. If there is no previous child, point - // Left of this. Perform another backspace. + /* Case: Left of a child. + * Point Right of the previous child. If there is no previous child, point + * Left of this. Perform another backspace. */ if (indexOfPointedExpression == 0) { cursor->setPointedExpressionLayout(this); } else if (indexOfPointedExpression > 0) { @@ -49,8 +47,7 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { } assert(cursor->pointedExpressionLayout() == this); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - // Case: Right. - // Point to the last child and perform backspace. + // Case: Right. Point to the last child and perform backspace. cursor->setPointedExpressionLayout(editableChild(numberOfChildren() - 1)); cursor->performBackspace(); return; @@ -75,8 +72,8 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex int oldChildIndex = indexOfChild(oldChild); if (newChild->isEmpty()) { if (numberOfChildren() > 1) { - // If the new layout is empty and the horizontal layout has other - // children, just delete the old child. + /* If the new layout is empty and the horizontal layout has other + * children, just delete the old child. */ if (!newChild->hasAncestor(oldChild)) { delete newChild; } @@ -93,9 +90,9 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex cursor->setPosition(ExpressionLayoutCursor::Position::Right); return; } - // If the new layout is empty and it was the only horizontal layout child, - // replace the horizontal layout with this empty layout (only if this is not - // the main layout, so only if the layout has a parent). + /* If the new layout is empty and it was the only horizontal layout child, + * replace the horizontal layout with this empty layout (only if this is not + * the main layout, so only if the layout has a parent). */ if (m_parent) { if (!deleteOldChild) { removeChildAtIndex(indexOfChild(oldChild), false); @@ -107,8 +104,8 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex replaceWith(newChild, deleteOldChild); return; } - // If this is the main horizontal layout, the old child its only child and - // the new child is Empty, remove the old child and delete the new child. + /* If this is the main horizontal layout, the old child its only child and + * the new child is Empty, remove the old child and delete the new child. */ assert(m_parent == nullptr); removeChildAtIndex(0, deleteOldChild); delete newChild; @@ -119,15 +116,15 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex cursor->setPosition(ExpressionLayoutCursor::Position::Left); return; } - // If the new child is also an horizontal layout, steal the children of the - // new layout then destroy it. + /* If the new child is also an horizontal layout, steal the children of the + * new layout then destroy it. */ if (newChild->isHorizontal()) { int indexForInsertion = indexOfChild(oldChild); if (cursor != nullptr) { - // If the old layout is not an ancestor of the new layout, or if the - // cursor was on the right of the new layout, place the cursor on the - // right of the new layout, which is left of the next brother or right of - // the parent. + /* If the old layout is not an ancestor of the new layout, or if the + * cursor was on the right of the new layout, place the cursor on the + * right of the new layout, which is left of the next brother or right of + * the parent. */ if (!oldWasAncestorOfNewLayout || cursor->position() == ExpressionLayoutCursor::Position::Right) { if (oldChildIndex == numberOfChildren() - 1) { cursor->setPointedExpressionLayout(this); @@ -137,8 +134,8 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex cursor->setPosition(ExpressionLayoutCursor::Position::Left); } } else { - // Else place the cursor on the left of the new layout, which is right - // of the previous brother or left of the parent. + /* Else place the cursor on the left of the new layout, which is right + * of the previous brother or left of the parent. */ if (oldChildIndex == 0) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); @@ -175,8 +172,7 @@ void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, } bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { if (m_parent) { @@ -185,9 +181,9 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRe return false; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Go to the last child if there is one, and move Left. - // Else go Left and ask the parent. + /* Case: Right. + * Go to the last child if there is one, and move Left. + * Else go Left and ask the parent. */ if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { @@ -206,24 +202,21 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRe int childIndex = indexOfChild(cursor->pointedExpressionLayout()); assert(childIndex >= 0); if (childIndex == 0) { - // Case: the child is the leftmost. - // Ask the parent. + // Case: the child is the leftmost. Ask the parent. if (m_parent) { cursor->setPointedExpressionLayout(this); return m_parent->moveLeft(cursor, shouldRecomputeLayout); } return false; } - // Case: the child is not the leftmost. - // Go to its left brother and move Left. + // Case: the child is not the leftmost. Go to its left brother and move Left. cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return editableChild(childIndex-1)->moveLeft(cursor, shouldRecomputeLayout); } bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { if (m_parent) { @@ -232,9 +225,9 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR return false; } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Go to the first child if there is one, and move Right. - // Else go Right and ask the parent. + /* Case: Left. + * Go to the first child if there is one, and move Right. + * Else go Right and ask the parent. */ if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { @@ -261,8 +254,8 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR } return false; } - // Case: the child is not the rightmost. - // Go to its right brother and move Right. + /* Case: the child is not the rightmost. Go to its right brother and move + * Right. */ cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return editableChild(childIndex+1)->moveRight(cursor, shouldRecomputeLayout); @@ -460,9 +453,9 @@ bool HorizontalLayout::tryMoveVerticallyFromAnotherLayout(ExpressionLayout * oth } void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { - // If the child to remove is at index 0 and its right brother must have a left - // brother (e.g. it is a VerticalOffsetLayout), replace the child with an - // EmptyLayout instead of removing it. + /* If the child to remove is at index 0 and its right brother must have a left + * brother (e.g. it is a VerticalOffsetLayout), replace the child with an + * EmptyLayout instead of removing it. */ if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { addChildAtIndex(new EmptyLayout(), index + 1); } @@ -471,15 +464,15 @@ void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemo int HorizontalLayout::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { int newIndex = index; - // If empty, remove the child that would be on the right of the inserted - // layout. + /* If empty, remove the child that would be on the right of the inserted + * layout. */ if (newIndex < numberOfChildren() && child(newIndex)->isEmpty()) { privateRemoveChildAtIndex(newIndex, true, true); } - // If empty, remove the child that would be on the left of the inserted - // layout. + /* If empty, remove the child that would be on the left of the inserted + * layout. */ if (shouldRemoveOnLeft && newIndex - 1 >= 0 && newIndex - 1 <= numberOfChildren() -1 From 8b4cc7146e54a8c63bc6612d491d50017f94fc6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 16:30:42 +0200 Subject: [PATCH 289/459] [poicare] isVerticalOffset method. Change-Id: I8ddbfe2b14a495a691ad6b5cb3f615430dbe4846 --- poincare/include/poincare/expression_layout.h | 3 +++ poincare/src/layout/expression_layout.cpp | 4 ++-- poincare/src/layout/fraction_layout.cpp | 2 +- poincare/src/layout/parenthesis_left_layout.cpp | 4 ++-- poincare/src/layout/vertical_offset_layout.h | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 2286410af..1694204e8 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -115,6 +115,9 @@ public: * returns true, because |3|2 means |3|*2. A '+' CharLayout returns false, * because +'something' nevers means +*'something'. */ virtual bool mustHaveLeftBrother() const { return false; } + virtual bool isVerticalOffset() const { return false; } + /* For now, mustHaveLeftBrother and isVerticalOffset behave the same, but code + * is clearer with different names. */ virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } virtual bool isRightParenthesis() const { return false; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index e26c85d08..897e49688 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -293,11 +293,11 @@ bool ExpressionLayout::canBeOmittedMultiplicationLeftFactor() const { bool ExpressionLayout::canBeOmittedMultiplicationRightFactor() const { /* WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when - * isCollapsable is true and mustHaveLeftBrother is false. If one of these + * isCollapsable is true and isVerticalOffset is false. If one of these * functions changes, it might not be the case anymore so make sure to modify * canBeOmittedMultiplicationRightFactor if needed. */ int numberOfOpenParentheses = 0; - return isCollapsable(&numberOfOpenParentheses, false) && !mustHaveLeftBrother(); + return isCollapsable(&numberOfOpenParentheses, false) && !isVerticalOffset(); } void ExpressionLayout::detachChildAtIndex(int i) { diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 4e9dd3a95..f1c612b9c 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -191,7 +191,7 @@ int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO } bool addParenthesis = false; - if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) { + if (indexInParent >= 0 && indexInParent < (m_parent->numberOfChildren() - 1) && m_parent->isHorizontal() && m_parent->child(indexInParent + 1)->isVerticalOffset()) { addParenthesis = true; // Add parenthesis buffer[numberOfChar++] = '('; diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 2ed96c93a..e1ac24b97 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -71,7 +71,7 @@ void ParenthesisLeftLayout::computeOperandHeight() { int currentNumberOfOpenParentheses = 1; int numberOfBrothers = m_parent->numberOfChildren(); if (indexInParent < numberOfBrothers - 1 - && m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) + && m_parent->child(indexInParent + 1)->isVerticalOffset()) { // If the parenthesis is the base of a superscript layout, it should have a // default height, else it creates an infinite loop because the parenthesis @@ -116,7 +116,7 @@ void ParenthesisLeftLayout::computeBaseline() { m_baselined = true; return; } - if (m_parent->child(indexInParent + 1)->mustHaveLeftBrother()) { + if (m_parent->child(indexInParent + 1)->isVerticalOffset()) { // If the parenthesis is the base of a superscript layout, it should have a // default baseline, else it creates an infinite loop because the // parenthesis needs the superscript height, which needs the parenthesis diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index d63ca2e9c..33699f74a 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -20,6 +20,7 @@ public: bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftBrother() const override { return true; } + bool isVerticalOffset() const { return true; } protected: ExpressionLayout * indiceLayout(); ExpressionLayout * baseLayout(); From 83b243977d60d4a5616cd681c5951d637638bcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 17:13:33 +0200 Subject: [PATCH 290/459] [poincare] Adding multiple empty powers is better maneged Change-Id: I58609d4a13eadf7171d05796dbe743507fa85853 --- poincare/src/expression_layout_cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 2fefcf2f9..38ac60048 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -92,7 +92,7 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { if (baseForNewPowerLayout()) { m_pointedExpressionLayout->addBrother(this, offsetLayout); setPointedExpressionLayout(offsetLayout->editableChild(0)); - setPosition(ExpressionLayoutCursor::Position::Left); + setPosition(ExpressionLayoutCursor::Position::Right); return; } // Else, add an empty base From a1c0dae36984bc627060b0b6a01916755c636b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 17:14:46 +0200 Subject: [PATCH 291/459] [poincare] Add parenthesis to the base when adding an ambiguous power Change-Id: I6ea22a816b884cd7003bd3ab755fa55d3eb69000 --- .../src/layout/vertical_offset_layout.cpp | 32 +++++++++++++++++++ poincare/src/layout/vertical_offset_layout.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 16d1bd1ae..14bb1da9f 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -1,5 +1,7 @@ #include "vertical_offset_layout.h" #include "empty_layout.h" +#include "parenthesis_left_layout.h" +#include "parenthesis_right_layout.h" #include #include #include @@ -274,4 +276,34 @@ KDPoint VerticalOffsetLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(0, base->size().height() - base->baseline() - k_indiceHeight); } +void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { + if (brother->isVerticalOffset()){ + VerticalOffsetLayout * verticalOffsetBrother = static_cast(brother); + if (verticalOffsetBrother->type() == Type::Superscript) { + // Add parenthesis + assert(m_parent->isHorizontal()); + int indexInParent = m_parent->indexOfChild(this); + // Add the right parenthesis + ParenthesisRightLayout * parenthesisRight = new ParenthesisRightLayout(); + m_parent->addChildAtIndex(parenthesisRight, indexInParent + 1); + // Add the left parenthesis + ParenthesisLeftLayout * parenthesisLeft = new ParenthesisLeftLayout(); + int leftParenthesisIndex = indexInParent; + int numberOfOpenParenthesis = 0; + while (leftParenthesisIndex > 0 && editableParent()->editableChild(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis,true)) { + leftParenthesisIndex--; + } + m_parent->addChildAtIndex(parenthesisLeft, leftParenthesisIndex); + if (moveCursor) { + parenthesisRight->addBrotherAndMoveCursor(cursor, brother); + } else { + parenthesisRight->addBrother(cursor, brother); + } + return; + } + } + ExpressionLayout::privateAddBrother(cursor, brother, moveCursor); +} + + } diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 33699f74a..1c797f7c8 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -12,6 +12,7 @@ public: Superscript }; VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); + Type type() const { return m_type; } ExpressionLayout * clone() const override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -28,6 +29,7 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; + void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; Type m_type; private: constexpr static KDCoordinate k_indiceHeight = 5; From 021d98da7c5b461c92ce5ce3fba865c44f2be792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 17:29:56 +0200 Subject: [PATCH 292/459] [poincare] More beautiful separation of exponential and root indexes Exponent Layout (VerticalOffsetLayout of Superscript type) now add a margin to their layout only when they are next to a layout that has an upper left index. Change-Id: I670e8aefc7c6bcace8f61bbe4a4b6cea0936d96c --- poincare/include/poincare/expression_layout.h | 1 + poincare/src/layout/nth_root_layout.h | 1 + poincare/src/layout/vertical_offset_layout.cpp | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 1694204e8..9dff32dfb 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -125,6 +125,7 @@ public: virtual bool isRightBracket() const { return false; } virtual bool isEmpty() const { return false; } virtual bool isMatrix() const { return false; } + virtual bool hasUpperLeftIndex() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index f5d31c723..c62b896e0 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -26,6 +26,7 @@ public: /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool hasUpperLeftIndex() const override { return numberOfChildren() > 1; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 14bb1da9f..f921efa76 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -246,7 +246,12 @@ KDSize VerticalOffsetLayout::computeSize() { KDSize indiceSize = indiceLayout()->size(); KDCoordinate width = indiceSize.width(); if (m_type == Type::Superscript) { - width += 5; + assert(m_parent != nullptr); + assert(m_parent->isHorizontal()); + int indexInParent = m_parent->indexOfChild(this); + if (indexInParent < m_parent-> numberOfChildren() - 1 && m_parent->editableChild(indexInParent + 1)->hasUpperLeftIndex()) { + width += 5; + } } KDCoordinate height = 0; if (m_type == Type::Subscript) { From f8b001d0267441c012971ef86872a054ab15198a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 17 Apr 2018 17:45:14 +0200 Subject: [PATCH 293/459] [poincare] More beautiful Radix sign margins. Change-Id: I8e6eac125767cade2be55aba9b0aba8aa03baf0f --- poincare/src/layout/nth_root_layout.cpp | 12 +++++++++--- poincare/src/layout/nth_root_layout.h | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index e365e68d7..b28bc0de7 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -7,6 +7,8 @@ namespace Poincare { +static inline uint16_t max(uint16_t x, uint16_t y) { return (x>y ? x : y); } + const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_leftRadixWidth] = { {0x00, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0x00, 0xFF, 0xFF, 0xFF}, @@ -224,7 +226,7 @@ int NthRootLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOf void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize radicandSize = radicandLayout()->size(); - KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); + KDSize indexSize = adjustedIndexSize(); KDColor workingBuffer[k_leftRadixWidth*k_leftRadixHeight]; KDRect leftRadixFrame(p.x() + indexSize.width() + k_widthMargin - k_leftRadixWidth, p.y() + baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, @@ -266,7 +268,7 @@ void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDSize NthRootLayout::computeSize() { KDSize radicandSize = radicandLayout()->size(); - KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); + KDSize indexSize = adjustedIndexSize(); return KDSize( indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width() + k_radixHorizontalOverflow, baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin @@ -286,7 +288,7 @@ void NthRootLayout::computeBaseline() { KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { KDCoordinate x = 0; KDCoordinate y = 0; - KDSize indexSize = indexLayout() != nullptr ? indexLayout()->size() : KDSize(k_leftRadixWidth,0); + KDSize indexSize = adjustedIndexSize(); if (child == radicandLayout()) { x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; y = baseline() - radicandLayout()->baseline(); @@ -310,4 +312,8 @@ ExpressionLayout * NthRootLayout::indexLayout() { return nullptr; } +KDSize NthRootLayout::adjustedIndexSize() { + return indexLayout() != nullptr ? KDSize(max(k_leftRadixWidth, indexLayout()->size().width()), indexLayout()->size().height()) : KDSize(k_leftRadixWidth,0); +} + } diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index c62b896e0..fa3463365 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -37,10 +37,11 @@ private: constexpr static KDCoordinate k_radixHorizontalOverflow = 2; constexpr static KDCoordinate k_indexHeight = 4; constexpr static KDCoordinate k_heightMargin = 2; - constexpr static KDCoordinate k_widthMargin = 1; + constexpr static KDCoordinate k_widthMargin = 2; constexpr static KDCoordinate k_radixLineThickness = 1; ExpressionLayout * radicandLayout(); ExpressionLayout * indexLayout(); + KDSize adjustedIndexSize(); }; } From 5a9788521208ce9ab5d1d474b69640fa9304e7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 10:02:35 +0200 Subject: [PATCH 294/459] [poincare] Add parenthesis when inserting a power next to a power Change-Id: I93b228811b11968df434feaee46442447b726fbc --- .../src/layout/vertical_offset_layout.cpp | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index f921efa76..16c11ab53 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -282,23 +282,33 @@ KDPoint VerticalOffsetLayout::positionOfChild(ExpressionLayout * child) { } void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { - if (brother->isVerticalOffset()){ + if (brother->isVerticalOffset()) { VerticalOffsetLayout * verticalOffsetBrother = static_cast(brother); if (verticalOffsetBrother->type() == Type::Superscript) { - // Add parenthesis assert(m_parent->isHorizontal()); + + // Add the Left parenthesis int indexInParent = m_parent->indexOfChild(this); - // Add the right parenthesis - ParenthesisRightLayout * parenthesisRight = new ParenthesisRightLayout(); - m_parent->addChildAtIndex(parenthesisRight, indexInParent + 1); - // Add the left parenthesis - ParenthesisLeftLayout * parenthesisLeft = new ParenthesisLeftLayout(); int leftParenthesisIndex = indexInParent; + ParenthesisLeftLayout * parenthesisLeft = new ParenthesisLeftLayout(); int numberOfOpenParenthesis = 0; - while (leftParenthesisIndex > 0 && editableParent()->editableChild(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis,true)) { + while (leftParenthesisIndex > 0 + && editableParent()->editableChild(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis, true)) + { leftParenthesisIndex--; } m_parent->addChildAtIndex(parenthesisLeft, leftParenthesisIndex); + indexInParent++; + + // Add the Right parenthesis + ParenthesisRightLayout * parenthesisRight = new ParenthesisRightLayout(); + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + m_parent->addChildAtIndex(parenthesisRight, indexInParent + 1); + } else { + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + m_parent->addChildAtIndex(parenthesisRight, indexInParent); + } + cursor->setPointedExpressionLayout(parenthesisRight); if (moveCursor) { parenthesisRight->addBrotherAndMoveCursor(cursor, brother); } else { From 88429ef2e3dd160f77dfed4f215071545ddbdf75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 10:38:07 +0200 Subject: [PATCH 295/459] [poincare] addBrother checks if the neighbour is VerticalOffsetLayout Change-Id: Ie96747a1877a6fd0363551ab89baa954f2f26c5a --- poincare/src/layout/expression_layout.cpp | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 897e49688..753ead5dd 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -374,7 +374,29 @@ void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres * privateAddBrother and only an HorizontalLayout can be the root layout. */ assert(m_parent); if (m_parent->isHorizontal()) { - int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? m_parent->indexOfChild(this) : m_parent->indexOfChild(this) + 1; + int indexInParent = m_parent->indexOfChild(this); + int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? indexInParent : indexInParent + 1; + + /* Special case: If the neighbour brother is a VerticalOffsetLayout, let it + * handle the insertion of the new brother. */ + ExpressionLayout * neighbour = nullptr; + if (cursor->position() == ExpressionLayoutCursor::Position::Left && indexInParent > 0) { + neighbour = m_parent->editableChild(indexInParent - 1); + } else if (cursor->position() == ExpressionLayoutCursor::Position::Right && indexInParent < m_parent->numberOfChildren() - 1) { + neighbour = m_parent->editableChild(indexInParent + 1); + } + if (neighbour != nullptr && neighbour->isVerticalOffset()) { + cursor->setPointedExpressionLayout(neighbour); + cursor->setPosition(cursor->position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left); + if (moveCursor) { + neighbour->addBrotherAndMoveCursor(cursor, brother); + } else { + neighbour->addBrother(cursor, brother); + } + return; + } + + // Else, let the parent add the brother. if (moveCursor) { if (brotherIndex < m_parent->numberOfChildren()) { cursor->setPointedExpressionLayout(m_parent->editableChild(brotherIndex)); From b430cba3358ae169f91aeb8a72b5c3c1e9dc4ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 11:26:21 +0200 Subject: [PATCH 296/459] [apps/poincare] Fix "random()" layout creation. Change-Id: Ic8e12dfba925066fafa172b750162e820eeef82b --- apps/shared/toolbox_helpers.cpp | 28 +++++++++++++--------------- apps/shared/toolbox_helpers.h | 4 ++-- poincare/src/layout_engine.cpp | 10 ++++++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index 33c7b4461..ee39e138d 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -19,15 +19,16 @@ int CursorIndexInCommandText(const char * text) { return strlen(text); } -void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { - TextToInsertForCommandText(I18n::translate(message), buffer, bufferSize); +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar) { + TextToInsertForCommandText(I18n::translate(message), buffer, bufferSize, replaceArgsWithEmptyChar); } -void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize) { +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar) { int currentNewTextIndex = 0; int numberOfOpenParentheses = 0; int numberOfOpenBrackets = 0; bool insideQuote = false; + bool argumentAlreadyReplaced = false; size_t commandLength = strlen(command); for (size_t i = 0; i < commandLength; i++) { if (command[i] == ')') { @@ -41,7 +42,15 @@ void TextToInsertForCommandText(const char * command, char * buffer, int bufferS || (numberOfOpenBrackets > 0 && (command[i] == ',' || command[i] == '[' || command[i] == ']'))) && (!insideQuote || command[i] == '\'')) { assert(currentNewTextIndex < bufferSize); + if (argumentAlreadyReplaced) { + argumentAlreadyReplaced = false; + } buffer[currentNewTextIndex++] = command[i]; + } else { + if (replaceArgsWithEmptyChar && !argumentAlreadyReplaced) { + buffer[currentNewTextIndex++] = Ion::Charset::Empty; + argumentAlreadyReplaced = true; + } } if (command[i] == '(') { numberOfOpenParentheses++; @@ -61,18 +70,7 @@ void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer } void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize) { - TextToInsertForCommandText(command, buffer, bufferSize); - size_t bufferLength = strlen(buffer); - for (size_t i = 0; i < bufferLength; i++) { - if (buffer[i] == '(' || buffer[i] == ',' || (i < bufferLength - 1 && buffer[i] == '[' && buffer[i+1] == ']')) { - // Shift the buffer to make room for the new char. Use memmove to avoid - // overwritting. - memmove(&buffer[i+2], &buffer[i+1], bufferLength - (i+1) + 1); - bufferLength++; - i++; - buffer[i] = Ion::Charset::Empty; - } - } + TextToInsertForCommandText(command, buffer, bufferSize, true); } } diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index 0065993a2..ae8226644 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -13,8 +13,8 @@ int CursorIndexInCommandText(const char * text); * - The end of the text */ -void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize); -void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize); +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar = false); +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar = false); /* Removes the arguments from a command: * - Removes text between parentheses or brackets, except commas */ void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize); diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 9b2e43ddb..48f21fd80 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -37,13 +37,15 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); // Create the layout of arguments separated by commas. - HorizontalLayout * args = new HorizontalLayout(); + ExpressionLayout * args = nullptr; int numberOfOperands = expression->numberOfOperands(); if (numberOfOperands > 0) { - args->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0, true); + args = new HorizontalLayout(); + HorizontalLayout * horizontalArgs = static_cast(args); + horizontalArgs->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0, true); for (int i = 1; i < numberOfOperands; i++) { - args->addChildAtIndex(new CharLayout(','), args->numberOfChildren()); - args->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args->numberOfChildren(), true); + horizontalArgs->addChildAtIndex(new CharLayout(','), args->numberOfChildren()); + horizontalArgs->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), horizontalArgs->numberOfChildren(), true); } } // Add the parenthesed arguments. From afcac95315cb07457946844ca7ce5bad15215678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 15:20:10 +0200 Subject: [PATCH 297/459] [poincare] The cursor changes its size. Change-Id: I3366ff956a9f12b347a8b05066800619e61308c5 --- escher/src/expression_view_with_cursor.cpp | 7 ++- .../poincare/expression_layout_cursor.h | 6 +- poincare/src/expression_layout_cursor.cpp | 57 +++++++++++++++++++ .../src/layout/vertical_offset_layout.cpp | 9 +-- 4 files changed, 68 insertions(+), 11 deletions(-) diff --git a/escher/src/expression_view_with_cursor.cpp b/escher/src/expression_view_with_cursor.cpp index f53fa5aa8..657ca5b32 100644 --- a/escher/src/expression_view_with_cursor.cpp +++ b/escher/src/expression_view_with_cursor.cpp @@ -54,11 +54,12 @@ void ExpressionViewWithCursor::layoutCursorSubview() { return; } KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); - KDPoint cursoredExpressionViewOrigin = m_cursor.pointedExpressionLayout()->absoluteOrigin(); + ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayoutEquivalentChild(); + KDPoint cursoredExpressionViewOrigin = pointedLayout->absoluteOrigin(); KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); if (m_cursor.position() == ExpressionLayoutCursor::Position::Right) { - cursorX += m_cursor.pointedExpressionLayout()->size().width(); + cursorX += pointedLayout->size().width(); } - KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + m_cursor.pointedExpressionLayout()->baseline()-m_cursor.cursorHeight()/2); + KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayout->baseline() - m_cursor.baseline()); m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor.cursorHeight())); } diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index ee4ec84c6..aede79920 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -20,10 +20,13 @@ public: /* Getters and setters */ ExpressionLayout * pointedExpressionLayout() { return m_pointedExpressionLayout; } + ExpressionLayout * pointedExpressionLayoutEquivalentChild(); void setPointedExpressionLayout(ExpressionLayout * expressionLayout) { m_pointedExpressionLayout = expressionLayout; } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } - KDCoordinate cursorHeight() const { return k_cursorHeight; } + KDCoordinate cursorHeight(); + KDCoordinate baseline(); + ExpressionLayout * equivalentPointedBrotherLayout(); /* Comparison */ bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position); @@ -56,6 +59,7 @@ private: constexpr static KDCoordinate k_cursorHeight = 18; bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); + KDCoordinate pointedLayoutHeight(); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 38ac60048..a756257ff 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -6,6 +6,49 @@ namespace Poincare { +static inline KDCoordinate max(KDCoordinate x, KDCoordinate y) { return (x>y ? x : y); } + +ExpressionLayout * ExpressionLayoutCursor::pointedExpressionLayoutEquivalentChild() { + if (m_pointedExpressionLayout->isHorizontal() && m_pointedExpressionLayout->numberOfChildren() > 0) { + return m_position == Position::Left ? m_pointedExpressionLayout->editableChild(0) : m_pointedExpressionLayout->editableChild(m_pointedExpressionLayout->numberOfChildren()-1); + } + return m_pointedExpressionLayout; +} + +KDCoordinate ExpressionLayoutCursor::cursorHeight() { + KDCoordinate height = pointedLayoutHeight(); + return height == 0 ? k_cursorHeight : height; +} + +KDCoordinate ExpressionLayoutCursor::baseline() { + if (pointedLayoutHeight() == 0) { + return k_cursorHeight / 2; + } + KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); + KDCoordinate baseline2 = (KDCoordinate)0; + ExpressionLayout * equivalentBrotherLayout = equivalentPointedBrotherLayout(); + if (equivalentBrotherLayout != nullptr) { + baseline2 = equivalentBrotherLayout->baseline(); + } + return max(baseline1, baseline2); +} + +ExpressionLayout * ExpressionLayoutCursor::equivalentPointedBrotherLayout() { + if (m_pointedExpressionLayout->parent() != nullptr + && m_pointedExpressionLayout->parent()->isHorizontal()) + { + ExpressionLayout * pointedLayoutParent = m_pointedExpressionLayout->editableParent(); + int indexOfPointedLayoutInParent = pointedLayoutParent->indexOfChild(m_pointedExpressionLayout); + if (m_position == Position::Left && indexOfPointedLayoutInParent > 0) { + return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent - 1); + } + if (m_position == Position::Right && indexOfPointedLayoutInParent < pointedLayoutParent->numberOfChildren() - 1) { + return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent + 1); + } + } + return nullptr; +} + bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position) { assert(expressionLayout != nullptr); return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position); @@ -236,5 +279,19 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { return false; } +KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { + KDCoordinate height = pointedExpressionLayoutEquivalentChild()->size().height(); + KDCoordinate height1 = height; + ExpressionLayout * equivalentBrotherLayout = equivalentPointedBrotherLayout(); + if (equivalentBrotherLayout != nullptr) { + KDCoordinate height2 = equivalentBrotherLayout->size().height(); + KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); + KDCoordinate baseline2 = equivalentBrotherLayout->baseline(); + height = max(baseline1, baseline2) + + max(height1 - baseline1, height2 - baseline2); + } + return height; +} + } diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 16c11ab53..a51ae624d 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -253,12 +253,7 @@ KDSize VerticalOffsetLayout::computeSize() { width += 5; } } - KDCoordinate height = 0; - if (m_type == Type::Subscript) { - height = positionOfChild(indiceLayout()).y()+ indiceLayout()->size().height(); - } else { - height = indiceLayout()->size().height() + baseLayout()->baseline() - k_indiceHeight; - } + KDCoordinate height = baseLayout()->size().height() + indiceLayout()->size().height() - k_indiceHeight; return KDSize(width, height); } @@ -266,7 +261,7 @@ void VerticalOffsetLayout::computeBaseline() { if (m_type == Type::Subscript) { m_baseline = 0; } else { - m_baseline = size().height(); + m_baseline = indiceLayout()->size().height() - k_indiceHeight + baseLayout()->baseline(); } m_baselined = true; } From 29cdcd0ef0e0497e4553aafcfbd912359c50e2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 15:24:07 +0200 Subject: [PATCH 298/459] [poincare] Put constant value in header. Change-Id: I67baf95528d530176812c5f378192854968b7fb9 --- poincare/src/layout/vertical_offset_layout.cpp | 2 +- poincare/src/layout/vertical_offset_layout.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index a51ae624d..9a4e9e2a4 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -250,7 +250,7 @@ KDSize VerticalOffsetLayout::computeSize() { assert(m_parent->isHorizontal()); int indexInParent = m_parent->indexOfChild(this); if (indexInParent < m_parent-> numberOfChildren() - 1 && m_parent->editableChild(indexInParent + 1)->hasUpperLeftIndex()) { - width += 5; + width += k_separationMargin; } } KDCoordinate height = baseLayout()->size().height() + indiceLayout()->size().height() - k_indiceHeight; diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 1c797f7c8..719de510d 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -33,6 +33,7 @@ protected: Type m_type; private: constexpr static KDCoordinate k_indiceHeight = 5; + constexpr static KDCoordinate k_separationMargin = 5; }; } From 2f4ad7576cc936db6f79a72bb81274f81cff1283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 16:11:17 +0200 Subject: [PATCH 299/459] [poincare] Fix hide/showEmptyLayout. Change-Id: I2e042b3aac232f44c59960f165eb93a770cfa243 --- poincare/src/expression_layout_cursor.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index a756257ff..e60946c87 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -226,9 +226,17 @@ bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { * neighbour in an Horizontal layout */ // Check the pointed layout - if (m_pointedExpressionLayout->isEmpty()) { - /* An empty layout is either an EmptyLayout or an HorizontalLayout with one - * child only, and this child is an EmptyLayout. */ + if (m_pointedExpressionLayout->isEmpty() + || (m_position == Position::Left + && m_pointedExpressionLayout->isHorizontal() + && m_pointedExpressionLayout->numberOfChildren() > 0 + && m_pointedExpressionLayout->editableChild(0)->isEmpty())) + { + /* The cursor is next to an EmptyLayout if the pointed layout is an empty + * layout (either an EmptyLayout or HorizontalLayout with one child only, + * and this child is an EmptyLayout), or if the cursor points to the left of + * an HorizontalLayout that starts with an EmptyLayout (for instance, the + * emty base of a vertical offset layout). */ if (m_pointedExpressionLayout->isHorizontal()) { static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); } else { From e503fc8fd6926c540b73832b5b73d7a9e6094aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 16:16:53 +0200 Subject: [PATCH 300/459] [poincare] Use equivalentPointedBrotherLayout. Change-Id: Ie1b04127bea7bfccb7dc870cc131f6f0fc531b97 --- .../poincare/expression_layout_cursor.h | 2 +- poincare/src/expression_layout_cursor.cpp | 50 ++++++++----------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index aede79920..3291bec29 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -26,7 +26,6 @@ public: void setPosition(Position position) { m_position = position; } KDCoordinate cursorHeight(); KDCoordinate baseline(); - ExpressionLayout * equivalentPointedBrotherLayout(); /* Comparison */ bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position); @@ -60,6 +59,7 @@ private: bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); KDCoordinate pointedLayoutHeight(); + ExpressionLayout * equivalentPointedBrotherLayout(); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index e60946c87..3c835d8d9 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -33,22 +33,6 @@ KDCoordinate ExpressionLayoutCursor::baseline() { return max(baseline1, baseline2); } -ExpressionLayout * ExpressionLayoutCursor::equivalentPointedBrotherLayout() { - if (m_pointedExpressionLayout->parent() != nullptr - && m_pointedExpressionLayout->parent()->isHorizontal()) - { - ExpressionLayout * pointedLayoutParent = m_pointedExpressionLayout->editableParent(); - int indexOfPointedLayoutInParent = pointedLayoutParent->indexOfChild(m_pointedExpressionLayout); - if (m_position == Position::Left && indexOfPointedLayoutInParent > 0) { - return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent - 1); - } - if (m_position == Position::Right && indexOfPointedLayoutInParent < pointedLayoutParent->numberOfChildren() - 1) { - return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent + 1); - } - } - return nullptr; -} - bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position) { assert(expressionLayout != nullptr); return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position); @@ -243,20 +227,14 @@ bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { static_cast(m_pointedExpressionLayout)->setVisible(show); } return true; - } else if (m_pointedExpressionLayout->parent() != nullptr - && m_pointedExpressionLayout->parent()->isHorizontal()) - { + } else { // Check the neighbour of the pointed layout in an HorizontalLayout - int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); - int indexToCheck = m_position == Position::Right ? indexInParent + 1 : indexInParent - 1; - if (indexToCheck >=0 - && indexToCheck < m_pointedExpressionLayout->parent()->numberOfChildren() - && m_pointedExpressionLayout->parent()->child(indexToCheck)->isEmpty()) - { - if (m_pointedExpressionLayout->isHorizontal()) { - static_cast(m_pointedExpressionLayout->editableParent()->editableChild(indexToCheck)->editableChild(0))->setVisible(show); + ExpressionLayout * equivalentPointedLayout = equivalentPointedBrotherLayout(); + if (equivalentPointedLayout != nullptr && equivalentPointedLayout->isEmpty()) { + if (equivalentPointedLayout->isHorizontal()) { + static_cast(equivalentPointedLayout->editableChild(0))->setVisible(show); } else { - static_cast(m_pointedExpressionLayout->editableParent()->editableChild(indexToCheck))->setVisible(show); + static_cast(equivalentPointedLayout)->setVisible(show); } return true; } @@ -301,5 +279,21 @@ KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { return height; } +ExpressionLayout * ExpressionLayoutCursor::equivalentPointedBrotherLayout() { + if (m_pointedExpressionLayout->parent() != nullptr + && m_pointedExpressionLayout->parent()->isHorizontal()) + { + ExpressionLayout * pointedLayoutParent = m_pointedExpressionLayout->editableParent(); + int indexOfPointedLayoutInParent = pointedLayoutParent->indexOfChild(m_pointedExpressionLayout); + if (m_position == Position::Left && indexOfPointedLayoutInParent > 0) { + return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent - 1); + } + if (m_position == Position::Right && indexOfPointedLayoutInParent < pointedLayoutParent->numberOfChildren() - 1) { + return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent + 1); + } + } + return nullptr; +} + } From ff03b6dfa3ad46153bf2ee7dbfce30a44ec7c644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 16:34:40 +0200 Subject: [PATCH 301/459] [poincare] Fix the fraction line size Change-Id: I69da69b53708093cd43c696bfb84691b53bc95aa --- poincare/src/layout/fraction_layout.cpp | 2 +- poincare/src/layout/fraction_layout.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index f1c612b9c..d81ba547a 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -230,7 +230,7 @@ ExpressionLayout * FractionLayout::layoutToPointWhenInserting() { void FractionLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDCoordinate fractionLineY = p.y() + numeratorLayout()->size().height() + k_fractionLineMargin; - ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, size().width()-2*Metric::FractionAndConjugateHorizontalMargin, 1), expressionColor); + ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, fractionLineY, size().width()-2*Metric::FractionAndConjugateHorizontalMargin, k_fractionLineHeight), expressionColor); } KDSize FractionLayout::computeSize() { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 1ed0becba..c3008171c 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -31,7 +31,7 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; private: constexpr static KDCoordinate k_fractionLineMargin = 2; - constexpr static KDCoordinate k_fractionLineHeight = 2; + constexpr static KDCoordinate k_fractionLineHeight = 1; ExpressionLayout * numeratorLayout(); ExpressionLayout * denominatorLayout(); }; From e5b298e1c3dd5dd1842acb3e8d6d5e8cbbc7360e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 17:06:09 +0200 Subject: [PATCH 302/459] [poincare] Make AbsoluteValue/Floor/Ceil vertical bars taller. This helps distinguishing with the cursor. Change-Id: I8b823c5ad46fab023f518d6aa702cc4883ba22c1 --- poincare/src/layout/bracket_layout.cpp | 15 ++++++++------- poincare/src/layout/bracket_layout.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index d6cf73c42..2fdf40672 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -121,15 +121,16 @@ void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, operandLayout()->size().height()), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, operandLayout()->size().height()), expressionColor); + KDCoordinate verticalBarHeight = operandLayout()->size().height() + 2*k_verticalMargin; + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, verticalBarHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, verticalBarHeight), expressionColor); if (renderTopBar()) { ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); } if (renderBottomBar()) { - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+operandSize.height()-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); } } @@ -137,18 +138,18 @@ KDSize BracketLayout::computeSize() { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); - return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height()); + return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height() + 2 * k_verticalMargin); } void BracketLayout::computeBaseline() { - m_baseline = operandLayout()->baseline(); + m_baseline = operandLayout()->baseline() + k_verticalMargin; m_baselined = true; } KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); - return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, 0); + return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, k_verticalMargin); } } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index a55f6f8fe..9dabab877 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -28,6 +28,7 @@ protected: private: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_verticalMargin = 1; }; } From 887f3c222abf9ae653302130133832758a9003e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Apr 2018 17:24:42 +0200 Subject: [PATCH 303/459] [poincare] Change some layouts deletion. Change-Id: I3675874892c7200172a7751b15853952fa2bd96f --- poincare/src/layout/bracket_layout.cpp | 9 +++------ poincare/src/layout/conjugate_layout.cpp | 13 ------------- poincare/src/layout/conjugate_layout.h | 1 - poincare/src/layout/integral_layout.cpp | 13 ++----------- poincare/src/layout/nth_root_layout.cpp | 11 +---------- poincare/src/layout/sequence_layout.cpp | 7 ++----- 6 files changed, 8 insertions(+), 46 deletions(-) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 2fdf40672..2fb7ae8d2 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -15,7 +15,7 @@ ExpressionLayout * BracketLayout::clone() const { } void BracketLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { - // If the operand layouts is not HorizontalLayouts, replace it with one. + // If the operand layout is not an HorizontalLayout, replace it with one. if (!operandLayout()->isHorizontal()) { HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); replaceChild(operandLayout(), horizontalOperandLayout, false); @@ -26,11 +26,8 @@ void BracketLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * curso } void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Case: Right. - // Delete the layout, keep the operand. + if (cursor->positionIsEquivalentTo(operandLayout(), ExpressionLayoutCursor::Position::Left)) { + // Case: Left of the operand. Delete the layout, keep the operand. replaceWithAndMoveCursor(operandLayout(), true, cursor); return; } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index e6d2038ba..3afffb399 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -26,19 +26,6 @@ void ConjugateLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cur cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -void ConjugateLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Case: Right. - // Move to the operand and delete. - cursor->setPointedExpressionLayout(operandLayout()); - cursor->performBackspace(); - return; - } - ExpressionLayout::backspaceAtCursor(cursor); -} - bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. // Move Left. diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 265c911bd..b8ef87955 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -11,7 +11,6 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index e3042631b..837587a47 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -27,17 +27,8 @@ ExpressionLayout * IntegralLayout::clone() const { } void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Case: Right. - // Delete the layout, keep the integrand. - replaceWithAndMoveCursor(integrandLayout(), true, cursor); - return; - } - if (cursor->pointedExpressionLayout() == integrandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { + + if (cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { // Case: Left of the integrand. // Delete the layout, keep the integrand. replaceWithAndMoveCursor(integrandLayout(), true, cursor); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index b28bc0de7..11f71bd7b 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -40,19 +40,10 @@ void NthRootLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * curso } void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Case: Right. - // Delete the layout, keep the radicand. - replaceWithAndMoveCursor(radicandLayout(), true, cursor); - return; - } if (cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - // Case: Left of the radicand. - // Delete the layout, keep the radicand. + // Case: Left of the radicand. Delete the layout, keep the radicand. replaceWithAndMoveCursor(radicandLayout(), true, cursor); return; } diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 2194214cb..96a192d29 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -9,11 +9,8 @@ namespace Poincare { void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - // Case: Right. - // Delete the layout, keep the operand. + if (cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { + // Case: Left of the argument. Delete the layout, keep the argument. replaceWithAndMoveCursor(argumentLayout(), true, cursor); return; } From 2b57c00a47909e45209cbfa69ba48bba76657b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 10:43:54 +0200 Subject: [PATCH 304/459] [poincare] Factorize computeBaseline/OperandHeight in ParLeftRightLayout Change-Id: I5a7e4f73df75d26a1b7e21460f888f5f1901307b --- .../src/layout/parenthesis_left_layout.cpp | 89 --------------- poincare/src/layout/parenthesis_left_layout.h | 2 - .../layout/parenthesis_left_right_layout.cpp | 103 ++++++++++++++++++ .../layout/parenthesis_left_right_layout.h | 3 +- .../src/layout/parenthesis_right_layout.cpp | 68 ------------ .../src/layout/parenthesis_right_layout.h | 2 - 6 files changed, 105 insertions(+), 162 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index e1ac24b97..4e3d241fb 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -1,5 +1,4 @@ #include "parenthesis_left_layout.h" -#include extern "C" { #include #include @@ -62,92 +61,4 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio expressionColor); } -void ParenthesisLeftLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - KDCoordinate max_under_baseline = 0; - KDCoordinate max_above_baseline = 0; - int indexInParent = m_parent->indexOfChild(this); - int currentNumberOfOpenParentheses = 1; - int numberOfBrothers = m_parent->numberOfChildren(); - if (indexInParent < numberOfBrothers - 1 - && m_parent->child(indexInParent + 1)->isVerticalOffset()) - { - // If the parenthesis is the base of a superscript layout, it should have a - // default height, else it creates an infinite loop because the parenthesis - // needs the superscript height, which needs the parenthesis height. - return; - } - for (int i = indexInParent + 1; i < numberOfBrothers; i++) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isRightParenthesis()) { - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } - return; - } - } else if (brother->isLeftParenthesis()) { - currentNumberOfOpenParentheses++; - } - KDCoordinate brotherHeight = brother->size().height(); - KDCoordinate brotherBaseline = brother->baseline(); - if (brotherHeight - brotherBaseline > max_under_baseline) { - max_under_baseline = brotherHeight - brotherBaseline ; - } - if (brotherBaseline > max_above_baseline) { - max_above_baseline = brotherBaseline; - } - } - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } -} - -void ParenthesisLeftLayout::computeBaseline() { - assert(m_parent != nullptr); - int currentNumberOfOpenParentheses = 1; - int indexInParent = m_parent->indexOfChild(this); - int numberOfBrothers = m_parent->numberOfChildren(); - if (indexInParent == numberOfBrothers - 1) { - // The parenthesis is the rightmost child of its parent. - m_baseline = operandHeight()/2; - m_baselined = true; - return; - } - if (m_parent->child(indexInParent + 1)->isVerticalOffset()) { - // If the parenthesis is the base of a superscript layout, it should have a - // default baseline, else it creates an infinite loop because the - // parenthesis needs the superscript height, which needs the parenthesis - // baseline. - m_baseline = operandHeight()/2; - m_baselined = true; - return; - } - - m_baseline = 0; - for (int i = indexInParent + 1; i < numberOfBrothers; i++) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isRightParenthesis()) { - if (i == indexInParent + 1) { - // If the parenthesis is immediately closed, we set the baseline to half - // the parenthesis height. - m_baseline = operandHeight()/2; - break; - } - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - break; - } - } else if (brother->isLeftParenthesis()) { - currentNumberOfOpenParentheses++; - } - if (brother->baseline() > m_baseline) { - m_baseline = brother->baseline(); - } - } - m_baselined = true; -} - } diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 99c070fe4..565719038 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -19,8 +19,6 @@ public: bool isLeftParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - void computeOperandHeight() override; - void computeBaseline() override; }; } diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index b7d8f819e..9d9fd8bb1 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -1,4 +1,5 @@ #include "parenthesis_left_right_layout.h" +#include #include extern "C" { #include @@ -56,6 +57,55 @@ KDSize ParenthesisLeftRightLayout::computeSize() { return KDSize(parenthesisWidth(), operandHeight()); } +void ParenthesisLeftRightLayout::computeBaseline() { + assert(m_parent != nullptr); + bool isParenthesisLeft = isLeftParenthesis(); + int indexInParent = m_parent->indexOfChild(this); + int numberOfBrothers = m_parent->numberOfChildren(); + if ((isParenthesisLeft && indexInParent == numberOfBrothers - 1) + || (!isParenthesisLeft && indexInParent == 0) + || (isParenthesisLeft && indexInParent < numberOfBrothers - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset())) + { + /* The parenthesis does not have brothers on its open direction, or it is a + * left parenthesis that is base of a superscript layout. In the latter + * case, it should have a default baseline, else it creates an infinite loop + * because the parenthesis needs the superscript height, which needs the + * parenthesis baseline. */ + m_baseline = operandHeight()/2; + m_baselined = true; + return; + } + + int currentNumberOfOpenParentheses = 1; + m_baseline = 0; + int increment = isParenthesisLeft ? 1 : -1; + for (int i = indexInParent + increment; i >= 0 && i <= numberOfBrothers - 1; i+= increment) { + ExpressionLayout * brother = m_parent->editableChild(i); + if ((isParenthesisLeft && brother->isRightParenthesis()) + || (!isParenthesisLeft && brother->isLeftParenthesis())) + { + if (i == indexInParent + increment) { + /* If the parenthesis is immediately closed, we set the baseline to half + * the parenthesis height. */ + m_baseline = size().height()/2; + break; + } + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + break; + } + } else if ((isParenthesisLeft && brother->isLeftParenthesis()) + || (!isParenthesisLeft && brother->isRightParenthesis())) + { + currentNumberOfOpenParentheses++; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; +} + KDCoordinate ParenthesisLeftRightLayout::operandHeight() { if (!m_operandHeightComputed) { computeOperandHeight(); @@ -64,6 +114,59 @@ KDCoordinate ParenthesisLeftRightLayout::operandHeight() { return m_operandHeight; } +void ParenthesisLeftRightLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; + bool isParenthesisLeft = isLeftParenthesis(); + int indexInParent = m_parent->indexOfChild(this); + int numberOfBrothers = m_parent->numberOfChildren(); + if (isParenthesisLeft + && indexInParent < numberOfBrothers - 1 + && m_parent->child(indexInParent + 1)->isVerticalOffset()) + { + /* If a left parenthesis is the base of a superscript layout, it should have + * a default height, else it creates an infinite loop because the + * parenthesis needs the superscript height, which needs the parenthesis + * height. */ + return; + } + + KDCoordinate max_under_baseline = 0; + KDCoordinate max_above_baseline = 0; + + int currentNumberOfOpenParentheses = 1; + int increment = isParenthesisLeft ? 1 : -1; + for (int i = indexInParent + increment; i >= 0 && i < numberOfBrothers; i+= increment) { + ExpressionLayout * brother = m_parent->editableChild(i); + if ((!isParenthesisLeft && brother->isLeftParenthesis()) + || (isParenthesisLeft && brother->isRightParenthesis())) + { + currentNumberOfOpenParentheses--; + if (currentNumberOfOpenParentheses == 0) { + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; + } + return; + } + } else if ((isParenthesisLeft && brother->isLeftParenthesis()) + || (!isParenthesisLeft && brother->isRightParenthesis())) + { + currentNumberOfOpenParentheses++; + } + KDCoordinate brotherHeight = brother->size().height(); + KDCoordinate brotherBaseline = brother->baseline(); + if (brotherHeight - brotherBaseline > max_under_baseline) { + max_under_baseline = brotherHeight - brotherBaseline ; + } + if (brotherBaseline > max_above_baseline) { + max_above_baseline = brotherBaseline; + } + } + if (max_under_baseline + max_above_baseline > m_operandHeight) { + m_operandHeight = max_under_baseline + max_above_baseline; + } +} + KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index b40f2536d..ba6c1a7cd 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -21,8 +21,9 @@ public: protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; + void computeBaseline() override; KDCoordinate operandHeight(); - virtual void computeOperandHeight() = 0; + void computeOperandHeight(); KDPoint positionOfChild(ExpressionLayout * child) override; bool m_operandHeightComputed; uint16_t m_operandHeight; diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index e0346d42b..08fb8f5cb 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -1,5 +1,4 @@ #include "parenthesis_right_layout.h" -#include extern "C" { #include #include @@ -62,73 +61,6 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi expressionColor); } -void ParenthesisRightLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - KDCoordinate max_under_baseline = 0; - KDCoordinate max_above_baseline = 0; - int currentNumberOfOpenParentheses = 1; - for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isLeftParenthesis()) { - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } - return; - } - } else if (brother->isRightParenthesis()) { - currentNumberOfOpenParentheses++; - } - KDCoordinate brotherHeight = brother->size().height(); - KDCoordinate brotherBaseline = brother->baseline(); - if (brotherHeight - brotherBaseline > max_under_baseline) { - max_under_baseline = brotherHeight - brotherBaseline ; - } - if (brotherBaseline > max_above_baseline) { - max_above_baseline = brotherBaseline; - } - } - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } -} - -void ParenthesisRightLayout::computeBaseline() { - assert(m_parent != nullptr); - int currentNumberOfOpenParentheses = 1; - int indexInParent = m_parent->indexOfChild(this); - if (indexInParent == 0) { - // The parenthesis is the leftmost child of its parent. - m_baseline = operandHeight()/2; - m_baselined = true; - return; - } - m_baseline = 0; - for (int i = indexInParent - 1; i >= 0; i--) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isLeftParenthesis()) { - if (i == indexInParent - 1) { - // If the parenthesis is immediately closed, we set the baseline to half - // the parenthesis height. - m_baseline = operandHeight()/2; - break; - } - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - break; - } - } else if (brother->isRightParenthesis()) { - currentNumberOfOpenParentheses++; - } - if (brother->baseline() > m_baseline) { - m_baseline = brother->baseline(); - } - } - m_baselined = true; -} - } diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index edf361dfb..964bf3d60 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -19,8 +19,6 @@ public: bool isRightParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - void computeOperandHeight() override; - void computeBaseline() override; }; } From ec67de26ba46ed93f0b2edb052888498f8d03f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 10:44:33 +0200 Subject: [PATCH 305/459] [poincare] Increment a nested parentheses heights. Change-Id: I4df49fe0e6bf0941d7668a32f0e35a9c07e64998 --- .../layout/parenthesis_left_right_layout.cpp | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 9d9fd8bb1..169f30441 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -8,6 +8,9 @@ extern "C" { namespace Poincare { +static inline uint16_t max(uint16_t x, uint16_t y) { return (x>y ? x : y); } + + ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : StaticLayoutHierarchy<0>(), m_operandHeightComputed(false) @@ -54,7 +57,28 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool } KDSize ParenthesisLeftRightLayout::computeSize() { - return KDSize(parenthesisWidth(), operandHeight()); + uint16_t maxNumberOfNestedParenthesis = 0; + assert(m_parent != nullptr); + if (m_parent->isHorizontal()) { + int index = m_parent->indexOfChild(this); + uint16_t numberOfOpenParenthesis = 1; + bool goingLeft = isRightParenthesis(); + while (numberOfOpenParenthesis > 0) { + if ((goingLeft && index == 0) + || (!goingLeft && index == m_parent->numberOfChildren() - 1)) + { + break; + } + index += goingLeft ? -1 : 1; + if (m_parent->child(index)->isLeftParenthesis()) { + numberOfOpenParenthesis += goingLeft ? -1 : 1; + } else if (m_parent->child(index)->isRightParenthesis()) { + numberOfOpenParenthesis += goingLeft ? 1 : -1; + } + maxNumberOfNestedParenthesis = max(maxNumberOfNestedParenthesis, numberOfOpenParenthesis); + } + } + return KDSize(parenthesisWidth(), operandHeight()+maxNumberOfNestedParenthesis*2); } void ParenthesisLeftRightLayout::computeBaseline() { From 077c9f91cfe975458b1b5d51c4b357422645c065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 10:36:56 +0200 Subject: [PATCH 306/459] [poincare] Fix incremental nested parenthesis height. Change-Id: Ic2af21604ee5e2485c2aa8c97e0db4ecee625d10 --- poincare/src/layout/parenthesis_left_layout.cpp | 4 ++-- .../src/layout/parenthesis_left_right_layout.cpp | 14 ++++++++------ poincare/src/layout/parenthesis_right_layout.cpp | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 4e3d241fb..fcd377dcf 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -48,7 +48,7 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + size().height() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -57,7 +57,7 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_lineThickness, - operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + size().height() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 169f30441..06ad6d5dd 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -8,7 +8,7 @@ extern "C" { namespace Poincare { -static inline uint16_t max(uint16_t x, uint16_t y) { return (x>y ? x : y); } +static inline int max(int x, int y) { return (x>y ? x : y); } ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : @@ -57,11 +57,11 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool } KDSize ParenthesisLeftRightLayout::computeSize() { - uint16_t maxNumberOfNestedParenthesis = 0; + int maxNumberOfNestedParenthesis = 0; assert(m_parent != nullptr); if (m_parent->isHorizontal()) { int index = m_parent->indexOfChild(this); - uint16_t numberOfOpenParenthesis = 1; + int numberOfOpenParenthesis = 1; bool goingLeft = isRightParenthesis(); while (numberOfOpenParenthesis > 0) { if ((goingLeft && index == 0) @@ -75,7 +75,7 @@ KDSize ParenthesisLeftRightLayout::computeSize() { } else if (m_parent->child(index)->isRightParenthesis()) { numberOfOpenParenthesis += goingLeft ? 1 : -1; } - maxNumberOfNestedParenthesis = max(maxNumberOfNestedParenthesis, numberOfOpenParenthesis); + maxNumberOfNestedParenthesis = max(maxNumberOfNestedParenthesis, numberOfOpenParenthesis-1); } } return KDSize(parenthesisWidth(), operandHeight()+maxNumberOfNestedParenthesis*2); @@ -95,7 +95,7 @@ void ParenthesisLeftRightLayout::computeBaseline() { * case, it should have a default baseline, else it creates an infinite loop * because the parenthesis needs the superscript height, which needs the * parenthesis baseline. */ - m_baseline = operandHeight()/2; + m_baseline = size().height()/2; m_baselined = true; return; } @@ -112,7 +112,8 @@ void ParenthesisLeftRightLayout::computeBaseline() { /* If the parenthesis is immediately closed, we set the baseline to half * the parenthesis height. */ m_baseline = size().height()/2; - break; + m_baselined = true; + return; } currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { @@ -127,6 +128,7 @@ void ParenthesisLeftRightLayout::computeBaseline() { m_baseline = brother->baseline(); } } + m_baseline += (size().height() - operandHeight()) / 2; m_baselined = true; } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index 08fb8f5cb..c3e256ab0 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -48,7 +48,7 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + size().height() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -57,7 +57,7 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_widthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+2, ParenthesisLeftRightLayout::k_lineThickness, - operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + size().height() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } From 1b505d1cb4cf6a0a8d7cf44d8c9eb7a35d7cf213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 11:06:26 +0200 Subject: [PATCH 307/459] [poincare] Linear parenthesis height increase. Change-Id: I8e073b10e4e7ea7741520e7e5e9ff5c08c3cb902 --- .../layout/parenthesis_left_right_layout.cpp | 23 +------------------ .../layout/parenthesis_left_right_layout.h | 1 + 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 06ad6d5dd..75f0afc8e 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -57,28 +57,7 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool } KDSize ParenthesisLeftRightLayout::computeSize() { - int maxNumberOfNestedParenthesis = 0; - assert(m_parent != nullptr); - if (m_parent->isHorizontal()) { - int index = m_parent->indexOfChild(this); - int numberOfOpenParenthesis = 1; - bool goingLeft = isRightParenthesis(); - while (numberOfOpenParenthesis > 0) { - if ((goingLeft && index == 0) - || (!goingLeft && index == m_parent->numberOfChildren() - 1)) - { - break; - } - index += goingLeft ? -1 : 1; - if (m_parent->child(index)->isLeftParenthesis()) { - numberOfOpenParenthesis += goingLeft ? -1 : 1; - } else if (m_parent->child(index)->isRightParenthesis()) { - numberOfOpenParenthesis += goingLeft ? 1 : -1; - } - maxNumberOfNestedParenthesis = max(maxNumberOfNestedParenthesis, numberOfOpenParenthesis-1); - } - } - return KDSize(parenthesisWidth(), operandHeight()+maxNumberOfNestedParenthesis*2); + return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin); } void ParenthesisLeftRightLayout::computeBaseline() { diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index ba6c1a7cd..67e663121 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -18,6 +18,7 @@ public: constexpr static KDCoordinate k_externHeightMargin = 2; constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_verticalMargin = 4; protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; From dfd34cbd0446e8d922d1b1535476dfea6b1b2311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 14:59:42 +0200 Subject: [PATCH 308/459] [poincare] Rename ParenthesisLeftRightLayout into ParenthesisLayout Change-Id: I45e7812d43318bbc13f712a36d758c43ce8781a5 --- poincare/Makefile | 2 +- .../layout/binomial_coefficient_layout.cpp | 4 +-- ...ight_layout.cpp => parenthesis_layout.cpp} | 20 ++++++------ ...ft_right_layout.h => parenthesis_layout.h} | 8 ++--- .../src/layout/parenthesis_left_layout.cpp | 32 +++++++++---------- poincare/src/layout/parenthesis_left_layout.h | 6 ++-- .../src/layout/parenthesis_right_layout.cpp | 32 +++++++++---------- .../src/layout/parenthesis_right_layout.h | 6 ++-- 8 files changed, 55 insertions(+), 55 deletions(-) rename poincare/src/layout/{parenthesis_left_right_layout.cpp => parenthesis_layout.cpp} (88%) rename poincare/src/layout/{parenthesis_left_right_layout.h => parenthesis_layout.h} (85%) diff --git a/poincare/Makefile b/poincare/Makefile index 6d900aa72..4634ba8c1 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -110,7 +110,7 @@ objs += $(addprefix poincare/src/layout/,\ matrix_layout.o\ nth_root_layout.o\ parenthesis_left_layout.o\ - parenthesis_left_right_layout.o\ + parenthesis_layout.o\ parenthesis_right_layout.o\ product_layout.o\ sequence_layout.o\ diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 300ccf0b2..7e39c9883 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -3,7 +3,7 @@ #include "grid_layout.h" #include "horizontal_layout.h" #include "parenthesis_left_layout.h" -#include "parenthesis_left_right_layout.h" +#include "parenthesis_layout.h" #include "parenthesis_right_layout.h" #include #include @@ -108,7 +108,7 @@ void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expre KDSize BinomialCoefficientLayout::computeSize() { KDSize coefficientsSize = GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true).size(); - return KDSize(coefficientsSize.width() + 2*ParenthesisLeftRightLayout::parenthesisWidth(), coefficientsSize.height()); + return KDSize(coefficientsSize.width() + 2*ParenthesisLayout::parenthesisWidth(), coefficientsSize.height()); } void BinomialCoefficientLayout::computeBaseline() { diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp similarity index 88% rename from poincare/src/layout/parenthesis_left_right_layout.cpp rename to poincare/src/layout/parenthesis_layout.cpp index 75f0afc8e..de28adc27 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -1,4 +1,4 @@ -#include "parenthesis_left_right_layout.h" +#include "parenthesis_layout.h" #include #include extern "C" { @@ -11,18 +11,18 @@ namespace Poincare { static inline int max(int x, int y) { return (x>y ? x : y); } -ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : +ParenthesisLayout::ParenthesisLayout() : StaticLayoutHierarchy<0>(), m_operandHeightComputed(false) { } -void ParenthesisLeftRightLayout::invalidAllSizesPositionsAndBaselines() { +void ParenthesisLayout::invalidAllSizesPositionsAndBaselines() { m_operandHeightComputed = false; ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -39,7 +39,7 @@ bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool return false; } -bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -56,11 +56,11 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool return false; } -KDSize ParenthesisLeftRightLayout::computeSize() { +KDSize ParenthesisLayout::computeSize() { return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin); } -void ParenthesisLeftRightLayout::computeBaseline() { +void ParenthesisLayout::computeBaseline() { assert(m_parent != nullptr); bool isParenthesisLeft = isLeftParenthesis(); int indexInParent = m_parent->indexOfChild(this); @@ -111,7 +111,7 @@ void ParenthesisLeftRightLayout::computeBaseline() { m_baselined = true; } -KDCoordinate ParenthesisLeftRightLayout::operandHeight() { +KDCoordinate ParenthesisLayout::operandHeight() { if (!m_operandHeightComputed) { computeOperandHeight(); m_operandHeightComputed = true; @@ -119,7 +119,7 @@ KDCoordinate ParenthesisLeftRightLayout::operandHeight() { return m_operandHeight; } -void ParenthesisLeftRightLayout::computeOperandHeight() { +void ParenthesisLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; bool isParenthesisLeft = isLeftParenthesis(); @@ -172,7 +172,7 @@ void ParenthesisLeftRightLayout::computeOperandHeight() { } } -KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { +KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; } diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_layout.h similarity index 85% rename from poincare/src/layout/parenthesis_left_right_layout.h rename to poincare/src/layout/parenthesis_layout.h index 67e663121..46cc1bbd0 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -1,13 +1,13 @@ -#ifndef POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H -#define POINCARE_PARENTHESIS_LEFT_RIGHT_LAYOUT_H +#ifndef POINCARE_PARENTHESIS_LAYOUT_H +#define POINCARE_PARENTHESIS_LAYOUT_H #include namespace Poincare { -class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { +class ParenthesisLayout : public StaticLayoutHierarchy<0> { public: - ParenthesisLeftRightLayout(); + ParenthesisLayout(); void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index fcd377dcf..bd486d9c2 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -6,7 +6,7 @@ extern "C" { namespace Poincare { -const uint8_t topLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { +const uint8_t topLeftCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, @@ -16,7 +16,7 @@ const uint8_t topLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight] {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, }; -const uint8_t bottomLeftCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { +const uint8_t bottomLeftCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, @@ -40,24 +40,24 @@ bool ParenthesisLeftLayout::isCollapsable(int * numberOfOpenParenthesis, bool go } void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y()+ParenthesisLeftRightLayout::k_externHeightMargin, - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + KDRect frame(p.x()+ParenthesisLayout::k_externWidthMargin, + p.y()+ParenthesisLayout::k_externHeightMargin, + ParenthesisLayout::k_parenthesisCurveWidth, + ParenthesisLayout::k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLayout::s_parenthesisWorkingBuffer)); - frame = KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y() + size().height() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + frame = KDRect(p.x()+ParenthesisLayout::k_externWidthMargin, + p.y() + size().height() - ParenthesisLayout::k_parenthesisCurveHeight - ParenthesisLayout::k_externHeightMargin, + ParenthesisLayout::k_parenthesisCurveWidth, + ParenthesisLayout::k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomLeftCurve, (KDColor *)(ParenthesisLayout::s_parenthesisWorkingBuffer)); - ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin, - ParenthesisLeftRightLayout::k_lineThickness, - size().height() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + ctx->fillRect(KDRect(p.x()+ParenthesisLayout::k_externWidthMargin, + p.y()+ParenthesisLayout::k_parenthesisCurveHeight+ParenthesisLayout::k_externHeightMargin, + ParenthesisLayout::k_lineThickness, + size().height() - 2*(ParenthesisLayout::k_parenthesisCurveHeight+ParenthesisLayout::k_externHeightMargin)), expressionColor); } diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index 565719038..13aaff112 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -1,16 +1,16 @@ #ifndef POINCARE_PARENTHESIS_LEFT_LAYOUT_H #define POINCARE_PARENTHESIS_LEFT_LAYOUT_H -#include +#include #include namespace Poincare { -class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { +class ParenthesisLeftLayout : public ParenthesisLayout { friend class BinomialCoefficientLayout; friend class SequenceLayout; public: - using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; + using ParenthesisLayout::ParenthesisLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '('); diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index c3e256ab0..7ac78ef93 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -6,7 +6,7 @@ extern "C" { namespace Poincare { -const uint8_t topRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { +const uint8_t topRightCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, @@ -16,7 +16,7 @@ const uint8_t topRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, }; -const uint8_t bottomRightCurve[ParenthesisLeftRightLayout::k_parenthesisCurveHeight][ParenthesisLeftRightLayout::k_parenthesisCurveWidth] = { +const uint8_t bottomRightCurve[ParenthesisLayout::k_parenthesisCurveHeight][ParenthesisLayout::k_parenthesisCurveWidth] = { {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, @@ -40,24 +40,24 @@ bool ParenthesisRightLayout::isCollapsable(int * numberOfOpenParenthesis, bool g } void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - p.y() + ParenthesisLeftRightLayout::k_externHeightMargin, - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + KDRect frame = KDRect(p.x() + ParenthesisLayout::k_widthMargin + ParenthesisLayout::k_lineThickness - ParenthesisLayout::k_parenthesisCurveWidth, + p.y() + ParenthesisLayout::k_externHeightMargin, + ParenthesisLayout::k_parenthesisCurveWidth, + ParenthesisLayout::k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLayout::s_parenthesisWorkingBuffer)); - frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - p.y() + size().height() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - ParenthesisLeftRightLayout::k_parenthesisCurveHeight); + frame = KDRect(p.x() + ParenthesisLayout::k_widthMargin + ParenthesisLayout::k_lineThickness - ParenthesisLayout::k_parenthesisCurveWidth, + p.y() + size().height() - ParenthesisLayout::k_parenthesisCurveHeight - ParenthesisLayout::k_externHeightMargin, + ParenthesisLayout::k_parenthesisCurveWidth, + ParenthesisLayout::k_parenthesisCurveHeight); - ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomRightCurve, (KDColor *)(ParenthesisLayout::s_parenthesisWorkingBuffer)); - ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_widthMargin, - p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+2, - ParenthesisLeftRightLayout::k_lineThickness, - size().height() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + ctx->fillRect(KDRect(p.x()+ParenthesisLayout::k_widthMargin, + p.y()+ParenthesisLayout::k_parenthesisCurveHeight+2, + ParenthesisLayout::k_lineThickness, + size().height() - 2*(ParenthesisLayout::k_parenthesisCurveHeight+ParenthesisLayout::k_externHeightMargin)), expressionColor); } diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 964bf3d60..63565c827 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -1,16 +1,16 @@ #ifndef POINCARE_PARENTHESIS_RIGHT_LAYOUT_H #define POINCARE_PARENTHESIS_RIGHT_LAYOUT_H -#include +#include #include namespace Poincare { -class ParenthesisRightLayout : public ParenthesisLeftRightLayout { +class ParenthesisRightLayout : public ParenthesisLayout { friend class BinomialCoefficientLayout; friend class SequenceLayout; public: - using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; + using ParenthesisLayout::ParenthesisLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ')'); From 16fa9a09759ce5136ef6eb3af154fcbb08fe3da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 15:07:04 +0200 Subject: [PATCH 309/459] [poincare] Rename ParenthesisRightLayout into RightParenthesisLayout Change-Id: I4f104d5a214c98024ad2e0a0bb2f5ffe63c92495 --- poincare/Makefile | 2 +- poincare/include/poincare_layouts.h | 2 +- poincare/src/expression_layout_cursor.cpp | 2 +- .../src/layout/binomial_coefficient_layout.cpp | 6 +++--- ...ght_layout.cpp => right_parenthesis_layout.cpp} | 10 +++++----- ...s_right_layout.h => right_parenthesis_layout.h} | 6 +++--- poincare/src/layout/sequence_layout.cpp | 6 +++--- poincare/src/layout/vertical_offset_layout.cpp | 14 +++++++------- poincare/src/layout_engine.cpp | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) rename poincare/src/layout/{parenthesis_right_layout.cpp => right_parenthesis_layout.cpp} (89%) rename poincare/src/layout/{parenthesis_right_layout.h => right_parenthesis_layout.h} (84%) diff --git a/poincare/Makefile b/poincare/Makefile index 4634ba8c1..7c4f18a88 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -111,7 +111,7 @@ objs += $(addprefix poincare/src/layout/,\ nth_root_layout.o\ parenthesis_left_layout.o\ parenthesis_layout.o\ - parenthesis_right_layout.o\ + right_parenthesis_layout.o\ product_layout.o\ sequence_layout.o\ static_layout_hierarchy.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 28e742db7..fff7cef2c 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 3c835d8d9..442b90c21 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -176,7 +176,7 @@ void ExpressionLayoutCursor::insertText(const char * text) { pointedChild = newChild; } } else if (text[i] == ')') { - newChild = new ParenthesisRightLayout(); + newChild = new RightParenthesisLayout(); } else if (text[i] == '[') { newChild = new BracketLeftLayout(); } else if (text[i] == ']') { diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 7e39c9883..c1b8167c1 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -4,7 +4,7 @@ #include "horizontal_layout.h" #include "parenthesis_left_layout.h" #include "parenthesis_layout.h" -#include "parenthesis_right_layout.h" +#include "right_parenthesis_layout.h" #include #include extern "C" { @@ -97,7 +97,7 @@ bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Render the parentheses. ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); - ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); KDPoint leftParenthesisPoint = dummyLayout.positionOfChild(dummyLeftParenthesis); @@ -118,7 +118,7 @@ void BinomialCoefficientLayout::computeBaseline() { KDPoint BinomialCoefficientLayout::positionOfChild(ExpressionLayout * child) { ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); - ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); if (child == nLayout()) { diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/right_parenthesis_layout.cpp similarity index 89% rename from poincare/src/layout/parenthesis_right_layout.cpp rename to poincare/src/layout/right_parenthesis_layout.cpp index 7ac78ef93..369cca075 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/right_parenthesis_layout.cpp @@ -1,4 +1,4 @@ -#include "parenthesis_right_layout.h" +#include "right_parenthesis_layout.h" extern "C" { #include #include @@ -26,12 +26,12 @@ const uint8_t bottomRightCurve[ParenthesisLayout::k_parenthesisCurveHeight][Pare {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, }; -ExpressionLayout * ParenthesisRightLayout::clone() const { - ParenthesisRightLayout * layout = new ParenthesisRightLayout(); +ExpressionLayout * RightParenthesisLayout::clone() const { + RightParenthesisLayout * layout = new RightParenthesisLayout(); return layout; } -bool ParenthesisRightLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { +bool RightParenthesisLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { if (*numberOfOpenParenthesis == 0 && !goingLeft) { return false; } @@ -39,7 +39,7 @@ bool ParenthesisRightLayout::isCollapsable(int * numberOfOpenParenthesis, bool g return true; } -void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void RightParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDRect frame = KDRect(p.x() + ParenthesisLayout::k_widthMargin + ParenthesisLayout::k_lineThickness - ParenthesisLayout::k_parenthesisCurveWidth, p.y() + ParenthesisLayout::k_externHeightMargin, ParenthesisLayout::k_parenthesisCurveWidth, diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/right_parenthesis_layout.h similarity index 84% rename from poincare/src/layout/parenthesis_right_layout.h rename to poincare/src/layout/right_parenthesis_layout.h index 63565c827..a4606acce 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/right_parenthesis_layout.h @@ -1,12 +1,12 @@ -#ifndef POINCARE_PARENTHESIS_RIGHT_LAYOUT_H -#define POINCARE_PARENTHESIS_RIGHT_LAYOUT_H +#ifndef POINCARE_RIGHT_PARENTHESIS_LAYOUT_H +#define POINCARE_RIGHT_PARENTHESIS_LAYOUT_H #include #include namespace Poincare { -class ParenthesisRightLayout : public ParenthesisLayout { +class RightParenthesisLayout : public ParenthesisLayout { friend class BinomialCoefficientLayout; friend class SequenceLayout; public: diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 96a192d29..76a17985e 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -2,7 +2,7 @@ #include "char_layout.h" #include "horizontal_layout.h" #include "parenthesis_left_layout.h" -#include "parenthesis_right_layout.h" +#include "right_parenthesis_layout.h" #include #include @@ -194,7 +194,7 @@ ExpressionLayout * SequenceLayout::argumentLayout() { KDSize SequenceLayout::computeSize() { KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); - ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDSize dummyLayoutSize = dummyLayout2.size(); KDSize upperBoundSize = upperBoundLayout()->size(); @@ -240,7 +240,7 @@ void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, // Render the parentheses. ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); - ParenthesisRightLayout * dummyRightParenthesis = new ParenthesisRightLayout(); + RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); KDPoint rightParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 9a4e9e2a4..7d523a402 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -1,7 +1,7 @@ #include "vertical_offset_layout.h" #include "empty_layout.h" #include "parenthesis_left_layout.h" -#include "parenthesis_right_layout.h" +#include "right_parenthesis_layout.h" #include #include #include @@ -296,18 +296,18 @@ void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Ex indexInParent++; // Add the Right parenthesis - ParenthesisRightLayout * parenthesisRight = new ParenthesisRightLayout(); + RightParenthesisLayout * rightParenthesis = new RightParenthesisLayout(); if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - m_parent->addChildAtIndex(parenthesisRight, indexInParent + 1); + m_parent->addChildAtIndex(rightParenthesis, indexInParent + 1); } else { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - m_parent->addChildAtIndex(parenthesisRight, indexInParent); + m_parent->addChildAtIndex(rightParenthesis, indexInParent); } - cursor->setPointedExpressionLayout(parenthesisRight); + cursor->setPointedExpressionLayout(rightParenthesis); if (moveCursor) { - parenthesisRight->addBrotherAndMoveCursor(cursor, brother); + rightParenthesis->addBrotherAndMoveCursor(cursor, brother); } else { - parenthesisRight->addBrother(cursor, brother); + rightParenthesis->addBrother(cursor, brother); } return; } diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 48f21fd80..4bc28c2d0 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -2,7 +2,7 @@ #include "layout/char_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_left_layout.h" -#include "layout/parenthesis_right_layout.h" +#include "layout/right_parenthesis_layout.h" #include "layout/vertical_offset_layout.h" extern "C" { #include @@ -59,7 +59,7 @@ ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layo if (layout != nullptr) { result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1, true); } - result->addChildAtIndex(new ParenthesisRightLayout(), result->numberOfChildren()); + result->addChildAtIndex(new RightParenthesisLayout(), result->numberOfChildren()); return result; } From e4dccc8cc11828ff4ef8f0ffc41231efa205bbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 15:13:20 +0200 Subject: [PATCH 310/459] [poincare] Rename ParenthesisLeftLayout into LeftParenthesisLayout Change-Id: Iaedd556ce912d650432d395b294c39e53bfc16a0 --- poincare/Makefile | 2 +- poincare/include/poincare_layouts.h | 2 +- poincare/src/expression_layout_cursor.cpp | 2 +- poincare/src/layout/binomial_coefficient_layout.cpp | 6 +++--- ...sis_left_layout.cpp => left_parenthesis_layout.cpp} | 10 +++++----- ...nthesis_left_layout.h => left_parenthesis_layout.h} | 6 +++--- poincare/src/layout/sequence_layout.cpp | 8 ++++---- poincare/src/layout/vertical_offset_layout.cpp | 6 +++--- poincare/src/layout_engine.cpp | 4 ++-- 9 files changed, 23 insertions(+), 23 deletions(-) rename poincare/src/layout/{parenthesis_left_layout.cpp => left_parenthesis_layout.cpp} (88%) rename poincare/src/layout/{parenthesis_left_layout.h => left_parenthesis_layout.h} (84%) diff --git a/poincare/Makefile b/poincare/Makefile index 7c4f18a88..fc310b5dd 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -109,7 +109,7 @@ objs += $(addprefix poincare/src/layout/,\ integral_layout.o\ matrix_layout.o\ nth_root_layout.o\ - parenthesis_left_layout.o\ + left_parenthesis_layout.o\ parenthesis_layout.o\ right_parenthesis_layout.o\ product_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index fff7cef2c..e68c0c256 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 442b90c21..ab2656ca4 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -171,7 +171,7 @@ void ExpressionLayoutCursor::insertText(const char * text) { ExpressionLayout * pointedChild = nullptr; for (int i = 0; i < textLength; i++) { if (text[i] == '(') { - newChild = new ParenthesisLeftLayout(); + newChild = new LeftParenthesisLayout(); if (pointedChild == nullptr) { pointedChild = newChild; } diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index c1b8167c1..e10b32a7a 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -2,7 +2,7 @@ #include "empty_layout.h" #include "grid_layout.h" #include "horizontal_layout.h" -#include "parenthesis_left_layout.h" +#include "left_parenthesis_layout.h" #include "parenthesis_layout.h" #include "right_parenthesis_layout.h" #include @@ -96,7 +96,7 @@ bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { // Render the parentheses. - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); @@ -117,7 +117,7 @@ void BinomialCoefficientLayout::computeBaseline() { } KDPoint BinomialCoefficientLayout::positionOfChild(ExpressionLayout * child) { - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); GridLayout * dummyGridLayout = new GridLayout(ExpressionLayoutArray(nLayout(), kLayout()).array(), 2, 1, true); HorizontalLayout dummyLayout(dummyLeftParenthesis, dummyGridLayout, dummyRightParenthesis, false); diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/left_parenthesis_layout.cpp similarity index 88% rename from poincare/src/layout/parenthesis_left_layout.cpp rename to poincare/src/layout/left_parenthesis_layout.cpp index bd486d9c2..880225bb6 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/left_parenthesis_layout.cpp @@ -1,4 +1,4 @@ -#include "parenthesis_left_layout.h" +#include "left_parenthesis_layout.h" extern "C" { #include #include @@ -26,12 +26,12 @@ const uint8_t bottomLeftCurve[ParenthesisLayout::k_parenthesisCurveHeight][Paren {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, }; -ExpressionLayout * ParenthesisLeftLayout::clone() const { - ParenthesisLeftLayout * layout = new ParenthesisLeftLayout(); +ExpressionLayout * LeftParenthesisLayout::clone() const { + LeftParenthesisLayout * layout = new LeftParenthesisLayout(); return layout; } -bool ParenthesisLeftLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { +bool LeftParenthesisLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { if (*numberOfOpenParenthesis == 0 && goingLeft) { return false; } @@ -39,7 +39,7 @@ bool ParenthesisLeftLayout::isCollapsable(int * numberOfOpenParenthesis, bool go return true; } -void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void LeftParenthesisLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDRect frame(p.x()+ParenthesisLayout::k_externWidthMargin, p.y()+ParenthesisLayout::k_externHeightMargin, ParenthesisLayout::k_parenthesisCurveWidth, diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/left_parenthesis_layout.h similarity index 84% rename from poincare/src/layout/parenthesis_left_layout.h rename to poincare/src/layout/left_parenthesis_layout.h index 13aaff112..2d9878c5c 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/left_parenthesis_layout.h @@ -1,12 +1,12 @@ -#ifndef POINCARE_PARENTHESIS_LEFT_LAYOUT_H -#define POINCARE_PARENTHESIS_LEFT_LAYOUT_H +#ifndef POINCARE_LEFT_PARENTHESIS_LAYOUT_H +#define POINCARE_LEFT_PARENTHESIS_LAYOUT_H #include #include namespace Poincare { -class ParenthesisLeftLayout : public ParenthesisLayout { +class LeftParenthesisLayout : public ParenthesisLayout { friend class BinomialCoefficientLayout; friend class SequenceLayout; public: diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 76a17985e..9fc35c4c5 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -1,7 +1,7 @@ #include "sequence_layout.h" #include "char_layout.h" #include "horizontal_layout.h" -#include "parenthesis_left_layout.h" +#include "left_parenthesis_layout.h" #include "right_parenthesis_layout.h" #include #include @@ -193,7 +193,7 @@ ExpressionLayout * SequenceLayout::argumentLayout() { KDSize SequenceLayout::computeSize() { KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDSize dummyLayoutSize = dummyLayout2.size(); @@ -209,7 +209,7 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { HorizontalLayout dummyLayout1(new CharLayout('n'), new CharLayout('='), lowerBoundClone, false); KDSize lowerBoundSizeWithNEquals = dummyLayout1.size(); KDSize upperBoundSize = upperBoundLayout()->size(); - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), false); KDCoordinate x = 0; KDCoordinate y = 0; @@ -239,7 +239,7 @@ void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN->fontSize(), expressionColor, backgroundColor); // Render the parentheses. - ParenthesisLeftLayout * dummyLeftParenthesis = new ParenthesisLeftLayout(); + LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 7d523a402..d54100597 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -1,6 +1,6 @@ #include "vertical_offset_layout.h" #include "empty_layout.h" -#include "parenthesis_left_layout.h" +#include "left_parenthesis_layout.h" #include "right_parenthesis_layout.h" #include #include @@ -285,14 +285,14 @@ void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Ex // Add the Left parenthesis int indexInParent = m_parent->indexOfChild(this); int leftParenthesisIndex = indexInParent; - ParenthesisLeftLayout * parenthesisLeft = new ParenthesisLeftLayout(); + LeftParenthesisLayout * leftParenthesis = new LeftParenthesisLayout(); int numberOfOpenParenthesis = 0; while (leftParenthesisIndex > 0 && editableParent()->editableChild(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis, true)) { leftParenthesisIndex--; } - m_parent->addChildAtIndex(parenthesisLeft, leftParenthesisIndex); + m_parent->addChildAtIndex(leftParenthesis, leftParenthesisIndex); indexInParent++; // Add the Right parenthesis diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 4bc28c2d0..65fc1ef3d 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -1,7 +1,7 @@ #include #include "layout/char_layout.h" #include "layout/horizontal_layout.h" -#include "layout/parenthesis_left_layout.h" +#include "layout/left_parenthesis_layout.h" #include "layout/right_parenthesis_layout.h" #include "layout/vertical_offset_layout.h" extern "C" { @@ -55,7 +55,7 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout) { HorizontalLayout * result = new HorizontalLayout(); - result->addChildAtIndex(new ParenthesisLeftLayout(), 0); + result->addChildAtIndex(new LeftParenthesisLayout(), 0); if (layout != nullptr) { result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1, true); } From 70f28aea4b1121e0309367770260b61a6abf6f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 15:17:35 +0200 Subject: [PATCH 311/459] [Coding style] Change "brother" into "sibling" Change-Id: I6f07be262358641875d3024d1741285c5895b8d6 --- ...scrollable_expression_view_with_cursor.cpp | 2 +- poincare/include/poincare/expression_layout.h | 16 ++--- .../poincare/expression_layout_cursor.h | 4 +- poincare/src/expression_layout_cursor.cpp | 48 +++++++-------- poincare/src/layout/bracket_layout.cpp | 2 +- poincare/src/layout/bracket_layout.h | 2 +- poincare/src/layout/bracket_left_layout.cpp | 30 +++++----- poincare/src/layout/bracket_right_layout.cpp | 22 +++---- poincare/src/layout/conjugate_layout.cpp | 2 +- poincare/src/layout/conjugate_layout.h | 2 +- .../src/layout/dynamic_layout_hierarchy.cpp | 2 +- poincare/src/layout/empty_layout.cpp | 10 ++-- poincare/src/layout/empty_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 60 +++++++++---------- poincare/src/layout/fraction_layout.cpp | 2 +- poincare/src/layout/fraction_layout.h | 4 +- poincare/src/layout/grid_layout.cpp | 4 +- poincare/src/layout/horizontal_layout.cpp | 40 ++++++------- poincare/src/layout/horizontal_layout.h | 2 +- poincare/src/layout/nth_root_layout.cpp | 2 +- poincare/src/layout/nth_root_layout.h | 2 +- poincare/src/layout/parenthesis_layout.cpp | 52 ++++++++-------- .../src/layout/vertical_offset_layout.cpp | 14 ++--- poincare/src/layout/vertical_offset_layout.h | 4 +- 24 files changed, 165 insertions(+), 165 deletions(-) diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index b62b69646..7de8c9802 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -141,7 +141,7 @@ bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event e return true; } if (event == Ion::Events::Division) { - m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseBrothers(); + m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseSiblings(); return true; } if (event == Ion::Events::XNT) { diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 9dff32dfb..0ed484c87 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -50,12 +50,12 @@ public: /* Dynamic Layout */ // Collapse - virtual void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor); + virtual void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor); // Add virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } - void addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); - void addBrotherAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * brother); + void addSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling); + void addSiblingAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling); // Replace virtual ExpressionLayout * replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace); @@ -103,7 +103,7 @@ public: bool addGreySquaresToAllMatrixAncestors(); bool hasText() const; virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } - /* isCollapsable is used when adding a brother fraction: should the layout be + /* isCollapsable is used when adding a sibling fraction: should the layout be * inserted in the numerator (or denominator)? For instance, 1+2|3-4 should * become 1+ 2/3 - 4 when pressing "Divide": a CharLayout is collapsable if * its char is not +, -, or *. */ @@ -114,9 +114,9 @@ public: * with an omitted multiplication sign. For instance, an absolute value layout * returns true, because |3|2 means |3|*2. A '+' CharLayout returns false, * because +'something' nevers means +*'something'. */ - virtual bool mustHaveLeftBrother() const { return false; } + virtual bool mustHaveLeftSibling() const { return false; } virtual bool isVerticalOffset() const { return false; } - /* For now, mustHaveLeftBrother and isVerticalOffset behave the same, but code + /* For now, mustHaveLeftSibling and isVerticalOffset behave the same, but code * is clearer with different names. */ virtual bool isHorizontal() const { return false; } virtual bool isLeftParenthesis() const { return false; } @@ -140,12 +140,12 @@ protected: ExpressionLayout ** childResult, void * resultPosition, int * resultScore); - virtual void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor); + virtual void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor); void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); ExpressionLayout * m_parent; KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to - * the fraction bar of an hypothetical fraction brother layout. If the top of + * the fraction bar of an hypothetical fraction sibling layout. If the top of * the layout is under that bar, the baseline is negative. */ bool m_sized; bool m_baselined; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 3291bec29..5bdc266c6 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -43,7 +43,7 @@ public: /* Edition */ void addLayoutAndMoveCursor(ExpressionLayout * layout); void addEmptyExponentialLayout(); - void addFractionLayoutAndCollapseBrothers(); + void addFractionLayoutAndCollapseSiblings(); void addEmptyMatrixLayout(int numberOfRows = 1, int numberOfColumns = 1); void addEmptyPowerLayout(); void addEmptySquareRootLayout(); @@ -59,7 +59,7 @@ private: bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); KDCoordinate pointedLayoutHeight(); - ExpressionLayout * equivalentPointedBrotherLayout(); + ExpressionLayout * equivalentPointedSiblingLayout(); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index ab2656ca4..5c4a3e88c 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -26,9 +26,9 @@ KDCoordinate ExpressionLayoutCursor::baseline() { } KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); KDCoordinate baseline2 = (KDCoordinate)0; - ExpressionLayout * equivalentBrotherLayout = equivalentPointedBrotherLayout(); - if (equivalentBrotherLayout != nullptr) { - baseline2 = equivalentBrotherLayout->baseline(); + ExpressionLayout * equivalentSiblingLayout = equivalentPointedSiblingLayout(); + if (equivalentSiblingLayout != nullptr) { + baseline2 = equivalentSiblingLayout->baseline(); } return max(baseline1, baseline2); } @@ -70,9 +70,9 @@ bool ExpressionLayoutCursor::moveDown(bool * shouldRecomputeLayout) { void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { bool layoutWillBeMerged = layout->isHorizontal(); - pointedExpressionLayout()->addBrotherAndMoveCursor(this, layout); + pointedExpressionLayout()->addSiblingAndMoveCursor(this, layout); if (!layoutWillBeMerged) { - layout->collapseBrothersAndMoveCursor(this); + layout->collapseSiblingsAndMoveCursor(this); } } @@ -80,18 +80,18 @@ void ExpressionLayoutCursor::addEmptyExponentialLayout() { CharLayout * child1 = new CharLayout(Ion::Charset::Exponential); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyLayout(), VerticalOffsetLayout::Type::Superscript, false); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); - pointedExpressionLayout()->addBrother(this, newChild); + pointedExpressionLayout()->addSibling(this, newChild); setPointedExpressionLayout(offsetLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Right); } -void ExpressionLayoutCursor::addFractionLayoutAndCollapseBrothers() { +void ExpressionLayoutCursor::addFractionLayoutAndCollapseSiblings() { // Add a new FractionLayout HorizontalLayout * child1 = new HorizontalLayout(new EmptyLayout(), false); HorizontalLayout * child2 = new HorizontalLayout(new EmptyLayout(), false); FractionLayout * newChild = new FractionLayout(child1, child2, false); - pointedExpressionLayout()->addBrother(this, newChild); - newChild->collapseBrothersAndMoveCursor(this); + pointedExpressionLayout()->addSibling(this, newChild); + newChild->collapseSiblingsAndMoveCursor(this); } void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOfColumns) { @@ -108,7 +108,7 @@ void ExpressionLayoutCursor::addEmptyMatrixLayout(int numberOfRows, int numberOf } } ExpressionLayout * matrixLayout = new MatrixLayout(const_cast(const_cast(children)), numberOfRows+1, numberOfColumns+1, false); - m_pointedExpressionLayout->addBrother(this, matrixLayout); + m_pointedExpressionLayout->addSibling(this, matrixLayout); setPointedExpressionLayout(matrixLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Right); } @@ -117,7 +117,7 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(new EmptyLayout(), VerticalOffsetLayout::Type::Superscript, false); // If there is already a base if (baseForNewPowerLayout()) { - m_pointedExpressionLayout->addBrother(this, offsetLayout); + m_pointedExpressionLayout->addSibling(this, offsetLayout); setPointedExpressionLayout(offsetLayout->editableChild(0)); setPosition(ExpressionLayoutCursor::Position::Right); return; @@ -125,7 +125,7 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { // Else, add an empty base EmptyLayout * child1 = new EmptyLayout(); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); - m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout->addSibling(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); } @@ -133,8 +133,8 @@ void ExpressionLayoutCursor::addEmptyPowerLayout() { void ExpressionLayoutCursor::addEmptySquareRootLayout() { HorizontalLayout * child1 = new HorizontalLayout(new EmptyLayout(), false); NthRootLayout * newChild = new NthRootLayout(child1, false); - m_pointedExpressionLayout->addBrother(this, newChild); - newChild->collapseBrothersAndMoveCursor(this); + m_pointedExpressionLayout->addSibling(this, newChild); + newChild->collapseSiblingsAndMoveCursor(this); } void ExpressionLayoutCursor::addEmptySquarePowerLayout() { @@ -142,7 +142,7 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(indiceLayout, VerticalOffsetLayout::Type::Superscript, false); // If there is already a base if (baseForNewPowerLayout()) { - m_pointedExpressionLayout->addBrother(this, offsetLayout); + m_pointedExpressionLayout->addSibling(this, offsetLayout); setPointedExpressionLayout(offsetLayout); setPosition(ExpressionLayoutCursor::Position::Right); return; @@ -150,14 +150,14 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { // Else, add an empty base EmptyLayout * child1 = new EmptyLayout(); HorizontalLayout * newChild = new HorizontalLayout(child1, offsetLayout, false); - m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout->addSibling(this, newChild); setPointedExpressionLayout(child1); setPosition(ExpressionLayoutCursor::Position::Right); } void ExpressionLayoutCursor::addXNTCharLayout() { CharLayout * newChild = new CharLayout(m_pointedExpressionLayout->XNTChar()); - m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout->addSibling(this, newChild); setPointedExpressionLayout(newChild); setPosition(ExpressionLayoutCursor::Position::Right); } @@ -184,7 +184,7 @@ void ExpressionLayoutCursor::insertText(const char * text) { } else { newChild = new CharLayout(text[i]); } - m_pointedExpressionLayout->addBrother(this, newChild); + m_pointedExpressionLayout->addSibling(this, newChild); m_pointedExpressionLayout = newChild; m_position = Position::Right; } @@ -229,7 +229,7 @@ bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { return true; } else { // Check the neighbour of the pointed layout in an HorizontalLayout - ExpressionLayout * equivalentPointedLayout = equivalentPointedBrotherLayout(); + ExpressionLayout * equivalentPointedLayout = equivalentPointedSiblingLayout(); if (equivalentPointedLayout != nullptr && equivalentPointedLayout->isEmpty()) { if (equivalentPointedLayout->isHorizontal()) { static_cast(equivalentPointedLayout->editableChild(0))->setVisible(show); @@ -268,18 +268,18 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { KDCoordinate height = pointedExpressionLayoutEquivalentChild()->size().height(); KDCoordinate height1 = height; - ExpressionLayout * equivalentBrotherLayout = equivalentPointedBrotherLayout(); - if (equivalentBrotherLayout != nullptr) { - KDCoordinate height2 = equivalentBrotherLayout->size().height(); + ExpressionLayout * equivalentSiblingLayout = equivalentPointedSiblingLayout(); + if (equivalentSiblingLayout != nullptr) { + KDCoordinate height2 = equivalentSiblingLayout->size().height(); KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); - KDCoordinate baseline2 = equivalentBrotherLayout->baseline(); + KDCoordinate baseline2 = equivalentSiblingLayout->baseline(); height = max(baseline1, baseline2) + max(height1 - baseline1, height2 - baseline2); } return height; } -ExpressionLayout * ExpressionLayoutCursor::equivalentPointedBrotherLayout() { +ExpressionLayout * ExpressionLayoutCursor::equivalentPointedSiblingLayout() { if (m_pointedExpressionLayout->parent() != nullptr && m_pointedExpressionLayout->parent()->isHorizontal()) { diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 2fb7ae8d2..af92bb48d 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -14,7 +14,7 @@ ExpressionLayout * BracketLayout::clone() const { return layout; } -void BracketLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { +void BracketLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the operand layout is not an HorizontalLayout, replace it with one. if (!operandLayout()->isHorizontal()) { HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 9dabab877..aa4707a98 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -10,7 +10,7 @@ class BracketLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; + void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/bracket_left_layout.cpp index 324b7ae15..c2028ee66 100644 --- a/poincare/src/layout/bracket_left_layout.cpp +++ b/poincare/src/layout/bracket_left_layout.cpp @@ -21,20 +21,20 @@ void BracketLeftLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; - int numberOfBrothers = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isRightBracket()) { + int numberOfSiblings = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfSiblings; i++) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if (sibling->isRightBracket()) { currentNumberOfOpenBrackets--; if (currentNumberOfOpenBrackets == 0) { return; } - } else if (brother->isLeftBracket()) { + } else if (sibling->isLeftBracket()) { currentNumberOfOpenBrackets++; } - KDCoordinate brotherHeight = brother->size().height(); - if (brotherHeight > m_operandHeight) { - m_operandHeight = brotherHeight; + KDCoordinate siblingHeight = sibling->size().height(); + if (siblingHeight > m_operandHeight) { + m_operandHeight = siblingHeight; } } } @@ -43,19 +43,19 @@ void BracketLeftLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; int currentNumberOfOpenBrackets = 1; - int numberOfBrothers = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isRightBracket()) { + int numberOfSiblings = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfSiblings; i++) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if (sibling->isRightBracket()) { currentNumberOfOpenBrackets--; if (currentNumberOfOpenBrackets == 0) { break; } - } else if (brother->isLeftBracket()) { + } else if (sibling->isLeftBracket()) { currentNumberOfOpenBrackets++; } - if (brother->baseline() > m_baseline) { - m_baseline = brother->baseline(); + if (sibling->baseline() > m_baseline) { + m_baseline = sibling->baseline(); } } m_baselined = true; diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/bracket_right_layout.cpp index a1f5ce663..cfeea9e03 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/bracket_right_layout.cpp @@ -22,18 +22,18 @@ void BracketRightLayout::computeOperandHeight() { m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isLeftBracket()) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if (sibling->isLeftBracket()) { currentNumberOfOpenBrackets--; if (currentNumberOfOpenBrackets == 0) { return; } - } else if (brother->isRightBracket()) { + } else if (sibling->isRightBracket()) { currentNumberOfOpenBrackets++; } - KDCoordinate brotherHeight = brother->size().height(); - if (brotherHeight > m_operandHeight) { - m_operandHeight = brotherHeight; + KDCoordinate siblingHeight = sibling->size().height(); + if (siblingHeight > m_operandHeight) { + m_operandHeight = siblingHeight; } } } @@ -43,17 +43,17 @@ void BracketRightLayout::computeBaseline() { m_baseline = operandHeight()/2; int currentNumberOfOpenBrackets = 1; for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { - ExpressionLayout * brother = m_parent->editableChild(i); - if (brother->isLeftBracket()) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if (sibling->isLeftBracket()) { currentNumberOfOpenBrackets--; if (currentNumberOfOpenBrackets == 0) { break; } - } else if (brother->isRightBracket()) { + } else if (sibling->isRightBracket()) { currentNumberOfOpenBrackets++; } - if (brother->baseline() > m_baseline) { - m_baseline = brother->baseline(); + if (sibling->baseline() > m_baseline) { + m_baseline = sibling->baseline(); } } m_baselined = true; diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 3afffb399..593225e91 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -15,7 +15,7 @@ ExpressionLayout * ConjugateLayout::clone() const { return layout; } -void ConjugateLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { +void ConjugateLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the operand layouts is not HorizontalLayouts, replace it with one. if (!operandLayout()->isHorizontal()) { HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index b8ef87955..cd3822f57 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -10,7 +10,7 @@ class ConjugateLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; + void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 15cf10b5b..5bbcad605 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -64,7 +64,7 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * for (int i=0; iisEmpty() - || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftBrother())) + || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftSibling())) { const_cast(operands[i])->setParent(this); newOperands[currentIndex++] = operands[i]; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 55da8f382..7e41d0715 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -71,18 +71,18 @@ void EmptyLayout::computeBaseline() { m_baselined = true; } -void EmptyLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { +void EmptyLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { Color currentColor = m_color; int indexInParent = m_parent->indexOfChild(this); ExpressionLayout * parent = m_parent; - if (brother->mustHaveLeftBrother()) { + if (sibling->mustHaveLeftSibling()) { m_color = Color::Yellow; - ExpressionLayout::privateAddBrother(cursor, brother, moveCursor); + ExpressionLayout::privateAddSibling(cursor, sibling, moveCursor); } else { if (moveCursor) { - replaceWithAndMoveCursor(brother, true, cursor); + replaceWithAndMoveCursor(sibling, true, cursor); } else { - replaceWith(brother, true); + replaceWith(sibling, true); } } if (currentColor == Color::Grey) { diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 4003da2c1..bdb31db5f 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -31,7 +31,7 @@ protected: assert(false); return KDPointZero; } - void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; + void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; private: constexpr static KDCoordinate k_width = 7; constexpr static KDCoordinate k_height = 13; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 753ead5dd..8ee4eac41 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -105,15 +105,15 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { return m_parent->hasAncestor(e); } -void ExpressionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { +void ExpressionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { } -void ExpressionLayout::addBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - privateAddBrother(cursor, brother, false); +void ExpressionLayout::addSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling) { + privateAddSibling(cursor, sibling, false); } -void ExpressionLayout::addBrotherAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * brother) { - privateAddBrother(cursor, brother, true); +void ExpressionLayout::addSiblingAndMoveCursor(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling) { + privateAddSibling(cursor, sibling, true); } ExpressionLayout * ExpressionLayout::replaceWith(ExpressionLayout * newChild, bool deleteAfterReplace) { @@ -197,7 +197,7 @@ void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool de bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor) { - cursor->pointedExpressionLayout()->addBrother(cursor, newChild); + cursor->pointedExpressionLayout()->addSibling(cursor, newChild); return true; } @@ -369,16 +369,16 @@ void ExpressionLayout::moveCursorInsideAtDirection ( } } -void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { +void ExpressionLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { /* The layout must have a parent, because HorizontalLayout overrides - * privateAddBrother and only an HorizontalLayout can be the root layout. */ + * privateAddSibling and only an HorizontalLayout can be the root layout. */ assert(m_parent); if (m_parent->isHorizontal()) { int indexInParent = m_parent->indexOfChild(this); - int brotherIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? indexInParent : indexInParent + 1; + int siblingIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? indexInParent : indexInParent + 1; - /* Special case: If the neighbour brother is a VerticalOffsetLayout, let it - * handle the insertion of the new brother. */ + /* Special case: If the neighbour sibling is a VerticalOffsetLayout, let it + * handle the insertion of the new sibling. */ ExpressionLayout * neighbour = nullptr; if (cursor->position() == ExpressionLayoutCursor::Position::Left && indexInParent > 0) { neighbour = m_parent->editableChild(indexInParent - 1); @@ -389,32 +389,32 @@ void ExpressionLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres cursor->setPointedExpressionLayout(neighbour); cursor->setPosition(cursor->position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left); if (moveCursor) { - neighbour->addBrotherAndMoveCursor(cursor, brother); + neighbour->addSiblingAndMoveCursor(cursor, sibling); } else { - neighbour->addBrother(cursor, brother); + neighbour->addSibling(cursor, sibling); } return; } - // Else, let the parent add the brother. + // Else, let the parent add the sibling. if (moveCursor) { - if (brotherIndex < m_parent->numberOfChildren()) { - cursor->setPointedExpressionLayout(m_parent->editableChild(brotherIndex)); + if (siblingIndex < m_parent->numberOfChildren()) { + cursor->setPointedExpressionLayout(m_parent->editableChild(siblingIndex)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); } else { cursor->setPointedExpressionLayout(m_parent); cursor->setPosition(ExpressionLayoutCursor::Position::Right); } } - static_cast(m_parent)->addOrMergeChildAtIndex(brother, brotherIndex, true); + static_cast(m_parent)->addOrMergeChildAtIndex(sibling, siblingIndex, true); return; } ExpressionLayout * juxtapositionLayout = nullptr; if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - juxtapositionLayout = replaceWithJuxtapositionOf(brother, this, false); + juxtapositionLayout = replaceWithJuxtapositionOf(sibling, this, false); } else { assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - juxtapositionLayout = replaceWithJuxtapositionOf(this, brother, false); + juxtapositionLayout = replaceWithJuxtapositionOf(this, sibling, false); } if (moveCursor) { cursor->setPointedExpressionLayout(juxtapositionLayout); @@ -427,7 +427,7 @@ void ExpressionLayout::collapseOnDirection(HorizontalDirection direction, int ab return; } int indexInParent = parent()->indexOfChild(this); - int numberOfBrothers = parent()->numberOfChildren(); + int numberOfSiblings = parent()->numberOfChildren(); int numberOfOpenParenthesis = 0; bool canCollapse = true; ExpressionLayout * absorbingChild = editableChild(absorbingChildIndex); @@ -435,24 +435,24 @@ void ExpressionLayout::collapseOnDirection(HorizontalDirection direction, int ab return; } HorizontalLayout * horizontalAbsorbingChild = static_cast(absorbingChild); - if (direction == HorizontalDirection::Right && indexInParent < numberOfBrothers - 1) { - canCollapse = !(editableParent()->editableChild(indexInParent+1)->mustHaveLeftBrother()); + if (direction == HorizontalDirection::Right && indexInParent < numberOfSiblings - 1) { + canCollapse = !(editableParent()->editableChild(indexInParent+1)->mustHaveLeftSibling()); } - ExpressionLayout * brother = nullptr; + ExpressionLayout * sibling = nullptr; while (canCollapse) { - if (direction == HorizontalDirection::Right && indexInParent == numberOfBrothers - 1) { + if (direction == HorizontalDirection::Right && indexInParent == numberOfSiblings - 1) { break; } if (direction == HorizontalDirection::Left && indexInParent == 0) { break; } - int brotherIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; - brother = editableParent()->editableChild(brotherIndex); - if (brother->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left)) { - editableParent()->removeChildAtIndex(brotherIndex, false); + int siblingIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; + sibling = editableParent()->editableChild(siblingIndex); + if (sibling->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left)) { + editableParent()->removeChildAtIndex(siblingIndex, false); int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; - horizontalAbsorbingChild->addOrMergeChildAtIndex(brother, newIndex, true); - numberOfBrothers--; + horizontalAbsorbingChild->addOrMergeChildAtIndex(sibling, newIndex, true); + numberOfSiblings--; if (direction == HorizontalDirection::Left) { indexInParent--; } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index d81ba547a..fb257f1c5 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -14,7 +14,7 @@ ExpressionLayout * FractionLayout::clone() const { return layout; } -void FractionLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { +void FractionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { /* If the numerator or denominator layouts are not HorizontalLayouts, replace * them with one. */ if (!numeratorLayout()->isHorizontal()) { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index c3008171c..b11aa158b 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -10,7 +10,7 @@ class FractionLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; + void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -20,7 +20,7 @@ public: ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } /* WARNING: We need to override this function, else 1/2 3/4 would be - * serialized as 1/2**3/4, as the two Fraction layouts think their brother is + * serialized as 1/2**3/4, as the two Fraction layouts think their sibling is * an omitted multiplication layout factor. We have the same problem with * 2^3 1/2 being serialized as 2^3**1/2, so must override the Right version * and not canBeOmittedMultiplicationLeftFactor. */ diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 2ac10b22c..0c75fed4d 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -43,7 +43,7 @@ bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomput return true; } // Case: Left of another child. - // Go Right of its brother on the left. + // Go Right of its sibling on the left. cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return true; @@ -80,7 +80,7 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecompu return true; } // Case: Right of another child. - // Go Left of its brother on the right. + // Go Left of its sibling on the right. cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index e84002647..8732b2bd0 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -123,7 +123,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex if (cursor != nullptr) { /* If the old layout is not an ancestor of the new layout, or if the * cursor was on the right of the new layout, place the cursor on the - * right of the new layout, which is left of the next brother or right of + * right of the new layout, which is left of the next sibling or right of * the parent. */ if (!oldWasAncestorOfNewLayout || cursor->position() == ExpressionLayoutCursor::Position::Right) { if (oldChildIndex == numberOfChildren() - 1) { @@ -135,7 +135,7 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex } } else { /* Else place the cursor on the left of the new layout, which is right - * of the previous brother or left of the parent. */ + * of the previous sibling or left of the parent. */ if (oldChildIndex == 0) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); @@ -209,7 +209,7 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRe } return false; } - // Case: the child is not the leftmost. Go to its left brother and move Left. + // Case: the child is not the leftmost. Go to its left sibling and move Left. cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); return editableChild(childIndex-1)->moveLeft(cursor, shouldRecomputeLayout); @@ -254,7 +254,7 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR } return false; } - /* Case: the child is not the rightmost. Go to its right brother and move + /* Case: the child is not the rightmost. Go to its right sibling and move * Right. */ cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); @@ -270,12 +270,12 @@ bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRe } void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { - int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, !operands[0]->mustHaveLeftBrother()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, !operands[0]->mustHaveLeftSibling()); DynamicLayoutHierarchy::addChildrenAtIndex(operands, numberOfOperands, newIndex, removeEmptyChildren); } bool HorizontalLayout::addChildAtIndex(ExpressionLayout * operand, int index) { - int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, !operand->mustHaveLeftBrother()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, !operand->mustHaveLeftSibling()); return DynamicLayoutHierarchy::addChildAtIndex(operand, newIndex); } @@ -287,7 +287,7 @@ void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int ind /* If the layout to insert starts with a vertical offset layout, the child * empty layout on the left of the inserted layout (if there is one) shoul not * be reomved, as it wil be the base for the VerticalOffsetLayout. */ - bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? !(eL->child(0)->mustHaveLeftBrother()) : true; + bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? !(eL->child(0)->mustHaveLeftSibling()) : true; int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); } @@ -363,8 +363,8 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { - // Add the "brother" as a child. +void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { + // Add the "sibling" as a child. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { // If the first child is empty, remove it before adding the layout. if (numberOfChildren() > 0 && editableChild(0)->isEmpty()) { @@ -378,7 +378,7 @@ void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres cursor->setPosition(ExpressionLayoutCursor::Position::Right); } } - addOrMergeChildAtIndex(brother, 0, false); + addOrMergeChildAtIndex(sibling, 0, false); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); @@ -387,7 +387,7 @@ void HorizontalLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Expres if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty()) { removeChildAtIndex(childrenCount - 1, true); } - addOrMergeChildAtIndex(brother, numberOfChildren(), false); + addOrMergeChildAtIndex(sibling, numberOfChildren(), false); if (moveCursor) { cursor->setPointedExpressionLayout(this); } @@ -402,21 +402,21 @@ bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direct assert(direction == ExpressionLayout::VerticalDirection::Down); return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } - // If the cursor Left or Right of a child, try moving it up from its brother. + // If the cursor Left or Right of a child, try moving it up from its sibling. int previousLayoutIndex = indexOfChild(previousLayout); if (previousLayoutIndex > -1) { - ExpressionLayout * brother = nullptr; + ExpressionLayout * sibling = nullptr; ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { - brother = editableChild(previousLayoutIndex - 1); + sibling = editableChild(previousLayoutIndex - 1); newPosition = ExpressionLayoutCursor::Position::Right; } if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < numberOfChildren() - 1) { - brother = editableChild(previousLayoutIndex + 1); + sibling = editableChild(previousLayoutIndex + 1); newPosition = ExpressionLayoutCursor::Position::Left; } - if (brother && cursor->positionIsEquivalentTo(brother, newPosition)) { - if (tryMoveVerticallyFromAnotherLayout(brother, newPosition, direction, cursor, shouldRecomputeLayout, previousLayout)) { + if (sibling && cursor->positionIsEquivalentTo(sibling, newPosition)) { + if (tryMoveVerticallyFromAnotherLayout(sibling, newPosition, direction, cursor, shouldRecomputeLayout, previousLayout)) { return true; } } @@ -453,10 +453,10 @@ bool HorizontalLayout::tryMoveVerticallyFromAnotherLayout(ExpressionLayout * oth } void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { - /* If the child to remove is at index 0 and its right brother must have a left - * brother (e.g. it is a VerticalOffsetLayout), replace the child with an + /* If the child to remove is at index 0 and its right sibling must have a left + * sibling (e.g. it is a VerticalOffsetLayout), replace the child with an * EmptyLayout instead of removing it. */ - if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftBrother()) { + if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftSibling()) { addChildAtIndex(new EmptyLayout(), index + 1); } DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index d69cd0daf..ba92d4786 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -46,7 +46,7 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; + void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; private: bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); bool tryMoveVerticallyFromAnotherLayout(ExpressionLayout * otherLayout, ExpressionLayoutCursor::Position otherPosition, ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 11f71bd7b..733e9ba43 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -28,7 +28,7 @@ ExpressionLayout * NthRootLayout::clone() const { return new NthRootLayout(const_cast(this)->radicandLayout(), const_cast(this)->indexLayout(), true); } -void NthRootLayout::collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) { +void NthRootLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the radicand layout is not an HorizontalLayout, replace it with one. if (!radicandLayout()->isHorizontal()) { HorizontalLayout * horizontalRadicandLayout = new HorizontalLayout(radicandLayout(), false); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index fa3463365..293a56106 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -14,7 +14,7 @@ public: ExpressionLayout * clone() const override; /* Dynamic Layout*/ - void collapseBrothersAndMoveCursor(ExpressionLayoutCursor * cursor) override; + void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index de28adc27..3c34d020e 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -64,12 +64,12 @@ void ParenthesisLayout::computeBaseline() { assert(m_parent != nullptr); bool isParenthesisLeft = isLeftParenthesis(); int indexInParent = m_parent->indexOfChild(this); - int numberOfBrothers = m_parent->numberOfChildren(); - if ((isParenthesisLeft && indexInParent == numberOfBrothers - 1) + int numberOfSiblings = m_parent->numberOfChildren(); + if ((isParenthesisLeft && indexInParent == numberOfSiblings - 1) || (!isParenthesisLeft && indexInParent == 0) - || (isParenthesisLeft && indexInParent < numberOfBrothers - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset())) + || (isParenthesisLeft && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset())) { - /* The parenthesis does not have brothers on its open direction, or it is a + /* The parenthesis does not have siblings on its open direction, or it is a * left parenthesis that is base of a superscript layout. In the latter * case, it should have a default baseline, else it creates an infinite loop * because the parenthesis needs the superscript height, which needs the @@ -82,10 +82,10 @@ void ParenthesisLayout::computeBaseline() { int currentNumberOfOpenParentheses = 1; m_baseline = 0; int increment = isParenthesisLeft ? 1 : -1; - for (int i = indexInParent + increment; i >= 0 && i <= numberOfBrothers - 1; i+= increment) { - ExpressionLayout * brother = m_parent->editableChild(i); - if ((isParenthesisLeft && brother->isRightParenthesis()) - || (!isParenthesisLeft && brother->isLeftParenthesis())) + for (int i = indexInParent + increment; i >= 0 && i <= numberOfSiblings - 1; i+= increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((isParenthesisLeft && sibling->isRightParenthesis()) + || (!isParenthesisLeft && sibling->isLeftParenthesis())) { if (i == indexInParent + increment) { /* If the parenthesis is immediately closed, we set the baseline to half @@ -98,13 +98,13 @@ void ParenthesisLayout::computeBaseline() { if (currentNumberOfOpenParentheses == 0) { break; } - } else if ((isParenthesisLeft && brother->isLeftParenthesis()) - || (!isParenthesisLeft && brother->isRightParenthesis())) + } else if ((isParenthesisLeft && sibling->isLeftParenthesis()) + || (!isParenthesisLeft && sibling->isRightParenthesis())) { currentNumberOfOpenParentheses++; } - if (brother->baseline() > m_baseline) { - m_baseline = brother->baseline(); + if (sibling->baseline() > m_baseline) { + m_baseline = sibling->baseline(); } } m_baseline += (size().height() - operandHeight()) / 2; @@ -124,9 +124,9 @@ void ParenthesisLayout::computeOperandHeight() { m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; bool isParenthesisLeft = isLeftParenthesis(); int indexInParent = m_parent->indexOfChild(this); - int numberOfBrothers = m_parent->numberOfChildren(); + int numberOfSiblings = m_parent->numberOfChildren(); if (isParenthesisLeft - && indexInParent < numberOfBrothers - 1 + && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset()) { /* If a left parenthesis is the base of a superscript layout, it should have @@ -141,10 +141,10 @@ void ParenthesisLayout::computeOperandHeight() { int currentNumberOfOpenParentheses = 1; int increment = isParenthesisLeft ? 1 : -1; - for (int i = indexInParent + increment; i >= 0 && i < numberOfBrothers; i+= increment) { - ExpressionLayout * brother = m_parent->editableChild(i); - if ((!isParenthesisLeft && brother->isLeftParenthesis()) - || (isParenthesisLeft && brother->isRightParenthesis())) + for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((!isParenthesisLeft && sibling->isLeftParenthesis()) + || (isParenthesisLeft && sibling->isRightParenthesis())) { currentNumberOfOpenParentheses--; if (currentNumberOfOpenParentheses == 0) { @@ -153,18 +153,18 @@ void ParenthesisLayout::computeOperandHeight() { } return; } - } else if ((isParenthesisLeft && brother->isLeftParenthesis()) - || (!isParenthesisLeft && brother->isRightParenthesis())) + } else if ((isParenthesisLeft && sibling->isLeftParenthesis()) + || (!isParenthesisLeft && sibling->isRightParenthesis())) { currentNumberOfOpenParentheses++; } - KDCoordinate brotherHeight = brother->size().height(); - KDCoordinate brotherBaseline = brother->baseline(); - if (brotherHeight - brotherBaseline > max_under_baseline) { - max_under_baseline = brotherHeight - brotherBaseline ; + KDCoordinate siblingHeight = sibling->size().height(); + KDCoordinate siblingBaseline = sibling->baseline(); + if (siblingHeight - siblingBaseline > max_under_baseline) { + max_under_baseline = siblingHeight - siblingBaseline ; } - if (brotherBaseline > max_above_baseline) { - max_above_baseline = brotherBaseline; + if (siblingBaseline > max_above_baseline) { + max_above_baseline = siblingBaseline; } } if (max_under_baseline + max_above_baseline > m_operandHeight) { diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index d54100597..8b613ba16 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -276,10 +276,10 @@ KDPoint VerticalOffsetLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(0, base->size().height() - base->baseline() - k_indiceHeight); } -void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) { - if (brother->isVerticalOffset()) { - VerticalOffsetLayout * verticalOffsetBrother = static_cast(brother); - if (verticalOffsetBrother->type() == Type::Superscript) { +void VerticalOffsetLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { + if (sibling->isVerticalOffset()) { + VerticalOffsetLayout * verticalOffsetSibling = static_cast(sibling); + if (verticalOffsetSibling->type() == Type::Superscript) { assert(m_parent->isHorizontal()); // Add the Left parenthesis @@ -305,14 +305,14 @@ void VerticalOffsetLayout::privateAddBrother(ExpressionLayoutCursor * cursor, Ex } cursor->setPointedExpressionLayout(rightParenthesis); if (moveCursor) { - rightParenthesis->addBrotherAndMoveCursor(cursor, brother); + rightParenthesis->addSiblingAndMoveCursor(cursor, sibling); } else { - rightParenthesis->addBrother(cursor, brother); + rightParenthesis->addSibling(cursor, sibling); } return; } } - ExpressionLayout::privateAddBrother(cursor, brother, moveCursor); + ExpressionLayout::privateAddSibling(cursor, sibling, moveCursor); } diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 719de510d..a37b31c70 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -20,7 +20,7 @@ public: bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - bool mustHaveLeftBrother() const override { return true; } + bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const { return true; } protected: ExpressionLayout * indiceLayout(); @@ -29,7 +29,7 @@ protected: KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; - void privateAddBrother(ExpressionLayoutCursor * cursor, ExpressionLayout * brother, bool moveCursor) override; + void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; Type m_type; private: constexpr static KDCoordinate k_indiceHeight = 5; From 1e9b4d4c0775c63a63762648da57e9a09d62e358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 15:20:13 +0200 Subject: [PATCH 312/459] [poincare] Rename backspaceAtCursor -> deleteBeforeCursor Change-Id: Ia5196b46fa58a82347bb1b02a7b7ef9a816ff66f --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/expression_layout_cursor.cpp | 2 +- poincare/src/layout/bracket_layout.cpp | 4 ++-- poincare/src/layout/bracket_layout.h | 2 +- poincare/src/layout/empty_layout.cpp | 4 ++-- poincare/src/layout/empty_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 4 ++-- poincare/src/layout/fraction_layout.cpp | 4 ++-- poincare/src/layout/fraction_layout.h | 2 +- poincare/src/layout/horizontal_layout.cpp | 4 ++-- poincare/src/layout/horizontal_layout.h | 2 +- poincare/src/layout/integral_layout.cpp | 4 ++-- poincare/src/layout/integral_layout.h | 2 +- poincare/src/layout/nth_root_layout.cpp | 4 ++-- poincare/src/layout/nth_root_layout.h | 2 +- poincare/src/layout/sequence_layout.cpp | 4 ++-- poincare/src/layout/sequence_layout.h | 2 +- poincare/src/layout/vertical_offset_layout.cpp | 4 ++-- poincare/src/layout/vertical_offset_layout.h | 2 +- 19 files changed, 28 insertions(+), 28 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 0ed484c87..793bb763f 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -77,7 +77,7 @@ public: // User input bool insertLayoutAtCursor(ExpressionLayout * newChild, ExpressionLayoutCursor * cursor); - virtual void backspaceAtCursor(ExpressionLayoutCursor * cursor); + virtual void deleteBeforeCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 5c4a3e88c..54ba3457a 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -194,7 +194,7 @@ void ExpressionLayoutCursor::insertText(const char * text) { } void ExpressionLayoutCursor::performBackspace() { - m_pointedExpressionLayout->backspaceAtCursor(this); + m_pointedExpressionLayout->deleteBeforeCursor(this); } bool ExpressionLayoutCursor::showEmptyLayoutIfNeeded() { diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index af92bb48d..77406f539 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -25,13 +25,13 @@ void BracketLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curso cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -void BracketLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void BracketLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->positionIsEquivalentTo(operandLayout(), ExpressionLayoutCursor::Position::Left)) { // Case: Left of the operand. Delete the layout, keep the operand. replaceWithAndMoveCursor(operandLayout(), true, cursor); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index aa4707a98..e0a9cd7ac 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -11,7 +11,7 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 7e41d0715..c4ea9317b 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -18,10 +18,10 @@ ExpressionLayout * EmptyLayout::clone() const { return layout; } -void EmptyLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void EmptyLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->backspaceAtCursor(cursor); + return m_parent->deleteBeforeCursor(cursor); } } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index bdb31db5f..969fd4726 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -14,7 +14,7 @@ public: }; EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 8ee4eac41..68958ea1d 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -201,7 +201,7 @@ bool ExpressionLayout::insertLayoutAtCursor(ExpressionLayout * newChild, Express return true; } -void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void ExpressionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { int indexOfPointedExpression = indexOfChild(cursor->pointedExpressionLayout()); if (indexOfPointedExpression >= 0) { // Case: The pointed layout is a child. Move Left. @@ -219,7 +219,7 @@ void ExpressionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { // Case: Left. Ask the parent. if (m_parent) { - m_parent->backspaceAtCursor(cursor); + m_parent->deleteBeforeCursor(cursor); } return; } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index fb257f1c5..bfdb99688 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -31,7 +31,7 @@ void FractionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curs cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { // Case: Left of the denominator. // Replace the fraction with a horizontal juxtaposition of the numerator and // the denominator. @@ -86,7 +86,7 @@ void FractionLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(denominatorLayout()); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index b11aa158b..4f40a9642 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -11,7 +11,7 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 8732b2bd0..79b7286dc 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -13,7 +13,7 @@ ExpressionLayout * HorizontalLayout::clone() const { return layout; } -void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void HorizontalLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left && m_parent == nullptr) @@ -52,7 +52,7 @@ void HorizontalLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->performBackspace(); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } void HorizontalLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index ba92d4786..c011f862c 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -15,7 +15,7 @@ class HorizontalLayout : public DynamicLayoutHierarchy { public: using DynamicLayoutHierarchy::DynamicLayoutHierarchy; ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Hierarchy */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 837587a47..61020915c 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -26,7 +26,7 @@ ExpressionLayout * IntegralLayout::clone() const { return layout; } -void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void IntegralLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { // Case: Left of the integrand. @@ -34,7 +34,7 @@ void IntegralLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { replaceWithAndMoveCursor(integrandLayout(), true, cursor); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index c165c6395..9b6d93137 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -14,7 +14,7 @@ public: ExpressionLayout * clone() const override; /* Dynamic Layout*/ - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 733e9ba43..a50bc9742 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -39,7 +39,7 @@ void NthRootLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curso cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void NthRootLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { @@ -47,7 +47,7 @@ void NthRootLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { replaceWithAndMoveCursor(radicandLayout(), true, cursor); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 293a56106..a6597a1e5 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -15,7 +15,7 @@ public: /* Dynamic Layout*/ void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 9fc35c4c5..58afc000d 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -8,13 +8,13 @@ namespace Poincare { -void SequenceLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void SequenceLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { // Case: Left of the argument. Delete the layout, keep the argument. replaceWithAndMoveCursor(argumentLayout(), true, cursor); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 37fc29b02..1949372f2 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -10,7 +10,7 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 8b613ba16..c246a5566 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -21,7 +21,7 @@ ExpressionLayout * VerticalOffsetLayout::clone() const { return layout; } -void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { +void VerticalOffsetLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->pointedExpressionLayout() == indiceLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); ExpressionLayout * base = baseLayout(); @@ -60,7 +60,7 @@ void VerticalOffsetLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) { cursor->setPointedExpressionLayout(indiceLayout()); return; } - ExpressionLayout::backspaceAtCursor(cursor); + ExpressionLayout::deleteBeforeCursor(cursor); } bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index a37b31c70..ed80b0418 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -14,7 +14,7 @@ public: VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); Type type() const { return m_type; } ExpressionLayout * clone() const override; - void backspaceAtCursor(ExpressionLayoutCursor * cursor) override; + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; From 01f01174d85f45d28ab779be03830d5fbca61104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 15:37:08 +0200 Subject: [PATCH 313/459] [poincare] Rename BracketLayout -> BracketPairLayout Change-Id: Iefa4a9773493e2e8bd92fed139e556fb40e0a287 --- poincare/Makefile | 2 +- poincare/include/poincare_layouts.h | 2 +- poincare/src/layout/absolute_value_layout.h | 6 ++-- ...ket_layout.cpp => bracket_pair_layout.cpp} | 28 +++++++++---------- ...bracket_layout.h => bracket_pair_layout.h} | 6 ++-- poincare/src/layout/ceiling_layout.h | 6 ++-- poincare/src/layout/floor_layout.h | 6 ++-- 7 files changed, 28 insertions(+), 28 deletions(-) rename poincare/src/layout/{bracket_layout.cpp => bracket_pair_layout.cpp} (81%) rename poincare/src/layout/{bracket_layout.h => bracket_pair_layout.h} (90%) diff --git a/poincare/Makefile b/poincare/Makefile index fc310b5dd..0aa804a7e 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -91,7 +91,7 @@ objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ binomial_coefficient_layout.o\ bounded_static_layout_hierarchy.o\ - bracket_layout.o\ + bracket_pair_layout.o\ bracket_left_layout.o\ bracket_left_right_layout.o\ bracket_right_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index e68c0c256..2342016ac 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index eddb3ad55..0888296b7 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -1,15 +1,15 @@ #ifndef POINCARE_ABSOLUTE_VALUE_LAYOUT_H #define POINCARE_ABSOLUTE_VALUE_LAYOUT_H -#include "bracket_layout.h" +#include "bracket_pair_layout.h" #include #include namespace Poincare { -class AbsoluteValueLayout : public BracketLayout { +class AbsoluteValueLayout : public BracketPairLayout { public: - using BracketLayout::BracketLayout; + using BracketPairLayout::BracketPairLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "abs"); diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp similarity index 81% rename from poincare/src/layout/bracket_layout.cpp rename to poincare/src/layout/bracket_pair_layout.cpp index 77406f539..0294cc9d1 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -1,4 +1,4 @@ -#include "bracket_layout.h" +#include "bracket_pair_layout.h" #include "horizontal_layout.h" #include #include @@ -9,12 +9,12 @@ extern "C" { namespace Poincare { -ExpressionLayout * BracketLayout::clone() const { - BracketLayout * layout = new BracketLayout(const_cast(this)->operandLayout(), true); +ExpressionLayout * BracketPairLayout::clone() const { + BracketPairLayout * layout = new BracketPairLayout(const_cast(this)->operandLayout(), true); return layout; } -void BracketLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { +void BracketPairLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the operand layout is not an HorizontalLayout, replace it with one. if (!operandLayout()->isHorizontal()) { HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); @@ -25,7 +25,7 @@ void BracketLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curso cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -void BracketLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { +void BracketPairLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { if (cursor->positionIsEquivalentTo(operandLayout(), ExpressionLayoutCursor::Position::Left)) { // Case: Left of the operand. Delete the layout, keep the operand. replaceWithAndMoveCursor(operandLayout(), true, cursor); @@ -34,7 +34,7 @@ void BracketLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BracketPairLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. // Go Left of the brackets. if (operandLayout() @@ -61,7 +61,7 @@ bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecom return false; } -bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BracketPairLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right of the operand. // Go Right of the brackets. if (operandLayout() @@ -89,7 +89,7 @@ bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldReco return false; } -int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { +int BracketPairLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; } @@ -101,7 +101,7 @@ int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOf if (numberOfChar >= bufferSize-1) { return bufferSize-1;} // Write the argument - numberOfChar += const_cast(this)->operandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + numberOfChar += const_cast(this)->operandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the closing bracket @@ -110,11 +110,11 @@ int BracketLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOf return numberOfChar; } -ExpressionLayout * BracketLayout::operandLayout() { +ExpressionLayout * BracketPairLayout::operandLayout() { return editableChild(0); } -void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void BracketPairLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); @@ -131,19 +131,19 @@ void BracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, } } -KDSize BracketLayout::computeSize() { +KDSize BracketPairLayout::computeSize() { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height() + 2 * k_verticalMargin); } -void BracketLayout::computeBaseline() { +void BracketPairLayout::computeBaseline() { m_baseline = operandLayout()->baseline() + k_verticalMargin; m_baselined = true; } -KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { +KDPoint BracketPairLayout::positionOfChild(ExpressionLayout * child) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, k_verticalMargin); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_pair_layout.h similarity index 90% rename from poincare/src/layout/bracket_layout.h rename to poincare/src/layout/bracket_pair_layout.h index e0a9cd7ac..78074ceca 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -1,12 +1,12 @@ -#ifndef POINCARE_BRACKET_LAYOUT_H -#define POINCARE_BRACKET_LAYOUT_H +#ifndef POINCARE_BRACKET_PAIR_LAYOUT_H +#define POINCARE_BRACKET_PAIR_LAYOUT_H #include #include namespace Poincare { -class BracketLayout : public StaticLayoutHierarchy<1> { +class BracketPairLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/ceiling_layout.h b/poincare/src/layout/ceiling_layout.h index 1d60673d4..0a456ed6a 100644 --- a/poincare/src/layout/ceiling_layout.h +++ b/poincare/src/layout/ceiling_layout.h @@ -1,14 +1,14 @@ #ifndef POINCARE_CEILING_LAYOUT_H #define POINCARE_CEILING_LAYOUT_H -#include "bracket_layout.h" +#include "bracket_pair_layout.h" #include namespace Poincare { -class CeilingLayout : public BracketLayout { +class CeilingLayout : public BracketPairLayout { public: - using BracketLayout::BracketLayout; + using BracketPairLayout::BracketPairLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "ceil"); diff --git a/poincare/src/layout/floor_layout.h b/poincare/src/layout/floor_layout.h index 8d8d65227..bd5300b1d 100644 --- a/poincare/src/layout/floor_layout.h +++ b/poincare/src/layout/floor_layout.h @@ -1,14 +1,14 @@ #ifndef POINCARE_FLOOR_LAYOUT_H #define POINCARE_FLOOR_LAYOUT_H -#include "bracket_layout.h" +#include "bracket_pair_layout.h" #include namespace Poincare { -class FloorLayout : public BracketLayout { +class FloorLayout : public BracketPairLayout { public: - using BracketLayout::BracketLayout; + using BracketPairLayout::BracketPairLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "floor"); From a17fd523bbe33b0b97396093e57d91a192b020a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:02:47 +0200 Subject: [PATCH 314/459] [poincare] Do not use bracket left and right. Change-Id: Ieb7585b312850e414de5d1ae90b45d2f616b6248 --- poincare/src/layout/bracket_left_layout.h | 1 - poincare/src/layout/bracket_pair_layout.h | 1 + poincare/src/layout/bracket_right_layout.h | 1 - poincare/src/layout/matrix_layout.cpp | 27 +++++++--------------- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/bracket_left_layout.h index 9db160521..9325d48fa 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/bracket_left_layout.h @@ -7,7 +7,6 @@ namespace Poincare { class BracketLeftLayout : public BracketLeftRightLayout { - friend class MatrixLayout; public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index 78074ceca..33e9523f3 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -7,6 +7,7 @@ namespace Poincare { class BracketPairLayout : public StaticLayoutHierarchy<1> { + friend class MatrixLayout; public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/bracket_right_layout.h index 1b303c0d2..239dc268f 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/bracket_right_layout.h @@ -7,7 +7,6 @@ namespace Poincare { class BracketRightLayout : public BracketLeftRightLayout { - friend class MatrixLayout; public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 35be32544..11179818c 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -1,8 +1,6 @@ #include "matrix_layout.h" #include "empty_layout.h" -#include "horizontal_layout.h" -#include "bracket_left_layout.h" -#include "bracket_right_layout.h" +#include "bracket_pair_layout.h" #include #include extern "C" { @@ -248,30 +246,21 @@ void MatrixLayout::childWasReplacedAtIndex(int index) { } void MatrixLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); - BracketRightLayout * dummyRightBracket = new BracketRightLayout(); - ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); - HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); - KDPoint leftBracketPoint = dummyLayout.positionOfChild(dummyLeftBracket); - KDPoint rightBracketPoint = dummyLayout.positionOfChild(dummyRightBracket); - dummyLeftBracket->render(ctx, p.translatedBy(leftBracketPoint), expressionColor, backgroundColor); - dummyRightBracket->render(ctx, p.translatedBy(rightBracketPoint), expressionColor, backgroundColor); + const ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + BracketPairLayout dummyLayout(dummyGridLayout, false); + dummyLayout.render(ctx, p, expressionColor, backgroundColor); } KDSize MatrixLayout::computeSize() { - BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); - BracketRightLayout * dummyRightBracket = new BracketRightLayout(); -ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); - HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); + const ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + BracketPairLayout dummyLayout(dummyGridLayout, false); return dummyLayout.size(); } KDPoint MatrixLayout::positionOfChild(ExpressionLayout * child) { assert(indexOfChild(child) > -1); - BracketLeftLayout * dummyLeftBracket = new BracketLeftLayout(); - BracketRightLayout * dummyRightBracket = new BracketRightLayout(); -ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); - HorizontalLayout dummyLayout(dummyLeftBracket, dummyGridLayout, dummyRightBracket, false); + ExpressionLayout * dummyGridLayout = new GridLayout(children(), m_numberOfRows, m_numberOfColumns, true); + BracketPairLayout dummyLayout(dummyGridLayout, false); return GridLayout::positionOfChild(child).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); } From a2f2a64bbdb9901975572510cb1e3826beb39562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:06:43 +0200 Subject: [PATCH 315/459] [poincare] Remove use of BracketLeft/RightLayouts. Saves the binary 2K. Change-Id: I09ffa22aaffd32eb58f00437512b0da2fab6bb6a --- poincare/src/expression_layout_cursor.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 54ba3457a..e208535e9 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -177,11 +177,18 @@ void ExpressionLayoutCursor::insertText(const char * text) { } } else if (text[i] == ')') { newChild = new RightParenthesisLayout(); - } else if (text[i] == '[') { + } + + /* We never insert text with brackets for now. Removing this code saves the + * binary file 2K. */ +#if 0 + else if (text[i] == '[') { newChild = new BracketLeftLayout(); } else if (text[i] == ']') { newChild = new BracketRightLayout(); - } else { + } +#endif + else { newChild = new CharLayout(text[i]); } m_pointedExpressionLayout->addSibling(this, newChild); From 72f6946b14220a5287b7ffa48c19237141ccfb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:13:32 +0200 Subject: [PATCH 316/459] [poincare] Rename BracketRight/LeftLayout -> Right/LeftBracketLayout. Change-Id: I382ac960aeca861d1003cd2373709a6759ded685 --- poincare/Makefile | 4 ++-- poincare/include/poincare_layouts.h | 4 ++-- poincare/src/expression_layout_cursor.cpp | 4 ++-- ...acket_left_layout.cpp => left_bracket_layout.cpp} | 12 ++++++------ .../{bracket_left_layout.h => left_bracket_layout.h} | 2 +- ...ket_right_layout.cpp => right_bracket_layout.cpp} | 12 ++++++------ ...bracket_right_layout.h => right_bracket_layout.h} | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) rename poincare/src/layout/{bracket_left_layout.cpp => left_bracket_layout.cpp} (86%) rename poincare/src/layout/{bracket_left_layout.h => left_bracket_layout.h} (93%) rename poincare/src/layout/{bracket_right_layout.cpp => right_bracket_layout.cpp} (85%) rename poincare/src/layout/{bracket_right_layout.h => right_bracket_layout.h} (93%) diff --git a/poincare/Makefile b/poincare/Makefile index 0aa804a7e..bb5d2acd4 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -92,9 +92,9 @@ objs += $(addprefix poincare/src/layout/,\ binomial_coefficient_layout.o\ bounded_static_layout_hierarchy.o\ bracket_pair_layout.o\ - bracket_left_layout.o\ + left_bracket_layout.o\ bracket_left_right_layout.o\ - bracket_right_layout.o\ + right_bracket_layout.o\ ceiling_layout.o\ char_layout.o\ condensed_sum_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 2342016ac..5f2dc7096 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -5,8 +5,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index e208535e9..e5a1711c7 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -183,9 +183,9 @@ void ExpressionLayoutCursor::insertText(const char * text) { * binary file 2K. */ #if 0 else if (text[i] == '[') { - newChild = new BracketLeftLayout(); + newChild = new LeftBracketLayout(); } else if (text[i] == ']') { - newChild = new BracketRightLayout(); + newChild = new RightBracketLayout(); } #endif else { diff --git a/poincare/src/layout/bracket_left_layout.cpp b/poincare/src/layout/left_bracket_layout.cpp similarity index 86% rename from poincare/src/layout/bracket_left_layout.cpp rename to poincare/src/layout/left_bracket_layout.cpp index c2028ee66..27e99e0ff 100644 --- a/poincare/src/layout/bracket_left_layout.cpp +++ b/poincare/src/layout/left_bracket_layout.cpp @@ -1,4 +1,4 @@ -#include "bracket_left_layout.h" +#include "left_bracket_layout.h" #include extern "C" { #include @@ -6,18 +6,18 @@ extern "C" { namespace Poincare { -ExpressionLayout * BracketLeftLayout::clone() const { - BracketLeftLayout * layout = new BracketLeftLayout(); +ExpressionLayout * LeftBracketLayout::clone() const { + LeftBracketLayout * layout = new LeftBracketLayout(); return layout; } -void BracketLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void LeftBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -void BracketLeftLayout::computeOperandHeight() { +void LeftBracketLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; @@ -39,7 +39,7 @@ void BracketLeftLayout::computeOperandHeight() { } } -void BracketLeftLayout::computeBaseline() { +void LeftBracketLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; int currentNumberOfOpenBrackets = 1; diff --git a/poincare/src/layout/bracket_left_layout.h b/poincare/src/layout/left_bracket_layout.h similarity index 93% rename from poincare/src/layout/bracket_left_layout.h rename to poincare/src/layout/left_bracket_layout.h index 9325d48fa..0b5d94cd4 100644 --- a/poincare/src/layout/bracket_left_layout.h +++ b/poincare/src/layout/left_bracket_layout.h @@ -6,7 +6,7 @@ namespace Poincare { -class BracketLeftLayout : public BracketLeftRightLayout { +class LeftBracketLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/bracket_right_layout.cpp b/poincare/src/layout/right_bracket_layout.cpp similarity index 85% rename from poincare/src/layout/bracket_right_layout.cpp rename to poincare/src/layout/right_bracket_layout.cpp index cfeea9e03..f3743b1d8 100644 --- a/poincare/src/layout/bracket_right_layout.cpp +++ b/poincare/src/layout/right_bracket_layout.cpp @@ -1,4 +1,4 @@ -#include "bracket_right_layout.h" +#include "right_bracket_layout.h" #include extern "C" { #include @@ -6,18 +6,18 @@ extern "C" { namespace Poincare { -ExpressionLayout * BracketRightLayout::clone() const { - BracketRightLayout * layout = new BracketRightLayout(); +ExpressionLayout * RightBracketLayout::clone() const { + RightBracketLayout * layout = new RightBracketLayout(); return layout; } -void BracketRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void RightBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -void BracketRightLayout::computeOperandHeight() { +void RightBracketLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; @@ -38,7 +38,7 @@ void BracketRightLayout::computeOperandHeight() { } } -void BracketRightLayout::computeBaseline() { +void RightBracketLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; int currentNumberOfOpenBrackets = 1; diff --git a/poincare/src/layout/bracket_right_layout.h b/poincare/src/layout/right_bracket_layout.h similarity index 93% rename from poincare/src/layout/bracket_right_layout.h rename to poincare/src/layout/right_bracket_layout.h index 239dc268f..c2bfede34 100644 --- a/poincare/src/layout/bracket_right_layout.h +++ b/poincare/src/layout/right_bracket_layout.h @@ -6,7 +6,7 @@ namespace Poincare { -class BracketRightLayout : public BracketLeftRightLayout { +class RightBracketLayout : public BracketLeftRightLayout { public: using BracketLeftRightLayout::BracketLeftRightLayout; ExpressionLayout * clone() const override; From 054e2c078579a39f81d3f770452fe2fa3fbfaa2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:20:52 +0200 Subject: [PATCH 317/459] [poincare] Rename BracketLeftRightLayout -> BracketLayout Change-Id: If5e7b36a4d0a1d26b2793506f1ffb2eb146bf14f --- poincare/Makefile | 2 +- ..._left_right_layout.cpp => bracket_layout.cpp} | 16 ++++++++-------- ...cket_left_right_layout.h => bracket_layout.h} | 8 ++++---- poincare/src/layout/left_bracket_layout.h | 6 +++--- poincare/src/layout/right_bracket_layout.h | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) rename poincare/src/layout/{bracket_left_right_layout.cpp => bracket_layout.cpp} (73%) rename poincare/src/layout/{bracket_left_right_layout.h => bracket_layout.h} (80%) diff --git a/poincare/Makefile b/poincare/Makefile index bb5d2acd4..193bb6154 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -93,7 +93,7 @@ objs += $(addprefix poincare/src/layout/,\ bounded_static_layout_hierarchy.o\ bracket_pair_layout.o\ left_bracket_layout.o\ - bracket_left_right_layout.o\ + bracket_layout.o\ right_bracket_layout.o\ ceiling_layout.o\ char_layout.o\ diff --git a/poincare/src/layout/bracket_left_right_layout.cpp b/poincare/src/layout/bracket_layout.cpp similarity index 73% rename from poincare/src/layout/bracket_left_right_layout.cpp rename to poincare/src/layout/bracket_layout.cpp index 540a4ce89..f00ac99f8 100644 --- a/poincare/src/layout/bracket_left_right_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -1,4 +1,4 @@ -#include "bracket_left_right_layout.h" +#include "bracket_layout.h" #include extern "C" { #include @@ -7,18 +7,18 @@ extern "C" { namespace Poincare { -BracketLeftRightLayout::BracketLeftRightLayout() : +BracketLayout::BracketLayout() : StaticLayoutHierarchy<0>(), m_operandHeightComputed(false) { } -void BracketLeftRightLayout::invalidAllSizesPositionsAndBaselines() { +void BracketLayout::invalidAllSizesPositionsAndBaselines() { m_operandHeightComputed = false; ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. // Go Left. @@ -35,7 +35,7 @@ bool BracketLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * sh return false; } -bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. // Go Right. @@ -53,11 +53,11 @@ bool BracketLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor, bool * s } -KDSize BracketLeftRightLayout::computeSize() { +KDSize BracketLayout::computeSize() { return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); } -KDCoordinate BracketLeftRightLayout::operandHeight() { +KDCoordinate BracketLayout::operandHeight() { if (!m_operandHeightComputed) { computeOperandHeight(); m_operandHeightComputed = true; @@ -65,7 +65,7 @@ KDCoordinate BracketLeftRightLayout::operandHeight() { return m_operandHeight; } -KDPoint BracketLeftRightLayout::positionOfChild(ExpressionLayout * child) { +KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; } diff --git a/poincare/src/layout/bracket_left_right_layout.h b/poincare/src/layout/bracket_layout.h similarity index 80% rename from poincare/src/layout/bracket_left_right_layout.h rename to poincare/src/layout/bracket_layout.h index 9791e18c4..e37e6e8cd 100644 --- a/poincare/src/layout/bracket_left_right_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -1,13 +1,13 @@ -#ifndef POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H -#define POINCARE_BRACKET_LEFT_RIGHT_LAYOUT_H +#ifndef POINCARE_BRACKET_LAYOUT_H +#define POINCARE_BRACKET_LAYOUT_H #include namespace Poincare { -class BracketLeftRightLayout : public StaticLayoutHierarchy<0> { +class BracketLayout : public StaticLayoutHierarchy<0> { public: - BracketLeftRightLayout(); + BracketLayout(); void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/left_bracket_layout.h b/poincare/src/layout/left_bracket_layout.h index 0b5d94cd4..12cf64409 100644 --- a/poincare/src/layout/left_bracket_layout.h +++ b/poincare/src/layout/left_bracket_layout.h @@ -1,14 +1,14 @@ #ifndef POINCARE_BRACKET_LEFT_LAYOUT_H #define POINCARE_BRACKET_LEFT_LAYOUT_H -#include +#include #include namespace Poincare { -class LeftBracketLayout : public BracketLeftRightLayout { +class LeftBracketLayout : public BracketLayout { public: - using BracketLeftRightLayout::BracketLeftRightLayout; + using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '['); diff --git a/poincare/src/layout/right_bracket_layout.h b/poincare/src/layout/right_bracket_layout.h index c2bfede34..011c67cf8 100644 --- a/poincare/src/layout/right_bracket_layout.h +++ b/poincare/src/layout/right_bracket_layout.h @@ -1,14 +1,14 @@ #ifndef POINCARE_BRACKET_RIGHT_LAYOUT_H #define POINCARE_BRACKET_RIGHT_LAYOUT_H -#include +#include #include namespace Poincare { -class RightBracketLayout : public BracketLeftRightLayout { +class RightBracketLayout : public BracketLayout { public: - using BracketLeftRightLayout::BracketLeftRightLayout; + using BracketLayout::BracketLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ']'); From 7e9fba10321d833ea05b43027d3afa4466d16aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:31:02 +0200 Subject: [PATCH 318/459] [escher] Fix markRectAsDirty call. Change-Id: I50b3e7ce9bbeed2ab8b1c76857914d798d3f05b5 --- escher/src/modal_view_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index 1f7aaed18..75b402734 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -96,7 +96,7 @@ bool ModalViewController::ContentView::isDisplayingModal() const { } void ModalViewController::ContentView::reload() { - markRectAsDirty(frame()); + markRectAsDirty(bounds()); layoutSubviews(); } From b90dea7cee39820fe16a869823fc2243b9364bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:31:35 +0200 Subject: [PATCH 319/459] [escher] Rename frame() method in ModalViewController. Change-Id: I157b3fb20af5cb3013d53bef51ba98d192654409 --- escher/include/escher/modal_view_controller.h | 2 +- escher/src/modal_view_controller.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/escher/include/escher/modal_view_controller.h b/escher/include/escher/modal_view_controller.h index 3a326a12d..83e4b3001 100644 --- a/escher/include/escher/modal_view_controller.h +++ b/escher/include/escher/modal_view_controller.h @@ -33,7 +33,7 @@ private: bool isDisplayingModal() const; void reload(); private: - KDRect frame() const; + KDRect modalViewFrame() const; View * m_regularView; View * m_currentModalView; bool m_isDisplayingModal; diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index 75b402734..00c3564c8 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -24,7 +24,7 @@ void ModalViewController::ContentView::setMainView(View * regularView) { int ModalViewController::ContentView::numberOfSubviews() const { KDRect regularFrame = bounds(); - KDRect modalFrame = frame(); + KDRect modalFrame = modalViewFrame(); bool shouldDrawTheRegularViewBehind = !modalFrame.contains(regularFrame.topLeft()) || !modalFrame.contains(regularFrame.bottomRight()); return 1 + (m_isDisplayingModal && shouldDrawTheRegularViewBehind); } @@ -49,7 +49,7 @@ View * ModalViewController::ContentView::subviewAtIndex(int index) { } } -KDRect ModalViewController::ContentView::frame() const { +KDRect ModalViewController::ContentView::modalViewFrame() const { KDSize modalSize = m_isDisplayingModal ? m_currentModalView->minimalSizeForOptimalDisplay() : KDSize(0,0); KDCoordinate modalHeight = modalSize.height(); modalHeight = modalHeight == 0 ? bounds().height()-m_topMargin-m_bottomMargin : modalHeight; @@ -65,7 +65,7 @@ void ModalViewController::ContentView::layoutSubviews() { m_regularView->setFrame(bounds()); if (m_isDisplayingModal) { assert(m_currentModalView != nullptr); - m_currentModalView->setFrame(frame()); + m_currentModalView->setFrame(modalViewFrame()); } } @@ -79,13 +79,13 @@ void ModalViewController::ContentView::presentModalView(View * modalView, float m_leftMargin = leftMargin; m_bottomMargin = bottomMargin; m_rightMargin = rightMargin; - markRectAsDirty(frame()); + markRectAsDirty(modalViewFrame()); layoutSubviews(); } void ModalViewController::ContentView::dismissModalView() { m_isDisplayingModal = false; - markRectAsDirty(frame()); + markRectAsDirty(modalViewFrame()); m_currentModalView->resetSuperview(); m_currentModalView = nullptr; layoutSubviews(); From 56b2b505cd2067963775b0b2a7ec68fdbfe5ea36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:42:03 +0200 Subject: [PATCH 320/459] [escher] Avoid using floats to compute ints. Change-Id: I5637194badc75eec6f016f44bb9660b51d2157b9 --- escher/src/expression_view.cpp | 2 +- escher/src/stack_view.cpp | 2 +- escher/src/tab_view_cell.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index dfd23e3b3..a760f635a 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -49,7 +49,7 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const { KDPoint ExpressionView::drawingOrigin() const { KDSize expressionSize = m_expressionLayout->size(); - return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), 0.5f*(m_frame.height() - expressionSize.height())); + return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), (m_frame.height() - expressionSize.height())/2); } KDPoint ExpressionView::absoluteDrawingOrigin() const { diff --git a/escher/src/stack_view.cpp b/escher/src/stack_view.cpp index 5f125bea5..bd667671d 100644 --- a/escher/src/stack_view.cpp +++ b/escher/src/stack_view.cpp @@ -37,7 +37,7 @@ void StackView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(KDRect(0, height-1, width, 1), m_separatorColor); // Write title KDSize textSize = KDText::stringSize(m_controller->title(), KDText::FontSize::Small); - KDPoint origin(0.5f*(m_frame.width() - textSize.width()),0.5f*(m_frame.height() - textSize.height())); + KDPoint origin((m_frame.width() - textSize.width())/2,(m_frame.height() - textSize.height())/2); ctx->drawString(m_controller->title(), origin, KDText::FontSize::Small, m_textColor, m_backgroundColor); } diff --git a/escher/src/tab_view_cell.cpp b/escher/src/tab_view_cell.cpp index 7bea92c38..43be0c1c8 100644 --- a/escher/src/tab_view_cell.cpp +++ b/escher/src/tab_view_cell.cpp @@ -48,7 +48,7 @@ void TabViewCell::drawRect(KDContext * ctx, KDRect rect) const { } // Write title KDSize textSize = KDText::stringSize(m_controller->title(), KDText::FontSize::Small); - KDPoint origin(0.5f*(m_frame.width() - textSize.width()),0.5f*(m_frame.height() - textSize.height())); + KDPoint origin((m_frame.width() - textSize.width())/2, (m_frame.height() - textSize.height())/2); ctx->drawString(m_controller->title(), origin, KDText::FontSize::Small, text, background); } From 3e5b3457c1e76e1fe648a3a4ad63cf922f6df078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 16:45:50 +0200 Subject: [PATCH 321/459] [apps/coding style] Better code nesting. Change-Id: I26485d4b9917f67b3a73e73721b4f6f2f49c4aa1 --- apps/calculation/app.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index a9b82ee29..fba7dac4d 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -92,25 +92,26 @@ bool App::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressi /* Here, we check that the expression entered by the user can be printed with * less than k_printedExpressionLength characters. Otherwise, we prevent the * user from adding this expression to the calculation store. */ - if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event)) { - int bufferLength = TextField::maxBufferSize(); - char bufferForParsing[bufferLength]; - Poincare::ExpressionLayout * expressionLayout = scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout(); - expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); - Expression * exp = Expression::parse(bufferForParsing); - if (exp == nullptr) { - scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); - return true; - } - char buffer[Calculation::k_printedExpressionSize]; - int length = exp->writeTextInBuffer(buffer, sizeof(buffer)); - delete exp; - /* if the buffer is totally full, it is VERY likely that writeTextInBuffer - * escaped before printing utterly the expression. */ - if (length >= Calculation::k_printedExpressionSize-1) { - displayWarning(I18n::Message::SyntaxError); - return true; - } + if (!(scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event))) { + return false; + } + int bufferLength = TextField::maxBufferSize(); + char bufferForParsing[bufferLength]; + Poincare::ExpressionLayout * expressionLayout = scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout(); + expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); + Expression * exp = Expression::parse(bufferForParsing); + if (exp == nullptr) { + scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); + return true; + } + char buffer[Calculation::k_printedExpressionSize]; + int length = exp->writeTextInBuffer(buffer, sizeof(buffer)); + delete exp; + /* If the buffer is totally full, it is VERY likely that writeTextInBuffer + * escaped before printing utterly the expression. */ + if (length >= Calculation::k_printedExpressionSize-1) { + displayWarning(I18n::Message::SyntaxError); + return true; } return false; } From e4f3679add3b79a10ac2889e106cf59914881190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 17:23:47 +0200 Subject: [PATCH 322/459] [poincare] Fix binomial coefficient layout navigation typo Change-Id: I1bd397c4989001ba5d0cfb6eff16ac3d6c153b36 --- poincare/src/layout/binomial_coefficient_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index e10b32a7a..52832d876 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -91,7 +91,7 @@ bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * if (previousLayout == nLayout()) { return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); } void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { From 09db58d24c1ed041620c672c1fd33c3d0a473a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 17:56:43 +0200 Subject: [PATCH 323/459] [poincare] Remove some parameters in ExpressionLayout::moveUp/Down Change-Id: I406c02229aace0ec7417e5194d448023273fb3d0 --- poincare/include/poincare/expression_layout.h | 12 +--- .../layout/binomial_coefficient_layout.cpp | 12 ++-- .../src/layout/binomial_coefficient_layout.h | 4 +- poincare/src/layout/condensed_sum_layout.cpp | 16 ++--- poincare/src/layout/condensed_sum_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 8 +-- poincare/src/layout/fraction_layout.cpp | 12 ++-- poincare/src/layout/fraction_layout.h | 4 +- poincare/src/layout/grid_layout.cpp | 28 ++++---- poincare/src/layout/grid_layout.h | 4 +- poincare/src/layout/horizontal_layout.cpp | 67 ------------------- poincare/src/layout/horizontal_layout.h | 4 -- poincare/src/layout/integral_layout.cpp | 16 ++--- poincare/src/layout/integral_layout.h | 4 +- poincare/src/layout/matrix_layout.cpp | 28 ++++---- poincare/src/layout/matrix_layout.h | 4 +- poincare/src/layout/nth_root_layout.cpp | 12 ++-- poincare/src/layout/nth_root_layout.h | 4 +- poincare/src/layout/sequence_layout.cpp | 13 ++-- poincare/src/layout/sequence_layout.h | 4 +- .../src/layout/vertical_offset_layout.cpp | 8 +-- poincare/src/layout/vertical_offset_layout.h | 4 +- 22 files changed, 101 insertions(+), 171 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 793bb763f..3337adca1 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -82,16 +82,8 @@ public: /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual bool moveUp( - ExpressionLayoutCursor * cursor, - bool * shouldRecomputeLayout = nullptr, - ExpressionLayout * previousLayout = nullptr, - ExpressionLayout * previousPreviousLayout = nullptr); - virtual bool moveDown( - ExpressionLayoutCursor * cursor, - bool * shouldRecomputeLayout = nullptr, - ExpressionLayout * previousLayout = nullptr, - ExpressionLayout * previousPreviousLayout = nullptr); + virtual bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index 52832d876..edc58b377 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -76,22 +76,22 @@ bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor, bool return false; } -bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: kLayout. // Move to nLayout. - if (previousLayout == kLayout()) { + if (cursor->pointedExpressionLayout()->hasAncestor(kLayout())) { return nLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: nLayout. // Move to kLayout. - if (previousLayout == nLayout()) { + if (cursor->pointedExpressionLayout()->hasAncestor(nLayout())) { return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 5ba22a114..0cb91941d 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -13,8 +13,8 @@ public: ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 32e7dbb30..ac957bb85 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -90,38 +90,38 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul return false; } -bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the subscript layout, move it to the superscript. - if (subscriptLayout() && previousLayout == subscriptLayout()) { + if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout())) { assert(superscriptLayout() != nullptr); return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the superscript. if (baseLayout() - && previousLayout == baseLayout() + && cursor->pointedExpressionLayout()->hasAncestor(baseLayout()) && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(superscriptLayout() != nullptr); return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the superscript layout, move it to the subscript. - if (superscriptLayout() && previousLayout == superscriptLayout()) { + if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout())) { assert(subscriptLayout() != nullptr); return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the subscript. if (baseLayout() - && previousLayout == baseLayout() + && cursor->pointedExpressionLayout()->hasAncestor(baseLayout()) && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(subscriptLayout() != nullptr); return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index ec506a839..eafff7785 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -12,8 +12,8 @@ public: ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 68958ea1d..2fa2161ab 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -235,9 +235,9 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { if (m_parent) { - return m_parent->moveUp(cursor, shouldRecomputeLayout, this, previousLayout); + return m_parent->moveUp(cursor, shouldRecomputeLayout); } return false; } @@ -246,9 +246,9 @@ bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shou return moveInside(VerticalDirection::Up, cursor, shouldRecomputeLayout); } -bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { if (m_parent) { - return m_parent->moveDown(cursor, shouldRecomputeLayout, this, previousLayout); + return m_parent->moveDown(cursor, shouldRecomputeLayout); } return false; } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index bfdb99688..b78f2eb09 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -143,9 +143,9 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside denominator, move it to the numerator. - if (denominatorLayout() && previousLayout == denominatorLayout()) { + if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout())) { assert(numeratorLayout() != nullptr); return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } @@ -154,12 +154,12 @@ bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp assert(numeratorLayout() != nullptr); return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside numerator, move it to the denominator. - if (numeratorLayout() && previousLayout == numeratorLayout()) { + if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout())) { assert(denominatorLayout() != nullptr); return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } @@ -168,7 +168,7 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco assert(denominatorLayout() != nullptr); return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 4f40a9642..e1088a9b0 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -14,8 +14,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 0c75fed4d..9987c65e3 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -94,24 +94,28 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecompu return false; } -bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is child that is not on the top row, move it inside the upper // neighbourg. - int childIndex = indexOfChild(previousLayout); - if (childIndex >- 1 && !childIsTopOfGrid(childIndex)) { - return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor, shouldRecomputeLayout); + int childIndex = m_numberOfColumns; + while (childIndex < numberOfChildren()) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor, shouldRecomputeLayout); + } + childIndex++; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - // If the cursor is child that is not on the bottom row, move it inside the - // lower neighbourg. - int childIndex = indexOfChild(previousLayout); - if (childIndex >- 1 && !childIsBottomOfGrid(childIndex)) { - return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor, shouldRecomputeLayout); +bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + int childIndex = 0; + while (childIndex < numberOfChildren() - m_numberOfColumns) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor, shouldRecomputeLayout); + } + childIndex++; } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 15cf34725..8e883d92c 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -15,8 +15,8 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 79b7286dc..5d3adda7f 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -261,14 +261,6 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR return editableChild(childIndex+1)->moveRight(cursor, shouldRecomputeLayout); } -bool HorizontalLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - return moveVertically(ExpressionLayout::VerticalDirection::Up, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); -} - -bool HorizontalLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - return moveVertically(ExpressionLayout::VerticalDirection::Down, cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); -} - void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { int newIndex = removeEmptyChildBeforeInsertionAtIndex(indexForInsertion, !operands[0]->mustHaveLeftSibling()); DynamicLayoutHierarchy::addChildrenAtIndex(operands, numberOfOperands, newIndex, removeEmptyChildren); @@ -393,65 +385,6 @@ void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres } } -bool HorizontalLayout::moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - // Prevent looping fom child to parent - if (previousPreviousLayout == this) { - if (direction == ExpressionLayout::VerticalDirection::Up) { - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); - } - assert(direction == ExpressionLayout::VerticalDirection::Down); - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); - } - // If the cursor Left or Right of a child, try moving it up from its sibling. - int previousLayoutIndex = indexOfChild(previousLayout); - if (previousLayoutIndex > -1) { - ExpressionLayout * sibling = nullptr; - ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Right; - if (cursor->position() == ExpressionLayoutCursor::Position::Left && previousLayoutIndex > 0) { - sibling = editableChild(previousLayoutIndex - 1); - newPosition = ExpressionLayoutCursor::Position::Right; - } - if (cursor->position() == ExpressionLayoutCursor::Position::Right && previousLayoutIndex < numberOfChildren() - 1) { - sibling = editableChild(previousLayoutIndex + 1); - newPosition = ExpressionLayoutCursor::Position::Left; - } - if (sibling && cursor->positionIsEquivalentTo(sibling, newPosition)) { - if (tryMoveVerticallyFromAnotherLayout(sibling, newPosition, direction, cursor, shouldRecomputeLayout, previousLayout)) { - return true; - } - } - } - /* If the cursor is Left or Right of the HorizontalLayout, try moving it up - * from its extremal child. */ - if (cursor->pointedExpressionLayout() == this && previousLayout == nullptr && numberOfChildren() > 0) { - int indexOfChildToCheck = cursor->position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1; - if (tryMoveVerticallyFromAnotherLayout(editableChild(indexOfChildToCheck), cursor->position(), direction, cursor, shouldRecomputeLayout, previousLayout)) { - return true; - } - } - if (direction == ExpressionLayout::VerticalDirection::Up) { - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); - } - assert(direction == ExpressionLayout::VerticalDirection::Down); - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); -} - -bool HorizontalLayout::tryMoveVerticallyFromAnotherLayout(ExpressionLayout * otherLayout, ExpressionLayoutCursor::Position otherPosition, ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout) { - ExpressionLayout * previousPointedLayout = cursor->pointedExpressionLayout(); - ExpressionLayoutCursor::Position previousPosition = cursor->position(); - cursor->setPointedExpressionLayout(otherLayout); - cursor->setPosition(otherPosition); - if (direction == ExpressionLayout::VerticalDirection::Up && otherLayout->moveUp(cursor, shouldRecomputeLayout, this, previousLayout)) { - return true; - } - if (direction == ExpressionLayout::VerticalDirection::Down && otherLayout->moveDown(cursor, shouldRecomputeLayout, this, previousLayout)) { - return true; - } - cursor->setPointedExpressionLayout(previousPointedLayout); - cursor->setPosition(previousPosition); - return false; -} - void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { /* If the child to remove is at index 0 and its right sibling must have a left * sibling (e.g. it is a VerticalOffsetLayout), replace the child with an diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index c011f862c..c8a673bfa 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -25,8 +25,6 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; /* Dynamic layout */ void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) override; @@ -48,8 +46,6 @@ protected: KDPoint positionOfChild(ExpressionLayout * child) override; void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; private: - bool moveVertically(ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout); - bool tryMoveVerticallyFromAnotherLayout(ExpressionLayout * otherLayout, ExpressionLayoutCursor::Position otherPosition, ExpressionLayout::VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout); void privateReplaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor); void privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove); int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 61020915c..dcbf24328 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -117,38 +117,38 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { + if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout())) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() - && previousLayout == integrandLayout() + && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout()) && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && previousLayout == upperBoundLayout()) { + if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout())) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() - && previousLayout == integrandLayout() + && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout()) && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 9b6d93137..e8f377f3b 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -19,8 +19,8 @@ public: /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 11179818c..8803b150d 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -80,14 +80,16 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom return GridLayout::moveRight(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool shouldRemoveGreySquares = false; - int childIndex = indexOfChild(previousLayout); - if (childIndex >- 1 && childIsTopOfGrid(childIndex)) { - // The cursor is leaving the matrix, so remove the grey squares. - shouldRemoveGreySquares = true; + for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + // The cursor is leaving the matrix, so remove the grey squares. + shouldRemoveGreySquares = true; + break; + } } - bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout); if (returnValue && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); @@ -96,14 +98,16 @@ bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomput return returnValue; } -bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool shouldRemoveGreySquares = false; - int childIndex = indexOfChild(previousLayout); - if (childIndex >- 1 && childIsBottomOfGrid(childIndex)) { - // The cursor is leaving the matrix, so remove the grey squares. - shouldRemoveGreySquares = true; + for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + // The cursor is leaving the matrix, so remove the grey squares. + shouldRemoveGreySquares = true; + break; + } } - bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout); if (returnValue && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index f18cba8aa..b4789595e 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -13,8 +13,8 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout = nullptr, ExpressionLayout * previousLayout = nullptr, ExpressionLayout * previousPreviousLayout = nullptr) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index a50bc9742..887be5af3 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -133,11 +133,11 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldReco return false; } -bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() - && previousLayout == radicandLayout() + && cursor->pointedExpressionLayout()->hasAncestor(radicandLayout()) && cursor->positionIsEquivalentTo(radicandLayout(), ExpressionLayoutCursor::Position::Left)) { cursor->setPointedExpressionLayout(indexLayout()); @@ -153,11 +153,11 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { - if (indexLayout() && previousLayout == indexLayout()) { +bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout())) { // If the cursor is Right of the index, move it to the radicand. if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { assert(radicandLayout() != nullptr); @@ -172,7 +172,7 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecom return true; } } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } static_assert('\x90' == Ion::Charset::Root, "Unicode error"); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index a6597a1e5..28e2d4956 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -20,8 +20,8 @@ public: /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 58afc000d..adfb1690d 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -98,9 +98,9 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && previousLayout == lowerBoundLayout()) { + if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout())) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } @@ -111,11 +111,12 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { + +bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && previousLayout == upperBoundLayout()) { + if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout())) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } @@ -126,7 +127,7 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 1949372f2..7c4343b9c 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -13,8 +13,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; ExpressionLayout * layoutToPointWhenInserting() override; char XNTChar() const override; protected: diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index c246a5566..71c3e7afb 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -120,7 +120,7 @@ bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor, bool * sho return false; } -bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Superscript. if (m_type == VerticalOffsetLayout::Type::Superscript) { // Case: Right. @@ -151,10 +151,10 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * should cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); } -bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) { +bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Subscript. if (m_type == VerticalOffsetLayout::Type::Subscript) { // Case: Right. @@ -184,7 +184,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shou cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, previousLayout, previousPreviousLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); } int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index ed80b0418..d2aaaca8e 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -17,8 +17,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, ExpressionLayout * previousLayout, ExpressionLayout * previousPreviousLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const { return true; } From d6c39eafc002a3d5aa9bb2cc6468bd4dda771c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Apr 2018 18:09:55 +0200 Subject: [PATCH 324/459] [poincare] Change ExpressionLayout and ELCursor headers inclusion Change-Id: I6d3b7818d3acd4dbfb74665ba678871c865863cf --- poincare/include/poincare/expression_layout.h | 4 ++-- poincare/include/poincare/expression_layout_cursor.h | 3 ++- poincare/src/expression_layout_cursor.cpp | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 3337adca1..a04c627c8 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -3,11 +3,11 @@ #include #include +#include + namespace Poincare { -class ExpressionLayoutCursor; - class ExpressionLayout { public: enum class VerticalDirection { diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 5bdc266c6..e0473c915 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -1,11 +1,12 @@ #ifndef POINCARE_EXPRESSION_LAYOUT_CURSOR_H #define POINCARE_EXPRESSION_LAYOUT_CURSOR_H -#include #include namespace Poincare { +class ExpressionLayout; + class ExpressionLayoutCursor { public: enum class Position { diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index e5a1711c7..102f63e58 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -1,4 +1,5 @@ #include +#include #include #include //TODO: finer include? #include From 3d7615b3e111f2f2f4593a76e6b436c0c14db276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:17:29 +0200 Subject: [PATCH 325/459] [poincare] Add includeSelf parameter to hasAncestor in ExprLayout Change-Id: I41356d16c13375aa077656a2d377a9c70732cac7 --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index a04c627c8..42b9513fc 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -45,7 +45,7 @@ public: void setParent(ExpressionLayout * parent) { m_parent = parent; } const ExpressionLayout * parent() const { return m_parent; } ExpressionLayout * editableParent() { return m_parent; } - bool hasAncestor(const ExpressionLayout * e) const; + bool hasAncestor(const ExpressionLayout * e, bool includeSelf = false) const; /* Dynamic Layout */ diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 2fa2161ab..2672f233d 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -94,8 +94,10 @@ int ExpressionLayout::indexOfChild(const ExpressionLayout * child) const { return -1; } -bool ExpressionLayout::hasAncestor(const ExpressionLayout * e) const { - assert(m_parent != this); +bool ExpressionLayout::hasAncestor(const ExpressionLayout * e, bool includeSelf) const { + if (includeSelf && e == this) { + return true; + } if (m_parent == e) { return true; } From 08f3c834c6a16b73ae19c0b9d996141d545df2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:18:19 +0200 Subject: [PATCH 326/459] [poincare] Remove un-needed assert. Change-Id: I2eb568d440f2e4f484d0ff358a55f4ba782c263b --- poincare/src/expression.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 77dfb9b14..61ba5af80 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -146,7 +146,6 @@ void Expression::swapOperands(int i, int j) { } bool Expression::hasAncestor(const Expression * e) const { - assert(m_parent != this); if (m_parent == e) { return true; } From 829cd0668578f1da20d031394b4edd84e8933716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:26:14 +0200 Subject: [PATCH 327/459] [poincare] Fix some layouts up/down navigation Change-Id: I1a69651ca41899557489318fe4d4609e51308036 --- poincare/src/layout/binomial_coefficient_layout.cpp | 4 ++-- poincare/src/layout/condensed_sum_layout.cpp | 8 ++++---- poincare/src/layout/fraction_layout.cpp | 4 ++-- poincare/src/layout/grid_layout.cpp | 4 ++-- poincare/src/layout/integral_layout.cpp | 8 ++++---- poincare/src/layout/matrix_layout.cpp | 4 ++-- poincare/src/layout/nth_root_layout.cpp | 4 ++-- poincare/src/layout/sequence_layout.cpp | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index edc58b377..a22e88e94 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -79,7 +79,7 @@ bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor, bool bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: kLayout. // Move to nLayout. - if (cursor->pointedExpressionLayout()->hasAncestor(kLayout())) { + if (cursor->pointedExpressionLayout()->hasAncestor(kLayout(), true)) { return nLayout()->moveUpInside(cursor, shouldRecomputeLayout); } return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); @@ -88,7 +88,7 @@ bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * s bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: nLayout. // Move to kLayout. - if (cursor->pointedExpressionLayout()->hasAncestor(nLayout())) { + if (cursor->pointedExpressionLayout()->hasAncestor(nLayout(), true)) { return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); } return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index ac957bb85..b1ae4ca16 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -92,13 +92,13 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the subscript layout, move it to the superscript. - if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout())) { + if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout(), true)) { assert(superscriptLayout() != nullptr); return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the superscript. if (baseLayout() - && cursor->pointedExpressionLayout()->hasAncestor(baseLayout()) + && cursor->pointedExpressionLayout()->hasAncestor(baseLayout(), true) && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(superscriptLayout() != nullptr); @@ -109,13 +109,13 @@ bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRe bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the superscript layout, move it to the subscript. - if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout())) { + if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout(), true)) { assert(subscriptLayout() != nullptr); return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the subscript. if (baseLayout() - && cursor->pointedExpressionLayout()->hasAncestor(baseLayout()) + && cursor->pointedExpressionLayout()->hasAncestor(baseLayout(), true) && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) { assert(subscriptLayout() != nullptr); diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index b78f2eb09..98c30074b 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -145,7 +145,7 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside denominator, move it to the numerator. - if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout())) { + if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout(), true)) { assert(numeratorLayout() != nullptr); return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } @@ -159,7 +159,7 @@ bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside numerator, move it to the denominator. - if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout())) { + if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout(), true)) { assert(denominatorLayout() != nullptr); return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 9987c65e3..c83c9a5f3 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -99,7 +99,7 @@ bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeL // neighbourg. int childIndex = m_numberOfColumns; while (childIndex < numberOfChildren()) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor, shouldRecomputeLayout); } childIndex++; @@ -110,7 +110,7 @@ bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeL bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { int childIndex = 0; while (childIndex < numberOfChildren() - m_numberOfColumns) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor, shouldRecomputeLayout); } childIndex++; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index dcbf24328..8791625ab 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -119,13 +119,13 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout())) { + if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout()) + && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout(), true) && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(upperBoundLayout() != nullptr); @@ -136,13 +136,13 @@ bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout())) { + if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout()) + && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout(), true) && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { assert(lowerBoundLayout() != nullptr); diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 8803b150d..4e12f4271 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -83,7 +83,7 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool shouldRemoveGreySquares = false; for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { // The cursor is leaving the matrix, so remove the grey squares. shouldRemoveGreySquares = true; break; @@ -101,7 +101,7 @@ bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomput bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { bool shouldRemoveGreySquares = false; for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex))) { + if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { // The cursor is leaving the matrix, so remove the grey squares. shouldRemoveGreySquares = true; break; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 887be5af3..ec605c3e9 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -137,7 +137,7 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(radicandLayout()) + && cursor->pointedExpressionLayout()->hasAncestor(radicandLayout(), true) && cursor->positionIsEquivalentTo(radicandLayout(), ExpressionLayoutCursor::Position::Left)) { cursor->setPointedExpressionLayout(indexLayout()); @@ -157,7 +157,7 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu } bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout())) { + if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { // If the cursor is Right of the index, move it to the radicand. if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { assert(radicandLayout() != nullptr); diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index adfb1690d..16fb1722f 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -100,7 +100,7 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout())) { + if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } @@ -116,7 +116,7 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout())) { + if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } From f2aa4df8a7e24b79ee89af7a372e19d53fbf98f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:31:35 +0200 Subject: [PATCH 328/459] [poincare] Use the new hasAncestor parameter. Change-Id: I1dcb612e01f7ba9ffbeaea7b53ab5e678667f02b --- poincare/src/layout/conjugate_layout.cpp | 2 +- poincare/src/layout/dynamic_layout_hierarchy.cpp | 2 +- poincare/src/layout/expression_layout.cpp | 2 +- poincare/src/layout/matrix_layout.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 593225e91..e113afd2f 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -94,7 +94,7 @@ void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChil void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); + assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 5bbcad605..60b0de32b 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -116,7 +116,7 @@ void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemov void DynamicLayoutHierarchy::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); + assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); if (numberOfChildren() == 1) { if (m_parent) { if (!deleteAfterRemoval) { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 2672f233d..bb8ed4b83 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -184,7 +184,7 @@ void ExpressionLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { void ExpressionLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); + assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); removeChildAtIndex(index, deleteAfterRemoval); if (index < numberOfChildren()) { cursor->setPointedExpressionLayout(editableChild(index)); diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 4e12f4271..df13a623f 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -163,7 +163,7 @@ void MatrixLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, void MatrixLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { assert(index >= 0 && index < numberOfChildren()); - assert((cursor->pointedExpressionLayout() == child(index)) || (cursor->pointedExpressionLayout()->hasAncestor(child(index)))); + assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); } From 0487be1ab08f2adb4051c69e4ad3c8062c68f0af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:33:04 +0200 Subject: [PATCH 329/459] [poincare] equivalentCursor method. Change-Id: I937f4ef8e28bdedc03b51ef6e24517264c385e54 --- poincare/include/poincare/expression_layout.h | 3 ++ .../poincare/expression_layout_cursor.h | 3 ++ poincare/src/layout/expression_layout.cpp | 10 +++++ poincare/src/layout/horizontal_layout.cpp | 41 +++++++++++++++++++ poincare/src/layout/horizontal_layout.h | 3 ++ 5 files changed, 60 insertions(+) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 42b9513fc..3f49bed49 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -90,6 +90,9 @@ public: /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; + /* Cursor */ + virtual ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor * cursor); + /* Other */ virtual ExpressionLayout * layoutToPointWhenInserting(); bool addGreySquaresToAllMatrixAncestors(); diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index e0473c915..34d4dd563 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -19,6 +19,9 @@ public: m_position(Position::Right) {}; + /* Definition */ + bool isDefined() const { return m_pointedExpressionLayout != nullptr; } + /* Getters and setters */ ExpressionLayout * pointedExpressionLayout() { return m_pointedExpressionLayout; } ExpressionLayout * pointedExpressionLayoutEquivalentChild(); diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index bb8ed4b83..458619abc 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -259,6 +259,16 @@ bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * sh return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); } +ExpressionLayoutCursor ExpressionLayout::equivalentCursor(ExpressionLayoutCursor * cursor) { + // Only HorizontalLayout may not have a parent, and it overload this function + assert(m_parent); + if (cursor->pointedExpressionLayout() == this) { + return m_parent->equivalentCursor(cursor); + } else { + return ExpressionLayoutCursor(); + } +} + ExpressionLayout * ExpressionLayout::layoutToPointWhenInserting() { if (numberOfChildren() > 0) { return editableChild(0); diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 5d3adda7f..135c22b6d 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -295,6 +295,47 @@ int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize, int numbe return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); } +ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor * cursor) { + ExpressionLayoutCursor result; + ExpressionLayout * newPointedLayout = nullptr; + ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Left; + if (cursor->pointedExpressionLayout() == this) { + // First or last child, if any + if(numberOfChildren() == 0) { + return result; + } else { + newPointedLayout = editableChild(cursor->position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1); + newPosition = cursor->position(); + } + } else { + // Left or right child + int indexOfPointedLayout = indexOfChild(cursor->pointedExpressionLayout()); + if (indexOfPointedLayout < 0) { + return result; + } else if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (indexOfPointedLayout == 0) { + newPointedLayout = this; + newPosition = ExpressionLayoutCursor::Position::Left; + } else { + newPointedLayout = editableChild(indexOfPointedLayout - 1); + newPosition = ExpressionLayoutCursor::Position::Right; + } + } else { + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + if (indexOfPointedLayout == numberOfChildren() - 1) { + newPointedLayout = this; + newPosition = ExpressionLayoutCursor::Position::Right; + } else { + newPointedLayout = editableChild(indexOfPointedLayout + 1); + newPosition = ExpressionLayoutCursor::Position::Left; + } + } + } + result.setPointedExpressionLayout(newPointedLayout); + result.setPosition(newPosition); + return result; +} + bool HorizontalLayout::isEmpty() const { if (m_numberOfChildren == 1 && child(0)->isEmpty()) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index c8a673bfa..2dd1110fe 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -35,6 +35,9 @@ public: /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + /* Cursor */ + ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor * cursor) override; + /* Other */ bool isHorizontal() const override { return true; } bool isEmpty() const override; From 8d32930eaea539ef07a67aaa7f1d040cb2015251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 11:34:02 +0200 Subject: [PATCH 330/459] [poincare] Check equivalent positions when moving Up and Down Change-Id: I5043d0a43c981592b0b72fd1221769497520b342 --- poincare/include/poincare/expression_layout.h | 5 ++- .../layout/binomial_coefficient_layout.cpp | 8 ++-- .../src/layout/binomial_coefficient_layout.h | 4 +- poincare/src/layout/condensed_sum_layout.cpp | 8 ++-- poincare/src/layout/condensed_sum_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 37 ++++++++++++++----- poincare/src/layout/fraction_layout.cpp | 8 ++-- poincare/src/layout/fraction_layout.h | 4 +- poincare/src/layout/grid_layout.cpp | 8 ++-- poincare/src/layout/grid_layout.h | 4 +- poincare/src/layout/integral_layout.cpp | 8 ++-- poincare/src/layout/integral_layout.h | 4 +- poincare/src/layout/matrix_layout.cpp | 8 ++-- poincare/src/layout/matrix_layout.h | 4 +- poincare/src/layout/nth_root_layout.cpp | 8 ++-- poincare/src/layout/nth_root_layout.h | 4 +- poincare/src/layout/sequence_layout.cpp | 8 ++-- poincare/src/layout/sequence_layout.h | 4 +- .../src/layout/vertical_offset_layout.cpp | 8 ++-- poincare/src/layout/vertical_offset_layout.h | 4 +- 20 files changed, 84 insertions(+), 66 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 3f49bed49..8de727f69 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -82,8 +82,8 @@ public: /* Tree navigation */ virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); - virtual bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); @@ -147,6 +147,7 @@ protected: bool m_positioned; private: void detachChildAtIndex(int i); + bool moveVertically(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index a22e88e94..fce62238f 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -76,22 +76,22 @@ bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor, bool return false; } -bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: kLayout. // Move to nLayout. if (cursor->pointedExpressionLayout()->hasAncestor(kLayout(), true)) { return nLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: nLayout. // Move to kLayout. if (cursor->pointedExpressionLayout()->hasAncestor(nLayout(), true)) { return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 0cb91941d..b59671b7f 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -13,8 +13,8 @@ public: ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index b1ae4ca16..4d597292e 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -90,7 +90,7 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul return false; } -bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the subscript layout, move it to the superscript. if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout(), true)) { assert(superscriptLayout() != nullptr); @@ -104,10 +104,10 @@ bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRe assert(superscriptLayout() != nullptr); return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the superscript layout, move it to the subscript. if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout(), true)) { assert(subscriptLayout() != nullptr); @@ -121,7 +121,7 @@ bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * should assert(subscriptLayout() != nullptr); return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index eafff7785..2f5164ae3 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -12,8 +12,8 @@ public: ExpressionLayout * clone() const override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 458619abc..74b5eebca 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -237,22 +237,16 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - if (m_parent) { - return m_parent->moveUp(cursor, shouldRecomputeLayout); - } - return false; +bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return moveVertically(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); } bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { return moveInside(VerticalDirection::Up, cursor, shouldRecomputeLayout); } -bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - if (m_parent) { - return m_parent->moveDown(cursor, shouldRecomputeLayout); - } - return false; +bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return moveVertically(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); } bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { @@ -343,6 +337,29 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC return true; } +bool ExpressionLayout::moveVertically(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (!equivalentPositionVisited) { + ExpressionLayoutCursor cursorEquivalent = equivalentCursor(cursor); + if (cursorEquivalent.isDefined()) { + cursor->setPointedExpressionLayout(cursorEquivalent.pointedExpressionLayout()); + cursor->setPosition(cursorEquivalent.position()); + if (direction == VerticalDirection::Up) { + return cursor->pointedExpressionLayout()->moveUp(cursor, shouldRecomputeLayout, true); + } else { + return cursor->pointedExpressionLayout()->moveDown(cursor, shouldRecomputeLayout, true); + } + } + } + if (m_parent) { + if (direction == VerticalDirection::Up) { + return m_parent->moveUp(cursor, shouldRecomputeLayout, true); + } else { + return m_parent->moveDown(cursor, shouldRecomputeLayout, true); + } + } + return false; +} + void ExpressionLayout::moveCursorInsideAtDirection ( VerticalDirection direction, ExpressionLayoutCursor * cursor, diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 98c30074b..7a485fb4a 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -143,7 +143,7 @@ bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside denominator, move it to the numerator. if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout(), true)) { assert(numeratorLayout() != nullptr); @@ -154,10 +154,10 @@ bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp assert(numeratorLayout() != nullptr); return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside numerator, move it to the denominator. if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout(), true)) { assert(denominatorLayout() != nullptr); @@ -168,7 +168,7 @@ bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco assert(denominatorLayout() != nullptr); return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index e1088a9b0..b329e4aae 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -14,8 +14,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index c83c9a5f3..601b8a502 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -94,7 +94,7 @@ bool GridLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecompu return false; } -bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is child that is not on the top row, move it inside the upper // neighbourg. int childIndex = m_numberOfColumns; @@ -104,10 +104,10 @@ bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeL } childIndex++; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { int childIndex = 0; while (childIndex < numberOfChildren() - m_numberOfColumns) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { @@ -115,7 +115,7 @@ bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomput } childIndex++; } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 8e883d92c..d0e2313a8 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -15,8 +15,8 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 8791625ab..004f252c9 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -117,7 +117,7 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); @@ -131,10 +131,10 @@ bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); @@ -148,7 +148,7 @@ bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index e8f377f3b..e8a7b8e74 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -19,8 +19,8 @@ public: /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index df13a623f..29bd302c5 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -80,7 +80,7 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom return GridLayout::moveRight(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { @@ -89,7 +89,7 @@ bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomput break; } } - bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout); + bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); if (returnValue && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); @@ -98,7 +98,7 @@ bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomput return returnValue; } -bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { @@ -107,7 +107,7 @@ bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomp break; } } - bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout); + bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); if (returnValue && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index b4789595e..8a96f538e 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -13,8 +13,8 @@ public: /* Navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index ec605c3e9..7b5f35d3d 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -133,7 +133,7 @@ bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldReco return false; } -bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() @@ -153,10 +153,10 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { // If the cursor is Right of the index, move it to the radicand. if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { @@ -172,7 +172,7 @@ bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecom return true; } } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } static_assert('\x90' == Ion::Charset::Root, "Unicode error"); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 28e2d4956..ad562b75b 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -20,8 +20,8 @@ public: /* Tree navigation */ bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 16fb1722f..c6531e706 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -98,7 +98,7 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec return false; } -bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); @@ -111,10 +111,10 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); @@ -127,7 +127,7 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 7c4343b9c..593259d91 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -13,8 +13,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayout * layoutToPointWhenInserting() override; char XNTChar() const override; protected: diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 71c3e7afb..7ef567f0f 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -120,7 +120,7 @@ bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor, bool * sho return false; } -bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Superscript. if (m_type == VerticalOffsetLayout::Type::Superscript) { // Case: Right. @@ -151,10 +151,10 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * should cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Subscript. if (m_type == VerticalOffsetLayout::Type::Subscript) { // Case: Right. @@ -184,7 +184,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shou cursor->setPointedExpressionLayout(this); return true; } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout); + return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index d2aaaca8e..1b6cadb88 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -17,8 +17,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const { return true; } From 565b5130917aaecf7b27ac94cc20fdf3c2e1e749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 13:44:28 +0200 Subject: [PATCH 331/459] [poincare] Cleaner ExpressionLayoutCursor methods Change-Id: I2ab31a43332dc05ff22d9349e90d8c336336ae85 --- .../poincare/expression_layout_cursor.h | 9 ++++---- poincare/src/expression_layout_cursor.cpp | 22 +++++++------------ poincare/src/layout/bracket_pair_layout.cpp | 2 +- poincare/src/layout/condensed_sum_layout.cpp | 10 ++------- poincare/src/layout/expression_layout.cpp | 4 ++-- poincare/src/layout/integral_layout.cpp | 9 +++----- poincare/src/layout/nth_root_layout.cpp | 7 +++--- poincare/src/layout/sequence_layout.cpp | 6 ++--- .../src/layout/vertical_offset_layout.cpp | 12 +++++----- 9 files changed, 32 insertions(+), 49 deletions(-) diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 34d4dd563..f33d0d239 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -14,9 +14,9 @@ public: Right }; - ExpressionLayoutCursor() : - m_pointedExpressionLayout(nullptr), - m_position(Position::Right) + ExpressionLayoutCursor(ExpressionLayout * layout = nullptr, Position position = Position::Right) : + m_pointedExpressionLayout(layout), + m_position(position) {}; /* Definition */ @@ -32,11 +32,10 @@ public: KDCoordinate baseline(); /* Comparison */ - bool positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position); + bool isEquivalentTo(ExpressionLayoutCursor cursor); /* Position */ KDPoint middleLeftPoint(); - KDPoint middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position); /* Move */ bool moveLeft(bool * shouldRecomputeLayout); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 102f63e58..85f625fad 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -34,23 +34,17 @@ KDCoordinate ExpressionLayoutCursor::baseline() { return max(baseline1, baseline2); } -bool ExpressionLayoutCursor::positionIsEquivalentTo(ExpressionLayout * expressionLayout, Position position) { - assert(expressionLayout != nullptr); - return middleLeftPoint() == middleLeftPointOfCursor(expressionLayout, position); +bool ExpressionLayoutCursor::isEquivalentTo(ExpressionLayoutCursor cursor) { + assert(isDefined()); + assert(cursor.isDefined()); + return middleLeftPoint() == cursor.middleLeftPoint(); } KDPoint ExpressionLayoutCursor::middleLeftPoint() { - return middleLeftPointOfCursor(m_pointedExpressionLayout, m_position); -} - -KDPoint ExpressionLayoutCursor::middleLeftPointOfCursor(ExpressionLayout * expressionLayout, Position position) { - KDPoint layoutOrigin = expressionLayout->absoluteOrigin(); - KDCoordinate y = layoutOrigin.y() + expressionLayout->baseline() - k_cursorHeight/2; - if (position == Position::Left) { - return KDPoint(layoutOrigin.x(), y); - } - assert(position == Position::Right); - return KDPoint(layoutOrigin.x() + expressionLayout->size().width(), y); + KDPoint layoutOrigin = m_pointedExpressionLayout->absoluteOrigin(); + KDCoordinate x = layoutOrigin.x() + (m_position == Position::Left ? 0 : m_pointedExpressionLayout->size().width()); + KDCoordinate y = layoutOrigin.y() + m_pointedExpressionLayout->baseline() - k_cursorHeight/2; + return KDPoint(x, y); } bool ExpressionLayoutCursor::moveLeft(bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index 0294cc9d1..8e53fc65e 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -26,7 +26,7 @@ void BracketPairLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * c } void BracketPairLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { - if (cursor->positionIsEquivalentTo(operandLayout(), ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left))) { // Case: Left of the operand. Delete the layout, keep the operand. replaceWithAndMoveCursor(operandLayout(), true, cursor); return; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 4d597292e..51688a4ea 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -97,10 +97,7 @@ bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRe return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the superscript. - if (baseLayout() - && cursor->pointedExpressionLayout()->hasAncestor(baseLayout(), true) - && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) - { + if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { assert(superscriptLayout() != nullptr); return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } @@ -114,10 +111,7 @@ bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * should return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the subscript. - if (baseLayout() - && cursor->pointedExpressionLayout()->hasAncestor(baseLayout(), true) - && cursor->positionIsEquivalentTo(baseLayout(), ExpressionLayoutCursor::Position::Left)) - { + if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { assert(subscriptLayout() != nullptr); return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 74b5eebca..61c924213 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -375,7 +375,7 @@ void ExpressionLayout::moveCursorInsideAtDirection ( if (layoutIsUnderOrAbove) { // Check the distance to a Left cursor. - int currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Left).squareDistanceTo(cursorMiddleLeft); + int currentDistance = ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left).middleLeftPoint().squareDistanceTo(cursorMiddleLeft); if (currentDistance <= *resultScore ){ *childResult = this; *castedResultPosition = ExpressionLayoutCursor::Position::Left; @@ -383,7 +383,7 @@ void ExpressionLayout::moveCursorInsideAtDirection ( } // Check the distance to a Right cursor. - currentDistance = cursor->middleLeftPointOfCursor(this, ExpressionLayoutCursor::Position::Right).squareDistanceTo(cursorMiddleLeft); + currentDistance = ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right).middleLeftPoint().squareDistanceTo(cursorMiddleLeft); if (currentDistance < *resultScore) { *childResult = this; *castedResultPosition = ExpressionLayoutCursor::Position::Right; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 004f252c9..c28d1ebac 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -27,8 +27,7 @@ ExpressionLayout * IntegralLayout::clone() const { } void IntegralLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { - - if (cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { // Case: Left of the integrand. // Delete the layout, keep the integrand. replaceWithAndMoveCursor(integrandLayout(), true, cursor); @@ -125,8 +124,7 @@ bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout(), true) - && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) + && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); @@ -142,8 +140,7 @@ bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(integrandLayout(), true) - && cursor->positionIsEquivalentTo(integrandLayout(), ExpressionLayoutCursor::Position::Left)) + && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 7b5f35d3d..5af07f1e5 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -137,8 +137,7 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() - && cursor->pointedExpressionLayout()->hasAncestor(radicandLayout(), true) - && cursor->positionIsEquivalentTo(radicandLayout(), ExpressionLayoutCursor::Position::Left)) + && cursor->isEquivalentTo(ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left))) { cursor->setPointedExpressionLayout(indexLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); @@ -159,14 +158,14 @@ bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecompu bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { // If the cursor is Right of the index, move it to the radicand. - if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Right)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right))) { assert(radicandLayout() != nullptr); cursor->setPointedExpressionLayout(radicandLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; } // If the cursor is Left of the index, move it Left . - if (cursor->positionIsEquivalentTo(indexLayout(), ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left))) { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Left); return true; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index c6531e706..fd9800526 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -9,7 +9,7 @@ namespace Poincare { void SequenceLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { - if (cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { // Case: Left of the argument. Delete the layout, keep the argument. replaceWithAndMoveCursor(argumentLayout(), true, cursor); return; @@ -106,7 +106,7 @@ bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomp } // If the cursor is Left of the argument, move it to the upper bound. if (argumentLayout() - && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) + && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); @@ -122,7 +122,7 @@ bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldReco } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() - && cursor->positionIsEquivalentTo(argumentLayout(), ExpressionLayoutCursor::Position::Left)) + && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 7ef567f0f..c02a86378 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -125,7 +125,7 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * should if (m_type == VerticalOffsetLayout::Type::Superscript) { // Case: Right. // Move to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); @@ -133,7 +133,7 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * should } // Case: Left. // Move to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); @@ -145,8 +145,8 @@ bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * should // Put the cursor at the same position, pointing this. if (m_type == VerticalOffsetLayout::Type::Subscript && indiceLayout() != nullptr - && (cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Left) - || cursor->positionIsEquivalentTo(indiceLayout(), ExpressionLayoutCursor::Position::Right))) + && (cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left)) + || cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right)))) { cursor->setPointedExpressionLayout(this); return true; @@ -159,7 +159,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shou if (m_type == VerticalOffsetLayout::Type::Subscript) { // Case: Right. // Move to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Right)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Right); @@ -167,7 +167,7 @@ bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shou } // Case: Left. // Move to the indice. - if (cursor->positionIsEquivalentTo(this, ExpressionLayoutCursor::Position::Left)) { + if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); cursor->setPointedExpressionLayout(indiceLayout()); cursor->setPosition(ExpressionLayoutCursor::Position::Left); From 1d6e0bb060c24e1058a2b1f033403cc8e1dd5c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 13:49:39 +0200 Subject: [PATCH 332/459] [poincare] Make ExpressionLayoutCursor constructor constexpr Change-Id: I860a2779523cd5913028a7010017eca983f30ee0 --- poincare/include/poincare/expression_layout_cursor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index f33d0d239..b3127c4c0 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -14,7 +14,7 @@ public: Right }; - ExpressionLayoutCursor(ExpressionLayout * layout = nullptr, Position position = Position::Right) : + constexpr ExpressionLayoutCursor(ExpressionLayout * layout = nullptr, Position position = Position::Right) : m_pointedExpressionLayout(layout), m_position(position) {}; From 9e87172800d54a4c871e8ca60fe7c3cf5df666c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 15:39:35 +0200 Subject: [PATCH 333/459] [poincare] moveLeft renamed cursorOnLeft, same for other directions Change-Id: Ic46604ea81eabdb2e10755a67307169d90654efd --- .../escher/expression_view_with_cursor.h | 1 + ...scrollable_expression_view_with_cursor.cpp | 35 ++++--- poincare/include/poincare/expression_layout.h | 18 ++-- .../poincare/expression_layout_cursor.h | 8 +- poincare/src/expression_layout_cursor.cpp | 16 ++-- .../layout/binomial_coefficient_layout.cpp | 61 +++++------- .../src/layout/binomial_coefficient_layout.h | 8 +- poincare/src/layout/bracket_layout.cpp | 31 +++--- poincare/src/layout/bracket_layout.h | 4 +- poincare/src/layout/bracket_pair_layout.cpp | 42 ++++---- poincare/src/layout/bracket_pair_layout.h | 4 +- poincare/src/layout/char_layout.cpp | 30 +++--- poincare/src/layout/char_layout.h | 4 +- poincare/src/layout/condensed_sum_layout.cpp | 75 ++++++--------- poincare/src/layout/condensed_sum_layout.h | 8 +- poincare/src/layout/conjugate_layout.cpp | 42 ++++---- poincare/src/layout/conjugate_layout.h | 4 +- poincare/src/layout/empty_layout.cpp | 12 +-- poincare/src/layout/empty_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 44 ++++----- poincare/src/layout/fraction_layout.cpp | 58 +++++------ poincare/src/layout/fraction_layout.h | 8 +- poincare/src/layout/grid_layout.cpp | 76 ++++++--------- poincare/src/layout/grid_layout.h | 8 +- poincare/src/layout/horizontal_layout.cpp | 39 ++++---- poincare/src/layout/horizontal_layout.h | 4 +- poincare/src/layout/integral_layout.cpp | 69 ++++++-------- poincare/src/layout/integral_layout.h | 8 +- poincare/src/layout/matrix_layout.cpp | 67 ++++++------- poincare/src/layout/matrix_layout.h | 12 +-- poincare/src/layout/nth_root_layout.cpp | 86 ++++++----------- poincare/src/layout/nth_root_layout.h | 8 +- poincare/src/layout/parenthesis_layout.cpp | 30 +++--- poincare/src/layout/parenthesis_layout.h | 4 +- poincare/src/layout/sequence_layout.cpp | 73 ++++++-------- poincare/src/layout/sequence_layout.h | 8 +- .../src/layout/vertical_offset_layout.cpp | 95 +++++++------------ poincare/src/layout/vertical_offset_layout.h | 8 +- 38 files changed, 461 insertions(+), 651 deletions(-) diff --git a/escher/include/escher/expression_view_with_cursor.h b/escher/include/escher/expression_view_with_cursor.h index 3128d3aca..cecd62ec0 100644 --- a/escher/include/escher/expression_view_with_cursor.h +++ b/escher/include/escher/expression_view_with_cursor.h @@ -12,6 +12,7 @@ public: ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout); bool isEditing() const { return m_isEditing; } void setEditing(bool isEditing); + void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } void cursorPositionChanged(); KDRect cursorRect(); Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/scrollable_expression_view_with_cursor.cpp index 7de8c9802..63dae9514 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/scrollable_expression_view_with_cursor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include ScrollableExpressionViewWithCursor::ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ScrollableExpressionViewWithCursorDelegate * delegate) : @@ -79,26 +80,24 @@ KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const } bool ScrollableExpressionViewWithCursor::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { + Poincare::ExpressionLayoutCursor result; if (event == Ion::Events::Left) { - return m_expressionViewWithCursor.cursor()->moveLeft(shouldRecomputeLayout); + result = m_expressionViewWithCursor.cursor()->cursorOnLeft(shouldRecomputeLayout); + } else if (event == Ion::Events::Right) { + result = m_expressionViewWithCursor.cursor()->cursorOnRight(shouldRecomputeLayout); + } else if (event == Ion::Events::Up) { + result = m_expressionViewWithCursor.cursor()->cursorAbove(shouldRecomputeLayout); + } else if (event == Ion::Events::Down) { + result = m_expressionViewWithCursor.cursor()->cursorUnder(shouldRecomputeLayout); + } else if (event == Ion::Events::ShiftLeft) { + result.setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + result.setPosition(Poincare::ExpressionLayoutCursor::Position::Left); + } else if (event == Ion::Events::ShiftRight) { + result.setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + result.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } - if (event == Ion::Events::Right) { - return m_expressionViewWithCursor.cursor()->moveRight(shouldRecomputeLayout); - } - if (event == Ion::Events::Up) { - return m_expressionViewWithCursor.cursor()->moveUp(shouldRecomputeLayout); - } - if (event == Ion::Events::Down) { - return m_expressionViewWithCursor.cursor()->moveDown(shouldRecomputeLayout); - } - if (event == Ion::Events::ShiftLeft) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Left); - return true; - } - if (event == Ion::Events::ShiftRight) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + if (result.isDefined()) { + m_expressionViewWithCursor.setCursor(result); return true; } return false; diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 8de727f69..d2e94ddda 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -80,12 +80,12 @@ public: virtual void deleteBeforeCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ - virtual bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); - virtual bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); - virtual bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); - virtual bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; + virtual ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; + virtual ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; @@ -128,7 +128,7 @@ protected: virtual KDSize computeSize() = 0; virtual void computeBaseline() = 0; virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; - void moveCursorInsideAtDirection ( + void scoreCursorInDescendantsVerticalOf ( VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, @@ -147,8 +147,8 @@ protected: bool m_positioned; private: void detachChildAtIndex(int i); - bool moveVertically(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); - bool moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + ExpressionLayoutCursor cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; }; diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index b3127c4c0..11ad4a8a9 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -38,10 +38,10 @@ public: KDPoint middleLeftPoint(); /* Move */ - bool moveLeft(bool * shouldRecomputeLayout); - bool moveRight(bool * shouldRecomputeLayout); - bool moveUp(bool * shouldRecomputeLayout); - bool moveDown(bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorOnLeft(bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorOnRight(bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorAbove(bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorUnder(bool * shouldRecomputeLayout); /* Edition */ void addLayoutAndMoveCursor(ExpressionLayout * layout); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 85f625fad..1029a2ef1 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -47,20 +47,20 @@ KDPoint ExpressionLayoutCursor::middleLeftPoint() { return KDPoint(x, y); } -bool ExpressionLayoutCursor::moveLeft(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->moveLeft(this, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayoutCursor::cursorOnLeft(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->cursorLeftOf(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveRight(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->moveRight(this, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayoutCursor::cursorOnRight(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->cursorRightOf(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveUp(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->moveUp(this, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayoutCursor::cursorAbove(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->cursorAbove(this, shouldRecomputeLayout); } -bool ExpressionLayoutCursor::moveDown(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->moveDown(this, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayoutCursor::cursorUnder(bool * shouldRecomputeLayout) { + return m_pointedExpressionLayout->cursorUnder(this, shouldRecomputeLayout); } void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index fce62238f..a1599f5d4 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -18,80 +18,67 @@ ExpressionLayout * BinomialCoefficientLayout::clone() const { return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); } -bool BinomialCoefficientLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the children. - // Go Left. +ExpressionLayoutCursor BinomialCoefficientLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the children. Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Left && (cursor->pointedExpressionLayout() == nLayout() || cursor->pointedExpressionLayout() == kLayout())) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the kLayout. + // Case: Right. Go to the kLayout. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(kLayout() != nullptr); - cursor->setPointedExpressionLayout(kLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(kLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool BinomialCoefficientLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the children. - // Go Right. +ExpressionLayoutCursor BinomialCoefficientLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the children. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Right && (cursor->pointedExpressionLayout() == nLayout() || cursor->pointedExpressionLayout() == kLayout())) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Left of the nLayout. + // Case: Left. Go Left of the nLayout. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(nLayout() != nullptr); - cursor->setPointedExpressionLayout(nLayout()); - return true; + return ExpressionLayoutCursor(nLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool BinomialCoefficientLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // Case: kLayout. - // Move to nLayout. +ExpressionLayoutCursor BinomialCoefficientLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + // Case: kLayout. Move to nLayout. if (cursor->pointedExpressionLayout()->hasAncestor(kLayout(), true)) { - return nLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return nLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool BinomialCoefficientLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // Case: nLayout. - // Move to kLayout. +ExpressionLayoutCursor BinomialCoefficientLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + // Case: nLayout. Move to kLayout. if (cursor->pointedExpressionLayout()->hasAncestor(nLayout(), true)) { - return kLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return kLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } void BinomialCoefficientLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index b59671b7f..a2dcdf58d 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -11,10 +11,10 @@ class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index f00ac99f8..9ce509275 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -18,41 +18,34 @@ void BracketLayout::invalidAllSizesPositionsAndBaselines() { ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool BracketLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Left. + // Case: Right. Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool BracketLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Right. + // Case: Left. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } - KDSize BracketLayout::computeSize() { return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index e37e6e8cd..4f8ee41bf 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -9,8 +9,8 @@ class BracketLayout : public StaticLayoutHierarchy<0> { public: BracketLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; protected: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index 8e53fc65e..010774c61 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -34,59 +34,49 @@ void BracketPairLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool BracketPairLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the operand. - // Go Left of the brackets. +ExpressionLayoutCursor BracketPairLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the operand. Go Left of the brackets. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right of the brackets. - // Go Right of the operand. + // Case: Right of the brackets. Go Right of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - return true; + return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left of the brackets. - // Ask the parent. + // Case: Left of the brackets. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool BracketPairLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the operand. - // Go Right of the brackets. +ExpressionLayoutCursor BracketPairLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the operand. Go Right of the brackets. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left of the brackets. - // Go Left of the operand. + // Case: Left of the brackets. Go Left of the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - return true; + return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right of the brackets. - // Ask the parent. + // Case: Right of the brackets. Ask the parent. cursor->setPointedExpressionLayout(this); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } int BracketPairLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index 33e9523f3..2d3515ac7 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -13,8 +13,8 @@ public: ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: ExpressionLayout * operandLayout(); diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index 2a86c61f2..fadaaa46a 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -18,36 +18,30 @@ ExpressionLayout * CharLayout::clone() const { return layout; } -bool CharLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor CharLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Left. + // Case: Right. Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool CharLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor CharLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Right. + // Case: Left. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } bool CharLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 90b7de8bb..3afce1439 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -17,8 +17,8 @@ public: char character() { return m_char; } KDText::FontSize fontSize() const { return m_fontSize; } - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 51688a4ea..0866e06e4 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -10,58 +10,46 @@ ExpressionLayout * CondensedSumLayout::clone() const { return layout; } -bool CondensedSumLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the bounds. - // Go Left of the sum. +ExpressionLayoutCursor CondensedSumLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the bounds. Go Left of the sum. if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left of the base. - // Go Right of the lower bound. + // Case: Left of the base. Go Right of the lower bound. if (baseLayout() && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(subscriptLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(subscriptLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the base and move Left. + // Case: Right. Go to the base and move Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(baseLayout()); cursor->setPointedExpressionLayout(baseLayout()); - return baseLayout()->moveLeft(cursor, shouldRecomputeLayout); + return baseLayout()->cursorLeftOf(cursor, shouldRecomputeLayout); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the bounds. - // Go Left of the operand. +ExpressionLayoutCursor CondensedSumLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the bounds. Go Left of the operand. if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(baseLayout() != nullptr); - cursor->setPointedExpressionLayout(baseLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; - } - // Case: Right of the base. - // Ask the parent. + return ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left); + } + // Case: Right of the base. Ask the parent. if (baseLayout() && cursor->pointedExpressionLayout() == baseLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) @@ -69,53 +57,50 @@ bool CondensedSumLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shoul cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the upper bound. + // Case: Left. Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(superscriptLayout()); - cursor->setPointedExpressionLayout(superscriptLayout()); - return true; + return ExpressionLayoutCursor(superscriptLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool CondensedSumLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor CondensedSumLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the subscript layout, move it to the superscript. if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout(), true)) { assert(superscriptLayout() != nullptr); - return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return superscriptLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the superscript. if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { assert(superscriptLayout() != nullptr); - return superscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return superscriptLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool CondensedSumLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor CondensedSumLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the superscript layout, move it to the subscript. if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout(), true)) { assert(subscriptLayout() != nullptr); - return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return subscriptLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left of the base layout, move it to the subscript. if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { assert(subscriptLayout() != nullptr); - return subscriptLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return subscriptLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 2f5164ae3..d42aafc41 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -10,10 +10,10 @@ class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index e113afd2f..4ae95a010 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -26,58 +26,48 @@ void ConjugateLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cur cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -bool ConjugateLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the operand. - // Move Left. +ExpressionLayoutCursor ConjugateLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the operand. Move Left. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the operand. + // Case: Right. Go to the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - return true; + return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool ConjugateLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the operand. - // Move Right. +ExpressionLayoutCursor ConjugateLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the operand. Move Right. if (operandLayout() && cursor->pointedExpressionLayout() == operandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the operand. + // Case: Left. Go to the operand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); - cursor->setPointedExpressionLayout(operandLayout()); - return true; + return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index cd3822f57..2146a3be1 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -11,8 +11,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index c4ea9317b..84a811b6a 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -25,24 +25,24 @@ void EmptyLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { } } -bool EmptyLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor EmptyLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool EmptyLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 969fd4726..c73f7e8df 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -15,8 +15,8 @@ public: EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 61c924213..33e26b81d 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -209,7 +209,7 @@ void ExpressionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { // Case: The pointed layout is a child. Move Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); bool shouldRecomputeLayout = false; - cursor->moveLeft(&shouldRecomputeLayout); + cursor->cursorOnLeft(&shouldRecomputeLayout); return; } assert(cursor->pointedExpressionLayout() == this); @@ -237,20 +237,20 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -bool ExpressionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - return moveVertically(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); +ExpressionLayoutCursor ExpressionLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return cursorVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool ExpressionLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - return moveInside(VerticalDirection::Up, cursor, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + return cursorInDescendantsVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout); } -bool ExpressionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - return moveVertically(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); +ExpressionLayoutCursor ExpressionLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return cursorVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool ExpressionLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - return moveInside(VerticalDirection::Down, cursor, shouldRecomputeLayout); +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + return cursorInDescendantsVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout); } ExpressionLayoutCursor ExpressionLayout::equivalentCursor(ExpressionLayoutCursor * cursor) { @@ -317,7 +317,7 @@ void ExpressionLayout::detachChildAtIndex(int i) { m_baselined = false; } -bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; @@ -325,42 +325,40 @@ bool ExpressionLayout::moveInside(VerticalDirection direction, ExpressionLayoutC * than this initial value of score. */ int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; - moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResultPtr, &resultPosition, &resultScore); + scoreCursorInDescendantsVerticalOf(direction, cursor, shouldRecomputeLayout, childResultPtr, &resultPosition, &resultScore); // If there is a valid result if (*childResultPtr == nullptr) { - return false; + return ExpressionLayoutCursor(); } - cursor->setPointedExpressionLayout(*childResultPtr); - cursor->setPosition(resultPosition); *shouldRecomputeLayout = (*childResultPtr)->addGreySquaresToAllMatrixAncestors(); - return true; + return ExpressionLayoutCursor(*childResultPtr, resultPosition); } -bool ExpressionLayout::moveVertically(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor ExpressionLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (!equivalentPositionVisited) { ExpressionLayoutCursor cursorEquivalent = equivalentCursor(cursor); if (cursorEquivalent.isDefined()) { cursor->setPointedExpressionLayout(cursorEquivalent.pointedExpressionLayout()); cursor->setPosition(cursorEquivalent.position()); if (direction == VerticalDirection::Up) { - return cursor->pointedExpressionLayout()->moveUp(cursor, shouldRecomputeLayout, true); + return cursor->pointedExpressionLayout()->cursorAbove(cursor, shouldRecomputeLayout, true); } else { - return cursor->pointedExpressionLayout()->moveDown(cursor, shouldRecomputeLayout, true); + return cursor->pointedExpressionLayout()->cursorUnder(cursor, shouldRecomputeLayout, true); } } } if (m_parent) { if (direction == VerticalDirection::Up) { - return m_parent->moveUp(cursor, shouldRecomputeLayout, true); + return m_parent->cursorAbove(cursor, shouldRecomputeLayout, true); } else { - return m_parent->moveDown(cursor, shouldRecomputeLayout, true); + return m_parent->cursorUnder(cursor, shouldRecomputeLayout, true); } } - return false; + return ExpressionLayoutCursor(); } -void ExpressionLayout::moveCursorInsideAtDirection ( +void ExpressionLayout::scoreCursorInDescendantsVerticalOf ( VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, @@ -393,7 +391,7 @@ void ExpressionLayout::moveCursorInsideAtDirection ( if (layoutIsUnderOrAbove || layoutContains) { int childIndex = 0; while (child(childIndex++)) { - editableChild(childIndex-1)->moveCursorInsideAtDirection(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); + editableChild(childIndex-1)->scoreCursorInDescendantsVerticalOf(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); } } } diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 7a485fb4a..01bc6c18c 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -89,86 +89,76 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool FractionLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the numerator or the denominator. - // Go Left of the fraction. +ExpressionLayoutCursor FractionLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the numerator or the denominator. Go Left of the fraction. if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the denominator. + // Case: Right. Go to the denominator. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(denominatorLayout() != nullptr); - cursor->setPointedExpressionLayout(denominatorLayout()); - return true; + return ExpressionLayoutCursor(denominatorLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool FractionLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the numerator or the denominator. - // Go Right of the fraction. +ExpressionLayoutCursor FractionLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the numerator or the denominator. Go Right of the fraction. if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the numerator. + // Case: Left. Go to the numerator. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(numeratorLayout() != nullptr); - cursor->setPointedExpressionLayout(numeratorLayout()); - return true; + return ExpressionLayoutCursor(numeratorLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool FractionLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor FractionLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside denominator, move it to the numerator. if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout(), true)) { assert(numeratorLayout() != nullptr); - return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return numeratorLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the numerator. if (cursor->pointedExpressionLayout() == this){ assert(numeratorLayout() != nullptr); - return numeratorLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return numeratorLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool FractionLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor FractionLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside numerator, move it to the denominator. if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout(), true)) { assert(denominatorLayout() != nullptr); - return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return denominatorLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the denominator. if (cursor->pointedExpressionLayout() == this){ assert(denominatorLayout() != nullptr); - return denominatorLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return denominatorLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int FractionLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index b329e4aae..0a089cc71 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -12,10 +12,10 @@ public: ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index 601b8a502..ae3e7a1a5 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -21,101 +21,83 @@ ExpressionLayout * GridLayout::clone() const { return layout; } -bool GridLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right. - // Go to the last entry. +ExpressionLayoutCursor GridLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right. Go to the last entry. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { ExpressionLayout * lastChild = editableChild(m_numberOfColumns*m_numberOfRows-1); assert(lastChild != nullptr); - cursor->setPointedExpressionLayout(lastChild); - return true; + return ExpressionLayoutCursor(lastChild, ExpressionLayoutCursor::Position::Right); } // Case: The cursor points to a grid's child. int childIndex = indexOfChild(cursor->pointedExpressionLayout()); if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Left) { if (childIsLeftOfGrid(childIndex)) { - // Case: Left of a child on the left of the grid. - // Go Left of the grid - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + // Case: Left of a child on the left of the grid. Go Left of the grid + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left of another child. - // Go Right of its sibling on the left. - cursor->setPointedExpressionLayout(editableChild(childIndex-1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + // Case: Left of another child. Go Right of its sibling on the left. + return ExpressionLayoutCursor(editableChild(childIndex-1), ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool GridLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left. - // Go to the first entry. +ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left. Go to the first entry. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(m_numberOfColumns*m_numberOfRows >= 1); ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); - cursor->setPointedExpressionLayout(firstChild); - return true; - } + return ExpressionLayoutCursor(firstChild, ExpressionLayoutCursor::Position::Left); + } // Case: The cursor points to a grid's child. int childIndex = indexOfChild(cursor->pointedExpressionLayout()); if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Right) { if (childIsRightOfGrid(childIndex)) { - // Case: Right of a child on the right of the grid. - // Go Right of the grid. - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + // Case: Right of a child on the right of the grid. Go Right of the grid. + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - // Case: Right of another child. - // Go Left of its sibling on the right. - cursor->setPointedExpressionLayout(editableChild(childIndex+1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + // Case: Right of another child. Go Left of its sibling on the right. + return ExpressionLayoutCursor(editableChild(childIndex+1), ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool GridLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // If the cursor is child that is not on the top row, move it inside the upper - // neighbourg. +ExpressionLayoutCursor GridLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + /* If the cursor is child that is not on the top row, move it inside its upper + * neighbour.*/ int childIndex = m_numberOfColumns; while (childIndex < numberOfChildren()) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { - return editableChild(childIndex - m_numberOfColumns)->moveUpInside(cursor, shouldRecomputeLayout); + return editableChild(childIndex - m_numberOfColumns)->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } childIndex++; } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool GridLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor GridLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { int childIndex = 0; while (childIndex < numberOfChildren() - m_numberOfColumns) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { - return editableChild(childIndex + m_numberOfColumns)->moveDownInside(cursor, shouldRecomputeLayout); + return editableChild(childIndex + m_numberOfColumns)->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } childIndex++; } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } void GridLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index d0e2313a8..379d44ff3 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -13,10 +13,10 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 135c22b6d..ef3e9a9a4 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -171,14 +171,14 @@ void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, addChildAtIndex(eL, index); } -bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor HorizontalLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Left. Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Left) { if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); /* Case: Right. @@ -187,14 +187,14 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRe if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } ExpressionLayout * lastChild = editableChild(numberOfChildren()-1); assert(lastChild != nullptr); cursor->setPointedExpressionLayout(lastChild); - return lastChild->moveLeft(cursor, shouldRecomputeLayout); + return lastChild->cursorLeftOf(cursor, shouldRecomputeLayout); } // Case: The cursor is Left of a child. @@ -205,24 +205,24 @@ bool HorizontalLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRe // Case: the child is the leftmost. Ask the parent. if (m_parent) { cursor->setPointedExpressionLayout(this); - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } // Case: the child is not the leftmost. Go to its left sibling and move Left. cursor->setPointedExpressionLayout(editableChild(childIndex-1)); cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return editableChild(childIndex-1)->moveLeft(cursor, shouldRecomputeLayout); + return editableChild(childIndex-1)->cursorLeftOf(cursor, shouldRecomputeLayout); } -bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor HorizontalLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right. Ask the parent. if (cursor->pointedExpressionLayout() == this) { if (cursor->position() == ExpressionLayoutCursor::Position::Right) { if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); /* Case: Left. @@ -231,14 +231,14 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR if (numberOfChildren() < 1) { cursor->setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); cursor->setPointedExpressionLayout(firstChild); - return firstChild->moveRight(cursor, shouldRecomputeLayout); + return firstChild->cursorRightOf(cursor, shouldRecomputeLayout); } // Case: The cursor is Right of a child. @@ -246,19 +246,18 @@ bool HorizontalLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldR int childIndex = indexOfChild(cursor->pointedExpressionLayout()); assert(childIndex >= 0); if (childIndex == numberOfChildren() - 1) { - // Case: the child is the rightmost. - // Ask the parent. + // Case: the child is the rightmost. Ask the parent. if (m_parent) { cursor->setPointedExpressionLayout(this); - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } /* Case: the child is not the rightmost. Go to its right sibling and move * Right. */ cursor->setPointedExpressionLayout(editableChild(childIndex+1)); cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return editableChild(childIndex+1)->moveRight(cursor, shouldRecomputeLayout); + return editableChild(childIndex+1)->cursorRightOf(cursor, shouldRecomputeLayout); } void HorizontalLayout::addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 2dd1110fe..8b4dcec35 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -23,8 +23,8 @@ public: void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index c28d1ebac..2e66cca90 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -36,47 +36,39 @@ void IntegralLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool IntegralLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left the upper or lower bound. - // Go Left of the integral. +ExpressionLayoutCursor IntegralLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left the upper or lower bound. Go Left of the integral. if (((upperBoundLayout() && cursor->pointedExpressionLayout() == upperBoundLayout()) || (lowerBoundLayout() && cursor->pointedExpressionLayout() == lowerBoundLayout())) && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left the integrand. - // Go Right of the lower bound. + // Case: Left the integrand. Go Right of the lower bound. if (integrandLayout() && cursor->pointedExpressionLayout() == integrandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(lowerBoundLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right of the integral. - // Go to the integrand. + // Case: Right of the integral. Go to the integrand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()); - return true; + return ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left of the brackets. - // Ask the parent. + // Case: Left of the brackets. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor IntegralLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { // Case: Right the upper or lower bound. // Go Left of the integrand. if (((upperBoundLayout() @@ -86,66 +78,59 @@ bool IntegralLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec && cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); - cursor->setPointedExpressionLayout(integrandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right the integrand. - // Go Right. + // Case: Right the integrand. Go Right. if (integrandLayout() && cursor->pointedExpressionLayout() == integrandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left of the integral. - // Go to the upper bound. + // Case: Left of the integral. Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(upperBoundLayout()); - return true; + return ExpressionLayoutCursor(upperBoundLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool IntegralLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor IntegralLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool IntegralLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor IntegralLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index e8a7b8e74..1c1b8efd3 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -17,10 +17,10 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 29bd302c5..51890fffd 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -15,24 +15,21 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } -bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor MatrixLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { int childIndex = indexOfChild(cursor->pointedExpressionLayout()); if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Left && childIsLeftOfGrid(childIndex)) { - // Case: Left of a child on the left of the grid. - // Remove the grey squares of the grid, then go left of the grid. + /* Case: Left of a child on the left of the grid. + * Remove the grey squares of the grid, then go left of the grid. */ assert(hasGreySquares()); removeGreySquares(); *shouldRecomputeLayout = true; - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Right. - // Add the grey squares to the matrix, then move to the bottom right non empty - // nor grey child. + /* Case: Right. Add the grey squares to the matrix, then move to the bottom + * right non empty nor grey child. */ if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { @@ -41,15 +38,13 @@ bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomp *shouldRecomputeLayout = true; ExpressionLayout * lastChild = editableChild((m_numberOfColumns-1)*(m_numberOfRows-1)); assert(lastChild != nullptr); - cursor->setPointedExpressionLayout(lastChild); - return true; + return ExpressionLayoutCursor(lastChild, ExpressionLayoutCursor::Position::Right); } - return GridLayout::moveLeft(cursor, shouldRecomputeLayout); + return GridLayout::cursorLeftOf(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left. - // Add the grey squares to the matrix,, then go to the first entry. +ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left. Add the grey squares to the matrix, then go to the first entry. if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left) { @@ -59,8 +54,7 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom assert(m_numberOfColumns*m_numberOfRows >= 1); ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); - cursor->setPointedExpressionLayout(firstChild); - return true; + return ExpressionLayoutCursor(firstChild, ExpressionLayoutCursor::Position::Left); } // Case: The cursor points to a grid's child. int childIndex = indexOfChild(cursor->pointedExpressionLayout()); @@ -68,19 +62,18 @@ bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecom && cursor->position() == ExpressionLayoutCursor::Position::Right && childIsRightOfGrid(childIndex)) { - // Case: Right of a child on the right of the grid. - // Remove the grey squares of the grid, then go right of the grid. - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + /* Case: Right of a child on the right of the grid. Remove the grey squares + * of the grid, then go right of the grid. */ assert(hasGreySquares()); removeGreySquares(); *shouldRecomputeLayout = true; - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); + } - return GridLayout::moveRight(cursor, shouldRecomputeLayout); + return GridLayout::cursorRightOf(cursor, shouldRecomputeLayout); } -bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor MatrixLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { @@ -89,16 +82,16 @@ bool MatrixLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomput break; } } - bool returnValue = GridLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); - if (returnValue && shouldRemoveGreySquares) { + ExpressionLayoutCursor resultCursor = GridLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); + if (resultCursor.isDefined() && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); *shouldRecomputeLayout = true; } - return returnValue; + return resultCursor; } -bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { @@ -107,18 +100,18 @@ bool MatrixLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomp break; } } - bool returnValue = GridLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); - if (returnValue && shouldRemoveGreySquares) { + ExpressionLayoutCursor resultCursor = GridLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + if (resultCursor.isDefined() && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); *shouldRecomputeLayout = true; } - return returnValue; + return resultCursor; } -bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - bool result = GridLayout::moveUpInside(cursor, shouldRecomputeLayout); - if (result && cursor->pointedExpressionLayout() != this) { +ExpressionLayoutCursor MatrixLayout::cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + ExpressionLayoutCursor result = GridLayout::cursorInDescendantsAbove(cursor, shouldRecomputeLayout); + if (result.isDefined() && cursor->pointedExpressionLayout() != this) { // Add the grey squares if the cursor is pointing at a matrix descendant, // not at the matrix itself. assert(!hasGreySquares()); @@ -128,9 +121,9 @@ bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRe return result; } -bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - bool result = GridLayout::moveDownInside(cursor, shouldRecomputeLayout); - if (result && cursor->pointedExpressionLayout() != this) { +ExpressionLayoutCursor MatrixLayout::cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + ExpressionLayoutCursor result = GridLayout::cursorInDescendantsUnder(cursor, shouldRecomputeLayout); + if (result.isDefined() && cursor->pointedExpressionLayout() != this) { // Add the grey squares if the cursor is pointing at a matrix descendant, // not at the matrix itself. assert(!hasGreySquares()); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 8a96f538e..1765bf1ec 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -11,12 +11,12 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveUpInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveDownInside(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 5af07f1e5..1376c098b 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -50,128 +50,102 @@ void NthRootLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool NthRootLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the radicand. - // Go the index if there is one, else go Left of the root. +ExpressionLayoutCursor NthRootLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the radicand. Go the index if any, else go Left of the root. if (radicandLayout() && cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { if (indexLayout()) { - cursor->setPointedExpressionLayout(indexLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right); } - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left of the index. - // Go Left of the root. + // Case: Left of the index. Go Left of the root. if (indexLayout() && cursor->pointedExpressionLayout() == indexLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Right of the radicand. + // Case: Right. Go Right of the radicand. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(radicandLayout() != nullptr); - cursor->setPointedExpressionLayout(radicandLayout()); - return true; + return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool NthRootLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the radicand. - // Go the Right of the root. +ExpressionLayoutCursor NthRootLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the radicand. Go the Right of the root. if (radicandLayout() && cursor->pointedExpressionLayout() == radicandLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - // Case: Right of the index. - // Go Left of the integrand. + // Case: Right of the index. Go Left of the integrand. if (indexLayout() && cursor->pointedExpressionLayout() == indexLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(radicandLayout() != nullptr); - cursor->setPointedExpressionLayout(radicandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go index if there is one, else go to the radicand. + // Case: Left. Go index if there is one, else go to the radicand. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { if (indexLayout()) { - cursor->setPointedExpressionLayout(indexLayout()); - return true; + return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left); } assert(radicandLayout() != nullptr); - cursor->setPointedExpressionLayout(radicandLayout()); - return true; + return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool NthRootLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor NthRootLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left))) { - cursor->setPointedExpressionLayout(indexLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right); } // If the cursor is Left, move it to the index. if (indexLayout() && cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(indexLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool NthRootLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor NthRootLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { // If the cursor is Right of the index, move it to the radicand. if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right))) { assert(radicandLayout() != nullptr); - cursor->setPointedExpressionLayout(radicandLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } // If the cursor is Left of the index, move it Left . if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left))) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } static_assert('\x90' == Ion::Charset::Root, "Unicode error"); diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index ad562b75b..6fb59077f 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -18,10 +18,10 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp index 3c34d020e..59e2d8e36 100644 --- a/poincare/src/layout/parenthesis_layout.cpp +++ b/poincare/src/layout/parenthesis_layout.cpp @@ -22,38 +22,32 @@ void ParenthesisLayout::invalidAllSizesPositionsAndBaselines() { ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -bool ParenthesisLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ParenthesisLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go Left. + // Case: Right. Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool ParenthesisLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ParenthesisLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go Right. + // Case: Left. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } KDSize ParenthesisLayout::computeSize() { diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 46cc1bbd0..72ec20901 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -9,8 +9,8 @@ class ParenthesisLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLayout(); void invalidAllSizesPositionsAndBaselines() override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index fd9800526..53d2df118 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -17,49 +17,40 @@ void SequenceLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool SequenceLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the bounds. - // Go Left of the sequence. +ExpressionLayoutCursor SequenceLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the bounds. Go Left of the sequence. if (cursor->position() == ExpressionLayoutCursor::Position::Left && ((lowerBoundLayout() && cursor->pointedExpressionLayout() == lowerBoundLayout()) || (upperBoundLayout() && cursor->pointedExpressionLayout() == upperBoundLayout()))) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - // Case: Left of the argument. - // Go Right of the lower bound. + // Case: Left of the argument. Go Right of the lower bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left && argumentLayout() && cursor->pointedExpressionLayout() == argumentLayout()) { assert(lowerBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(lowerBoundLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(lowerBoundLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the argument and move Left. + // Case: Right. Go to the argument and move Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(argumentLayout() != nullptr); - cursor->setPointedExpressionLayout(argumentLayout()); - return true; + return ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Right); } assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the bounds. - // Go Left of the argument. +ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the bounds. Go Left of the argument. if (cursor->position() == ExpressionLayoutCursor::Position::Right && ((lowerBoundLayout() && cursor->pointedExpressionLayout() == lowerBoundLayout()) @@ -67,67 +58,59 @@ bool SequenceLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRec && cursor->pointedExpressionLayout() == upperBoundLayout()))) { assert(argumentLayout() != nullptr); - cursor->setPointedExpressionLayout(argumentLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right of the argument. - // Ask the parent. + // Case: Right of the argument. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Right && argumentLayout() && cursor->pointedExpressionLayout() == argumentLayout()) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the upper bound. + // Case: Left. Go to the upper bound. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); - cursor->setPointedExpressionLayout(upperBoundLayout()); - return true; + return ExpressionLayoutCursor(upperBoundLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool SequenceLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the upper bound. if (argumentLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); - return upperBoundLayout()->moveUpInside(cursor, shouldRecomputeLayout); + return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool SequenceLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor SequenceLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout()->moveDownInside(cursor, shouldRecomputeLayout); + return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 593259d91..934d1378a 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -11,10 +11,10 @@ public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayout * layoutToPointWhenInserting() override; char XNTChar() const override; protected: diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index c02a86378..bf493b980 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -63,128 +63,101 @@ void VerticalOffsetLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -bool VerticalOffsetLayout::moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the indice. - // Go Left. +ExpressionLayoutCursor VerticalOffsetLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Left of the indice. Go Left. if (indiceLayout() && cursor->pointedExpressionLayout() == indiceLayout() && cursor->position() == ExpressionLayoutCursor::Position::Left) { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } assert(cursor->pointedExpressionLayout() == this); - // Case: Right. - // Go to the indice. + // Case: Right. Go to the indice. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Ask the parent. + // Case: Left. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { - return m_parent->moveLeft(cursor, shouldRecomputeLayout); + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool VerticalOffsetLayout::moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the indice. - // Go Right. +ExpressionLayoutCursor VerticalOffsetLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the indice. Go Right. if (indiceLayout() && cursor->pointedExpressionLayout() == indiceLayout() && cursor->position() == ExpressionLayoutCursor::Position::Right) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); - // Case: Left. - // Go to the indice. + // Case: Left. Go to the indice. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } - // Case: Right. - // Ask the parent. + // Case: Right. Ask the parent. assert(cursor->position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { - return m_parent->moveRight(cursor, shouldRecomputeLayout); + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } - return false; + return ExpressionLayoutCursor(); } -bool VerticalOffsetLayout::moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Superscript. if (m_type == VerticalOffsetLayout::Type::Superscript) { - // Case: Right. - // Move to the indice. + // Case: Right. Move to the indice. if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Move to the indice. + // Case: Left. Move to the indice. if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } } - // Case: Subscript. - // Case: Left or Right of the indice. - // Put the cursor at the same position, pointing this. + /* Case: Subscript, Left or Right of the indice. Put the cursor at the same + * position, pointing this. */ if (m_type == VerticalOffsetLayout::Type::Subscript && indiceLayout() != nullptr && (cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left)) || cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right)))) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, cursor->position()); } - return ExpressionLayout::moveUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -bool VerticalOffsetLayout::moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Subscript. if (m_type == VerticalOffsetLayout::Type::Subscript) { - // Case: Right. - // Move to the indice. + // Case: Right. Move to the indice. if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } - // Case: Left. - // Move to the indice. + // Case: Left. Move to the indice. if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); - cursor->setPointedExpressionLayout(indiceLayout()); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); - return true; + return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } } - // Case: Superscript. - // Case: Left or Right of the indice. - // Put the cursor at the same position, pointing this. + /* Case: Superscript, Left or Right of the indice. Put the cursor at the same + * position, pointing this. */ if (m_type == VerticalOffsetLayout::Type::Superscript && indiceLayout() != nullptr && cursor->pointedExpressionLayout() == indiceLayout()) { - cursor->setPointedExpressionLayout(this); - return true; + return ExpressionLayoutCursor(this, cursor->position()); } - return ExpressionLayout::moveDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 1b6cadb88..03668876a 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -15,10 +15,10 @@ public: Type type() const { return m_type; } ExpressionLayout * clone() const override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - bool moveLeft(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveRight(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - bool moveUp(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - bool moveDown(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const { return true; } From 31face58a2039a80be79530df7229f4ee6050783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 15:53:45 +0200 Subject: [PATCH 334/459] [apps/escher] ScrollableEVWithCursor renamed ExpressionLayoutField Change-Id: Id0e4610fb677d8ad36721eef1a85f1c424d1743e --- apps/calculation/app.cpp | 10 ++-- apps/calculation/app.h | 2 +- .../edit_expression_controller.cpp | 26 +++++----- apps/calculation/edit_expression_controller.h | 16 +++--- apps/calculation/editable_expression_view.cpp | 4 +- apps/calculation/editable_expression_view.h | 2 +- apps/math_toolbox.cpp | 4 +- apps/math_toolbox.h | 2 +- apps/sequence/list/list_controller.cpp | 4 +- apps/sequence/list/list_controller.h | 6 +-- apps/shared/Makefile | 2 +- .../editable_expression_view_delegate_app.cpp | 30 +++++------ .../editable_expression_view_delegate_app.h | 10 ++-- .../expression_layout_field_delegate.cpp | 31 ++++++++++++ .../shared/expression_layout_field_delegate.h | 23 +++++++++ ...e_expression_view_with_cursor_delegate.cpp | 31 ------------ ...ble_expression_view_with_cursor_delegate.h | 23 --------- apps/variable_box_controller.cpp | 20 ++++---- apps/variable_box_controller.h | 6 +-- escher/Makefile | 2 +- escher/include/escher.h | 4 +- .../include/escher/editable_expression_view.h | 10 ++-- ...ith_cursor.h => expression_layout_field.h} | 16 +++--- .../escher/expression_layout_field_delegate.h | 19 +++++++ escher/include/escher/input_view_controller.h | 24 ++++----- ...ble_expression_view_with_cursor_delegate.h | 19 ------- escher/src/editable_expression_view.cpp | 32 ++++++------ ...cursor.cpp => expression_layout_field.cpp} | 50 +++++++++---------- escher/src/input_view_controller.cpp | 24 ++++----- 29 files changed, 226 insertions(+), 226 deletions(-) create mode 100644 apps/shared/expression_layout_field_delegate.cpp create mode 100644 apps/shared/expression_layout_field_delegate.h delete mode 100644 apps/shared/scrollable_expression_view_with_cursor_delegate.cpp delete mode 100644 apps/shared/scrollable_expression_view_with_cursor_delegate.h rename escher/include/escher/{scrollable_expression_view_with_cursor.h => expression_layout_field.h} (57%) create mode 100644 escher/include/escher/expression_layout_field_delegate.h delete mode 100644 escher/include/escher/scrollable_expression_view_with_cursor_delegate.h rename escher/src/{scrollable_expression_view_with_cursor.cpp => expression_layout_field.cpp} (78%) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index fba7dac4d..b6b10e1aa 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -85,23 +85,23 @@ bool App::textInputIsCorrect(const char * text) { return true; } -bool App::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - if ((event == Ion::Events::Var || event == Ion::Events::XNT) && EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event)) { +bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && EditableExpressionViewDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { return true; } /* Here, we check that the expression entered by the user can be printed with * less than k_printedExpressionLength characters. Otherwise, we prevent the * user from adding this expression to the calculation store. */ - if (!(scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event))) { + if (!(expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event))) { return false; } int bufferLength = TextField::maxBufferSize(); char bufferForParsing[bufferLength]; - Poincare::ExpressionLayout * expressionLayout = scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout(); + Poincare::ExpressionLayout * expressionLayout = expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout(); expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); Expression * exp = Expression::parse(bufferForParsing); if (exp == nullptr) { - scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); + expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } char buffer[Calculation::k_printedExpressionSize]; diff --git a/apps/calculation/app.h b/apps/calculation/app.h index ecc8ab991..6284ff992 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -29,7 +29,7 @@ public: }; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textInputIsCorrect(const char * text); - bool scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; + bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; const char * XNT() override; private: App(Container * container, Snapshot * snapshot); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 37cd3c772..e6dc301f2 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -9,10 +9,10 @@ using namespace Shared; namespace Calculation { -EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : +EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : View(), m_mainView(subview), - m_editableExpressionView(parentResponder, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) + m_editableExpressionView(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) { } @@ -91,26 +91,26 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) return inputViewDidAbortEditing(textField->text()); } -bool EditExpressionController::scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); - if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event) && !expressionLayout()->hasText() && m_calculationStore->numberOfCalculations() > 0) { +bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); + if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayout()->hasText() && m_calculationStore->numberOfCalculations() > 0) { return inputViewDidReceiveEvent(event); } - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); + return editableExpressionViewDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); } -bool EditExpressionController::scrollableExpressionViewWithCursorDidFinishEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { - assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); +bool EditExpressionController::expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { + assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); return inputViewDidFinishEditing(text, event); } -bool EditExpressionController::scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); +bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) { + assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); return inputViewDidAbortEditing(nullptr); } -void EditExpressionController::scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - assert(scrollableExpressionViewWithCursor == ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()); +void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) { + assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); reloadView(); } @@ -177,7 +177,7 @@ void EditExpressionController::viewDidDisappear() { } Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { - return ((ContentView *)view())->editableExpressionView()->scrollableExpressionViewWithCursor()->expressionViewWithCursor()->expressionView()->expressionLayout(); + return ((ContentView *)view())->editableExpressionView()->expressionLayoutField()->expressionViewWithCursor()->expressionView()->expressionLayout(); } } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 7275e411f..21ffd5b22 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -4,7 +4,7 @@ #include #include "editable_expression_view.h" #include "../shared/text_field_delegate.h" -#include "../shared/scrollable_expression_view_with_cursor_delegate.h" +#include "../shared/expression_layout_field_delegate.h" #include "history_controller.h" #include "calculation_store.h" @@ -12,7 +12,7 @@ namespace Calculation { class HistoryController; /* TODO: implement a split view */ -class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::ScrollableExpressionViewWithCursorDelegate { +class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate { public: EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore); void didBecomeFirstResponder() override; @@ -26,16 +26,16 @@ public: bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(::TextField * textField) override; - /* ScrollableExpressionViewWithCursorDelegate */ - bool scrollableExpressionViewWithCursorDidReceiveEvent(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidFinishEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; - void scrollableExpressionViewWithCursorDidChangeSize(::ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + /* ExpressionLayoutFieldDelegate */ + bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) override; + bool expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) override; + void expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) override; private: class ContentView : public View { public: - ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void reload(); TableView * mainView() { return m_mainView; } EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } diff --git a/apps/calculation/editable_expression_view.cpp b/apps/calculation/editable_expression_view.cpp index ac9b2000d..cc5377154 100644 --- a/apps/calculation/editable_expression_view.cpp +++ b/apps/calculation/editable_expression_view.cpp @@ -2,8 +2,8 @@ namespace Calculation { -EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : - ::EditableExpressionView(parentResponder, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) +EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : + ::EditableExpressionView(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) { setEditing(true); } diff --git a/apps/calculation/editable_expression_view.h b/apps/calculation/editable_expression_view.h index 52a1faad3..d0e1aa1ab 100644 --- a/apps/calculation/editable_expression_view.h +++ b/apps/calculation/editable_expression_view.h @@ -7,7 +7,7 @@ namespace Calculation { class EditableExpressionView : public ::EditableExpressionView { public: - EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); protected: bool handleEvent(Ion::Events::Event event) override; }; diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 61b5ca479..f452663fb 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -118,8 +118,8 @@ void MathToolbox::setSenderAndAction(Responder * sender, Action action) { m_action = action; } -void MathToolbox::actionForScrollableExpressionViewWithCursor(void * sender, const char * text, bool removeArguments) { - ScrollableExpressionViewWithCursor * expressionLayoutEditorSender = static_cast(sender); +void MathToolbox::actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments) { + ExpressionLayoutField * expressionLayoutEditorSender = static_cast(sender); Expression * resultExpression = nullptr; if (removeArguments) { // Replace the arguments with Empty chars. diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index e4f29bda2..6079054e2 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -10,7 +10,7 @@ public: typedef void (*Action)(void * sender, const char * text, bool removeArguments); MathToolbox(); void setSenderAndAction(Responder * sender, Action action); - static void actionForScrollableExpressionViewWithCursor(void * sender, const char * text, bool removeArguments = true); + static void actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments = true); static void actionForTextInput(void * sender, const char * text, bool removeArguments = true); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 3a4a7f185..269668c78 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -29,9 +29,9 @@ Toolbox * ListController::toolboxForTextInput(TextInput * textInput) { return &m_sequenceToolbox; } -Toolbox * ListController::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { +Toolbox * ListController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { setToolboxExtraCells(); - m_sequenceToolbox.setSenderAndAction(scrollableExpressionViewWithCursor, MathToolbox::actionForScrollableExpressionViewWithCursor); + m_sequenceToolbox.setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField); return &m_sequenceToolbox; } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 7b4c5c853..452a06472 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -7,7 +7,7 @@ #include "../../shared/function_expression_cell.h" #include "../../shared/list_controller.h" #include "../../shared/new_function_cell.h" -#include "../../shared/scrollable_expression_view_with_cursor_delegate.h" +#include "../../shared/expression_layout_field_delegate.h" #include "../../shared/text_field_delegate.h" #include "list_parameter_controller.h" #include "sequence_toolbox.h" @@ -15,7 +15,7 @@ namespace Sequence { -class ListController : public Shared::ListController, public Shared::TextFieldDelegate, public Shared::ScrollableExpressionViewWithCursorDelegate { +class ListController : public Shared::ListController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate { public: ListController(Responder * parentResponder, SequenceStore * sequenceStore, ButtonRowController * header, ButtonRowController * footer); const char * title() override; @@ -23,7 +23,7 @@ public: virtual KDCoordinate rowHeight(int j) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; Toolbox * toolboxForTextInput(TextInput * textInput) override; - Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; void selectPreviousNewSequenceCell(); private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index b7f4c0574..c91980070 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -38,7 +38,7 @@ app_objs += $(addprefix apps/shared/,\ regular_table_view_data_source.o\ round_cursor_view.o\ simple_interactive_curve_view_controller.o\ - scrollable_expression_view_with_cursor_delegate.o\ + expression_layout_field_delegate.o\ store_controller.o\ store_parameter_controller.o\ sum_graph_controller.o\ diff --git a/apps/shared/editable_expression_view_delegate_app.cpp b/apps/shared/editable_expression_view_delegate_app.cpp index 3ce1f53cb..cd4f4336c 100644 --- a/apps/shared/editable_expression_view_delegate_app.cpp +++ b/apps/shared/editable_expression_view_delegate_app.cpp @@ -8,48 +8,48 @@ namespace Shared { EditableExpressionViewDelegateApp::EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : TextFieldDelegateApp(container, snapshot, rootViewController), - ScrollableExpressionViewWithCursorDelegate() + ExpressionLayoutFieldDelegate() { } -bool EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { +bool EditableExpressionViewDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } -bool EditableExpressionViewDelegateApp::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - if (scrollableExpressionViewWithCursor->isEditing() && scrollableExpressionViewWithCursor->scrollableExpressionViewWithCursorShouldFinishEditing(event)) { - if (!scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout()->hasText()) { - scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); +bool EditableExpressionViewDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { + if (!expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout()->hasText()) { + expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } int bufferSize = 256; char buffer[bufferSize]; - scrollableExpressionViewWithCursor->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); Expression * exp = Expression::parse(buffer); if (exp != nullptr) { delete exp; } if (exp == nullptr) { - scrollableExpressionViewWithCursor->app()->displayWarning(I18n::Message::SyntaxError); + expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } } if (event == Ion::Events::Var) { - if (!scrollableExpressionViewWithCursor->isEditing()) { - scrollableExpressionViewWithCursor->setEditing(true); + if (!expressionLayoutField->isEditing()) { + expressionLayoutField->setEditing(true); } - AppsContainer * appsContainer = (AppsContainer *)scrollableExpressionViewWithCursor->app()->container(); + AppsContainer * appsContainer = (AppsContainer *)expressionLayoutField->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setScrollableExpressionViewWithCursorSender(scrollableExpressionViewWithCursor); - scrollableExpressionViewWithCursor->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + variableBoxController->setExpressionLayoutFieldSender(expressionLayoutField); + expressionLayoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } return false; } -Toolbox * EditableExpressionViewDelegateApp::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { +Toolbox * EditableExpressionViewDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { Toolbox * toolbox = container()->mathToolbox(); - static_cast(toolbox)->setSenderAndAction(scrollableExpressionViewWithCursor, MathToolbox::actionForScrollableExpressionViewWithCursor); + static_cast(toolbox)->setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField); return toolbox; } diff --git a/apps/shared/editable_expression_view_delegate_app.h b/apps/shared/editable_expression_view_delegate_app.h index 626b3fac7..a4911e7f7 100644 --- a/apps/shared/editable_expression_view_delegate_app.h +++ b/apps/shared/editable_expression_view_delegate_app.h @@ -2,16 +2,16 @@ #define SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H #include "text_field_delegate_app.h" -#include +#include namespace Shared { -class EditableExpressionViewDelegateApp : public TextFieldDelegateApp, public ScrollableExpressionViewWithCursorDelegate { +class EditableExpressionViewDelegateApp : public TextFieldDelegateApp, public ExpressionLayoutFieldDelegate { public: virtual ~EditableExpressionViewDelegateApp() = default; - bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - virtual bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; protected: EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); }; diff --git a/apps/shared/expression_layout_field_delegate.cpp b/apps/shared/expression_layout_field_delegate.cpp new file mode 100644 index 000000000..11dfb78bd --- /dev/null +++ b/apps/shared/expression_layout_field_delegate.cpp @@ -0,0 +1,31 @@ +#include "expression_layout_field_delegate.h" + +using namespace Poincare; + +namespace Shared { + +bool ExpressionLayoutFieldDelegate::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->expressionLayoutFieldShouldFinishEditing(expressionLayoutField, event); +} + +bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); +} + +bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { + return editableExpressionViewDelegateApp()->expressionLayoutFieldDidFinishEditing(expressionLayoutField, text, event); +} + +bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { + return editableExpressionViewDelegateApp()->expressionLayoutFieldDidAbortEditing(expressionLayoutField); +} + +void ExpressionLayoutFieldDelegate::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { + return editableExpressionViewDelegateApp()->expressionLayoutFieldDidChangeSize(expressionLayoutField); +} + +Toolbox * ExpressionLayoutFieldDelegate::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { + return editableExpressionViewDelegateApp()->toolboxForExpressionLayoutField(expressionLayoutField); +} + +} diff --git a/apps/shared/expression_layout_field_delegate.h b/apps/shared/expression_layout_field_delegate.h new file mode 100644 index 000000000..132f353aa --- /dev/null +++ b/apps/shared/expression_layout_field_delegate.h @@ -0,0 +1,23 @@ +#ifndef SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H +#define SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H + +#include +#include "editable_expression_view_delegate_app.h" + +namespace Shared { + +class ExpressionLayoutFieldDelegate : public ::ExpressionLayoutFieldDelegate { +public: + bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) override; + bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override; + void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override; + Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; +private: + virtual EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() = 0; +}; + +} + +#endif diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp b/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp deleted file mode 100644 index 84a29933c..000000000 --- a/apps/shared/scrollable_expression_view_with_cursor_delegate.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "scrollable_expression_view_with_cursor_delegate.h" - -using namespace Poincare; - -namespace Shared { - -bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorShouldFinishEditing(scrollableExpressionViewWithCursor, event); -} - -bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); -} - -bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidFinishEditing(scrollableExpressionViewWithCursor, text, event); -} - -bool ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidAbortEditing(scrollableExpressionViewWithCursor); -} - -void ScrollableExpressionViewWithCursorDelegate::scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - return editableExpressionViewDelegateApp()->scrollableExpressionViewWithCursorDidChangeSize(scrollableExpressionViewWithCursor); -} - -Toolbox * ScrollableExpressionViewWithCursorDelegate::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - return editableExpressionViewDelegateApp()->toolboxForScrollableExpressionViewWithCursor(scrollableExpressionViewWithCursor); -} - -} diff --git a/apps/shared/scrollable_expression_view_with_cursor_delegate.h b/apps/shared/scrollable_expression_view_with_cursor_delegate.h deleted file mode 100644 index 093cecf71..000000000 --- a/apps/shared/scrollable_expression_view_with_cursor_delegate.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SHARED_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H -#define SHARED_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H - -#include -#include "editable_expression_view_delegate_app.h" - -namespace Shared { - -class ScrollableExpressionViewWithCursorDelegate : public ::ScrollableExpressionViewWithCursorDelegate { -public: - bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; - void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; - Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; -private: - virtual EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() = 0; -}; - -} - -#endif diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 1413861e1..cfa4a143f 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -200,9 +200,9 @@ void VariableBoxController::ContentViewController::setTextFieldSender(TextField m_insertTextAction = &insertTextInTextInput; } -void VariableBoxController::ContentViewController::setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - m_sender = scrollableExpressionViewWithCursor; - m_insertTextAction = &insertTextInScrollableExpressionViewWithCursor; +void VariableBoxController::ContentViewController::setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField) { + m_sender = expressionLayoutField; + m_insertTextAction = &insertTextInExpressionLayoutField; } void VariableBoxController::ContentViewController::reloadData() { @@ -295,12 +295,12 @@ void VariableBoxController::ContentViewController::insertTextInTextInput(void * textInput->handleEventWithText(textToInsert); } -void VariableBoxController::ContentViewController::insertTextInScrollableExpressionViewWithCursor(void * sender, const char * textToInsert) { - ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor = static_cast(sender); - if (!scrollableExpressionViewWithCursor->isEditing()) { - scrollableExpressionViewWithCursor->setEditing(true); +void VariableBoxController::ContentViewController::insertTextInExpressionLayoutField(void * sender, const char * textToInsert) { + ExpressionLayoutField * expressionLayoutField = static_cast(sender); + if (!expressionLayoutField->isEditing()) { + expressionLayoutField->setEditing(true); } - scrollableExpressionViewWithCursor->insertLayoutFromTextAtCursor(textToInsert); + expressionLayoutField->insertLayoutFromTextAtCursor(textToInsert); } VariableBoxController::VariableBoxController(GlobalContext * context) : @@ -317,8 +317,8 @@ void VariableBoxController::setTextFieldSender(TextField * textField) { m_contentViewController.setTextFieldSender(textField); } -void VariableBoxController::setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - m_contentViewController.setScrollableExpressionViewWithCursorSender(scrollableExpressionViewWithCursor); +void VariableBoxController::setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField) { + m_contentViewController.setExpressionLayoutFieldSender(expressionLayoutField); } void VariableBoxController::viewWillAppear() { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index ca643a440..527b8ac77 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -14,7 +14,7 @@ public: VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; void setTextFieldSender(TextField * textField); - void setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor); + void setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField); void viewWillAppear() override; void viewDidDisappear() override; private: @@ -34,7 +34,7 @@ private: int indexFromCumulatedHeight(KDCoordinate offsetY) override; int typeAtLocation(int i, int j) override; void setTextFieldSender(TextField * textField); - void setScrollableExpressionViewWithCursorSender(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor); + void setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField); void reloadData(); void resetPage(); void viewDidDisappear() override; @@ -60,7 +60,7 @@ private: const Poincare::Expression * expressionForIndex(int index); Poincare::ExpressionLayout * expressionLayoutForIndex(int index); static void insertTextInTextInput(void * sender, const char * textToInsert); - static void insertTextInScrollableExpressionViewWithCursor(void * sender, const char * textToInsert); + static void insertTextInExpressionLayoutField(void * sender, const char * textToInsert); Poincare::GlobalContext * m_context; Responder * m_sender; Action m_insertTextAction; diff --git a/escher/Makefile b/escher/Makefile index 7eeebb132..dcc8e7df4 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -50,7 +50,7 @@ objs += $(addprefix escher/src/,\ scroll_view_data_source.o\ scroll_view_indicator.o\ scrollable_view.o\ - scrollable_expression_view_with_cursor.o\ + expression_layout_field.o\ selectable_table_view.o\ selectable_table_view_data_source.o\ selectable_table_view_delegate.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 8c07d9ea9..e3d3411b5 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -53,8 +53,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/editable_expression_view.h index 44d5f867e..eb28ffd87 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/editable_expression_view.h @@ -1,14 +1,14 @@ #ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_H #define ESCHER_EDITABLE_EXPRESSION_VIEW_H -#include -#include +#include +#include #include #include class EditableExpressionView : public Responder, public View { public: - EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void setEditing(bool isEditing, bool reinitDraftBuffer = true); bool isEditing() const; @@ -17,7 +17,7 @@ public: void insertText(const char * text); void reload(); TextField * textField() { return &m_textField; } - ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor() { return &m_scrollableExpressionViewWithCursor; } + ExpressionLayoutField * expressionLayoutField() { return &m_expressionLayoutField; } bool editionIsInTextField() const; bool isEmpty() const; bool heightIsMaximal() const; @@ -41,7 +41,7 @@ private: KDCoordinate inputViewHeight() const; KDCoordinate maximalHeight() const; TextField m_textField; - ScrollableExpressionViewWithCursor m_scrollableExpressionViewWithCursor; + ExpressionLayoutField m_expressionLayoutField; char m_textBody[k_bufferLength]; }; diff --git a/escher/include/escher/scrollable_expression_view_with_cursor.h b/escher/include/escher/expression_layout_field.h similarity index 57% rename from escher/include/escher/scrollable_expression_view_with_cursor.h rename to escher/include/escher/expression_layout_field.h index 7983e0ab7..8e81e40c3 100644 --- a/escher/include/escher/scrollable_expression_view_with_cursor.h +++ b/escher/include/escher/expression_layout_field.h @@ -1,15 +1,15 @@ -#ifndef ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H -#define ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_H +#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_H +#define ESCHER_EXPRESSION_LAYOUT_FIELD_H #include #include -#include +#include #include -class ScrollableExpressionViewWithCursor : public ScrollableView, public ScrollViewDataSource { +class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource { public: - ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ScrollableExpressionViewWithCursorDelegate * delegate = nullptr); - void setDelegate(ScrollableExpressionViewWithCursorDelegate * delegate) { m_delegate = delegate; } + ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr); + void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; } ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } bool isEditing() const; void setEditing(bool isEditing); @@ -21,7 +21,7 @@ public: Toolbox * toolbox() override; bool handleEvent(Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorShouldFinishEditing(Ion::Events::Event event); + bool expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event); void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout); void insertLayoutFromTextAtCursor(const char * text); @@ -34,7 +34,7 @@ protected: bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); ExpressionViewWithCursor m_expressionViewWithCursor; private: - ScrollableExpressionViewWithCursorDelegate * m_delegate; + ExpressionLayoutFieldDelegate * m_delegate; }; #endif diff --git a/escher/include/escher/expression_layout_field_delegate.h b/escher/include/escher/expression_layout_field_delegate.h new file mode 100644 index 000000000..80d284f85 --- /dev/null +++ b/escher/include/escher/expression_layout_field_delegate.h @@ -0,0 +1,19 @@ +#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H +#define ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H + +#include +#include + +class ExpressionLayoutField; + +class ExpressionLayoutFieldDelegate { +public: + virtual bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0; + virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0; + virtual bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { return false; } + virtual bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { return false; } + virtual void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) {} + virtual Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) = 0; +}; + +#endif diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 7c39d9b94..175d06ca8 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -2,7 +2,7 @@ #define ESCHER_INPUT_VIEW_CONTROLLER_H #include -#include +#include #include #include #include @@ -11,9 +11,9 @@ /* TODO Implement a split view. Because we use a modal view, the main view is * redrawn underneath the modal view, which is visible and ugly. */ -class InputViewController : public ModalViewController, TextFieldDelegate, ScrollableExpressionViewWithCursorDelegate { +class InputViewController : public ModalViewController, TextFieldDelegate, ExpressionLayoutFieldDelegate { public: - InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction); const char * textBody(); void abortEditionAndDismiss(); @@ -25,18 +25,18 @@ public: bool textFieldDidAbortEditing(TextField * textField) override; Toolbox * toolboxForTextInput(TextInput * textInput) override; - /* ScrollableExpressionViewWithCursorDelegate */ - bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) override; - bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; - void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; - Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) override; + /* ExpressionLayoutFieldDelegate */ + bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) override; + bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override; + void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override; + Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; private: class EditableExpressionViewController : public ViewController { public: - EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate); + EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void didBecomeFirstResponder() override; View * view() override { return &m_editableExpressionView; } EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } @@ -49,7 +49,7 @@ private: Invocation m_successAction; Invocation m_failureAction; TextFieldDelegate * m_textFieldDelegate; - ScrollableExpressionViewWithCursorDelegate * m_scrollableExpressionViewWithCursorDelegate; + ExpressionLayoutFieldDelegate * m_expressionLayoutFieldDelegate; bool m_inputViewHeightIsMaximal; }; diff --git a/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h b/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h deleted file mode 100644 index c2bf5fe96..000000000 --- a/escher/include/escher/scrollable_expression_view_with_cursor_delegate.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H -#define ESCHER_SCROLLABLE_EXPRESSION_VIEW_WITH_CURSOR_DELEGATE_H - -#include -#include - -class ScrollableExpressionViewWithCursor; - -class ScrollableExpressionViewWithCursorDelegate { -public: - virtual bool scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; - virtual bool scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) = 0; - virtual bool scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { return false; } - virtual bool scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { return false; } - virtual void scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) {} - virtual Toolbox * toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) = 0; -}; - -#endif diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 00c98bd13..aab5d9c72 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -2,11 +2,11 @@ #include #include -EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : +EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : Responder(parentResponder), View(), m_textField(parentResponder, m_textBody, m_textBody, k_bufferLength, textFieldDelegate, false), - m_scrollableExpressionViewWithCursor(parentResponder, new Poincare::HorizontalLayout(), scrollableExpressionViewWithCursorDelegate) + m_expressionLayoutField(parentResponder, new Poincare::HorizontalLayout(), expressionLayoutFieldDelegate) { m_textBody[0] = 0; } @@ -16,19 +16,19 @@ void EditableExpressionView::setEditing(bool isEditing, bool reinitDraftBuffer) m_textField.setEditing(isEditing, reinitDraftBuffer); } else { if (reinitDraftBuffer) { - m_scrollableExpressionViewWithCursor.clearLayout(); + m_expressionLayoutField.clearLayout(); } - m_scrollableExpressionViewWithCursor.setEditing(isEditing); + m_expressionLayoutField.setEditing(isEditing); } } bool EditableExpressionView::isEditing() const { - return editionIsInTextField() ? m_textField.isEditing() : m_scrollableExpressionViewWithCursor.isEditing(); + return editionIsInTextField() ? m_textField.isEditing() : m_expressionLayoutField.isEditing(); } const char * EditableExpressionView::text() { if (!editionIsInTextField()) { - m_scrollableExpressionViewWithCursor.expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(m_textBody, k_bufferLength); + m_expressionLayoutField.expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(m_textBody, k_bufferLength); } return m_textBody; } @@ -38,9 +38,9 @@ void EditableExpressionView::setText(const char * text) { m_textField.setText(text); return; } - m_scrollableExpressionViewWithCursor.clearLayout(); + m_expressionLayoutField.clearLayout(); if (strlen(text) > 0) { - m_scrollableExpressionViewWithCursor.insertLayoutFromTextAtCursor(text); + m_expressionLayoutField.insertLayoutFromTextAtCursor(text); } } @@ -48,8 +48,8 @@ void EditableExpressionView::insertText(const char * text) { if (editionIsInTextField()) { m_textField.handleEventWithText(text); } else { - m_scrollableExpressionViewWithCursor.setEditing(true); - m_scrollableExpressionViewWithCursor.insertLayoutFromTextAtCursor(text); + m_expressionLayoutField.setEditing(true); + m_expressionLayoutField.insertLayoutFromTextAtCursor(text); } } @@ -58,17 +58,17 @@ View * EditableExpressionView::subviewAtIndex(int index) { if (editionIsInTextField()) { return &m_textField; } - return &m_scrollableExpressionViewWithCursor; + return &m_expressionLayoutField; } void EditableExpressionView::layoutSubviews() { KDRect inputViewFrame(k_leftMargin, k_separatorThickness, bounds().width() - k_leftMargin, bounds().height() - k_separatorThickness); if (editionIsInTextField()) { m_textField.setFrame(inputViewFrame); - m_scrollableExpressionViewWithCursor.setFrame(KDRectZero); + m_expressionLayoutField.setFrame(KDRectZero); return; } - m_scrollableExpressionViewWithCursor.setFrame(inputViewFrame); + m_expressionLayoutField.setFrame(inputViewFrame); m_textField.setFrame(KDRectZero); } @@ -89,7 +89,7 @@ void EditableExpressionView::drawRect(KDContext * ctx, KDRect rect) const { } bool EditableExpressionView::handleEvent(Ion::Events::Event event) { - return editionIsInTextField() ? m_textField.handleEvent(event) : m_scrollableExpressionViewWithCursor.handleEvent(event); + return editionIsInTextField() ? m_textField.handleEvent(event) : m_expressionLayoutField.handleEvent(event); } KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { @@ -104,7 +104,7 @@ bool EditableExpressionView::isEmpty() const { if (editionIsInTextField()) { return m_textField.draftTextLength() == 0; } - Poincare::ExpressionLayout * layout = const_cast(&m_scrollableExpressionViewWithCursor)->expressionViewWithCursor()->expressionView()->expressionLayout(); + Poincare::ExpressionLayout * layout = const_cast(&m_expressionLayoutField)->expressionViewWithCursor()->expressionView()->expressionLayout(); return !layout->hasText(); } @@ -120,7 +120,7 @@ KDCoordinate EditableExpressionView::inputViewHeight() const { + k_verticalExpressionViewMargin + min(maximalHeight(), max(k_textFieldHeight, - m_scrollableExpressionViewWithCursor.minimalSizeForOptimalDisplay().height() + m_expressionLayoutField.minimalSizeForOptimalDisplay().height() + k_verticalExpressionViewMargin)); } diff --git a/escher/src/scrollable_expression_view_with_cursor.cpp b/escher/src/expression_layout_field.cpp similarity index 78% rename from escher/src/scrollable_expression_view_with_cursor.cpp rename to escher/src/expression_layout_field.cpp index 63dae9514..7c5fd81f4 100644 --- a/escher/src/scrollable_expression_view_with_cursor.cpp +++ b/escher/src/expression_layout_field.cpp @@ -1,44 +1,44 @@ -#include +#include #include #include #include #include #include -ScrollableExpressionViewWithCursor::ScrollableExpressionViewWithCursor(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ScrollableExpressionViewWithCursorDelegate * delegate) : +ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : ScrollableView(parentResponder, &m_expressionViewWithCursor, this), m_expressionViewWithCursor(expressionLayout), m_delegate(delegate) { } -bool ScrollableExpressionViewWithCursor::isEditing() const { +bool ExpressionLayoutField::isEditing() const { return m_expressionViewWithCursor.isEditing(); } -void ScrollableExpressionViewWithCursor::setEditing(bool isEditing) { +void ExpressionLayoutField::setEditing(bool isEditing) { m_expressionViewWithCursor.setEditing(isEditing); } -void ScrollableExpressionViewWithCursor::clearLayout() { +void ExpressionLayoutField::clearLayout() { delete m_expressionViewWithCursor.expressionView()->expressionLayout(); Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); } -void ScrollableExpressionViewWithCursor::scrollToCursor() { +void ExpressionLayoutField::scrollToCursor() { scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); } -Toolbox * ScrollableExpressionViewWithCursor::toolbox() { +Toolbox * ExpressionLayoutField::toolbox() { if (m_delegate) { - return m_delegate->toolboxForScrollableExpressionViewWithCursor(this); + return m_delegate->toolboxForExpressionLayoutField(this); } return nullptr; } -bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { +bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { KDSize previousSize = minimalSizeForOptimalDisplay(); bool didHandleEvent = false; bool shouldRecomputeLayout = m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); @@ -63,7 +63,7 @@ bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + m_delegate->expressionLayoutFieldDidChangeSize(this); reload(); } return true; @@ -71,15 +71,15 @@ bool ScrollableExpressionViewWithCursor::handleEvent(Ion::Events::Event event) { return false; } -bool ScrollableExpressionViewWithCursor::scrollableExpressionViewWithCursorShouldFinishEditing(Ion::Events::Event event) { - return m_delegate->scrollableExpressionViewWithCursorShouldFinishEditing(this, event); +bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event) { + return m_delegate->expressionLayoutFieldShouldFinishEditing(this, event); } -KDSize ScrollableExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { +KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); } -bool ScrollableExpressionViewWithCursor::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { +bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { Poincare::ExpressionLayoutCursor result; if (event == Ion::Events::Left) { result = m_expressionViewWithCursor.cursor()->cursorOnLeft(shouldRecomputeLayout); @@ -103,24 +103,24 @@ bool ScrollableExpressionViewWithCursor::privateHandleMoveEvent(Ion::Events::Eve return false; } -bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event event) { - if (m_delegate && m_delegate->scrollableExpressionViewWithCursorDidReceiveEvent(this, event)) { +bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { + if (m_delegate && m_delegate->expressionLayoutFieldDidReceiveEvent(this, event)) { return true; } if (Responder::handleEvent(event)) { /* The only event Responder handles is 'Toolbox' displaying. In that case, - * the ScrollableExpressionViewWithCursor is forced into editing mode. */ + * the ExpressionLayoutField is forced into editing mode. */ if (!isEditing()) { setEditing(true); } return true; } - if (isEditing() && scrollableExpressionViewWithCursorShouldFinishEditing(event)) { + if (isEditing() && expressionLayoutFieldShouldFinishEditing(event)) { setEditing(false); int bufferSize = TextField::maxBufferSize(); char buffer[bufferSize]; m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); - if (m_delegate->scrollableExpressionViewWithCursorDidFinishEditing(this, buffer, event)) { + if (m_delegate->expressionLayoutFieldDidFinishEditing(this, buffer, event)) { delete m_expressionViewWithCursor.expressionView()->expressionLayout(); Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); @@ -136,7 +136,7 @@ bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event e } if (event == Ion::Events::Back && isEditing()) { setEditing(false); - m_delegate->scrollableExpressionViewWithCursorDidAbortEditing(this); + m_delegate->expressionLayoutFieldDidAbortEditing(this); return true; } if (event == Ion::Events::Division) { @@ -197,7 +197,7 @@ bool ScrollableExpressionViewWithCursor::privateHandleEvent(Ion::Events::Event e return false; } -void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout) { +void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout) { if (layout == nullptr) { return; } @@ -219,11 +219,11 @@ void ScrollableExpressionViewWithCursor::insertLayoutAtCursor(Poincare::Expressi reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + m_delegate->expressionLayoutFieldDidChangeSize(this); } } -void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char * text) { +void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { Poincare::Expression * expression = Poincare::Expression::parse(text); if (expression != nullptr) { Poincare::ExpressionLayout * layout = expression->createLayout(); @@ -240,10 +240,10 @@ void ScrollableExpressionViewWithCursor::insertLayoutFromTextAtCursor(const char reload(); } -void ScrollableExpressionViewWithCursor::reload() { +void ExpressionLayoutField::reload() { m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); layoutSubviews(); - m_delegate->scrollableExpressionViewWithCursorDidChangeSize(this); + m_delegate->expressionLayoutFieldDidChangeSize(this); scrollToCursor(); m_expressionViewWithCursor.cursorPositionChanged(); markRectAsDirty(bounds()); diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index bd8e71d36..139eedc39 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -4,9 +4,9 @@ #include #include -InputViewController::EditableExpressionViewController::EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : +InputViewController::EditableExpressionViewController::EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ViewController(parentResponder), - m_editableExpressionView(this, textFieldDelegate, scrollableExpressionViewWithCursorDelegate) + m_editableExpressionView(this, textFieldDelegate, expressionLayoutFieldDelegate) { } @@ -14,13 +14,13 @@ void InputViewController::EditableExpressionViewController::didBecomeFirstRespon app()->setFirstResponder(&m_editableExpressionView); } -InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ScrollableExpressionViewWithCursorDelegate * scrollableExpressionViewWithCursorDelegate) : +InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ModalViewController(parentResponder, child), m_editableExpressionViewController(this, this, this), m_successAction(Invocation(nullptr, nullptr)), m_failureAction(Invocation(nullptr, nullptr)), m_textFieldDelegate(textFieldDelegate), - m_scrollableExpressionViewWithCursorDelegate(scrollableExpressionViewWithCursorDelegate), + m_expressionLayoutFieldDelegate(expressionLayoutFieldDelegate), m_inputViewHeightIsMaximal(false) { } @@ -64,23 +64,23 @@ Toolbox * InputViewController::toolboxForTextInput(TextInput * input) { return m_textFieldDelegate->toolboxForTextInput(input); } -bool InputViewController::scrollableExpressionViewWithCursorShouldFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { +bool InputViewController::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } -bool InputViewController::scrollableExpressionViewWithCursorDidReceiveEvent(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, Ion::Events::Event event) { - return m_scrollableExpressionViewWithCursorDelegate->scrollableExpressionViewWithCursorDidReceiveEvent(scrollableExpressionViewWithCursor, event); +bool InputViewController::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + return m_expressionLayoutFieldDelegate->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); } -bool InputViewController::scrollableExpressionViewWithCursorDidFinishEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor, const char * text, Ion::Events::Event event) { +bool InputViewController::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { return inputViewDidFinishEditing(); } -bool InputViewController::scrollableExpressionViewWithCursorDidAbortEditing(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { +bool InputViewController::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { return inputViewDidAbortEditing(); } -void InputViewController::scrollableExpressionViewWithCursorDidChangeSize(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { +void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { // Reload the view only if the EditableExpressionView height actually changes, // i.e. not if the height is already maximal and stays maximal. bool newInputViewHeightIsMaximal = m_editableExpressionViewController.editableExpressionView()->heightIsMaximal(); @@ -90,8 +90,8 @@ void InputViewController::scrollableExpressionViewWithCursorDidChangeSize(Scroll } } -Toolbox * InputViewController::toolboxForScrollableExpressionViewWithCursor(ScrollableExpressionViewWithCursor * scrollableExpressionViewWithCursor) { - return m_scrollableExpressionViewWithCursorDelegate->toolboxForScrollableExpressionViewWithCursor(scrollableExpressionViewWithCursor); +Toolbox * InputViewController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { + return m_expressionLayoutFieldDelegate->toolboxForExpressionLayoutField(expressionLayoutField); } bool InputViewController::inputViewDidFinishEditing() { From 22ab94209f1bfd220ea41a36cb9be6a130fc6456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 16:02:55 +0200 Subject: [PATCH 335/459] [apps/escher] Rename EditableExpressionView -> ExpressionField Change-Id: Iadfb220ee94e68762305060215f1ead0cac951fb --- apps/calculation/Makefile | 2 +- apps/calculation/app.cpp | 4 +- apps/calculation/app.h | 2 +- .../edit_expression_controller.cpp | 46 +++++++++---------- apps/calculation/edit_expression_controller.h | 8 ++-- apps/calculation/editable_expression_view.h | 17 ------- ...pression_view.cpp => expression_field.cpp} | 10 ++-- apps/calculation/expression_field.h | 17 +++++++ apps/sequence/list/list_controller.cpp | 2 +- apps/sequence/list/list_controller.h | 2 +- apps/shared/Makefile | 2 +- ....cpp => expression_field_delegate_app.cpp} | 10 ++-- ..._app.h => expression_field_delegate_app.h} | 10 ++-- .../expression_layout_field_delegate.cpp | 12 ++--- .../shared/expression_layout_field_delegate.h | 4 +- apps/shared/function_app.cpp | 2 +- apps/shared/function_app.h | 4 +- escher/Makefile | 2 +- escher/include/escher.h | 2 +- ...e_expression_view.h => expression_field.h} | 8 ++-- escher/include/escher/input_view_controller.h | 14 +++--- ...pression_view.cpp => expression_field.cpp} | 36 +++++++-------- escher/src/input_view_controller.cpp | 24 +++++----- 23 files changed, 120 insertions(+), 120 deletions(-) delete mode 100644 apps/calculation/editable_expression_view.h rename apps/calculation/{editable_expression_view.cpp => expression_field.cpp} (53%) create mode 100644 apps/calculation/expression_field.h rename apps/shared/{editable_expression_view_delegate_app.cpp => expression_field_delegate_app.cpp} (74%) rename apps/shared/{editable_expression_view_delegate_app.h => expression_field_delegate_app.h} (56%) rename escher/include/escher/{editable_expression_view.h => expression_field.h} (82%) rename escher/src/{editable_expression_view.cpp => expression_field.cpp} (74%) diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index 2393d9748..b5362a517 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -6,7 +6,7 @@ app_objs += $(addprefix apps/calculation/,\ calculation.o\ calculation_store.o\ edit_expression_controller.o\ - editable_expression_view.o\ + expression_field.o\ history_view_cell.o\ history_controller.o\ output_expressions_view.o\ diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index b6b10e1aa..be372c02c 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -43,7 +43,7 @@ void App::Snapshot::tidy() { } App::App(Container * container, Snapshot * snapshot) : - EditableExpressionViewDelegateApp(container, snapshot, &m_editExpressionController), + ExpressionFieldDelegateApp(container, snapshot, &m_editExpressionController), m_historyController(&m_editExpressionController, snapshot->calculationStore()), m_editExpressionController(&m_modalViewController, &m_historyController, snapshot->calculationStore()) { @@ -86,7 +86,7 @@ bool App::textInputIsCorrect(const char * text) { } bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - if ((event == Ion::Events::Var || event == Ion::Events::XNT) && EditableExpressionViewDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { return true; } /* Here, we check that the expression entered by the user can be printed with diff --git a/apps/calculation/app.h b/apps/calculation/app.h index 6284ff992..dea3fdca7 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -9,7 +9,7 @@ namespace Calculation { -class App : public Shared::EditableExpressionViewDelegateApp { +class App : public Shared::ExpressionFieldDelegateApp { public: class Descriptor : public ::App::Descriptor { public: diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index e6dc301f2..80e3f7155 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -12,7 +12,7 @@ namespace Calculation { EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : View(), m_mainView(subview), - m_editableExpressionView(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) + m_expressionField(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) { } @@ -22,15 +22,15 @@ View * EditExpressionController::ContentView::subviewAtIndex(int index) { return m_mainView; } assert(index == 1); - return &m_editableExpressionView; + return &m_expressionField; } void EditExpressionController::ContentView::layoutSubviews() { - KDCoordinate inputViewFrameHeight = m_editableExpressionView.minimalSizeForOptimalDisplay().height(); + KDCoordinate inputViewFrameHeight = m_expressionField.minimalSizeForOptimalDisplay().height(); KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight); m_mainView->setFrame(mainViewFrame); KDRect inputViewFrame(0, bounds().height() - inputViewFrameHeight, bounds().width(), inputViewFrameHeight); - m_editableExpressionView.setFrame(inputViewFrame); + m_expressionField.setFrame(inputViewFrame); } void EditExpressionController::ContentView::reload() { @@ -47,18 +47,18 @@ EditExpressionController::EditExpressionController(Responder * parentResponder, } const char * EditExpressionController::textBody() { - return ((ContentView *)view())->editableExpressionView()->text(); + return ((ContentView *)view())->expressionField()->text(); } void EditExpressionController::insertTextBody(const char * text) { - ((ContentView *)view())->editableExpressionView()->insertText(text); + ((ContentView *)view())->expressionField()->insertText(text); } bool EditExpressionController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Up) { if (m_calculationStore->numberOfCalculations() > 0) { m_cacheBuffer[0] = 0; - ((ContentView *)view())->editableExpressionView()->setEditing(false, false); + ((ContentView *)view())->expressionField()->setEditing(false, false); app()->setFirstResponder(m_historyController); } return true; @@ -69,12 +69,12 @@ bool EditExpressionController::handleEvent(Ion::Events::Event event) { void EditExpressionController::didBecomeFirstResponder() { int lastRow = m_calculationStore->numberOfCalculations() > 0 ? m_calculationStore->numberOfCalculations()-1 : 0; m_historyController->scrollToCell(0, lastRow); - ((ContentView *)view())->editableExpressionView()->setEditing(true, false); - app()->setFirstResponder(((ContentView *)view())->editableExpressionView()); + ((ContentView *)view())->expressionField()->setEditing(true, false); + app()->setFirstResponder(((ContentView *)view())->expressionField()); } bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { - assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); + assert(textField == ((ContentView *)view())->expressionField()->textField()); if (textField->isEditing() && textField->textFieldShouldFinishEditing(event) && textField->draftTextLength() == 0 && m_cacheBuffer[0] != 0) { return inputViewDidReceiveEvent(event); } @@ -82,35 +82,35 @@ bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, } bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) { - assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); + assert(textField == ((ContentView *)view())->expressionField()->textField()); return inputViewDidFinishEditing(text, event); } bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) { - assert(textField == ((ContentView *)view())->editableExpressionView()->textField()); + assert(textField == ((ContentView *)view())->expressionField()->textField()); return inputViewDidAbortEditing(textField->text()); } bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); + assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayout()->hasText() && m_calculationStore->numberOfCalculations() > 0) { return inputViewDidReceiveEvent(event); } - return editableExpressionViewDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); + return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); } bool EditExpressionController::expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { - assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); + assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); return inputViewDidFinishEditing(text, event); } bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) { - assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); + assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); return inputViewDidAbortEditing(nullptr); } void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) { - assert(expressionLayoutField == ((ContentView *)view())->editableExpressionView()->expressionLayoutField()); + assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); reloadView(); } @@ -118,7 +118,7 @@ TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() { return (App *)app(); } -EditableExpressionViewDelegateApp * EditExpressionController::editableExpressionViewDelegateApp() { +ExpressionFieldDelegateApp * EditExpressionController::expressionFieldDelegateApp() { return (App *)app(); } @@ -158,15 +158,15 @@ bool EditExpressionController::inputViewDidFinishEditing(const char * text, Ion: m_calculationStore->push(textBody(), calculationApp->localContext()); m_historyController->reload(); ((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1); - ((ContentView *)view())->editableExpressionView()->setEditing(true); - ((ContentView *)view())->editableExpressionView()->setText(""); + ((ContentView *)view())->expressionField()->setEditing(true); + ((ContentView *)view())->expressionField()->setText(""); return true; } bool EditExpressionController::inputViewDidAbortEditing(const char * text) { if (text != nullptr) { - ((ContentView *)view())->editableExpressionView()->setEditing(true, true); - ((ContentView *)view())->editableExpressionView()->setText(text); + ((ContentView *)view())->expressionField()->setEditing(true, true); + ((ContentView *)view())->expressionField()->setText(text); } return false; } @@ -177,7 +177,7 @@ void EditExpressionController::viewDidDisappear() { } Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { - return ((ContentView *)view())->editableExpressionView()->expressionLayoutField()->expressionViewWithCursor()->expressionView()->expressionLayout(); + return ((ContentView *)view())->expressionField()->expressionLayoutField()->expressionViewWithCursor()->expressionView()->expressionLayout(); } } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 21ffd5b22..def360628 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -2,7 +2,7 @@ #define CALCULATION_EDIT_EXPRESSION_CONTROLLER_H #include -#include "editable_expression_view.h" +#include "expression_field.h" #include "../shared/text_field_delegate.h" #include "../shared/expression_layout_field_delegate.h" #include "history_controller.h" @@ -38,14 +38,14 @@ private: ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void reload(); TableView * mainView() { return m_mainView; } - EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } + ExpressionField * expressionField() { return &m_expressionField; } /* View */ int numberOfSubviews() const override { return 2; } View * subviewAtIndex(int index) override; void layoutSubviews() override; private: TableView * m_mainView; - EditableExpressionView m_editableExpressionView; + ExpressionField m_expressionField; }; View * loadView() override; void unloadView(View * view) override; @@ -55,7 +55,7 @@ private: bool inputViewDidAbortEditing(const char * text); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; char m_cacheBuffer[TextField::maxBufferSize()]; - Shared::EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() override; + Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; Poincare::ExpressionLayout * expressionLayout(); HistoryController * m_historyController; CalculationStore * m_calculationStore; diff --git a/apps/calculation/editable_expression_view.h b/apps/calculation/editable_expression_view.h deleted file mode 100644 index d0e1aa1ab..000000000 --- a/apps/calculation/editable_expression_view.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef CALCULATION_EDITABLE_EXPRESSION_VIEW_H -#define CALCULATION_EDITABLE_EXPRESSION_VIEW_H - -#include - -namespace Calculation { - -class EditableExpressionView : public ::EditableExpressionView { -public: - EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); -protected: - bool handleEvent(Ion::Events::Event event) override; -}; - -} - -#endif diff --git a/apps/calculation/editable_expression_view.cpp b/apps/calculation/expression_field.cpp similarity index 53% rename from apps/calculation/editable_expression_view.cpp rename to apps/calculation/expression_field.cpp index cc5377154..8a368344a 100644 --- a/apps/calculation/editable_expression_view.cpp +++ b/apps/calculation/expression_field.cpp @@ -1,14 +1,14 @@ -#include "editable_expression_view.h" +#include "expression_field.h" namespace Calculation { -EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : - ::EditableExpressionView(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) +ExpressionField::ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : + ::ExpressionField(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) { setEditing(true); } -bool EditableExpressionView::handleEvent(Ion::Events::Event event) { +bool ExpressionField::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back) { return false; } @@ -25,7 +25,7 @@ bool EditableExpressionView::handleEvent(Ion::Events::Event event) { event == Ion::Events::Sto)) { insertText("ans"); } - return(::EditableExpressionView::handleEvent(event)); + return(::ExpressionField::handleEvent(event)); } } diff --git a/apps/calculation/expression_field.h b/apps/calculation/expression_field.h new file mode 100644 index 000000000..48a069d26 --- /dev/null +++ b/apps/calculation/expression_field.h @@ -0,0 +1,17 @@ +#ifndef CALCULATION_EXPRESSION_FIELD_H +#define CALCULATION_EXPRESSION_FIELD_H + +#include + +namespace Calculation { + +class ExpressionField : public ::ExpressionField { +public: + ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); +protected: + bool handleEvent(Ion::Events::Event event) override; +}; + +} + +#endif diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 269668c78..f570661b7 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -39,7 +39,7 @@ TextFieldDelegateApp * ListController::textFieldDelegateApp() { return (App *)app(); } -EditableExpressionViewDelegateApp * ListController::editableExpressionViewDelegateApp() { +ExpressionFieldDelegateApp * ListController::expressionFieldDelegateApp() { return (App *)app(); } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 452a06472..07c6f68bd 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -27,7 +27,7 @@ public: void selectPreviousNewSequenceCell(); private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override; - Shared::EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() override; + Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event); ListParameterController * parameterController() override; int maxNumberOfRows() override; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index c91980070..01c64faa4 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -6,7 +6,7 @@ app_objs += $(addprefix apps/shared/,\ curve_view_cursor.o\ curve_view_range.o\ editable_cell_table_view_controller.o\ - editable_expression_view_delegate_app.o\ + expression_field_delegate_app.o\ float_pair_store.o\ float_parameter_controller.o\ function.o\ diff --git a/apps/shared/editable_expression_view_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp similarity index 74% rename from apps/shared/editable_expression_view_delegate_app.cpp rename to apps/shared/expression_field_delegate_app.cpp index cd4f4336c..fc7943b82 100644 --- a/apps/shared/editable_expression_view_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -1,4 +1,4 @@ -#include "editable_expression_view_delegate_app.h" +#include "expression_field_delegate_app.h" #include "../i18n.h" #include "../apps_container.h" @@ -6,17 +6,17 @@ using namespace Poincare; namespace Shared { -EditableExpressionViewDelegateApp::EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : +ExpressionFieldDelegateApp::ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : TextFieldDelegateApp(container, snapshot, rootViewController), ExpressionLayoutFieldDelegate() { } -bool EditableExpressionViewDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { +bool ExpressionFieldDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } -bool EditableExpressionViewDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { +bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { if (!expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout()->hasText()) { expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); @@ -47,7 +47,7 @@ bool EditableExpressionViewDelegateApp::expressionLayoutFieldDidReceiveEvent(Exp return false; } -Toolbox * EditableExpressionViewDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { +Toolbox * ExpressionFieldDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { Toolbox * toolbox = container()->mathToolbox(); static_cast(toolbox)->setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField); return toolbox; diff --git a/apps/shared/editable_expression_view_delegate_app.h b/apps/shared/expression_field_delegate_app.h similarity index 56% rename from apps/shared/editable_expression_view_delegate_app.h rename to apps/shared/expression_field_delegate_app.h index a4911e7f7..4e8b0e2bc 100644 --- a/apps/shared/editable_expression_view_delegate_app.h +++ b/apps/shared/expression_field_delegate_app.h @@ -1,19 +1,19 @@ -#ifndef SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H -#define SHARED_EDITABLE_EXPRESSION_VIEW_DELEGATE_APP_H +#ifndef SHARED_EXPRESSION_FIELD_DELEGATE_APP_H +#define SHARED_EXPRESSION_FIELD_DELEGATE_APP_H #include "text_field_delegate_app.h" #include namespace Shared { -class EditableExpressionViewDelegateApp : public TextFieldDelegateApp, public ExpressionLayoutFieldDelegate { +class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public ExpressionLayoutFieldDelegate { public: - virtual ~EditableExpressionViewDelegateApp() = default; + virtual ~ExpressionFieldDelegateApp() = default; bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; protected: - EditableExpressionViewDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); + ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); }; } diff --git a/apps/shared/expression_layout_field_delegate.cpp b/apps/shared/expression_layout_field_delegate.cpp index 11dfb78bd..a6cc06de8 100644 --- a/apps/shared/expression_layout_field_delegate.cpp +++ b/apps/shared/expression_layout_field_delegate.cpp @@ -5,27 +5,27 @@ using namespace Poincare; namespace Shared { bool ExpressionLayoutFieldDelegate::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->expressionLayoutFieldShouldFinishEditing(expressionLayoutField, event); + return expressionFieldDelegateApp()->expressionLayoutFieldShouldFinishEditing(expressionLayoutField, event); } bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); + return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); } bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { - return editableExpressionViewDelegateApp()->expressionLayoutFieldDidFinishEditing(expressionLayoutField, text, event); + return expressionFieldDelegateApp()->expressionLayoutFieldDidFinishEditing(expressionLayoutField, text, event); } bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { - return editableExpressionViewDelegateApp()->expressionLayoutFieldDidAbortEditing(expressionLayoutField); + return expressionFieldDelegateApp()->expressionLayoutFieldDidAbortEditing(expressionLayoutField); } void ExpressionLayoutFieldDelegate::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { - return editableExpressionViewDelegateApp()->expressionLayoutFieldDidChangeSize(expressionLayoutField); + return expressionFieldDelegateApp()->expressionLayoutFieldDidChangeSize(expressionLayoutField); } Toolbox * ExpressionLayoutFieldDelegate::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { - return editableExpressionViewDelegateApp()->toolboxForExpressionLayoutField(expressionLayoutField); + return expressionFieldDelegateApp()->toolboxForExpressionLayoutField(expressionLayoutField); } } diff --git a/apps/shared/expression_layout_field_delegate.h b/apps/shared/expression_layout_field_delegate.h index 132f353aa..5d9ff3c04 100644 --- a/apps/shared/expression_layout_field_delegate.h +++ b/apps/shared/expression_layout_field_delegate.h @@ -2,7 +2,7 @@ #define SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H #include -#include "editable_expression_view_delegate_app.h" +#include "expression_field_delegate_app.h" namespace Shared { @@ -15,7 +15,7 @@ public: void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override; Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; private: - virtual EditableExpressionViewDelegateApp * editableExpressionViewDelegateApp() = 0; + virtual ExpressionFieldDelegateApp * expressionFieldDelegateApp() = 0; }; } diff --git a/apps/shared/function_app.cpp b/apps/shared/function_app.cpp index 60a122020..0d82d3dcb 100644 --- a/apps/shared/function_app.cpp +++ b/apps/shared/function_app.cpp @@ -53,7 +53,7 @@ void FunctionApp::Snapshot::reset() { } FunctionApp::FunctionApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : - EditableExpressionViewDelegateApp(container, snapshot, rootViewController) + ExpressionFieldDelegateApp(container, snapshot, rootViewController) { } diff --git a/apps/shared/function_app.h b/apps/shared/function_app.h index 362ec2af7..8fae050f1 100644 --- a/apps/shared/function_app.h +++ b/apps/shared/function_app.h @@ -2,7 +2,7 @@ #define SHARED_FUNCTION_APP_H #include -#include "editable_expression_view_delegate_app.h" +#include "expression_field_delegate_app.h" #include "curve_view_cursor.h" #include "interval.h" @@ -10,7 +10,7 @@ class AppsContainer; namespace Shared { -class FunctionApp : public EditableExpressionViewDelegateApp { +class FunctionApp : public ExpressionFieldDelegateApp { public: class Snapshot : public ::App::Snapshot, public TabViewDataSource { public: diff --git a/escher/Makefile b/escher/Makefile index dcc8e7df4..eae5aea8c 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -12,7 +12,7 @@ objs += $(addprefix escher/src/,\ dynamic_view_controller.o\ editable_text_cell.o\ ellipsis_view.o\ - editable_expression_view.o\ + expression_field.o\ even_odd_cell.o\ even_odd_cell_with_ellipsis.o\ even_odd_buffer_text_cell.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index e3d3411b5..c7356438f 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/escher/include/escher/editable_expression_view.h b/escher/include/escher/expression_field.h similarity index 82% rename from escher/include/escher/editable_expression_view.h rename to escher/include/escher/expression_field.h index eb28ffd87..84807a5a1 100644 --- a/escher/include/escher/editable_expression_view.h +++ b/escher/include/escher/expression_field.h @@ -1,14 +1,14 @@ -#ifndef ESCHER_EDITABLE_EXPRESSION_VIEW_H -#define ESCHER_EDITABLE_EXPRESSION_VIEW_H +#ifndef ESCHER_EXPRESSION_FIELD_H +#define ESCHER_EXPRESSION_FIELD_H #include #include #include #include -class EditableExpressionView : public Responder, public View { +class ExpressionField : public Responder, public View { public: - EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void setEditing(bool isEditing, bool reinitDraftBuffer = true); bool isEditing() const; diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 175d06ca8..ca8fad4a8 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -1,7 +1,7 @@ #ifndef ESCHER_INPUT_VIEW_CONTROLLER_H #define ESCHER_INPUT_VIEW_CONTROLLER_H -#include +#include #include #include #include @@ -34,18 +34,18 @@ public: Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; private: - class EditableExpressionViewController : public ViewController { + class ExpressionFieldController : public ViewController { public: - EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void didBecomeFirstResponder() override; - View * view() override { return &m_editableExpressionView; } - EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; } + View * view() override { return &m_expressionField; } + ExpressionField * expressionField() { return &m_expressionField; } private: - EditableExpressionView m_editableExpressionView; + ExpressionField m_expressionField; }; bool inputViewDidFinishEditing(); bool inputViewDidAbortEditing(); - EditableExpressionViewController m_editableExpressionViewController; + ExpressionFieldController m_expressionFieldController; Invocation m_successAction; Invocation m_failureAction; TextFieldDelegate * m_textFieldDelegate; diff --git a/escher/src/editable_expression_view.cpp b/escher/src/expression_field.cpp similarity index 74% rename from escher/src/editable_expression_view.cpp rename to escher/src/expression_field.cpp index aab5d9c72..d4e0f384d 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/expression_field.cpp @@ -1,8 +1,8 @@ -#include +#include #include #include -EditableExpressionView::EditableExpressionView(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +ExpressionField::ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : Responder(parentResponder), View(), m_textField(parentResponder, m_textBody, m_textBody, k_bufferLength, textFieldDelegate, false), @@ -11,7 +11,7 @@ EditableExpressionView::EditableExpressionView(Responder * parentResponder, Text m_textBody[0] = 0; } -void EditableExpressionView::setEditing(bool isEditing, bool reinitDraftBuffer) { +void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { if (editionIsInTextField()) { m_textField.setEditing(isEditing, reinitDraftBuffer); } else { @@ -22,18 +22,18 @@ void EditableExpressionView::setEditing(bool isEditing, bool reinitDraftBuffer) } } -bool EditableExpressionView::isEditing() const { +bool ExpressionField::isEditing() const { return editionIsInTextField() ? m_textField.isEditing() : m_expressionLayoutField.isEditing(); } -const char * EditableExpressionView::text() { +const char * ExpressionField::text() { if (!editionIsInTextField()) { m_expressionLayoutField.expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(m_textBody, k_bufferLength); } return m_textBody; } -void EditableExpressionView::setText(const char * text) { +void ExpressionField::setText(const char * text) { if (editionIsInTextField()) { m_textField.setText(text); return; @@ -44,7 +44,7 @@ void EditableExpressionView::setText(const char * text) { } } -void EditableExpressionView::insertText(const char * text) { +void ExpressionField::insertText(const char * text) { if (editionIsInTextField()) { m_textField.handleEventWithText(text); } else { @@ -53,7 +53,7 @@ void EditableExpressionView::insertText(const char * text) { } } -View * EditableExpressionView::subviewAtIndex(int index) { +View * ExpressionField::subviewAtIndex(int index) { assert(index == 0); if (editionIsInTextField()) { return &m_textField; @@ -61,7 +61,7 @@ View * EditableExpressionView::subviewAtIndex(int index) { return &m_expressionLayoutField; } -void EditableExpressionView::layoutSubviews() { +void ExpressionField::layoutSubviews() { KDRect inputViewFrame(k_leftMargin, k_separatorThickness, bounds().width() - k_leftMargin, bounds().height() - k_separatorThickness); if (editionIsInTextField()) { m_textField.setFrame(inputViewFrame); @@ -72,12 +72,12 @@ void EditableExpressionView::layoutSubviews() { m_textField.setFrame(KDRectZero); } -void EditableExpressionView::reload() { +void ExpressionField::reload() { layoutSubviews(); markRectAsDirty(bounds()); } -void EditableExpressionView::drawRect(KDContext * ctx, KDRect rect) const { +void ExpressionField::drawRect(KDContext * ctx, KDRect rect) const { // Draw the separator ctx->fillRect(KDRect(0, 0, bounds().width(), k_separatorThickness), Palette::GreyMiddle); // Color the left margin @@ -88,19 +88,19 @@ void EditableExpressionView::drawRect(KDContext * ctx, KDRect rect) const { } } -bool EditableExpressionView::handleEvent(Ion::Events::Event event) { +bool ExpressionField::handleEvent(Ion::Events::Event event) { return editionIsInTextField() ? m_textField.handleEvent(event) : m_expressionLayoutField.handleEvent(event); } -KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const { +KDSize ExpressionField::minimalSizeForOptimalDisplay() const { return KDSize(0, inputViewHeight()); } -bool EditableExpressionView::editionIsInTextField() const { +bool ExpressionField::editionIsInTextField() const { return Poincare::Preferences::sharedPreferences()->editionMode() == Poincare::Preferences::EditionMode::Edition1D; } -bool EditableExpressionView::isEmpty() const { +bool ExpressionField::isEmpty() const { if (editionIsInTextField()) { return m_textField.draftTextLength() == 0; } @@ -108,11 +108,11 @@ bool EditableExpressionView::isEmpty() const { return !layout->hasText(); } -bool EditableExpressionView::heightIsMaximal() const { +bool ExpressionField::heightIsMaximal() const { return inputViewHeight() == k_separatorThickness + k_verticalExpressionViewMargin + maximalHeight(); } -KDCoordinate EditableExpressionView::inputViewHeight() const { +KDCoordinate ExpressionField::inputViewHeight() const { if (editionIsInTextField()) { return k_separatorThickness + k_textFieldHeight; } @@ -124,6 +124,6 @@ KDCoordinate EditableExpressionView::inputViewHeight() const { + k_verticalExpressionViewMargin)); } -KDCoordinate EditableExpressionView::maximalHeight() const { +KDCoordinate ExpressionField::maximalHeight() const { return 0.6*Ion::Display::Height; } diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 139eedc39..a25b3558a 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -4,19 +4,19 @@ #include #include -InputViewController::EditableExpressionViewController::EditableExpressionViewController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ViewController(parentResponder), - m_editableExpressionView(this, textFieldDelegate, expressionLayoutFieldDelegate) + m_expressionField(this, textFieldDelegate, expressionLayoutFieldDelegate) { } -void InputViewController::EditableExpressionViewController::didBecomeFirstResponder() { - app()->setFirstResponder(&m_editableExpressionView); +void InputViewController::ExpressionFieldController::didBecomeFirstResponder() { + app()->setFirstResponder(&m_expressionField); } InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ModalViewController(parentResponder, child), - m_editableExpressionViewController(this, this, this), + m_expressionFieldController(this, this, this), m_successAction(Invocation(nullptr, nullptr)), m_failureAction(Invocation(nullptr, nullptr)), m_textFieldDelegate(textFieldDelegate), @@ -26,21 +26,21 @@ InputViewController::InputViewController(Responder * parentResponder, ViewContro } const char * InputViewController::textBody() { - return m_editableExpressionViewController.editableExpressionView()->text(); + return m_expressionFieldController.expressionField()->text(); } void InputViewController::edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction) { m_successAction = Invocation(successAction, context); m_failureAction = Invocation(failureAction, context); - displayModalViewController(&m_editableExpressionViewController, 1.0f, 1.0f); + displayModalViewController(&m_expressionFieldController, 1.0f, 1.0f); if (initialText != nullptr) { - m_editableExpressionViewController.editableExpressionView()->setText(initialText); + m_expressionFieldController.expressionField()->setText(initialText); } - m_editableExpressionViewController.editableExpressionView()->handleEvent(event); + m_expressionFieldController.expressionField()->handleEvent(event); } void InputViewController::abortEditionAndDismiss() { - m_editableExpressionViewController.editableExpressionView()->setEditing(false); + m_expressionFieldController.expressionField()->setEditing(false); dismissModalViewController(); } @@ -81,9 +81,9 @@ bool InputViewController::expressionLayoutFieldDidAbortEditing(ExpressionLayoutF } void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { - // Reload the view only if the EditableExpressionView height actually changes, + // 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_editableExpressionViewController.editableExpressionView()->heightIsMaximal(); + bool newInputViewHeightIsMaximal = m_expressionFieldController.expressionField()->heightIsMaximal(); if (!m_inputViewHeightIsMaximal || !newInputViewHeightIsMaximal) { m_inputViewHeightIsMaximal = newInputViewHeightIsMaximal; reloadView(); From 894080f1abf0bb89544d208e2ac609ab9655703d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 16:36:07 +0200 Subject: [PATCH 336/459] [apps/escher] EVWithCursor becomes ELField::ContentView Change-Id: I719218e4d1d360800e0f1ef3eebeea774c8d5660 --- apps/calculation/app.cpp | 3 +- .../edit_expression_controller.cpp | 2 +- apps/shared/expression_field_delegate_app.cpp | 4 +- escher/Makefile | 2 +- .../include/escher/expression_layout_field.h | 40 ++++++- escher/src/expression_field.cpp | 8 +- escher/src/expression_layout_field.cpp | 110 ++++++++++-------- ... expression_layout_field_content_view.cpp} | 18 +-- 8 files changed, 113 insertions(+), 74 deletions(-) rename escher/src/{expression_view_with_cursor.cpp => expression_layout_field_content_view.cpp} (74%) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index be372c02c..309def628 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -97,8 +97,7 @@ bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * express } int bufferLength = TextField::maxBufferSize(); char bufferForParsing[bufferLength]; - Poincare::ExpressionLayout * expressionLayout = expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout(); - expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength); + expressionLayoutField->writeTextInBuffer(bufferForParsing, bufferLength); Expression * exp = Expression::parse(bufferForParsing); if (exp == nullptr) { expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 80e3f7155..f5c695662 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -177,7 +177,7 @@ void EditExpressionController::viewDidDisappear() { } Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { - return ((ContentView *)view())->expressionField()->expressionLayoutField()->expressionViewWithCursor()->expressionView()->expressionLayout(); + return ((ContentView *)view())->expressionField()->expressionLayoutField()->expressionLayout(); } } diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index fc7943b82..870b4e351 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -18,13 +18,13 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldShouldFinishEditing(Expres bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { - if (!expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout()->hasText()) { + if (!expressionLayoutField->hasText()) { expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } int bufferSize = 256; char buffer[bufferSize]; - expressionLayoutField->expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + expressionLayoutField->writeTextInBuffer(buffer, bufferSize); Expression * exp = Expression::parse(buffer); if (exp != nullptr) { delete exp; diff --git a/escher/Makefile b/escher/Makefile index eae5aea8c..6ef22bc66 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -22,7 +22,6 @@ objs += $(addprefix escher/src/,\ expression_table_cell.o\ expression_table_cell_with_pointer.o\ expression_view.o\ - expression_view_with_cursor.o\ highlight_cell.o\ gauge_view.o\ image_view.o\ @@ -51,6 +50,7 @@ objs += $(addprefix escher/src/,\ scroll_view_indicator.o\ scrollable_view.o\ expression_layout_field.o\ + expression_layout_field_content_view.o\ selectable_table_view.o\ selectable_table_view_data_source.o\ selectable_table_view_delegate.o\ diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 8e81e40c3..f8f5a412b 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -1,21 +1,26 @@ #ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_H #define ESCHER_EXPRESSION_LAYOUT_FIELD_H -#include -#include +#include #include +#include +#include +#include +#include #include class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource { public: ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr); void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; } - ExpressionViewWithCursor * expressionViewWithCursor() { return &m_expressionViewWithCursor; } bool isEditing() const; void setEditing(bool isEditing); void clearLayout(); void scrollToCursor(); void reload(); + bool hasText() const; + void writeTextInBuffer(char * buffer, int bufferLength); + Poincare::ExpressionLayout * expressionLayout(); /* Responder */ Toolbox * toolbox() override; @@ -32,8 +37,35 @@ public: protected: virtual bool privateHandleEvent(Ion::Events::Event event); bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); - ExpressionViewWithCursor m_expressionViewWithCursor; private: + class ContentView : public View { + public: + ContentView(Poincare::ExpressionLayout * expressionLayout); + bool isEditing() const { return m_isEditing; } + void setEditing(bool isEditing); + void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } + void cursorPositionChanged(); + KDRect cursorRect(); + Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } + const ExpressionView * expressionView() const { return &m_expressionView; } + ExpressionView * editableExpressionView() { return &m_expressionView; } + /* View */ + KDSize minimalSizeForOptimalDisplay() const override; + private: + enum class Position { + Top, + Bottom + }; + int numberOfSubviews() const override { return 2; } + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + void layoutCursorSubview(); + Poincare::ExpressionLayoutCursor m_cursor; + ExpressionView m_expressionView; + TextCursorView m_cursorView; + bool m_isEditing; + }; + ContentView m_contentView; ExpressionLayoutFieldDelegate * m_delegate; }; diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index d4e0f384d..ef172771b 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -28,7 +28,7 @@ bool ExpressionField::isEditing() const { const char * ExpressionField::text() { if (!editionIsInTextField()) { - m_expressionLayoutField.expressionViewWithCursor()->expressionView()->expressionLayout()->writeTextInBuffer(m_textBody, k_bufferLength); + m_expressionLayoutField.writeTextInBuffer(m_textBody, k_bufferLength); } return m_textBody; } @@ -101,11 +101,7 @@ bool ExpressionField::editionIsInTextField() const { } bool ExpressionField::isEmpty() const { - if (editionIsInTextField()) { - return m_textField.draftTextLength() == 0; - } - Poincare::ExpressionLayout * layout = const_cast(&m_expressionLayoutField)->expressionViewWithCursor()->expressionView()->expressionLayout(); - return !layout->hasText(); + return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : m_expressionLayoutField.hasText(); } bool ExpressionField::heightIsMaximal() const { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 7c5fd81f4..712fe52e7 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -6,29 +6,29 @@ #include ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : - ScrollableView(parentResponder, &m_expressionViewWithCursor, this), - m_expressionViewWithCursor(expressionLayout), + ScrollableView(parentResponder, &m_contentView, this), + m_contentView(expressionLayout), m_delegate(delegate) { } bool ExpressionLayoutField::isEditing() const { - return m_expressionViewWithCursor.isEditing(); + return m_contentView.isEditing(); } void ExpressionLayoutField::setEditing(bool isEditing) { - m_expressionViewWithCursor.setEditing(isEditing); + m_contentView.setEditing(isEditing); } void ExpressionLayoutField::clearLayout() { - delete m_expressionViewWithCursor.expressionView()->expressionLayout(); + delete m_contentView.expressionView()->expressionLayout(); Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); - m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); + m_contentView.editableExpressionView()->setExpressionLayout(newLayout); + m_contentView.cursor()->setPointedExpressionLayout(newLayout); } void ExpressionLayoutField::scrollToCursor() { - scrollToContentRect(m_expressionViewWithCursor.cursorRect(), true); + scrollToContentRect(m_contentView.cursorRect(), true); } Toolbox * ExpressionLayoutField::toolbox() { @@ -41,7 +41,7 @@ Toolbox * ExpressionLayoutField::toolbox() { bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { KDSize previousSize = minimalSizeForOptimalDisplay(); bool didHandleEvent = false; - bool shouldRecomputeLayout = m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); + bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded(); bool moveEventChangedLayout = false; if (privateHandleMoveEvent(event, &moveEventChangedLayout)) { shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout; @@ -54,9 +54,9 @@ bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { if (!isEditing()) { setEditing(true); } - shouldRecomputeLayout = m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; + shouldRecomputeLayout = m_contentView.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; if (!shouldRecomputeLayout) { - m_expressionViewWithCursor.cursorPositionChanged(); + m_contentView.cursorPositionChanged(); scrollToCursor(); return true; } @@ -76,28 +76,28 @@ bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events } KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { - return m_expressionViewWithCursor.minimalSizeForOptimalDisplay(); + return m_contentView.minimalSizeForOptimalDisplay(); } bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { Poincare::ExpressionLayoutCursor result; if (event == Ion::Events::Left) { - result = m_expressionViewWithCursor.cursor()->cursorOnLeft(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorOnLeft(shouldRecomputeLayout); } else if (event == Ion::Events::Right) { - result = m_expressionViewWithCursor.cursor()->cursorOnRight(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorOnRight(shouldRecomputeLayout); } else if (event == Ion::Events::Up) { - result = m_expressionViewWithCursor.cursor()->cursorAbove(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorAbove(shouldRecomputeLayout); } else if (event == Ion::Events::Down) { - result = m_expressionViewWithCursor.cursor()->cursorUnder(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout); } else if (event == Ion::Events::ShiftLeft) { - result.setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + result.setPointedExpressionLayout(m_contentView.expressionView()->expressionLayout()); result.setPosition(Poincare::ExpressionLayoutCursor::Position::Left); } else if (event == Ion::Events::ShiftRight) { - result.setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); + result.setPointedExpressionLayout(m_contentView.expressionView()->expressionLayout()); result.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } if (result.isDefined()) { - m_expressionViewWithCursor.setCursor(result); + m_contentView.setCursor(result); return true; } return false; @@ -119,19 +119,19 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { setEditing(false); int bufferSize = TextField::maxBufferSize(); char buffer[bufferSize]; - m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); + m_contentView.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); if (m_delegate->expressionLayoutFieldDidFinishEditing(this, buffer, event)) { - delete m_expressionViewWithCursor.expressionView()->expressionLayout(); + delete m_contentView.expressionView()->expressionLayout(); Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); - m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout); + m_contentView.editableExpressionView()->setExpressionLayout(newLayout); + m_contentView.cursor()->setPointedExpressionLayout(newLayout); } return true; } if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { setEditing(true); - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(m_expressionViewWithCursor.expressionView()->expressionLayout()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_contentView.cursor()->setPointedExpressionLayout(m_contentView.expressionView()->expressionLayout()); + m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); return true; } if (event == Ion::Events::Back && isEditing()) { @@ -140,27 +140,27 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { return true; } if (event == Ion::Events::Division) { - m_expressionViewWithCursor.cursor()->addFractionLayoutAndCollapseSiblings(); + m_contentView.cursor()->addFractionLayoutAndCollapseSiblings(); return true; } if (event == Ion::Events::XNT) { - m_expressionViewWithCursor.cursor()->addXNTCharLayout(); + m_contentView.cursor()->addXNTCharLayout(); return true; } if (event == Ion::Events::Exp) { - m_expressionViewWithCursor.cursor()->addEmptyExponentialLayout(); + m_contentView.cursor()->addEmptyExponentialLayout(); return true; } if (event == Ion::Events::Power) { - m_expressionViewWithCursor.cursor()->addEmptyPowerLayout(); + m_contentView.cursor()->addEmptyPowerLayout(); return true; } if (event == Ion::Events::Sqrt) { - m_expressionViewWithCursor.cursor()->addEmptySquareRootLayout(); + m_contentView.cursor()->addEmptySquareRootLayout(); return true; } if (event == Ion::Events::Square) { - m_expressionViewWithCursor.cursor()->addEmptySquarePowerLayout(); + m_contentView.cursor()->addEmptySquarePowerLayout(); return true; } if (event.hasText()) { @@ -168,19 +168,19 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { if (textToInsert[1] == 0) { if (textToInsert[0] == Ion::Charset::MultiplicationSign) { const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - m_expressionViewWithCursor.cursor()->insertText(middleDotString); + m_contentView.cursor()->insertText(middleDotString); return true; } if (textToInsert[0] == '[' || textToInsert[0] == ']') { - m_expressionViewWithCursor.cursor()->addEmptyMatrixLayout(); + m_contentView.cursor()->addEmptyMatrixLayout(); return true; } } - m_expressionViewWithCursor.cursor()->insertText(textToInsert); + m_contentView.cursor()->insertText(textToInsert); return true; } if (event == Ion::Events::Backspace) { - m_expressionViewWithCursor.cursor()->performBackspace(); + m_contentView.cursor()->performBackspace(); return true; } if (event == Ion::Events::Paste) { @@ -201,21 +201,21 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la if (layout == nullptr) { return; } - m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); + m_contentView.cursor()->showEmptyLayoutIfNeeded(); KDSize previousSize = minimalSizeForOptimalDisplay(); if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } bool layoutWillBeMerged = layout->isHorizontal(); - m_expressionViewWithCursor.cursor()->addLayoutAndMoveCursor(layout); + m_contentView.cursor()->addLayoutAndMoveCursor(layout); if (pointedLayout != nullptr) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_contentView.cursor()->setPointedExpressionLayout(pointedLayout); + m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } else if (!layoutWillBeMerged) { - m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); - m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); + m_contentView.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); + m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } - m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { @@ -228,23 +228,35 @@ void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { if (expression != nullptr) { Poincare::ExpressionLayout * layout = expression->createLayout(); delete expression; - m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); + m_contentView.cursor()->showEmptyLayoutIfNeeded(); insertLayoutAtCursor(layout, nullptr); - m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); return; } - m_expressionViewWithCursor.cursor()->showEmptyLayoutIfNeeded(); - m_expressionViewWithCursor.cursor()->insertText(text); - m_expressionViewWithCursor.cursor()->hideEmptyLayoutIfNeeded(); + m_contentView.cursor()->showEmptyLayoutIfNeeded(); + m_contentView.cursor()->insertText(text); + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); } void ExpressionLayoutField::reload() { - m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); + m_contentView.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); layoutSubviews(); m_delegate->expressionLayoutFieldDidChangeSize(this); scrollToCursor(); - m_expressionViewWithCursor.cursorPositionChanged(); + m_contentView.cursorPositionChanged(); markRectAsDirty(bounds()); } + +bool ExpressionLayoutField::hasText() const { + return m_contentView.expressionView()->expressionLayout()->isEmpty(); +} + +void ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) { + m_contentView.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferLength); +} + +Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() { + return m_contentView.expressionView()->expressionLayout(); +} diff --git a/escher/src/expression_view_with_cursor.cpp b/escher/src/expression_layout_field_content_view.cpp similarity index 74% rename from escher/src/expression_view_with_cursor.cpp rename to escher/src/expression_layout_field_content_view.cpp index 657ca5b32..f20dcd1ca 100644 --- a/escher/src/expression_view_with_cursor.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -1,10 +1,10 @@ -#include +#include #include #include using namespace Poincare; -ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expressionLayout) : +ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) : m_cursor(), m_expressionView(), m_cursorView(), @@ -15,21 +15,21 @@ ExpressionViewWithCursor::ExpressionViewWithCursor(ExpressionLayout * expression m_expressionView.setExpressionLayout(expressionLayout); } -void ExpressionViewWithCursor::setEditing(bool isEditing) { +void ExpressionLayoutField::ContentView::setEditing(bool isEditing) { m_isEditing = isEditing; markRectAsDirty(bounds()); layoutSubviews(); } -void ExpressionViewWithCursor::cursorPositionChanged() { +void ExpressionLayoutField::ContentView::cursorPositionChanged() { layoutCursorSubview(); } -KDRect ExpressionViewWithCursor::cursorRect() { +KDRect ExpressionLayoutField::ContentView::cursorRect() { return m_cursorView.frame(); } -KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { +KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); KDSize cursorSize = isEditing() ? m_cursorView.minimalSizeForOptimalDisplay() : KDSizeZero; KDCoordinate resultWidth = expressionViewSize.width() + cursorSize.width(); @@ -37,18 +37,18 @@ KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const { return KDSize(resultWidth, resultHeight); } -View * ExpressionViewWithCursor::subviewAtIndex(int index) { +View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) { assert(index >= 0 && index < 2); View * m_views[] = {&m_expressionView, &m_cursorView}; return m_views[index]; } -void ExpressionViewWithCursor::layoutSubviews() { +void ExpressionLayoutField::ContentView::layoutSubviews() { m_expressionView.setFrame(bounds()); layoutCursorSubview(); } -void ExpressionViewWithCursor::layoutCursorSubview() { +void ExpressionLayoutField::ContentView::layoutCursorSubview() { if (!m_isEditing) { m_cursorView.setFrame(KDRectZero); return; From 117a6d460ab10a03b97a7f34028aa68fcbfd211a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 17:44:45 +0200 Subject: [PATCH 337/459] [poincare] Stop exposing text/expressionlayout fields in ExpressionField Change-Id: Ic1afb3f7c1f6bff5ea3bedc6f96bef986b74f6a8 --- .../edit_expression_controller.cpp | 15 ++++++----- apps/calculation/edit_expression_controller.h | 6 ++++- apps/calculation/expression_field.cpp | 4 +-- apps/calculation/expression_field.h | 2 +- escher/include/escher/expression_field.h | 9 +++---- .../include/escher/expression_layout_field.h | 1 + escher/include/escher/input_view_controller.h | 3 +++ escher/src/expression_field.cpp | 13 +++++----- escher/src/expression_layout_field.cpp | 5 +--- .../expression_layout_field_content_view.cpp | 4 +++ escher/src/input_view_controller.cpp | 2 +- .../poincare/dynamic_layout_hierarchy.h | 1 + poincare/include/poincare/expression_layout.h | 1 + .../poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 9 +++++++ .../src/layout/dynamic_layout_hierarchy.cpp | 26 ++++++++++++------- poincare/src/layout/expression_layout.cpp | 7 +++++ 17 files changed, 73 insertions(+), 36 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index f5c695662..e3707da8f 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -12,8 +12,14 @@ namespace Calculation { EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : View(), m_mainView(subview), - m_expressionField(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) + m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate), + m_layout(new Poincare::HorizontalLayout) { + m_textBody[0] = 0; +} + +EditExpressionController::ContentView::~ContentView() { + delete m_layout; } View * EditExpressionController::ContentView::subviewAtIndex(int index) { @@ -93,7 +99,7 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); - if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayout()->hasText() && m_calculationStore->numberOfCalculations() > 0) { + if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) { return inputViewDidReceiveEvent(event); } return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); @@ -127,7 +133,6 @@ View * EditExpressionController::loadView() { } void EditExpressionController::unloadView(View * view) { - delete expressionLayout(); delete view; } @@ -176,8 +181,4 @@ void EditExpressionController::viewDidDisappear() { m_historyController->viewDidDisappear(); } -Poincare::ExpressionLayout * EditExpressionController::expressionLayout() { - return ((ContentView *)view())->expressionField()->expressionLayoutField()->expressionLayout(); -} - } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index def360628..80bbf3b89 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -2,6 +2,7 @@ #define CALCULATION_EDIT_EXPRESSION_CONTROLLER_H #include +#include #include "expression_field.h" #include "../shared/text_field_delegate.h" #include "../shared/expression_layout_field_delegate.h" @@ -36,6 +37,7 @@ private: class ContentView : public View { public: ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ~ContentView(); void reload(); TableView * mainView() { return m_mainView; } ExpressionField * expressionField() { return &m_expressionField; } @@ -44,8 +46,11 @@ private: View * subviewAtIndex(int index) override; void layoutSubviews() override; private: + static constexpr int k_bufferLength = TextField::maxBufferSize(); TableView * m_mainView; ExpressionField m_expressionField; + char m_textBody[k_bufferLength]; + Poincare::ExpressionLayout * m_layout; }; View * loadView() override; void unloadView(View * view) override; @@ -56,7 +61,6 @@ private: Shared::TextFieldDelegateApp * textFieldDelegateApp() override; char m_cacheBuffer[TextField::maxBufferSize()]; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; - Poincare::ExpressionLayout * expressionLayout(); HistoryController * m_historyController; CalculationStore * m_calculationStore; }; diff --git a/apps/calculation/expression_field.cpp b/apps/calculation/expression_field.cpp index 8a368344a..06ef5d80d 100644 --- a/apps/calculation/expression_field.cpp +++ b/apps/calculation/expression_field.cpp @@ -2,8 +2,8 @@ namespace Calculation { -ExpressionField::ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : - ::ExpressionField(parentResponder, textFieldDelegate, expressionLayoutFieldDelegate) +ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : + ::ExpressionField(parentResponder, textBuffer, textBufferLength, layout, textFieldDelegate, expressionLayoutFieldDelegate) { setEditing(true); } diff --git a/apps/calculation/expression_field.h b/apps/calculation/expression_field.h index 48a069d26..34ba89ace 100644 --- a/apps/calculation/expression_field.h +++ b/apps/calculation/expression_field.h @@ -7,7 +7,7 @@ namespace Calculation { class ExpressionField : public ::ExpressionField { public: - ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); protected: bool handleEvent(Ion::Events::Event event) override; }; diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index 84807a5a1..d47f11317 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -5,10 +5,11 @@ #include #include #include +#include class ExpressionField : public Responder, public View { public: - ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); void setEditing(bool isEditing, bool reinitDraftBuffer = true); bool isEditing() const; @@ -16,8 +17,6 @@ public: void setText(const char * text); void insertText(const char * text); void reload(); - TextField * textField() { return &m_textField; } - ExpressionLayoutField * expressionLayoutField() { return &m_expressionLayoutField; } bool editionIsInTextField() const; bool isEmpty() const; bool heightIsMaximal() const; @@ -32,7 +31,6 @@ public: /* Responder */ bool handleEvent(Ion::Events::Event event) override; - static constexpr int k_bufferLength = TextField::maxBufferSize(); private: static constexpr KDCoordinate k_textFieldHeight = 37; static constexpr KDCoordinate k_leftMargin = 5; @@ -42,7 +40,8 @@ private: KDCoordinate maximalHeight() const; TextField m_textField; ExpressionLayoutField m_expressionLayoutField; - char m_textBody[k_bufferLength]; + char * m_textBuffer; + int m_textBufferLength; }; #endif diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index f8f5a412b..76a3cfa48 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -49,6 +49,7 @@ private: Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } const ExpressionView * expressionView() const { return &m_expressionView; } ExpressionView * editableExpressionView() { return &m_expressionView; } + void clearLayout(); /* View */ KDSize minimalSizeForOptimalDisplay() const override; private: diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index ca8fad4a8..aac58e3bc 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -41,7 +41,10 @@ private: View * view() override { return &m_expressionField; } ExpressionField * expressionField() { return &m_expressionField; } private: + static constexpr int k_bufferLength = TextField::maxBufferSize(); ExpressionField m_expressionField; + char m_textBuffer[k_bufferLength]; + Poincare::ExpressionLayout * m_layout; }; bool inputViewDidFinishEditing(); bool inputViewDidAbortEditing(); diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index ef172771b..cc89fdf05 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -2,13 +2,14 @@ #include #include -ExpressionField::ExpressionField(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : Responder(parentResponder), View(), - m_textField(parentResponder, m_textBody, m_textBody, k_bufferLength, textFieldDelegate, false), - m_expressionLayoutField(parentResponder, new Poincare::HorizontalLayout(), expressionLayoutFieldDelegate) + m_textField(parentResponder, textBuffer, textBuffer, textBufferLength, textFieldDelegate, false), + m_expressionLayoutField(parentResponder, layout, expressionLayoutFieldDelegate), + m_textBuffer(textBuffer), + m_textBufferLength(textBufferLength) { - m_textBody[0] = 0; } void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { @@ -28,9 +29,9 @@ bool ExpressionField::isEditing() const { const char * ExpressionField::text() { if (!editionIsInTextField()) { - m_expressionLayoutField.writeTextInBuffer(m_textBody, k_bufferLength); + m_expressionLayoutField.writeTextInBuffer(m_textBuffer, m_textBufferLength); } - return m_textBody; + return m_textBuffer; } void ExpressionField::setText(const char * text) { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 712fe52e7..9481ee866 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -21,10 +21,7 @@ void ExpressionLayoutField::setEditing(bool isEditing) { } void ExpressionLayoutField::clearLayout() { - delete m_contentView.expressionView()->expressionLayout(); - Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); - m_contentView.editableExpressionView()->setExpressionLayout(newLayout); - m_contentView.cursor()->setPointedExpressionLayout(newLayout); + m_contentView.clearLayout(); } void ExpressionLayoutField::scrollToCursor() { diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index f20dcd1ca..1ef370293 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -29,6 +29,10 @@ KDRect ExpressionLayoutField::ContentView::cursorRect() { return m_cursorView.frame(); } +void ExpressionLayoutField::ContentView::clearLayout() { + m_cursor.clearLayout(); +} + KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); KDSize cursorSize = isEditing() ? m_cursorView.minimalSizeForOptimalDisplay() : KDSizeZero; diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index a25b3558a..9ee810632 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -6,7 +6,7 @@ InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ViewController(parentResponder), - m_expressionField(this, textFieldDelegate, expressionLayoutFieldDelegate) + m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate) { } diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 43dbb606e..573e5be64 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -29,6 +29,7 @@ public: bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; + void removeAndDeleteChildren(); virtual void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren); // WITHOUT delete. protected: diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index d2e94ddda..19d07649e 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -46,6 +46,7 @@ public: const ExpressionLayout * parent() const { return m_parent; } ExpressionLayout * editableParent() { return m_parent; } bool hasAncestor(const ExpressionLayout * e, bool includeSelf = false) const; + ExpressionLayout * editableRoot(); /* Dynamic Layout */ diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 11ad4a8a9..74719f9b3 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -56,6 +56,7 @@ public: void performBackspace(); bool showEmptyLayoutIfNeeded(); bool hideEmptyLayoutIfNeeded(); + void clearLayout(); private: constexpr static KDCoordinate k_cursorHeight = 18; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 1029a2ef1..e619ffacc 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -207,6 +207,15 @@ bool ExpressionLayoutCursor::hideEmptyLayoutIfNeeded() { return privateShowHideEmptyLayoutIfNeeded(false); } +void ExpressionLayoutCursor::clearLayout() { + ExpressionLayout * rootLayout = m_pointedExpressionLayout->editableRoot(); + assert(rootLayout->isHorizontal()); + for (int i = 0; i < rootLayout->numberOfChildren(); i++) { + static_cast(rootLayout)->removeAndDeleteChildren(); + } + m_pointedExpressionLayout = rootLayout; +} + bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { /* Find Empty layouts adjacent to the cursor: Check the pointed layout and its * neighbour in an Horizontal layout */ diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 60b0de32b..c5d11739b 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -33,14 +33,7 @@ DynamicLayoutHierarchy::DynamicLayoutHierarchy(const ExpressionLayout * const * } DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { - if (m_children != nullptr) { - for (int i = 0; i < m_numberOfChildren; i++) { - if (m_children[i] != nullptr) { - delete m_children[i]; - } - } - } - delete[] m_children; + removeAndDeleteChildren(); } void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { @@ -73,7 +66,9 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * for (int i=indexForInsertion; isetPointedExpressionLayout(editableChild(indexOfNewPointedLayout)); } +void DynamicLayoutHierarchy::removeAndDeleteChildren() { + if (m_children != nullptr) { + for (int i = 0; i < m_numberOfChildren; i++) { + if (m_children[i] != nullptr) { + delete m_children[i]; + } + } + } + delete[] m_children; + m_children = nullptr; + m_numberOfChildren = 0; +} + } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 33e26b81d..4926117cc 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -110,6 +110,13 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e, bool includeSelf) void ExpressionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { } +ExpressionLayout * ExpressionLayout::editableRoot() { + if (m_parent == nullptr) { + return this; + } + return m_parent->editableRoot(); +} + void ExpressionLayout::addSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling) { privateAddSibling(cursor, sibling, false); } From e0356e18e70e51fc1760022befea3664a898e468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 17:48:23 +0200 Subject: [PATCH 338/459] [poincare] Inline empty method. Change-Id: I926252df6fefe61e61402a856656da3b3b6aadaf --- poincare/include/poincare/expression_layout.h | 2 +- poincare/src/layout/expression_layout.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 19d07649e..b1494dde4 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -51,7 +51,7 @@ public: /* Dynamic Layout */ // Collapse - virtual void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor); + virtual void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) {} // Add virtual bool addChildAtIndex(ExpressionLayout * child, int index) { return false; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 4926117cc..abf881acd 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -107,9 +107,6 @@ bool ExpressionLayout::hasAncestor(const ExpressionLayout * e, bool includeSelf) return m_parent->hasAncestor(e); } -void ExpressionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { -} - ExpressionLayout * ExpressionLayout::editableRoot() { if (m_parent == nullptr) { return this; From ce056e085b1df436f7d355c94d283610d49b6d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 17:52:55 +0200 Subject: [PATCH 339/459] [escher] Remove View::frame(), create TextCursorView::frame() Change-Id: I69c1aa5e94d93d2832564040abcca62bddc377ae --- escher/include/escher/text_cursor_view.h | 1 + escher/include/escher/view.h | 1 - escher/src/view.cpp | 4 ---- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/escher/include/escher/text_cursor_view.h b/escher/include/escher/text_cursor_view.h index a950c0ec4..6b9c02206 100644 --- a/escher/include/escher/text_cursor_view.h +++ b/escher/include/escher/text_cursor_view.h @@ -6,6 +6,7 @@ class TextCursorView : public View { public: using View::View; + KDRect frame() const { return m_frame; } void drawRect(KDContext * ctx, KDRect rect) const override; KDSize minimalSizeForOptimalDisplay() const override; constexpr static KDCoordinate k_width = 1; diff --git a/escher/include/escher/view.h b/escher/include/escher/view.h index 80d2d3714..c1f6bdde8 100644 --- a/escher/include/escher/view.h +++ b/escher/include/escher/view.h @@ -41,7 +41,6 @@ public: KDPoint pointFromPointInView(View * view, KDPoint point); KDRect bounds() const; - KDRect frame() const; View * subview(int index); virtual KDSize minimalSizeForOptimalDisplay() const; diff --git a/escher/src/view.cpp b/escher/src/view.cpp index a2092490a..46d3d9212 100644 --- a/escher/src/view.cpp +++ b/escher/src/view.cpp @@ -158,10 +158,6 @@ KDRect View::bounds() const { return m_frame.movedTo(KDPointZero); } -KDRect View::frame() const { - return KDRect(m_frame); -} - KDPoint View::absoluteOrigin() const { if (m_superview == nullptr) { assert(this == (View *)window()); From 5c2322a5a40eb0afe40c2d3ca5f31346dd742b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 17:57:14 +0200 Subject: [PATCH 340/459] [apps/calculation] Rule of 5 in EditExpressionController::ContentView Change-Id: I92ee8ee934c66674bb983780a5d8084a1562accf --- apps/calculation/edit_expression_controller.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 80bbf3b89..7334db33c 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -38,6 +38,10 @@ private: public: ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); ~ContentView(); + ContentView(const ContentView& other) = delete; + ContentView(ContentView&& other) = delete; + ContentView& operator=(const ContentView& other) = delete; + ContentView& operator=(ContentView&& other) = delete; void reload(); TableView * mainView() { return m_mainView; } ExpressionField * expressionField() { return &m_expressionField; } From 6d7464707d6820fb498b2df9fcfeaaed9e15de2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 18:01:34 +0200 Subject: [PATCH 341/459] [apps/calculation] Fix member initialization order. Change-Id: I16788edf23b9c2d70a781db5ad90ebfd67b926e7 --- apps/calculation/edit_expression_controller.cpp | 4 ++-- apps/calculation/edit_expression_controller.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index e3707da8f..c5b5a1cbb 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -12,8 +12,8 @@ namespace Calculation { EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : View(), m_mainView(subview), - m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate), - m_layout(new Poincare::HorizontalLayout) + m_layout(new Poincare::HorizontalLayout()), + m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate) { m_textBody[0] = 0; } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 7334db33c..339cfbca6 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -52,9 +52,9 @@ private: private: static constexpr int k_bufferLength = TextField::maxBufferSize(); TableView * m_mainView; - ExpressionField m_expressionField; char m_textBody[k_bufferLength]; Poincare::ExpressionLayout * m_layout; + ExpressionField m_expressionField; }; View * loadView() override; void unloadView(View * view) override; From d436e06a73d443b27242e1f0fd98f40a38afc92e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 20 Apr 2018 18:03:08 +0200 Subject: [PATCH 342/459] [escher] ~InputViewController and rule of 5 Change-Id: Iec7a3f005df01c59162c8898e136d94f7e69c236 --- escher/include/escher/input_view_controller.h | 9 +++++++-- escher/src/input_view_controller.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index aac58e3bc..59c9a7366 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -37,14 +37,19 @@ private: class ExpressionFieldController : public ViewController { public: ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ~ExpressionFieldController(); + ExpressionFieldController(const ExpressionFieldController& other) = delete; + ExpressionFieldController(ExpressionFieldController&& other) = delete; + ExpressionFieldController& operator=(const ExpressionFieldController& other) = delete; + ExpressionFieldController& operator=(ExpressionFieldController&& other) = delete; void didBecomeFirstResponder() override; View * view() override { return &m_expressionField; } ExpressionField * expressionField() { return &m_expressionField; } private: static constexpr int k_bufferLength = TextField::maxBufferSize(); - ExpressionField m_expressionField; - char m_textBuffer[k_bufferLength]; Poincare::ExpressionLayout * m_layout; + char m_textBuffer[k_bufferLength]; + ExpressionField m_expressionField; }; bool inputViewDidFinishEditing(); bool inputViewDidAbortEditing(); diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 9ee810632..4d0fdff73 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -6,8 +6,14 @@ InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : ViewController(parentResponder), + m_layout(new Poincare::HorizontalLayout()), m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate) { + m_textBuffer[0] = 0; +} + +InputViewController::ExpressionFieldController::~ExpressionFieldController() { + delete m_layout; } void InputViewController::ExpressionFieldController::didBecomeFirstResponder() { From c3433da2e2dc2c5f9d9c2eb1a63bab7268d64986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 11:24:47 +0200 Subject: [PATCH 343/459] [apps/calculation] Factorize some code. Change-Id: Id217a1d898c7100172a70cd1fedcf3573c2f68b9 --- apps/calculation/app.cpp | 51 +++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 309def628..b08026b81 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -65,6 +65,27 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e return false; } +bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { + return true; + } + if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { + if (!expressionLayoutField->hasText()) { + return true; + } + + int bufferLength = TextField::maxBufferSize(); + char bufferForParsing[bufferLength]; + expressionLayoutField->writeTextInBuffer(bufferForParsing, bufferLength); + + if (!textInputIsCorrect(bufferForParsing)) { + displayWarning(I18n::Message::SyntaxError); + return true; + } + } + return false; +} + bool App::textInputIsCorrect(const char * text) { /* Here, we check that the expression entered by the user can be printed with * less than k_printedExpressionLength characters. Otherwise, we prevent the @@ -85,36 +106,6 @@ bool App::textInputIsCorrect(const char * text) { return true; } -bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { - return true; - } - /* Here, we check that the expression entered by the user can be printed with - * less than k_printedExpressionLength characters. Otherwise, we prevent the - * user from adding this expression to the calculation store. */ - if (!(expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event))) { - return false; - } - int bufferLength = TextField::maxBufferSize(); - char bufferForParsing[bufferLength]; - expressionLayoutField->writeTextInBuffer(bufferForParsing, bufferLength); - Expression * exp = Expression::parse(bufferForParsing); - if (exp == nullptr) { - expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); - return true; - } - char buffer[Calculation::k_printedExpressionSize]; - int length = exp->writeTextInBuffer(buffer, sizeof(buffer)); - delete exp; - /* If the buffer is totally full, it is VERY likely that writeTextInBuffer - * escaped before printing utterly the expression. */ - if (length >= Calculation::k_printedExpressionSize-1) { - displayWarning(I18n::Message::SyntaxError); - return true; - } - return false; -} - const char * App::XNT() { return "x"; } From 5205d35973ce6c4db48db39b0a74c6e3c327fbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 11:25:35 +0200 Subject: [PATCH 344/459] [apps/calculation] Remove asserts that use obsolete functions Change-Id: I27252b48abb71755335e97d0903453e135247903 --- apps/calculation/edit_expression_controller.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index c5b5a1cbb..53c857809 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -80,7 +80,6 @@ void EditExpressionController::didBecomeFirstResponder() { } bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { - assert(textField == ((ContentView *)view())->expressionField()->textField()); if (textField->isEditing() && textField->textFieldShouldFinishEditing(event) && textField->draftTextLength() == 0 && m_cacheBuffer[0] != 0) { return inputViewDidReceiveEvent(event); } @@ -88,17 +87,14 @@ bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, } bool EditExpressionController::textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) { - assert(textField == ((ContentView *)view())->expressionField()->textField()); return inputViewDidFinishEditing(text, event); } bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) { - assert(textField == ((ContentView *)view())->expressionField()->textField()); return inputViewDidAbortEditing(textField->text()); } bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) { return inputViewDidReceiveEvent(event); } @@ -106,17 +102,14 @@ bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::Expression } bool EditExpressionController::expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, const char * text, Ion::Events::Event event) { - assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); return inputViewDidFinishEditing(text, event); } bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) { - assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); return inputViewDidAbortEditing(nullptr); } void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) { - assert(expressionLayoutField == ((ContentView *)view())->expressionField()->expressionLayoutField()); reloadView(); } From ad65ce2617d8666172452fccd3e582177d48d058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 11:26:30 +0200 Subject: [PATCH 345/459] [apps/calculation] Removed overrided ExpressionField constructor. Change-Id: Id893bb89c9f1282b7fc9e94acc0324a66c749a0c --- apps/calculation/expression_field.cpp | 6 ------ apps/calculation/expression_field.h | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/calculation/expression_field.cpp b/apps/calculation/expression_field.cpp index 06ef5d80d..37c2c4151 100644 --- a/apps/calculation/expression_field.cpp +++ b/apps/calculation/expression_field.cpp @@ -2,12 +2,6 @@ namespace Calculation { -ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : - ::ExpressionField(parentResponder, textBuffer, textBufferLength, layout, textFieldDelegate, expressionLayoutFieldDelegate) -{ - setEditing(true); -} - bool ExpressionField::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back) { return false; diff --git a/apps/calculation/expression_field.h b/apps/calculation/expression_field.h index 34ba89ace..a7fe0e20e 100644 --- a/apps/calculation/expression_field.h +++ b/apps/calculation/expression_field.h @@ -7,7 +7,7 @@ namespace Calculation { class ExpressionField : public ::ExpressionField { public: - ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + using ::ExpressionField::ExpressionField; protected: bool handleEvent(Ion::Events::Event event) override; }; From e5cabe6bda67344b679c6b2246fea6271fd51b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 11:27:14 +0200 Subject: [PATCH 346/459] [escher] Fix ExpressionLayoutField::hasText() Change-Id: I1e0bb0f7dfea6f6b35bbc3ea7374891ea75f48f1 --- escher/src/expression_field.cpp | 2 +- escher/src/expression_layout_field.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index cc89fdf05..1576268d3 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -102,7 +102,7 @@ bool ExpressionField::editionIsInTextField() const { } bool ExpressionField::isEmpty() const { - return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : m_expressionLayoutField.hasText(); + return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_expressionLayoutField.hasText(); } bool ExpressionField::heightIsMaximal() const { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 9481ee866..4bbdd6a6c 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -247,7 +247,7 @@ void ExpressionLayoutField::reload() { } bool ExpressionLayoutField::hasText() const { - return m_contentView.expressionView()->expressionLayout()->isEmpty(); + return m_contentView.expressionView()->expressionLayout()->hasText(); } void ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) { From 643aa89f743548eb8783403064e5a262e1209dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 11:28:18 +0200 Subject: [PATCH 347/459] [poincare] Fix hideEmptyLayoutIfNeeded Change-Id: Id535f49bb9a7b343c05e7d2f24264aeb8e531d85 --- poincare/src/expression_layout_cursor.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index e619ffacc..074a324dd 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -210,9 +210,7 @@ bool ExpressionLayoutCursor::hideEmptyLayoutIfNeeded() { void ExpressionLayoutCursor::clearLayout() { ExpressionLayout * rootLayout = m_pointedExpressionLayout->editableRoot(); assert(rootLayout->isHorizontal()); - for (int i = 0; i < rootLayout->numberOfChildren(); i++) { - static_cast(rootLayout)->removeAndDeleteChildren(); - } + static_cast(rootLayout)->removeAndDeleteChildren(); m_pointedExpressionLayout = rootLayout; } From 13ae1d25458d08aef2a230448d32e805f563f320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 14:57:46 +0200 Subject: [PATCH 348/459] [apps/escher/toolbox] handleEventWithText for all responders. This makes the code in the various toolbox more generic. The arguments of the text to insert are each replaced by a Ion::Charset::Empty. These Empty chars are used to create layouts in ExpressionLayoutFields, and to compute the position of the cursor in other fields, before being removed. Change-Id: Ie81c1e394b06fef2ab801ccff919d6550f70ec30 --- apps/code/python_toolbox.cpp | 3 +- apps/code/python_toolbox.h | 3 - apps/math_toolbox.cpp | 64 +++---------------- apps/math_toolbox.h | 5 -- apps/sequence/list/list_controller.cpp | 32 +++++----- apps/sequence/list/list_controller.h | 2 +- apps/sequence/list/sequence_toolbox.cpp | 21 +----- apps/shared/expression_field_delegate_app.cpp | 2 +- apps/shared/text_field_delegate_app.cpp | 2 +- apps/shared/toolbox_helpers.cpp | 13 +--- apps/shared/toolbox_helpers.h | 3 - escher/include/escher/expression_field.h | 3 +- .../include/escher/expression_layout_field.h | 1 + escher/include/escher/responder.h | 1 + escher/include/escher/text_input.h | 1 - escher/include/escher/text_input_helpers.h | 9 +-- escher/include/escher/toolbox.h | 4 +- escher/src/expression_field.cpp | 8 +++ escher/src/expression_layout_field.cpp | 45 ++++++++++++- escher/src/text_area.cpp | 18 +++++- escher/src/text_field.cpp | 40 ++++++++++-- escher/src/text_input_helpers.cpp | 17 +++-- escher/src/toolbox.cpp | 8 --- 23 files changed, 153 insertions(+), 152 deletions(-) diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp index 070470576..3ceeaf2ad 100644 --- a/apps/code/python_toolbox.cpp +++ b/apps/code/python_toolbox.cpp @@ -294,8 +294,7 @@ bool PythonToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { int strippedEditedTextMaxLength = strlen(editedText)+1; char strippedEditedText[strippedEditedTextMaxLength]; Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength); - TextInput * textInput = static_cast(sender()); - textInput->handleEventWithText(strippedEditedText, true); + sender()->handleEventWithText(strippedEditedText, true); app()->dismissModalViewController(); return true; } diff --git a/apps/code/python_toolbox.h b/apps/code/python_toolbox.h index 5d9dab80f..03c48ebf0 100644 --- a/apps/code/python_toolbox.h +++ b/apps/code/python_toolbox.h @@ -10,10 +10,7 @@ namespace Code { class PythonToolbox : public Toolbox { public: - typedef void (*Action)(void * sender, const char * text); PythonToolbox(); - - // StackViewController bool handleEvent(Ion::Events::Event event) override; protected: KDCoordinate rowHeight(int j) override; diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index f452663fb..62337c781 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -108,67 +108,21 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbo #endif MathToolbox::MathToolbox() : - Toolbox(nullptr, I18n::translate(rootModel()->label())), - m_action(actionForTextInput) + Toolbox(nullptr, I18n::translate(rootModel()->label())) { } -void MathToolbox::setSenderAndAction(Responder * sender, Action action) { - setSender(sender); - m_action = action; -} - -void MathToolbox::actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments) { - ExpressionLayoutField * expressionLayoutEditorSender = static_cast(sender); - Expression * resultExpression = nullptr; - if (removeArguments) { - // Replace the arguments with Empty chars. - int textToInsertMaxLength = strlen(text); - char textToInsert[textToInsertMaxLength]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandText(text, textToInsert, textToInsertMaxLength); - // Create the layout - resultExpression = Expression::parse(textToInsert); - } else { - resultExpression = Expression::parse(text); - } - if (resultExpression == nullptr) { - return; - } - ExpressionLayout * resultLayout = resultExpression->createLayout(); - // Find the pointed layout. - ExpressionLayout * pointedLayout = nullptr; - if (resultLayout->isHorizontal()) { - // If the layout is horizontal, pick the first open parenthesis. - // For now, all horizontal layouts in MathToolbox have parentheses. - for (int i = 0; i < resultLayout->numberOfChildren(); i++) { - if (resultLayout->editableChild(i)->isLeftParenthesis()) { - pointedLayout = resultLayout->editableChild(i); - break; - } - } - } - // Insert the layout. If pointedLayout is nullptr, the cursor will be on the - // right of the inserted layout. - expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout); -} - -void MathToolbox::actionForTextInput(void * sender, const char * text, bool removeArguments) { - TextInput * textInputSender = static_cast(sender); - if (removeArguments) { - int maxTextToInsertLength = strlen(text); - char textToInsert[maxTextToInsertLength]; - // Translate the message and remove the arguments. - Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength); - textInputSender->handleEventWithText(textToInsert); - } else { - textInputSender->handleEventWithText(text); - } -} - bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { ToolboxMessageTree * messageTree = selectedMessageTree; m_selectableTableView.deselectTable(); - m_action(sender(), I18n::translate(messageTree->insertedText()), true); + + // Translate the message and remove the arguments + const char * text = I18n::translate(messageTree->insertedText()); + int maxTextToInsertLength = strlen(text) + 1; + char textToInsert[maxTextToInsertLength]; + Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength, true); + + sender()->handleEventWithText(textToInsert); app()->dismissModalViewController(); return true; } diff --git a/apps/math_toolbox.h b/apps/math_toolbox.h index 6079054e2..fd7f1ad7a 100644 --- a/apps/math_toolbox.h +++ b/apps/math_toolbox.h @@ -7,11 +7,7 @@ class MathToolbox : public Toolbox { public: - typedef void (*Action)(void * sender, const char * text, bool removeArguments); MathToolbox(); - void setSenderAndAction(Responder * sender, Action action); - static void actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments = true); - static void actionForTextInput(void * sender, const char * text, bool removeArguments = true); protected: bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override; const ToolboxMessageTree * rootModel() override; @@ -19,7 +15,6 @@ protected: MessageTableCellWithChevron* nodeCellAtIndex(int index) override; int maxNumberOfDisplayedRows() override; constexpr static int k_maxNumberOfDisplayedRows = 6; // = 240/40 - Action m_action; private: MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows]; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index f570661b7..e253542ba 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -24,15 +24,11 @@ const char * ListController::title() { } Toolbox * ListController::toolboxForTextInput(TextInput * textInput) { - setToolboxExtraCells(); - m_sequenceToolbox.setSenderAndAction(textInput, MathToolbox::actionForTextInput); - return &m_sequenceToolbox; + return toolbox(textInput); } Toolbox * ListController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { - setToolboxExtraCells(); - m_sequenceToolbox.setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField); - return &m_sequenceToolbox; + return toolbox(expressionLayoutField); } TextFieldDelegateApp * ListController::textFieldDelegateApp() { @@ -87,6 +83,20 @@ void ListController::selectPreviousNewSequenceCell() { } } +Toolbox * ListController::toolbox(Responder * sender) { + // Set extra cells + int recurrenceDepth = -1; + int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); + Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow())); + if (sequenceDefinition == 0) { + recurrenceDepth = sequence->numberOfElements()-1; + } + m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth); + // Set sender + m_sequenceToolbox.setSender(sender); + return &m_sequenceToolbox; +} + void ListController::editExpression(Sequence * sequence, int sequenceDefinition, Ion::Events::Event event) { char * initialText = nullptr; char initialTextContent[TextField::maxBufferSize()]; @@ -309,14 +319,4 @@ void ListController::unloadView(View * view) { Shared::ListController::unloadView(view); } -void ListController::setToolboxExtraCells() { - int recurrenceDepth = -1; - int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow())); - if (sequenceDefinition == 0) { - recurrenceDepth = sequence->numberOfElements()-1; - } - m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth); -} - } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 07c6f68bd..658292e21 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -26,6 +26,7 @@ public: Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; void selectPreviousNewSequenceCell(); private: + Toolbox * toolbox(Responder * sender); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event); @@ -44,7 +45,6 @@ private: void reinitExpression(Shared::Function * function) override; View * loadView() override; void unloadView(View * view) override; - void setToolboxExtraCells(); static constexpr KDCoordinate k_emptySubRowHeight = 30; constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences; SequenceStore * m_sequenceStore; diff --git a/apps/sequence/list/sequence_toolbox.cpp b/apps/sequence/list/sequence_toolbox.cpp index 08d67f4fd..b27604498 100644 --- a/apps/sequence/list/sequence_toolbox.cpp +++ b/apps/sequence/list/sequence_toolbox.cpp @@ -114,26 +114,7 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){ int bufferSize = 10; char buffer[bufferSize]; m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize); - if (m_action == MathToolbox::actionForTextInput) { - /* DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout, - * which serializes into "_{}", but we want parentheses for text fields. We - * thus need to remove any underscores, and changes brackets into - * parentheses. */ - for (int i = 0; i < bufferSize; i++) { - if (buffer[i] == '{') { - buffer[i] = '('; - } - if (buffer[i] == '}') { - buffer[i] = ')'; - } - if (buffer[i] == '_') { - memmove(&buffer[i], &buffer[i+1], bufferSize - (i+1) + 1); - bufferSize--; - i--; - } - } - } - m_action(sender(), buffer, false); + sender()->handleEventWithText(buffer); app()->dismissModalViewController(); return true; } diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index 870b4e351..d3474691a 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -49,7 +49,7 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression Toolbox * ExpressionFieldDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { Toolbox * toolbox = container()->mathToolbox(); - static_cast(toolbox)->setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField); + toolbox->setSender(expressionLayoutField); return toolbox; } diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index 3e92edd1f..f9eda1ed4 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -109,7 +109,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion:: Toolbox * TextFieldDelegateApp::toolboxForTextInput(TextInput * textInput) { Toolbox * toolbox = container()->mathToolbox(); - static_cast(toolbox)->setSenderAndAction(textInput, MathToolbox::actionForTextInput); + toolbox->setSender(textInput); return toolbox; } diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index ee39e138d..0a0e50035 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -8,7 +8,8 @@ namespace Shared { namespace ToolboxHelpers { int CursorIndexInCommandText(const char * text) { - for (size_t i = 0; i < strlen(text); i++) { + size_t textLength = strlen(text); + for (size_t i = 0; i < textLength; i++) { if (text[i] == '(' || text[i] == '\'') { return i + 1; } @@ -16,7 +17,7 @@ int CursorIndexInCommandText(const char * text) { return i; } } - return strlen(text); + return textLength; } void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar) { @@ -65,13 +66,5 @@ void TextToInsertForCommandText(const char * command, char * buffer, int bufferS buffer[currentNewTextIndex] = 0; } -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { - TextToParseIntoLayoutForCommandText(I18n::translate(message), buffer, bufferSize); -} - -void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize) { - TextToInsertForCommandText(command, buffer, bufferSize, true); -} - } } diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index ae8226644..16233ffe6 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -17,9 +17,6 @@ void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int buf void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar = false); /* Removes the arguments from a command: * - Removes text between parentheses or brackets, except commas */ -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize); -void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize); -/* Removes the arguments from a command and replaces them with empty chars. */ } } diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index d47f11317..ae8238b6c 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -7,7 +7,7 @@ #include #include -class ExpressionField : public Responder, public View { +class ExpressionField : public Responder, public View { public: ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); @@ -20,6 +20,7 @@ public: bool editionIsInTextField() const; bool isEmpty() const; bool heightIsMaximal() const; + bool handleEventWithText(const char * text, bool indentation = false) override; /* View */ int numberOfSubviews() const override { return 1; } diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 76a3cfa48..48e01d365 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -20,6 +20,7 @@ public: void reload(); bool hasText() const; void writeTextInBuffer(char * buffer, int bufferLength); + bool handleEventWithText(const char * text, bool indentation = false); Poincare::ExpressionLayout * expressionLayout(); /* Responder */ diff --git a/escher/include/escher/responder.h b/escher/include/escher/responder.h index 691c4c208..45deaa8b9 100644 --- a/escher/include/escher/responder.h +++ b/escher/include/escher/responder.h @@ -10,6 +10,7 @@ class Responder { public: Responder(Responder * parentResponder); virtual bool handleEvent(Ion::Events::Event event); // Default implementation does nothing + virtual bool handleEventWithText(const char * text, bool indentation = false) { return false; } virtual void didBecomeFirstResponder(); virtual void willResignFirstResponder(); virtual void didEnterResponderChain(Responder * previousFirstResponder); diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 441bc33d0..136fb77b9 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -19,7 +19,6 @@ public: size_t cursorLocation() const { return nonEditableContentView()->cursorLocation(); } bool setCursorLocation(int location); virtual void scrollToCursor(); - virtual bool handleEventWithText(const char * text, bool indenting = false) = 0; protected: class ContentView : public View { public: diff --git a/escher/include/escher/text_input_helpers.h b/escher/include/escher/text_input_helpers.h index cb216bdaa..219eaba74 100644 --- a/escher/include/escher/text_input_helpers.h +++ b/escher/include/escher/text_input_helpers.h @@ -8,12 +8,9 @@ namespace TextInputHelpers { int CursorIndexInCommand(const char * text); /* Returns the index of the cursor position in a Command, which is the smallest * index between : - * - After the first open parenthesis/quote if the following element is - * either a quote, a coma or a parenthesi - * - The end of the text - * - Special case: when the text preceding the parenthesis is 'random', the - * cursor position is the end of the text. */ -constexpr static const char * k_random = "random"; + * - The first EmptyChar index (which is the position of the first argument) + * - The first empty quote + * - The end of the text */ } #endif diff --git a/escher/include/escher/toolbox.h b/escher/include/escher/toolbox.h index 30a87bd22..7c4f22bb5 100644 --- a/escher/include/escher/toolbox.h +++ b/escher/include/escher/toolbox.h @@ -12,7 +12,7 @@ class Toolbox : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource { public: Toolbox(Responder * parentResponder, const char * title = 0); - void setSender(Responder * sender); + void setSender(Responder * sender) { m_sender = sender; } // StackViewController bool handleEvent(Ion::Events::Event event) override; @@ -72,7 +72,7 @@ protected: bool handleEventForRow(Ion::Events::Event event, int selectedRow); bool selectSubMenu(ToolboxMessageTree * selectedMessageTree); bool returnToPreviousMenu(); - virtual Responder * sender(); + Responder * sender() { return m_sender; } virtual bool selectLeaf(ToolboxMessageTree * selectedMessageTree) = 0; virtual const ToolboxMessageTree * rootModel() = 0; virtual MessageTableCellWithMessage * leafCellAtIndex(int index) = 0; diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 1576268d3..1420db5e0 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -109,6 +109,14 @@ bool ExpressionField::heightIsMaximal() const { return inputViewHeight() == k_separatorThickness + k_verticalExpressionViewMargin + maximalHeight(); } +bool ExpressionField::handleEventWithText(const char * text, bool indentation) { + if (editionIsInTextField()) { + return m_textField.handleEventWithText(text, indentation); + } else { + return m_expressionLayoutField.handleEventWithText(text, indentation); + } +} + KDCoordinate ExpressionField::inputViewHeight() const { if (editionIsInTextField()) { return k_separatorThickness + k_textFieldHeight; diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 4bbdd6a6c..e56457672 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -1,9 +1,11 @@ #include #include #include -#include +#include #include +#include #include +#include ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : ScrollableView(parentResponder, &m_contentView, this), @@ -254,6 +256,47 @@ void ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) { m_contentView.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferLength); } +bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentation) { + size_t textLength = strlen(text) + 1; + size_t textToInsertMaxLength = 2*textLength; + char textToInsert[textToInsertMaxLength]; + + size_t textToInsertIndex = 0; + // Add empty chars where arguments are needed + for (size_t i = textToInsertIndex; i < textLength; i++) { + textToInsert[textToInsertIndex++] = text[i]; + if (((text[i] == '(' || text[i] == '[') + && text[i+1] == ',') + || (text[i] == ',' + && (text[i+1] == ')' || text[i+1] == ']'))) + { + textToInsert[textToInsertIndex++] = Ion::Charset::Empty; + } + } + + Poincare::Expression * resultExpression = Poincare::Expression::parse(textToInsert); + if (resultExpression == nullptr) { + return false; + } + Poincare::ExpressionLayout * resultLayout = resultExpression->createLayout(); + // Find the pointed layout. + Poincare::ExpressionLayout * pointedLayout = nullptr; + if (resultLayout->isHorizontal()) { + /* If the layout is horizontal, pick the first open parenthesis. For now, + * all horizontal layouts in MathToolbox have parentheses. */ + for (int i = 0; i < resultLayout->numberOfChildren(); i++) { + if (resultLayout->editableChild(i)->isLeftParenthesis()) { + pointedLayout = resultLayout->editableChild(i); + break; + } + } + } + /* Insert the layout. If pointedLayout is nullptr, the cursor will be on the + * right of the inserted layout. */ + insertLayoutAtCursor(resultLayout, pointedLayout); + return true; +} + Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() { return m_contentView.expressionView()->expressionLayout(); } diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index 7512d6bac..656766c59 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -293,8 +293,22 @@ TextArea::TextArea(Responder * parentResponder, char * textBuffer, bool TextArea::handleEventWithText(const char * text, bool indentation) { int nextCursorLocation = cursorLocation(); - if ((indentation && insertTextWithIndentation(text, cursorLocation())) || insertTextAtLocation(text, cursorLocation())) { - nextCursorLocation += TextInputHelpers::CursorIndexInCommand(text); + + int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(text); + + size_t eventTextSize = strlen(text) + 1; + char buffer[eventTextSize]; + size_t bufferIndex = 0; + + // Remove EmptyChars + for (size_t i = bufferIndex; i < eventTextSize; i++) { + if (text[i] != Ion::Charset::Empty) { + buffer[bufferIndex++] = text[i]; + } + } + + if ((indentation && insertTextWithIndentation(buffer, cursorLocation())) || insertTextAtLocation(buffer, cursorLocation())) { + nextCursorLocation += cursorIndexInCommand; } setCursorLocation(nextCursorLocation); return true; diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index e37cc4576..1721b9ba5 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include /* TextField::ContentView */ @@ -305,12 +306,41 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation) { if (!isEditing()) { setEditing(true); } + size_t eventTextSize = strlen(eventText) + 1; + char buffer[eventTextSize]; + size_t bufferIndex = 0; + + /* DIRTY + * We use the notation "_{}" to indicate a subscript layout. In a text field, + * such a subscript should be written using parentheses. For instance: "u_{n}" + * should be inserted as "u(n)". + * We thus remove underscores and changes brackets into parentheses. */ + for (size_t i = bufferIndex; i < eventTextSize; i++) { + if (eventText[i] == '{') { + buffer[bufferIndex++] = '('; + } else if (eventText[i] == '}') { + buffer[bufferIndex++] = ')'; + } else if (eventText[i] != '_') { + buffer[bufferIndex++] = eventText[i]; + } + } + + int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(eventText); + + bufferIndex = 0; + // Remove EmptyChars + for (size_t i = bufferIndex; i < eventTextSize; i++) { + if (buffer[i] != Ion::Charset::Empty) { + buffer[bufferIndex++] = buffer[i]; + } + } + int nextCursorLocation = draftTextLength(); - if (insertTextAtLocation(eventText, cursorLocation())) { - /* The cursor position depends on the text as we sometimes want to - * position the cursor at the end of the text and sometimes after the - * first parenthesis. */ - nextCursorLocation = cursorLocation() + TextInputHelpers::CursorIndexInCommand(eventText); + if (insertTextAtLocation(buffer, cursorLocation())) { + /* The cursor position depends on the text as we sometimes want to position + * the cursor at the end of the text and sometimes after the first + * parenthesis. */ + nextCursorLocation = cursorLocation() + cursorIndexInCommand; } setCursorLocation(nextCursorLocation); return m_delegate->textFieldDidHandleEvent(this, true, strlen(text()) != previousTextLength); diff --git a/escher/src/text_input_helpers.cpp b/escher/src/text_input_helpers.cpp index 1c6f88f0d..dd0307d42 100644 --- a/escher/src/text_input_helpers.cpp +++ b/escher/src/text_input_helpers.cpp @@ -1,20 +1,19 @@ #include +#include #include namespace TextInputHelpers { int CursorIndexInCommand(const char * text) { - for (size_t i = 0; i < strlen(text)-1; i++) { - if (text[i] == '(' || text[i] == '\'') { - if (text[i+1] == ')' || text[i+1] == '\'' || text[i+1] == ',') { - if (i >= strlen(k_random) && memcmp(&text[i-strlen(k_random)], k_random, strlen(k_random)) == 0) { - break; - } - return i + 1; - } + size_t textLength = strlen(text); + for (size_t i = 0; i < textLength - 1; i++) { + if (text[i] == '\'' && text[i+1] == '\'') { + return i + 1; + } else if (text[i] == Ion::Charset::Empty) { + return i; } } - return strlen(text); + return textLength; } } diff --git a/escher/src/toolbox.cpp b/escher/src/toolbox.cpp index c423a275d..8c1023009 100644 --- a/escher/src/toolbox.cpp +++ b/escher/src/toolbox.cpp @@ -94,10 +94,6 @@ Toolbox::Toolbox(Responder * parentResponder, const char * title) : { } -void Toolbox::setSender(Responder * sender) { - m_sender = sender; -} - bool Toolbox::handleEvent(Ion::Events::Event event) { return handleEventForRow(event, selectedRow()); } @@ -232,7 +228,3 @@ bool Toolbox::returnToPreviousMenu() { app()->setFirstResponder(&m_listController); return true; } - -Responder * Toolbox::sender() { - return m_sender; -} From 912d0841309e301c1d8fd393c3d9b7979e913cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 15:54:00 +0200 Subject: [PATCH 349/459] [escher] Fix textfield edition when initial text. Change-Id: Ieee10ec6fcbe6464dee2748de033f269169789d9 --- escher/src/expression_layout_field.cpp | 3 --- escher/src/text_field.cpp | 9 +++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index e56457672..e6d6f5e87 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -50,9 +50,6 @@ bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { didHandleEvent = true; } if (didHandleEvent) { - if (!isEditing()) { - setEditing(true); - } shouldRecomputeLayout = m_contentView.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; if (!shouldRecomputeLayout) { m_contentView.cursorPositionChanged(); diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index 1721b9ba5..a8374f65a 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -303,9 +303,7 @@ void TextField::scrollToCursor() { bool TextField::handleEventWithText(const char * eventText, bool indentation) { size_t previousTextLength = strlen(text()); - if (!isEditing()) { - setEditing(true); - } + size_t eventTextSize = strlen(eventText) + 1; char buffer[eventTextSize]; size_t bufferIndex = 0; @@ -325,7 +323,7 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation) { } } - int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(eventText); + int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(buffer); bufferIndex = 0; // Remove EmptyChars @@ -335,6 +333,9 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation) { } } + if (!isEditing()) { + setEditing(true); + } int nextCursorLocation = draftTextLength(); if (insertTextAtLocation(buffer, cursorLocation())) { /* The cursor position depends on the text as we sometimes want to position From fd3a2c3cbc8d8d56b718b4d1f44d2bc55d73ee0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 15:54:31 +0200 Subject: [PATCH 350/459] [apps/code] Use a special char to position the cursor in Python commands Change-Id: I7ae3d6098160212d8683a671c78d3bdb937fb701 --- apps/code/toolbox.universal.i18n | 2 +- apps/i18n.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/code/toolbox.universal.i18n b/apps/code/toolbox.universal.i18n index 0521ae967..86b596a02 100644 --- a/apps/code/toolbox.universal.i18n +++ b/apps/code/toolbox.universal.i18n @@ -40,7 +40,7 @@ ForInRange2ArgsLoop = "for i in range(,):\n " ForInRange2ArgsLoopWithArg = "for i in range(start, stop):\n instruction" ForInRange1ArgLoop = "for i in range():\n " ForInRange1ArgLoopWithArg = "for i in range(size):\n instruction" -PythonCommandDef = "def ():\n " +PythonCommandDef = "def •():\n " PythonCommandDefWithArg = "def function(x):" PythonCommandReturn = "return " RandomModule = "random" diff --git a/apps/i18n.py b/apps/i18n.py index 808df06bc..7a6a71ede 100644 --- a/apps/i18n.py +++ b/apps/i18n.py @@ -12,7 +12,8 @@ ion_special_characters = { u'μ': "Ion::Charset::SmallMu", u'σ': "Ion::Charset::SmallSigma", u'≤': "Ion::Charset::LessEqual", - u'≈': "Ion::Charset::AlmostEqual" + u'≈': "Ion::Charset::AlmostEqual", + u'•': "Ion::Charset::Empty" } def ion_char(i18n_letter): From fc357a27eebdcf870ccaafeb3969eb52fb8a6b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 16:33:18 +0200 Subject: [PATCH 351/459] [parser] Fix Unary minus. -1-7 would give +6 becaused it was parsed as -(1-7). Change-Id: Iff98a2ee52ff57c5ab47433aa208dd5fa4c6d3d6 --- poincare/src/expression_parser.y | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index c14f90b57..153ce31c9 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -224,17 +224,17 @@ mul : div { $$ = $1; } | mul MULTIPLY MINUS div { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Multiplication(terms, 2, false); } ; -min : mul { $$ = $1; } - | mul MINUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } - | mul MINUS MINUS min { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Subtraction(terms, false); } +unmin : mul { $$ = $1; } + | MINUS mul %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } ; -unmin : min { $$ = $1; } - | MINUS min %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } +min : unmin { $$ = $1; } + | unmin MINUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } + | unmin MINUS MINUS min { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Subtraction(terms, false); } ; -exp : unmin { $$ = $1; } - | exp PLUS unmin { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } +exp : min { $$ = $1; } + | exp PLUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } ; final_exp : exp { $$ = $1; } From fbb2df7fc8e21ef30cc4bff5f20ef340d903238e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 16:34:00 +0200 Subject: [PATCH 352/459] [poincare/tests] Add simple unary minus tests. Change-Id: I8fe2fe2578faf40feef4f11f19d9b9331d99020b --- poincare/test/addition.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index 85216991c..84581b3bc 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -34,6 +34,8 @@ QUIZ_CASE(poincare_addition_evaluate) { QUIZ_CASE(poincare_addition_simplify) { assert_parsed_expression_simplify_to("2+1", "3"); + assert_parsed_expression_simplify_to("-2+6", "4"); + assert_parsed_expression_simplify_to("-2-6", "-8"); assert_parsed_expression_simplify_to("2+A", "2+A"); assert_parsed_expression_simplify_to("1+2+3+4+5+6+7", "28"); assert_parsed_expression_simplify_to("1+2+3+4+5+A+6+7", "28+A"); From 0ae7c8a723f32c46231f7edb0d3b14e51ee34484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 17:16:26 +0200 Subject: [PATCH 353/459] [xnt] Insert the right XNT char. Change-Id: Ibc91a2ece310313fb368a68483c5a1b6fe14aad2 --- apps/shared/expression_field_delegate_app.cpp | 15 +++++++++++++++ apps/shared/expression_field_delegate_app.h | 1 + escher/include/escher/expression_layout_field.h | 1 + escher/src/expression_layout_field.cpp | 8 ++++---- poincare/src/layout/expression_layout.cpp | 3 ++- poincare/src/layout/integral_layout.h | 1 + poincare/src/layout/sequence_layout.cpp | 4 ---- poincare/src/layout/sequence_layout.h | 2 +- 8 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index d3474691a..1854ffbe7 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -12,6 +12,14 @@ ExpressionFieldDelegateApp::ExpressionFieldDelegateApp(Container * container, Sn { } +char ExpressionFieldDelegateApp::privateXNT(ExpressionLayoutField * expressionLayoutField) { + char xntCharFromLayout = expressionLayoutField->XNTChar(); + if (xntCharFromLayout != Ion::Charset::Empty) { + return xntCharFromLayout; + } + return XNT()[0]; +} + bool ExpressionFieldDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } @@ -44,6 +52,13 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression expressionLayoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } + if (event == Ion::Events::XNT) { + if (!expressionLayoutField->isEditing()) { + expressionLayoutField->setEditing(true); + } + const char xnt[2] = {privateXNT(expressionLayoutField), 0}; + return expressionLayoutField->handleEventWithText(xnt); + } return false; } diff --git a/apps/shared/expression_field_delegate_app.h b/apps/shared/expression_field_delegate_app.h index 4e8b0e2bc..264492a87 100644 --- a/apps/shared/expression_field_delegate_app.h +++ b/apps/shared/expression_field_delegate_app.h @@ -13,6 +13,7 @@ public: virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; protected: + char privateXNT(ExpressionLayoutField * expressionLayoutField); ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); }; diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 48e01d365..ab86ef184 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -22,6 +22,7 @@ public: void writeTextInBuffer(char * buffer, int bufferLength); bool handleEventWithText(const char * text, bool indentation = false); Poincare::ExpressionLayout * expressionLayout(); + char XNTChar(); /* Responder */ Toolbox * toolbox() override; diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index e6d6f5e87..48a7543cb 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -139,10 +139,6 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { m_contentView.cursor()->addFractionLayoutAndCollapseSiblings(); return true; } - if (event == Ion::Events::XNT) { - m_contentView.cursor()->addXNTCharLayout(); - return true; - } if (event == Ion::Events::Exp) { m_contentView.cursor()->addEmptyExponentialLayout(); return true; @@ -297,3 +293,7 @@ bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentat Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() { return m_contentView.expressionView()->expressionLayout(); } + +char ExpressionLayoutField::XNTChar() { + return m_contentView.cursor()->pointedExpressionLayout()->XNTChar(); +} diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index abf881acd..45926669d 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Poincare { @@ -236,7 +237,7 @@ void ExpressionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { char ExpressionLayout::XNTChar() const { if (m_parent == nullptr) { - return 'x'; + return Ion::Charset::Empty; } return m_parent->XNTChar(); } diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index 1c1b8efd3..ca2333dca 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -27,6 +27,7 @@ public: /* Other */ ExpressionLayout * layoutToPointWhenInserting() override; + char XNTChar() const override { return 'x'; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 53d2df118..0f6bc85eb 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -118,10 +118,6 @@ ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { return lowerBoundLayout(); } -char SequenceLayout::XNTChar() const { - return 'n'; -} - int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits) const { assert(operatorName != nullptr); if (bufferSize == 0) { diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 934d1378a..327e97d49 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -16,7 +16,7 @@ public: ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayout * layoutToPointWhenInserting() override; - char XNTChar() const override; + char XNTChar() const override { return 'n'; } protected: constexpr static KDCoordinate k_boundHeightMargin = 2; constexpr static KDCoordinate k_argumentWidthMargin = 2; From 4e165153441ee9407cb6d6ced61287b414498cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 17:23:00 +0200 Subject: [PATCH 354/459] [poincare] Do not insert an empty base for power layouts. This should be done only if the power is added to an horizontal layout with no child. Change-Id: I5f2f501420da127a2ed42d2b01042ec5968f488f --- poincare/src/expression_layout_cursor.cpp | 25 +++++++---------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 074a324dd..6aa8f482a 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -252,26 +252,15 @@ bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { } bool ExpressionLayoutCursor::baseForNewPowerLayout() { - // Returns true if the layout on the left of the pointed layout is suitable to - // be the base of a new power layout. - int numberOfOpenParenthesis = 0; - if (m_position == Position::Right - && m_pointedExpressionLayout->isCollapsable(&numberOfOpenParenthesis, true)) + /* Returns true if the layout on the left of the pointed layout is suitable to + * be the base of a new power layout: the base layout should be anything but + * an horizontal layout with no child. */ + if (m_pointedExpressionLayout->isHorizontal() + && m_pointedExpressionLayout->numberOfChildren() == 0) { - return true; + return false; } - if (m_pointedExpressionLayout->parent() != nullptr) { - int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); - if (m_position == Position::Left - && m_pointedExpressionLayout->parent()->isHorizontal() - && indexInParent > 0 - && (m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isEmpty() - || m_pointedExpressionLayout->editableParent()->editableChild(indexInParent-1)->isCollapsable(&numberOfOpenParenthesis, true))) - { - return true; - } - } - return false; + return true; } KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { From 9ea40cf5a1aedd0aadb0ff7bedab7e6213126630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 17:31:14 +0200 Subject: [PATCH 355/459] [poincare] Better differentiation between cursor and AbsoluteValueLayout Change-Id: Idbffc844b41fbc1ac940ea155c1b89245bb8aefe --- poincare/src/layout/absolute_value_layout.h | 1 + poincare/src/layout/bracket_pair_layout.cpp | 18 +++++++++--------- poincare/src/layout/bracket_pair_layout.h | 1 + 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index 0888296b7..bccc3a39e 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -16,6 +16,7 @@ public: } protected: KDCoordinate widthMargin() const override { return 2; } + virtual KDCoordinate verticalExternMargin() const { return 1; } bool renderTopBar() const override { return false; } bool renderBottomBar() const override { return false; } }; diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index 010774c61..cb88a4d1b 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -109,15 +109,15 @@ void BracketPairLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCol const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); KDCoordinate verticalBarHeight = operandLayout()->size().height() + 2*k_verticalMargin; - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, verticalBarHeight), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y(), k_lineThickness, verticalBarHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); if (renderTopBar()) { - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y() + verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); } if (renderBottomBar()) { - ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); } } @@ -125,18 +125,18 @@ KDSize BracketPairLayout::computeSize() { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); KDSize operandSize = operandLayout()->size(); - return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height() + 2 * k_verticalMargin); + return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height() + 2 * k_verticalMargin + 2*verticalExternMargin()); } void BracketPairLayout::computeBaseline() { - m_baseline = operandLayout()->baseline() + k_verticalMargin; + m_baseline = operandLayout()->baseline() + k_verticalMargin + verticalExternMargin(); m_baselined = true; } KDPoint BracketPairLayout::positionOfChild(ExpressionLayout * child) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); - return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, k_verticalMargin); + return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, k_verticalMargin + verticalExternMargin()); } } diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index 2d3515ac7..81f522031 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -20,6 +20,7 @@ protected: ExpressionLayout * operandLayout(); KDCoordinate externWidthMargin() const { return 2; } virtual KDCoordinate widthMargin() const { return 5; } + virtual KDCoordinate verticalExternMargin() const { return 0; } virtual bool renderTopBar() const { return true; } virtual bool renderBottomBar() const { return true; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; From c929390a44ca5a8cb2acfd10af4ff1b4312bdd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 17:33:51 +0200 Subject: [PATCH 356/459] [poincare] Fix SequenceLayout navigation Change-Id: I0a263343d8048b8924872c2d1119b2d1c4f5f09b --- poincare/src/layout/sequence_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 0f6bc85eb..40856ec07 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -65,7 +65,7 @@ ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor * cu && argumentLayout() && cursor->pointedExpressionLayout() == argumentLayout()) { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor->pointedExpressionLayout() == this); // Case: Left. Go to the upper bound. From 8afed56d61117ee54b4c3a1f26b79f280cd34aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 17:53:46 +0200 Subject: [PATCH 357/459] [poincare] Fix subscript layout position and baseline. Change-Id: I3c2efdfed6440b0bcb6fe98400ae2c5f32315396 --- poincare/src/layout/vertical_offset_layout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index bf493b980..5e51e94b5 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -226,13 +226,13 @@ KDSize VerticalOffsetLayout::computeSize() { width += k_separationMargin; } } - KDCoordinate height = baseLayout()->size().height() + indiceLayout()->size().height() - k_indiceHeight; + KDCoordinate height = baseLayout()->size().height() - k_indiceHeight + indiceLayout()->size().height(); return KDSize(width, height); } void VerticalOffsetLayout::computeBaseline() { if (m_type == Type::Subscript) { - m_baseline = 0; + m_baseline = baseLayout()->baseline(); } else { m_baseline = indiceLayout()->size().height() - k_indiceHeight + baseLayout()->baseline(); } @@ -246,7 +246,7 @@ KDPoint VerticalOffsetLayout::positionOfChild(ExpressionLayout * child) { } assert(m_type == Type::Subscript); ExpressionLayout * base = baseLayout(); - return KDPoint(0, base->size().height() - base->baseline() - k_indiceHeight); + return KDPoint(0, base->size().height() - k_indiceHeight); } void VerticalOffsetLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { From 861aea61009d670737ef80cc8272e648304d8f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 23 Apr 2018 18:00:20 +0200 Subject: [PATCH 358/459] [poincare] LinearEdition mode by default. Change-Id: I6783e695b4918424829fb0412f29eea22967ce92 --- poincare/src/preferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index 2dbc12bce..c9918d13b 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -6,7 +6,7 @@ namespace Poincare { Preferences::Preferences() : m_angleUnit(Expression::AngleUnit::Degree), m_displayMode(PrintFloat::Mode::Decimal), - m_editionMode(EditionMode::Edition2D), + m_editionMode(EditionMode::Edition1D), m_complexFormat(Expression::ComplexFormat::Cartesian), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits) { From 6dd20575931bef19999d6c2dbd7f9007e54fbf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 09:50:46 +0200 Subject: [PATCH 359/459] [apps/calculation] Re-arrange private attributes. Change-Id: I024e17fac84d8e3025745267ad488db83eeeb928 --- apps/calculation/edit_expression_controller.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index 339cfbca6..e6aed04f5 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -63,8 +63,8 @@ private: bool inputViewDidFinishEditing(const char * text, Ion::Events::Event event); bool inputViewDidAbortEditing(const char * text); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; - char m_cacheBuffer[TextField::maxBufferSize()]; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; + char m_cacheBuffer[TextField::maxBufferSize()]; HistoryController * m_historyController; CalculationStore * m_calculationStore; }; From 3dc55230f75b0a34e0c6dcbb4129c0e58b5cc5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 10:01:44 +0200 Subject: [PATCH 360/459] [poincare] Remove methods from CondensedSumLayout. This layout is never used with a cursor, so many methods can just be assert(false). Change-Id: I3591d8f1983e402130f55fa1875436f24dff637d --- poincare/src/layout/condensed_sum_layout.cpp | 91 +++----------------- 1 file changed, 10 insertions(+), 81 deletions(-) diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 0866e06e4..ccde86ae1 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -11,101 +11,30 @@ ExpressionLayout * CondensedSumLayout::clone() const { } ExpressionLayoutCursor CondensedSumLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Left of the bounds. Go Left of the sum. - if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) - || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); - } - // Case: Left of the base. Go Right of the lower bound. - if (baseLayout() - && cursor->pointedExpressionLayout() == baseLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) - { - return ExpressionLayoutCursor(subscriptLayout(), ExpressionLayoutCursor::Position::Right); - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. Go to the base and move Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - assert(baseLayout()); - cursor->setPointedExpressionLayout(baseLayout()); - return baseLayout()->cursorLeftOf(cursor, shouldRecomputeLayout); - } - // Case: Left. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - if (m_parent) { - return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); - } + /* CondensedSumLayout is only used in apps/shared/sum_graph_controller.cpp, in + * a view with no cursor. */ + assert(false); return ExpressionLayoutCursor(); } ExpressionLayoutCursor CondensedSumLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - // Case: Right of the bounds. Go Left of the operand. - if (((subscriptLayout() && cursor->pointedExpressionLayout() == subscriptLayout()) - || (superscriptLayout() && cursor->pointedExpressionLayout() == superscriptLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - assert(baseLayout() != nullptr); - return ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left); - } - // Case: Right of the base. Ask the parent. - if (baseLayout() - && cursor->pointedExpressionLayout() == baseLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) - { - cursor->setPointedExpressionLayout(this); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); - } - return ExpressionLayoutCursor(); - } - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. Go to the upper bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - assert(superscriptLayout()); - return ExpressionLayoutCursor(superscriptLayout(), ExpressionLayoutCursor::Position::Left); - } - // Case: Right. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - if (m_parent) { - return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); - } + assert(false); return ExpressionLayoutCursor(); } ExpressionLayoutCursor CondensedSumLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // If the cursor is inside the subscript layout, move it to the superscript. - if (subscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(subscriptLayout(), true)) { - assert(superscriptLayout() != nullptr); - return superscriptLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); - } - // If the cursor is Left of the base layout, move it to the superscript. - if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { - assert(superscriptLayout() != nullptr); - return superscriptLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); - } - return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); + assert(false); + return ExpressionLayoutCursor(); } ExpressionLayoutCursor CondensedSumLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // If the cursor is inside the superscript layout, move it to the subscript. - if (superscriptLayout() && cursor->pointedExpressionLayout()->hasAncestor(superscriptLayout(), true)) { - assert(subscriptLayout() != nullptr); - return subscriptLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); - } - // If the cursor is Left of the base layout, move it to the subscript. - if (baseLayout() && cursor->isEquivalentTo(ExpressionLayoutCursor(baseLayout(), ExpressionLayoutCursor::Position::Left))) { - assert(subscriptLayout() != nullptr); - return subscriptLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); - } - return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + assert(false); + return ExpressionLayoutCursor(); } ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { - assert(subscriptLayout() != nullptr); - return subscriptLayout(); + assert(false); + return nullptr; } void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { From 51e986606c15ebabcb85dea615f8ea2283836eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 10:16:22 +0200 Subject: [PATCH 361/459] [poincare] Factorize Left/RightBracket layouts code. Change-Id: I8708b9e0cfe0154232184f01afd532d4879b4cc0 --- poincare/src/layout/bracket_layout.cpp | 57 +++++++++++++++++++- poincare/src/layout/bracket_layout.h | 3 +- poincare/src/layout/left_bracket_layout.cpp | 51 +----------------- poincare/src/layout/left_bracket_layout.h | 2 - poincare/src/layout/right_bracket_layout.cpp | 49 +---------------- poincare/src/layout/right_bracket_layout.h | 2 - 6 files changed, 60 insertions(+), 104 deletions(-) diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index 9ce509275..0dd4cd6d7 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -1,4 +1,5 @@ #include "bracket_layout.h" +#include #include extern "C" { #include @@ -50,14 +51,68 @@ KDSize BracketLayout::computeSize() { return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); } +void BracketLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + int currentNumberOfOpenBrackets = 1; + int increment = isLeftBracket() ? 1 : -1; + int numberOfSiblings = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((isRightBracket() && sibling->isLeftBracket()) + || (isLeftBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isRightBracket() && sibling->isRightBracket()) + || (isLeftBracket() && sibling->isLeftBracket())) + { + currentNumberOfOpenBrackets++; + } + if (sibling->baseline() > m_baseline) { + m_baseline = sibling->baseline(); + } + } + m_baselined = true; +} + KDCoordinate BracketLayout::operandHeight() { if (!m_operandHeightComputed) { computeOperandHeight(); - m_operandHeightComputed = true; } return m_operandHeight; } +void BracketLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; + int currentNumberOfOpenBrackets = 1; + int increment = isLeftBracket() ? 1 : -1; + int numberOfSiblings = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((isRightBracket() && sibling->isLeftBracket()) + || (isLeftBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isRightBracket() && sibling->isRightBracket()) + || (isLeftBracket() && sibling->isLeftBracket())) + { + currentNumberOfOpenBrackets++; + } + KDCoordinate siblingHeight = sibling->size().height(); + if (siblingHeight > m_operandHeight) { + m_operandHeight = siblingHeight; + } + } + m_operandHeightComputed = true; +} + KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 4f8ee41bf..6418d45b8 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -17,8 +17,9 @@ protected: constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_externWidthMargin = 2; KDSize computeSize() override; + void computeBaseline() override; KDCoordinate operandHeight(); - virtual void computeOperandHeight() = 0; + void computeOperandHeight(); KDPoint positionOfChild(ExpressionLayout * child) override; bool m_operandHeightComputed; uint16_t m_operandHeight; diff --git a/poincare/src/layout/left_bracket_layout.cpp b/poincare/src/layout/left_bracket_layout.cpp index 27e99e0ff..21a3b5fe5 100644 --- a/poincare/src/layout/left_bracket_layout.cpp +++ b/poincare/src/layout/left_bracket_layout.cpp @@ -1,14 +1,9 @@ #include "left_bracket_layout.h" -#include -extern "C" { -#include -} namespace Poincare { ExpressionLayout * LeftBracketLayout::clone() const { - LeftBracketLayout * layout = new LeftBracketLayout(); - return layout; + return new LeftBracketLayout(); } void LeftBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { @@ -17,48 +12,4 @@ void LeftBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCol ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -void LeftBracketLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - int currentNumberOfOpenBrackets = 1; - int numberOfSiblings = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfSiblings; i++) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if (sibling->isRightBracket()) { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - return; - } - } else if (sibling->isLeftBracket()) { - currentNumberOfOpenBrackets++; - } - KDCoordinate siblingHeight = sibling->size().height(); - if (siblingHeight > m_operandHeight) { - m_operandHeight = siblingHeight; - } - } -} - -void LeftBracketLayout::computeBaseline() { - assert(m_parent != nullptr); - m_baseline = operandHeight()/2; - int currentNumberOfOpenBrackets = 1; - int numberOfSiblings = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + 1; i < numberOfSiblings; i++) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if (sibling->isRightBracket()) { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - break; - } - } else if (sibling->isLeftBracket()) { - currentNumberOfOpenBrackets++; - } - if (sibling->baseline() > m_baseline) { - m_baseline = sibling->baseline(); - } - } - m_baselined = true; -} - } diff --git a/poincare/src/layout/left_bracket_layout.h b/poincare/src/layout/left_bracket_layout.h index 12cf64409..f8c3881b6 100644 --- a/poincare/src/layout/left_bracket_layout.h +++ b/poincare/src/layout/left_bracket_layout.h @@ -16,8 +16,6 @@ public: bool isLeftBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - void computeOperandHeight() override; - void computeBaseline() override; }; } diff --git a/poincare/src/layout/right_bracket_layout.cpp b/poincare/src/layout/right_bracket_layout.cpp index f3743b1d8..c5626fb11 100644 --- a/poincare/src/layout/right_bracket_layout.cpp +++ b/poincare/src/layout/right_bracket_layout.cpp @@ -1,14 +1,9 @@ #include "right_bracket_layout.h" -#include -extern "C" { -#include -} namespace Poincare { ExpressionLayout * RightBracketLayout::clone() const { - RightBracketLayout * layout = new RightBracketLayout(); - return layout; + return new RightBracketLayout(); } void RightBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { @@ -17,46 +12,4 @@ void RightBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); } -void RightBracketLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - int currentNumberOfOpenBrackets = 1; - for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if (sibling->isLeftBracket()) { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - return; - } - } else if (sibling->isRightBracket()) { - currentNumberOfOpenBrackets++; - } - KDCoordinate siblingHeight = sibling->size().height(); - if (siblingHeight > m_operandHeight) { - m_operandHeight = siblingHeight; - } - } -} - -void RightBracketLayout::computeBaseline() { - assert(m_parent != nullptr); - m_baseline = operandHeight()/2; - int currentNumberOfOpenBrackets = 1; - for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if (sibling->isLeftBracket()) { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - break; - } - } else if (sibling->isRightBracket()) { - currentNumberOfOpenBrackets++; - } - if (sibling->baseline() > m_baseline) { - m_baseline = sibling->baseline(); - } - } - m_baselined = true; -} - } diff --git a/poincare/src/layout/right_bracket_layout.h b/poincare/src/layout/right_bracket_layout.h index 011c67cf8..bece05a12 100644 --- a/poincare/src/layout/right_bracket_layout.h +++ b/poincare/src/layout/right_bracket_layout.h @@ -16,8 +16,6 @@ public: bool isRightBracket() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - void computeOperandHeight() override; - void computeBaseline() override; }; } From e622d6aa437483d9ef69b4f7b667fc7ed390b0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 10:28:42 +0200 Subject: [PATCH 362/459] [poincare] Rename BracketLayout -> SquareBracketLayout Change-Id: I1c2c41a2dcdd0209f37b3a4f3317c91a52122117 --- poincare/Makefile | 10 +++++----- poincare/include/poincare_layouts.h | 4 ++-- poincare/src/expression_layout_cursor.cpp | 4 ++-- ...out.cpp => left_square_bracket_layout.cpp} | 8 ++++---- ..._layout.h => left_square_bracket_layout.h} | 10 +++++----- ...ut.cpp => right_square_bracket_layout.cpp} | 8 ++++---- ...layout.h => right_square_bracket_layout.h} | 10 +++++----- ...t_layout.cpp => square_bracket_layout.cpp} | 20 +++++++++---------- ...acket_layout.h => square_bracket_layout.h} | 8 ++++---- 9 files changed, 41 insertions(+), 41 deletions(-) rename poincare/src/layout/{left_bracket_layout.cpp => left_square_bracket_layout.cpp} (59%) rename poincare/src/layout/{left_bracket_layout.h => left_square_bracket_layout.h} (66%) rename poincare/src/layout/{right_bracket_layout.cpp => right_square_bracket_layout.cpp} (60%) rename poincare/src/layout/{right_bracket_layout.h => right_square_bracket_layout.h} (66%) rename poincare/src/layout/{bracket_layout.cpp => square_bracket_layout.cpp} (83%) rename poincare/src/layout/{bracket_layout.h => square_bracket_layout.h} (83%) diff --git a/poincare/Makefile b/poincare/Makefile index 193bb6154..cc057cbdc 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -92,9 +92,6 @@ objs += $(addprefix poincare/src/layout/,\ binomial_coefficient_layout.o\ bounded_static_layout_hierarchy.o\ bracket_pair_layout.o\ - left_bracket_layout.o\ - bracket_layout.o\ - right_bracket_layout.o\ ceiling_layout.o\ char_layout.o\ condensed_sum_layout.o\ @@ -107,13 +104,16 @@ objs += $(addprefix poincare/src/layout/,\ grid_layout.o\ horizontal_layout.o\ integral_layout.o\ + left_parenthesis_layout.o\ + left_square_bracket_layout.o\ matrix_layout.o\ nth_root_layout.o\ - left_parenthesis_layout.o\ parenthesis_layout.o\ - right_parenthesis_layout.o\ product_layout.o\ + right_parenthesis_layout.o\ + right_square_bracket_layout.o\ sequence_layout.o\ + square_bracket_layout.o\ static_layout_hierarchy.o\ sum_layout.o\ vertical_offset_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 5f2dc7096..8e31672a8 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -5,8 +5,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 6aa8f482a..7348bf6f0 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -178,9 +178,9 @@ void ExpressionLayoutCursor::insertText(const char * text) { * binary file 2K. */ #if 0 else if (text[i] == '[') { - newChild = new LeftBracketLayout(); + newChild = new LeftSquareBracketLayout(); } else if (text[i] == ']') { - newChild = new RightBracketLayout(); + newChild = new RightSquareBracketLayout(); } #endif else { diff --git a/poincare/src/layout/left_bracket_layout.cpp b/poincare/src/layout/left_square_bracket_layout.cpp similarity index 59% rename from poincare/src/layout/left_bracket_layout.cpp rename to poincare/src/layout/left_square_bracket_layout.cpp index 21a3b5fe5..fd82e06b5 100644 --- a/poincare/src/layout/left_bracket_layout.cpp +++ b/poincare/src/layout/left_square_bracket_layout.cpp @@ -1,12 +1,12 @@ -#include "left_bracket_layout.h" +#include "left_square_bracket_layout.h" namespace Poincare { -ExpressionLayout * LeftBracketLayout::clone() const { - return new LeftBracketLayout(); +ExpressionLayout * LeftSquareBracketLayout::clone() const { + return new LeftSquareBracketLayout(); } -void LeftBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void LeftSquareBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); diff --git a/poincare/src/layout/left_bracket_layout.h b/poincare/src/layout/left_square_bracket_layout.h similarity index 66% rename from poincare/src/layout/left_bracket_layout.h rename to poincare/src/layout/left_square_bracket_layout.h index f8c3881b6..b07709fda 100644 --- a/poincare/src/layout/left_bracket_layout.h +++ b/poincare/src/layout/left_square_bracket_layout.h @@ -1,14 +1,14 @@ -#ifndef POINCARE_BRACKET_LEFT_LAYOUT_H -#define POINCARE_BRACKET_LEFT_LAYOUT_H +#ifndef POINCARE_LEFT_SQUARE_BRACKET_LAYOUT_H +#define POINCARE_LEFT_SQUARE_BRACKET_LAYOUT_H -#include +#include #include namespace Poincare { -class LeftBracketLayout : public BracketLayout { +class LeftSquareBracketLayout : public SquareBracketLayout { public: - using BracketLayout::BracketLayout; + using SquareBracketLayout::SquareBracketLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '['); diff --git a/poincare/src/layout/right_bracket_layout.cpp b/poincare/src/layout/right_square_bracket_layout.cpp similarity index 60% rename from poincare/src/layout/right_bracket_layout.cpp rename to poincare/src/layout/right_square_bracket_layout.cpp index c5626fb11..019464bc6 100644 --- a/poincare/src/layout/right_bracket_layout.cpp +++ b/poincare/src/layout/right_square_bracket_layout.cpp @@ -1,12 +1,12 @@ -#include "right_bracket_layout.h" +#include "right_square_bracket_layout.h" namespace Poincare { -ExpressionLayout * RightBracketLayout::clone() const { - return new RightBracketLayout(); +ExpressionLayout * RightSquareBracketLayout::clone() const { + return new RightSquareBracketLayout(); } -void RightBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { +void RightSquareBracketLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, operandHeight()), expressionColor); ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y(), k_bracketWidth, k_lineThickness), expressionColor); ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + operandHeight(), k_bracketWidth, k_lineThickness), expressionColor); diff --git a/poincare/src/layout/right_bracket_layout.h b/poincare/src/layout/right_square_bracket_layout.h similarity index 66% rename from poincare/src/layout/right_bracket_layout.h rename to poincare/src/layout/right_square_bracket_layout.h index bece05a12..d99d3e6e4 100644 --- a/poincare/src/layout/right_bracket_layout.h +++ b/poincare/src/layout/right_square_bracket_layout.h @@ -1,14 +1,14 @@ -#ifndef POINCARE_BRACKET_RIGHT_LAYOUT_H -#define POINCARE_BRACKET_RIGHT_LAYOUT_H +#ifndef POINCARE_RIGHT_SQUARE_BRACKET_LAYOUT_H +#define POINCARE_RIGHT_SQUARE_BRACKET_LAYOUT_H -#include +#include #include namespace Poincare { -class RightBracketLayout : public BracketLayout { +class RightSquareBracketLayout : public SquareBracketLayout { public: - using BracketLayout::BracketLayout; + using SquareBracketLayout::SquareBracketLayout; ExpressionLayout * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ']'); diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/square_bracket_layout.cpp similarity index 83% rename from poincare/src/layout/bracket_layout.cpp rename to poincare/src/layout/square_bracket_layout.cpp index 0dd4cd6d7..1ca9ae3d6 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/square_bracket_layout.cpp @@ -1,4 +1,4 @@ -#include "bracket_layout.h" +#include "square_bracket_layout.h" #include #include extern "C" { @@ -8,18 +8,18 @@ extern "C" { namespace Poincare { -BracketLayout::BracketLayout() : +SquareBracketLayout::SquareBracketLayout() : StaticLayoutHierarchy<0>(), m_operandHeightComputed(false) { } -void BracketLayout::invalidAllSizesPositionsAndBaselines() { +void SquareBracketLayout::invalidAllSizesPositionsAndBaselines() { m_operandHeightComputed = false; ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor SquareBracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Right. Go Left. if (cursor->position() == ExpressionLayoutCursor::Position::Right) { @@ -33,7 +33,7 @@ ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * curs return ExpressionLayoutCursor(); } -ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor SquareBracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { assert(cursor->pointedExpressionLayout() == this); // Case: Left. Go Right. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { @@ -47,11 +47,11 @@ ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cur return ExpressionLayoutCursor(); } -KDSize BracketLayout::computeSize() { +KDSize SquareBracketLayout::computeSize() { return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); } -void BracketLayout::computeBaseline() { +void SquareBracketLayout::computeBaseline() { assert(m_parent != nullptr); m_baseline = operandHeight()/2; int currentNumberOfOpenBrackets = 1; @@ -78,14 +78,14 @@ void BracketLayout::computeBaseline() { m_baselined = true; } -KDCoordinate BracketLayout::operandHeight() { +KDCoordinate SquareBracketLayout::operandHeight() { if (!m_operandHeightComputed) { computeOperandHeight(); } return m_operandHeight; } -void BracketLayout::computeOperandHeight() { +void SquareBracketLayout::computeOperandHeight() { assert(m_parent != nullptr); m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; int currentNumberOfOpenBrackets = 1; @@ -113,7 +113,7 @@ void BracketLayout::computeOperandHeight() { m_operandHeightComputed = true; } -KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { +KDPoint SquareBracketLayout::positionOfChild(ExpressionLayout * child) { assert(false); return KDPointZero; } diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/square_bracket_layout.h similarity index 83% rename from poincare/src/layout/bracket_layout.h rename to poincare/src/layout/square_bracket_layout.h index 6418d45b8..03c131d89 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/square_bracket_layout.h @@ -1,13 +1,13 @@ -#ifndef POINCARE_BRACKET_LAYOUT_H -#define POINCARE_BRACKET_LAYOUT_H +#ifndef POINCARE_SQUARE_BRACKET_LAYOUT_H +#define POINCARE_SQUARE_BRACKET_LAYOUT_H #include namespace Poincare { -class BracketLayout : public StaticLayoutHierarchy<0> { +class SquareBracketLayout : public StaticLayoutHierarchy<0> { public: - BracketLayout(); + SquareBracketLayout(); void invalidAllSizesPositionsAndBaselines() override; ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; From 99b320c75440f353a25c0aa88f1aa9ebbdb80bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 11:25:46 +0200 Subject: [PATCH 363/459] [poincare] Factorize Parenthesis/SquareBracket layout in BracketLayout. Change-Id: I2aeddb950803f460b75e6e9a0efd3c0e2f16164e --- poincare/Makefile | 3 +- poincare/include/poincare_layouts.h | 6 +- poincare/src/layout/bracket_layout.cpp | 164 +++++++++++++++++ poincare/src/layout/bracket_layout.h | 24 +++ poincare/src/layout/parenthesis_layout.cpp | 174 ------------------ poincare/src/layout/parenthesis_layout.h | 20 +- poincare/src/layout/square_bracket_layout.cpp | 121 ------------ poincare/src/layout/square_bracket_layout.h | 19 +- 8 files changed, 205 insertions(+), 326 deletions(-) create mode 100644 poincare/src/layout/bracket_layout.cpp create mode 100644 poincare/src/layout/bracket_layout.h delete mode 100644 poincare/src/layout/parenthesis_layout.cpp delete mode 100644 poincare/src/layout/square_bracket_layout.cpp diff --git a/poincare/Makefile b/poincare/Makefile index cc057cbdc..ab2450b03 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -91,6 +91,7 @@ objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ binomial_coefficient_layout.o\ bounded_static_layout_hierarchy.o\ + bracket_layout.o\ bracket_pair_layout.o\ ceiling_layout.o\ char_layout.o\ @@ -108,12 +109,10 @@ objs += $(addprefix poincare/src/layout/,\ left_square_bracket_layout.o\ matrix_layout.o\ nth_root_layout.o\ - parenthesis_layout.o\ product_layout.o\ right_parenthesis_layout.o\ right_square_bracket_layout.o\ sequence_layout.o\ - square_bracket_layout.o\ static_layout_hierarchy.o\ sum_layout.o\ vertical_offset_layout.o\ diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 8e31672a8..74a2dd1ca 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include #include #include @@ -17,10 +15,12 @@ #include #include #include +#include +#include #include #include -#include #include +#include #include #include #include diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp new file mode 100644 index 000000000..d3af81e41 --- /dev/null +++ b/poincare/src/layout/bracket_layout.cpp @@ -0,0 +1,164 @@ +#include "bracket_layout.h" +#include +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +static inline KDCoordinate max(KDCoordinate x, KDCoordinate y) { return (x>y ? x : y); } + +BracketLayout::BracketLayout() : + StaticLayoutHierarchy<0>(), + m_operandHeightComputed(false) +{ +} + +void BracketLayout::invalidAllSizesPositionsAndBaselines() { + m_operandHeightComputed = false; + ExpressionLayout::invalidAllSizesPositionsAndBaselines(); +} + +ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Right. Go Left. + if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + // Case: Left. Ask the parent. + if (m_parent) { + return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); + } + return ExpressionLayoutCursor(); +} + +ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->pointedExpressionLayout() == this); + // Case: Left. Go Right. + if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); + } + assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + // Case: Right. Ask the parent. + if (m_parent) { + return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); + } + return ExpressionLayoutCursor(); +} + +void BracketLayout::computeBaseline() { + assert(m_parent != nullptr); + int indexInParent = m_parent->indexOfChild(this); + int numberOfSiblings = m_parent->numberOfChildren(); + if (((isLeftParenthesis() || isLeftBracket()) && indexInParent == numberOfSiblings - 1) + || ((isRightParenthesis() || isRightBracket()) && indexInParent == 0) + || ((isLeftParenthesis() || isLeftBracket()) && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset())) + { + /* The bracket does not have siblings on its open direction, or it is a left + * bracket that is base of a superscript layout. In the latter case, it + * should have a default baseline, else it creates an infinite loop as the + * bracket needs the superscript baseline, which needs the bracket baseline.*/ + m_baseline = size().height()/2; + m_baselined = true; + return; + } + + int currentNumberOfOpenBrackets = 1; + m_baseline = 0; + int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1; + for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+=increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((isLeftParenthesis() && sibling->isRightParenthesis()) + || (isLeftBracket() && sibling->isRightBracket()) + || (isRightParenthesis() && sibling->isLeftParenthesis()) + || (isRightBracket() && sibling->isLeftBracket())) + { + if (i == indexInParent + increment) { + /* If the bracket is immediately closed, we set the baseline to half the + * bracket height. */ + m_baseline = size().height()/2; + m_baselined = true; + return; + } + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isLeftParenthesis() && sibling->isLeftParenthesis()) + || (isLeftBracket() && sibling->isLeftBracket()) + || (isRightParenthesis() && sibling->isRightParenthesis()) + || (isRightBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets++; + } + m_baseline = max(m_baseline, sibling->baseline()); + } + m_baseline += (size().height() - operandHeight()) / 2; + m_baselined = true; +} + +KDCoordinate BracketLayout::operandHeight() { + if (!m_operandHeightComputed) { + computeOperandHeight(); + } + return m_operandHeight; +} + +void BracketLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; + int indexInParent = m_parent->indexOfChild(this); + int numberOfSiblings = m_parent->numberOfChildren(); + if ((isLeftParenthesis() || isLeftBracket()) + && indexInParent < numberOfSiblings - 1 + && m_parent->child(indexInParent + 1)->isVerticalOffset()) + { + /* If a left bracket is the base of a superscript layout, it should have a + * a default height, else it creates an infinite loop because the bracket + * needs the superscript height, which needs the bracket height. */ + m_operandHeightComputed = true; + return; + } + + KDCoordinate maxUnderBaseline = 0; + KDCoordinate maxAboveBaseline = 0; + + int currentNumberOfOpenBrackets = 1; + int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1; + for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) { + ExpressionLayout * sibling = m_parent->editableChild(i); + if ((isLeftParenthesis() && sibling->isRightParenthesis()) + || (isLeftBracket() && sibling->isRightBracket()) + || (isRightParenthesis() && sibling->isLeftParenthesis()) + || (isRightBracket() && sibling->isLeftBracket())) + { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isLeftParenthesis() && sibling->isLeftParenthesis()) + || (isLeftBracket() && sibling->isLeftBracket()) + || (isRightParenthesis() && sibling->isRightParenthesis()) + || (isRightBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets++; + } + KDCoordinate siblingHeight = sibling->size().height(); + KDCoordinate siblingBaseline = sibling->baseline(); + maxUnderBaseline = max(maxUnderBaseline, siblingHeight - siblingBaseline); + maxAboveBaseline = max(maxAboveBaseline, siblingBaseline); + } + m_operandHeight = max(m_operandHeight, maxUnderBaseline + maxAboveBaseline); + m_operandHeightComputed = true; + +} + +KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) { + assert(false); + return KDPointZero; +} + +} diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h new file mode 100644 index 000000000..31de5e208 --- /dev/null +++ b/poincare/src/layout/bracket_layout.h @@ -0,0 +1,24 @@ +#ifndef POINCARE_BRACKET_LAYOUT_H +#define POINCARE_BRACKET_LAYOUT_H + +#include + +namespace Poincare { + +class BracketLayout : public StaticLayoutHierarchy<0> { +public: + BracketLayout(); + void invalidAllSizesPositionsAndBaselines() override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; +protected: + void computeBaseline() override; + KDCoordinate operandHeight(); + void computeOperandHeight(); + KDPoint positionOfChild(ExpressionLayout * child) override; + bool m_operandHeightComputed; + uint16_t m_operandHeight; +}; +} + +#endif diff --git a/poincare/src/layout/parenthesis_layout.cpp b/poincare/src/layout/parenthesis_layout.cpp deleted file mode 100644 index 59e2d8e36..000000000 --- a/poincare/src/layout/parenthesis_layout.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "parenthesis_layout.h" -#include -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -static inline int max(int x, int y) { return (x>y ? x : y); } - - -ParenthesisLayout::ParenthesisLayout() : - StaticLayoutHierarchy<0>(), - m_operandHeightComputed(false) -{ -} - -void ParenthesisLayout::invalidAllSizesPositionsAndBaselines() { - m_operandHeightComputed = false; - ExpressionLayout::invalidAllSizesPositionsAndBaselines(); -} - -ExpressionLayoutCursor ParenthesisLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. Ask the parent. - if (m_parent) { - return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); - } - return ExpressionLayoutCursor(); -} - -ExpressionLayoutCursor ParenthesisLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. Ask the parent. - if (m_parent) { - return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); - } - return ExpressionLayoutCursor(); -} - -KDSize ParenthesisLayout::computeSize() { - return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin); -} - -void ParenthesisLayout::computeBaseline() { - assert(m_parent != nullptr); - bool isParenthesisLeft = isLeftParenthesis(); - int indexInParent = m_parent->indexOfChild(this); - int numberOfSiblings = m_parent->numberOfChildren(); - if ((isParenthesisLeft && indexInParent == numberOfSiblings - 1) - || (!isParenthesisLeft && indexInParent == 0) - || (isParenthesisLeft && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset())) - { - /* The parenthesis does not have siblings on its open direction, or it is a - * left parenthesis that is base of a superscript layout. In the latter - * case, it should have a default baseline, else it creates an infinite loop - * because the parenthesis needs the superscript height, which needs the - * parenthesis baseline. */ - m_baseline = size().height()/2; - m_baselined = true; - return; - } - - int currentNumberOfOpenParentheses = 1; - m_baseline = 0; - int increment = isParenthesisLeft ? 1 : -1; - for (int i = indexInParent + increment; i >= 0 && i <= numberOfSiblings - 1; i+= increment) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if ((isParenthesisLeft && sibling->isRightParenthesis()) - || (!isParenthesisLeft && sibling->isLeftParenthesis())) - { - if (i == indexInParent + increment) { - /* If the parenthesis is immediately closed, we set the baseline to half - * the parenthesis height. */ - m_baseline = size().height()/2; - m_baselined = true; - return; - } - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - break; - } - } else if ((isParenthesisLeft && sibling->isLeftParenthesis()) - || (!isParenthesisLeft && sibling->isRightParenthesis())) - { - currentNumberOfOpenParentheses++; - } - if (sibling->baseline() > m_baseline) { - m_baseline = sibling->baseline(); - } - } - m_baseline += (size().height() - operandHeight()) / 2; - m_baselined = true; -} - -KDCoordinate ParenthesisLayout::operandHeight() { - if (!m_operandHeightComputed) { - computeOperandHeight(); - m_operandHeightComputed = true; - } - return m_operandHeight; -} - -void ParenthesisLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - bool isParenthesisLeft = isLeftParenthesis(); - int indexInParent = m_parent->indexOfChild(this); - int numberOfSiblings = m_parent->numberOfChildren(); - if (isParenthesisLeft - && indexInParent < numberOfSiblings - 1 - && m_parent->child(indexInParent + 1)->isVerticalOffset()) - { - /* If a left parenthesis is the base of a superscript layout, it should have - * a default height, else it creates an infinite loop because the - * parenthesis needs the superscript height, which needs the parenthesis - * height. */ - return; - } - - KDCoordinate max_under_baseline = 0; - KDCoordinate max_above_baseline = 0; - - int currentNumberOfOpenParentheses = 1; - int increment = isParenthesisLeft ? 1 : -1; - for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if ((!isParenthesisLeft && sibling->isLeftParenthesis()) - || (isParenthesisLeft && sibling->isRightParenthesis())) - { - currentNumberOfOpenParentheses--; - if (currentNumberOfOpenParentheses == 0) { - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } - return; - } - } else if ((isParenthesisLeft && sibling->isLeftParenthesis()) - || (!isParenthesisLeft && sibling->isRightParenthesis())) - { - currentNumberOfOpenParentheses++; - } - KDCoordinate siblingHeight = sibling->size().height(); - KDCoordinate siblingBaseline = sibling->baseline(); - if (siblingHeight - siblingBaseline > max_under_baseline) { - max_under_baseline = siblingHeight - siblingBaseline ; - } - if (siblingBaseline > max_above_baseline) { - max_above_baseline = siblingBaseline; - } - } - if (max_under_baseline + max_above_baseline > m_operandHeight) { - m_operandHeight = max_under_baseline + max_above_baseline; - } -} - -KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) { - assert(false); - return KDPointZero; -} - -} diff --git a/poincare/src/layout/parenthesis_layout.h b/poincare/src/layout/parenthesis_layout.h index 72ec20901..7b826287a 100644 --- a/poincare/src/layout/parenthesis_layout.h +++ b/poincare/src/layout/parenthesis_layout.h @@ -1,16 +1,13 @@ #ifndef POINCARE_PARENTHESIS_LAYOUT_H #define POINCARE_PARENTHESIS_LAYOUT_H -#include +#include "bracket_layout.h" namespace Poincare { -class ParenthesisLayout : public StaticLayoutHierarchy<0> { +class ParenthesisLayout : public BracketLayout { public: - ParenthesisLayout(); - void invalidAllSizesPositionsAndBaselines() override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + using BracketLayout::BracketLayout; constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } constexpr static KDCoordinate k_parenthesisCurveWidth = 5; constexpr static KDCoordinate k_parenthesisCurveHeight = 7; @@ -21,14 +18,11 @@ public: constexpr static KDCoordinate k_verticalMargin = 4; protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; - KDSize computeSize() override; - void computeBaseline() override; - KDCoordinate operandHeight(); - void computeOperandHeight(); - KDPoint positionOfChild(ExpressionLayout * child) override; - bool m_operandHeightComputed; - uint16_t m_operandHeight; + KDSize computeSize() override { + return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin); + } }; + } #endif diff --git a/poincare/src/layout/square_bracket_layout.cpp b/poincare/src/layout/square_bracket_layout.cpp deleted file mode 100644 index 1ca9ae3d6..000000000 --- a/poincare/src/layout/square_bracket_layout.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "square_bracket_layout.h" -#include -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -SquareBracketLayout::SquareBracketLayout() : - StaticLayoutHierarchy<0>(), - m_operandHeightComputed(false) -{ -} - -void SquareBracketLayout::invalidAllSizesPositionsAndBaselines() { - m_operandHeightComputed = false; - ExpressionLayout::invalidAllSizesPositionsAndBaselines(); -} - -ExpressionLayoutCursor SquareBracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Right. Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - // Case: Left. Ask the parent. - if (m_parent) { - return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); - } - return ExpressionLayoutCursor(); -} - -ExpressionLayoutCursor SquareBracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); - // Case: Left. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); - } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. Ask the parent. - if (m_parent) { - return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); - } - return ExpressionLayoutCursor(); -} - -KDSize SquareBracketLayout::computeSize() { - return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); -} - -void SquareBracketLayout::computeBaseline() { - assert(m_parent != nullptr); - m_baseline = operandHeight()/2; - int currentNumberOfOpenBrackets = 1; - int increment = isLeftBracket() ? 1 : -1; - int numberOfSiblings = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if ((isRightBracket() && sibling->isLeftBracket()) - || (isLeftBracket() && sibling->isRightBracket())) - { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - break; - } - } else if ((isRightBracket() && sibling->isRightBracket()) - || (isLeftBracket() && sibling->isLeftBracket())) - { - currentNumberOfOpenBrackets++; - } - if (sibling->baseline() > m_baseline) { - m_baseline = sibling->baseline(); - } - } - m_baselined = true; -} - -KDCoordinate SquareBracketLayout::operandHeight() { - if (!m_operandHeightComputed) { - computeOperandHeight(); - } - return m_operandHeight; -} - -void SquareBracketLayout::computeOperandHeight() { - assert(m_parent != nullptr); - m_operandHeight = Metric::MinimalBracketAndParenthesisHeight; - int currentNumberOfOpenBrackets = 1; - int increment = isLeftBracket() ? 1 : -1; - int numberOfSiblings = m_parent->numberOfChildren(); - for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) { - ExpressionLayout * sibling = m_parent->editableChild(i); - if ((isRightBracket() && sibling->isLeftBracket()) - || (isLeftBracket() && sibling->isRightBracket())) - { - currentNumberOfOpenBrackets--; - if (currentNumberOfOpenBrackets == 0) { - break; - } - } else if ((isRightBracket() && sibling->isRightBracket()) - || (isLeftBracket() && sibling->isLeftBracket())) - { - currentNumberOfOpenBrackets++; - } - KDCoordinate siblingHeight = sibling->size().height(); - if (siblingHeight > m_operandHeight) { - m_operandHeight = siblingHeight; - } - } - m_operandHeightComputed = true; -} - -KDPoint SquareBracketLayout::positionOfChild(ExpressionLayout * child) { - assert(false); - return KDPointZero; -} - -} diff --git a/poincare/src/layout/square_bracket_layout.h b/poincare/src/layout/square_bracket_layout.h index 03c131d89..79ac9b05c 100644 --- a/poincare/src/layout/square_bracket_layout.h +++ b/poincare/src/layout/square_bracket_layout.h @@ -1,28 +1,21 @@ #ifndef POINCARE_SQUARE_BRACKET_LAYOUT_H #define POINCARE_SQUARE_BRACKET_LAYOUT_H -#include +#include "bracket_layout.h" namespace Poincare { -class SquareBracketLayout : public StaticLayoutHierarchy<0> { +class SquareBracketLayout : public BracketLayout { public: - SquareBracketLayout(); - void invalidAllSizesPositionsAndBaselines() override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + using BracketLayout::BracketLayout; protected: constexpr static KDCoordinate k_bracketWidth = 5; constexpr static KDCoordinate k_lineThickness = 1; constexpr static KDCoordinate k_widthMargin = 5; constexpr static KDCoordinate k_externWidthMargin = 2; - KDSize computeSize() override; - void computeBaseline() override; - KDCoordinate operandHeight(); - void computeOperandHeight(); - KDPoint positionOfChild(ExpressionLayout * child) override; - bool m_operandHeightComputed; - uint16_t m_operandHeight; + KDSize computeSize() override { + return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness); + } }; } From a5c50f8887e2a6e7fd3be3e8896343b87b550493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 11:42:18 +0200 Subject: [PATCH 364/459] [apps] Fix function name that was the same as virtual function. Change-Id: Idec43b9427571dbd5752ac551424447cbdb08d27 --- apps/sequence/list/list_controller.cpp | 6 +++--- apps/sequence/list/list_controller.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index e253542ba..23e0ecf2c 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -24,11 +24,11 @@ const char * ListController::title() { } Toolbox * ListController::toolboxForTextInput(TextInput * textInput) { - return toolbox(textInput); + return toolboxForSender(textInput); } Toolbox * ListController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { - return toolbox(expressionLayoutField); + return toolboxForSender(expressionLayoutField); } TextFieldDelegateApp * ListController::textFieldDelegateApp() { @@ -83,7 +83,7 @@ void ListController::selectPreviousNewSequenceCell() { } } -Toolbox * ListController::toolbox(Responder * sender) { +Toolbox * ListController::toolboxForSender(Responder * sender) { // Set extra cells int recurrenceDepth = -1; int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 658292e21..a6a95bc06 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -26,7 +26,7 @@ public: Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; void selectPreviousNewSequenceCell(); private: - Toolbox * toolbox(Responder * sender); + Toolbox * toolboxForSender(Responder * sender); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event); From 772187725ced26d624e27a2f350ae871308a07e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 11:45:35 +0200 Subject: [PATCH 365/459] [escher/poincare] Missing "override" keywords. Change-Id: Icbb9e25cb0983eb27913a4a7efd358a971664b7e --- escher/include/escher/expression_layout_field.h | 2 +- poincare/src/layout/absolute_value_layout.h | 2 +- poincare/src/layout/vertical_offset_layout.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index ab86ef184..ef053e143 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -20,7 +20,7 @@ public: void reload(); bool hasText() const; void writeTextInBuffer(char * buffer, int bufferLength); - bool handleEventWithText(const char * text, bool indentation = false); + bool handleEventWithText(const char * text, bool indentation = false) override; Poincare::ExpressionLayout * expressionLayout(); char XNTChar(); diff --git a/poincare/src/layout/absolute_value_layout.h b/poincare/src/layout/absolute_value_layout.h index bccc3a39e..c9ad4a6a0 100644 --- a/poincare/src/layout/absolute_value_layout.h +++ b/poincare/src/layout/absolute_value_layout.h @@ -16,7 +16,7 @@ public: } protected: KDCoordinate widthMargin() const override { return 2; } - virtual KDCoordinate verticalExternMargin() const { return 1; } + virtual KDCoordinate verticalExternMargin() const override { return 1; } bool renderTopBar() const override { return false; } bool renderBottomBar() const override { return false; } }; diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 03668876a..dbd1dd906 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -21,7 +21,7 @@ public: ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftSibling() const override { return true; } - bool isVerticalOffset() const { return true; } + bool isVerticalOffset() const override { return true; } protected: ExpressionLayout * indiceLayout(); ExpressionLayout * baseLayout(); From f6c3f7b0e930e627f0fe98cdaa3b7d2f1fc3e672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 13:27:40 +0200 Subject: [PATCH 366/459] [poincare] Remove old expression_view_with_cursor.h file Change-Id: I0f96e79fdf2d374c88c0f590101ff4e7205dcb54 --- escher/include/escher.h | 1 - .../escher/expression_view_with_cursor.h | 37 ------------------- 2 files changed, 38 deletions(-) delete mode 100644 escher/include/escher/expression_view_with_cursor.h diff --git a/escher/include/escher.h b/escher/include/escher.h index c7356438f..ac5efde2c 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/escher/include/escher/expression_view_with_cursor.h b/escher/include/escher/expression_view_with_cursor.h deleted file mode 100644 index cecd62ec0..000000000 --- a/escher/include/escher/expression_view_with_cursor.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ESCHER_EXPRESSION_VIEW_WITH_CURSOR_H -#define ESCHER_EXPRESSION_VIEW_WITH_CURSOR_H - -#include -#include -#include -#include -#include - -class ExpressionViewWithCursor : public View { -public: - ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout); - bool isEditing() const { return m_isEditing; } - void setEditing(bool isEditing); - void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } - void cursorPositionChanged(); - KDRect cursorRect(); - Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } - ExpressionView * expressionView() { return &m_expressionView; } - /* View */ - KDSize minimalSizeForOptimalDisplay() const override; -private: - enum class Position { - Top, - Bottom - }; - int numberOfSubviews() const override { return 2; } - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - void layoutCursorSubview(); - Poincare::ExpressionLayoutCursor m_cursor; - ExpressionView m_expressionView; - TextCursorView m_cursorView; - bool m_isEditing; -}; - -#endif From a27963597bc4c20141e5e88933bd32fb0f8e63ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 13:53:39 +0200 Subject: [PATCH 367/459] [apps] More generic VariableBoxController methods Before, the class differentiated between TextField and ExpressionLayoutField Change-Id: I1fce8bb650a0bfccb11ddf61d05335e452374abb --- apps/shared/expression_field_delegate_app.cpp | 2 +- apps/shared/text_field_delegate_app.cpp | 2 +- apps/variable_box_controller.cpp | 33 ++----------------- apps/variable_box_controller.h | 10 ++---- 4 files changed, 7 insertions(+), 40 deletions(-) diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index 1854ffbe7..c61514728 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -48,7 +48,7 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression } AppsContainer * appsContainer = (AppsContainer *)expressionLayoutField->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setExpressionLayoutFieldSender(expressionLayoutField); + variableBoxController->setSender(expressionLayoutField); expressionLayoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index f9eda1ed4..d8a26093a 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -93,7 +93,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion:: } AppsContainer * appsContainer = (AppsContainer *)textField->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setTextFieldSender(textField); + variableBoxController->setSender(textField); textField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index cfa4a143f..6ebb90f22 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -64,7 +64,7 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even char label[3]; putLabelAtIndexInBuffer(selectedRow(), label); const char * editedText = label; - m_insertTextAction(m_sender, editedText); + m_sender->handleEventWithText(editedText); #if MATRIX_VARIABLES m_selectableTableView.deselectTable(); m_currentPage = Page::RootMenu; @@ -195,16 +195,6 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) { return 0; } -void VariableBoxController::ContentViewController::setTextFieldSender(TextField * textField) { - m_sender = textField; - m_insertTextAction = &insertTextInTextInput; -} - -void VariableBoxController::ContentViewController::setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField) { - m_sender = expressionLayoutField; - m_insertTextAction = &insertTextInExpressionLayoutField; -} - void VariableBoxController::ContentViewController::reloadData() { m_selectableTableView.reloadData(); } @@ -290,19 +280,6 @@ ExpressionLayout * VariableBoxController::ContentViewController::expressionLayou return nullptr; } -void VariableBoxController::ContentViewController::insertTextInTextInput(void * sender, const char * textToInsert) { - TextInput * textInput = static_cast(sender); - textInput->handleEventWithText(textToInsert); -} - -void VariableBoxController::ContentViewController::insertTextInExpressionLayoutField(void * sender, const char * textToInsert) { - ExpressionLayoutField * expressionLayoutField = static_cast(sender); - if (!expressionLayoutField->isEditing()) { - expressionLayoutField->setEditing(true); - } - expressionLayoutField->insertLayoutFromTextAtCursor(textToInsert); -} - VariableBoxController::VariableBoxController(GlobalContext * context) : StackViewController(nullptr, &m_contentViewController, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark), m_contentViewController(this, context) @@ -313,12 +290,8 @@ void VariableBoxController::didBecomeFirstResponder() { app()->setFirstResponder(&m_contentViewController); } -void VariableBoxController::setTextFieldSender(TextField * textField) { - m_contentViewController.setTextFieldSender(textField); -} - -void VariableBoxController::setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField) { - m_contentViewController.setExpressionLayoutFieldSender(expressionLayoutField); +void VariableBoxController::setSender(Responder * sender) { + m_contentViewController.setSender(sender); } void VariableBoxController::viewWillAppear() { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 527b8ac77..bd536d80c 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -10,11 +10,9 @@ class VariableBoxController : public StackViewController { public: - typedef void (*Action)(void * sender, const char * text); VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; - void setTextFieldSender(TextField * textField); - void setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField); + void setSender(Responder * sender); void viewWillAppear() override; void viewDidDisappear() override; private: @@ -33,8 +31,7 @@ private: KDCoordinate cumulatedHeightFromIndex(int j) override; int indexFromCumulatedHeight(KDCoordinate offsetY) override; int typeAtLocation(int i, int j) override; - void setTextFieldSender(TextField * textField); - void setExpressionLayoutFieldSender(ExpressionLayoutField * expressionLayoutField); + void setSender(Responder * responder) { m_sender = responder; } void reloadData(); void resetPage(); void viewDidDisappear() override; @@ -59,11 +56,8 @@ private: I18n::Message nodeLabelAtIndex(int index); const Poincare::Expression * expressionForIndex(int index); Poincare::ExpressionLayout * expressionLayoutForIndex(int index); - static void insertTextInTextInput(void * sender, const char * textToInsert); - static void insertTextInExpressionLayoutField(void * sender, const char * textToInsert); Poincare::GlobalContext * m_context; Responder * m_sender; - Action m_insertTextAction; int m_firstSelectedRow; int m_previousSelectedRow; Page m_currentPage; From d51ddc55a1f987f9f11786c45df622b1972569bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 13:58:05 +0200 Subject: [PATCH 368/459] [apps/sequence] Put a condition on SeqType to get FirstInitialCondName This condition was removed non-intentionnally by a previous commit Change-Id: I643351b3ca965405753c0757971871c71838e405 --- apps/sequence/sequence.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 4e6150ca8..e6775f127 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -258,7 +258,10 @@ Poincare::ExpressionLayout * Sequence::definitionName() { Poincare::ExpressionLayout * Sequence::firstInitialConditionName() { char buffer[k_initialRankNumberOfDigits+1]; Integer(m_initialRank).writeTextInBuffer(buffer, k_initialRankNumberOfDigits+1); - if (m_firstInitialConditionName == nullptr) { + if (m_firstInitialConditionName == nullptr + && (m_type == Type::SingleRecurrence + || m_type == Type::DoubleRecurrence)) + { m_firstInitialConditionName = new HorizontalLayout( new CharLayout(name()[0], KDText::FontSize::Small), new VerticalOffsetLayout(new CharLayout('0', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), From 733473beb8184a72925a6779565d4d7aeed8beb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 24 Apr 2018 14:04:45 +0200 Subject: [PATCH 369/459] [poincare] Remove comment. Change-Id: If12942c2482756673e756fc8bcc6b809d2978e92 --- poincare/include/poincare/expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 15203c7cf..c8e2467c7 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -76,7 +76,7 @@ class Expression { friend class Trigonometry; friend class ApproximationEngine; friend class SimplificationEngine; - friend class LayoutEngine; //TODO MERGE SAISIEJOLIE: Remove? + friend class LayoutEngine; friend class Complex; friend class Complex; friend class EmptyExpression; From d9c89ea0c97c29c9a567a5c3916915c0fdafde5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 09:40:39 +0200 Subject: [PATCH 370/459] [escher] ModalViewCtrlr: don't dirty main view when dislaying sibling Change-Id: I7d1a555055bc3d9a3f9801e96c792d45ab2011d4 --- escher/src/modal_view_controller.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index 00c3564c8..dd45202c0 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -66,6 +66,10 @@ void ModalViewController::ContentView::layoutSubviews() { if (m_isDisplayingModal) { assert(m_currentModalView != nullptr); m_currentModalView->setFrame(modalViewFrame()); + } else { + if (m_currentModalView) { + m_currentModalView->setFrame(KDRectZero); + } } } @@ -79,16 +83,14 @@ void ModalViewController::ContentView::presentModalView(View * modalView, float m_leftMargin = leftMargin; m_bottomMargin = bottomMargin; m_rightMargin = rightMargin; - markRectAsDirty(modalViewFrame()); layoutSubviews(); } void ModalViewController::ContentView::dismissModalView() { m_isDisplayingModal = false; - markRectAsDirty(modalViewFrame()); + layoutSubviews(); m_currentModalView->resetSuperview(); m_currentModalView = nullptr; - layoutSubviews(); } bool ModalViewController::ContentView::isDisplayingModal() const { From 9f09ee8339d1bb6e7c2c2a93eb3b70fca450fc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 09:48:49 +0200 Subject: [PATCH 371/459] [escher] Remove big modal view drawing hack. Change-Id: I09b0d9ee1db8db9a736577770f540e69cc78d660 --- escher/src/modal_view_controller.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index dd45202c0..d589d061d 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -23,18 +23,12 @@ void ModalViewController::ContentView::setMainView(View * regularView) { } int ModalViewController::ContentView::numberOfSubviews() const { - KDRect regularFrame = bounds(); - KDRect modalFrame = modalViewFrame(); - bool shouldDrawTheRegularViewBehind = !modalFrame.contains(regularFrame.topLeft()) || !modalFrame.contains(regularFrame.bottomRight()); - return 1 + (m_isDisplayingModal && shouldDrawTheRegularViewBehind); + return 1 + m_isDisplayingModal; } View * ModalViewController::ContentView::subviewAtIndex(int index) { switch (index) { case 0: - if (m_isDisplayingModal && numberOfSubviews() == 1) { - return m_currentModalView; - } return m_regularView; case 1: if (numberOfSubviews() == 2) { From 34d60288821d2ed41df6a08e2de1be16c365b44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 13:43:09 +0200 Subject: [PATCH 372/459] [kandinsky] Add method KDRect::differencedWith(const KDRect & other) Change-Id: Ib6c61bbd3bffc90bc3e704a7133eae0731500864 --- kandinsky/include/kandinsky/rect.h | 1 + kandinsky/src/rect.cpp | 41 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/kandinsky/include/kandinsky/rect.h b/kandinsky/include/kandinsky/rect.h index d5c93ae82..fc3fe47af 100644 --- a/kandinsky/include/kandinsky/rect.h +++ b/kandinsky/include/kandinsky/rect.h @@ -62,6 +62,7 @@ public: bool intersects(const KDRect & other) const; KDRect intersectedWith(const KDRect & other) const; KDRect unionedWith(const KDRect & other) const; // Returns the smallest rectangle containing r1 and r2 + KDRect differencedWith(const KDRect & other) const; // Returns the smallest rectangle containing r1\r2 bool contains(KDPoint p) const; bool isAbove(KDPoint p) const; bool isUnder(KDPoint p) const; diff --git a/kandinsky/src/rect.cpp b/kandinsky/src/rect.cpp index 9cf0df654..4373d4f93 100644 --- a/kandinsky/src/rect.cpp +++ b/kandinsky/src/rect.cpp @@ -101,6 +101,47 @@ KDRect KDRect::unionedWith(const KDRect & other) const { ); } +KDRect KDRect::differencedWith(const KDRect & other) const { + if (this->isEmpty() || other.isEmpty()) { + return *this; + } + + KDRect intersection = intersectedWith(other); + if (intersection.isEmpty()) { + return *this; + } + + if (intersection == *this) { + return KDRectZero; + } + + KDCoordinate resultLeft = left(); + KDCoordinate resultTop = top(); + KDCoordinate resultRight = right(); + KDCoordinate resultBottom = bottom(); + + if (intersection.height() == height()) { + if (intersection.left() == left()) { + resultLeft = intersection.right() + 1; + } else if (intersection.right() == right()) { + resultRight = intersection.left() - 1; + } + } else if (intersection.width() == width()) { + if (intersection.top() == top()) { + resultTop = intersection.bottom() + 1; + } else if (intersection.bottom() == bottom()) { + resultBottom = intersection.top() - 1; + } + } + + return KDRect( + resultLeft, + resultTop, + resultRight-resultLeft+1, + resultBottom-resultTop+1 + ); +} + bool KDRect::contains(KDPoint p) const { return (p.x() >= x() && p.x() <= right() && p.y() >= y() && p.y() <= bottom()); } From 2aa9b6947efebf14c84aec711455dfcc1a824b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 13:44:26 +0200 Subject: [PATCH 373/459] [kandinsky] Add test cases for KDRect::differencedWith Change-Id: I27371f94e590cb75712154b47efe4db27d0a082d --- kandinsky/test/rect.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/kandinsky/test/rect.cpp b/kandinsky/test/rect.cpp index 284213a55..198adac2a 100644 --- a/kandinsky/test/rect.cpp +++ b/kandinsky/test/rect.cpp @@ -58,3 +58,45 @@ QUIZ_CASE(kandinsky_rect_empty_union) { assert(t.width() == a.width()); assert(t.height() == a.height()); } + +QUIZ_CASE(kandinsky_rect_difference) { + KDRect a(-1, 0, 11, 2); + KDRect b(-4, -3, 4, 7); + KDRect c(3, -2, 1, 5); + KDRect d(7, -3, 5, 7); + KDRect e(-2, -1, 13, 5); + KDRect f(2, -4, 3, 3); + + KDRect t = e.differencedWith(a); + assert(t == e); + + t = a.differencedWith(e); + assert(t == KDRectZero); + + t = f.differencedWith(d); + assert(t == f); + + t = f.differencedWith(e); + assert(t == f); + + t = b.differencedWith(e); + assert(t == b); + + t = c.differencedWith(f); + assert(t == KDRect(3, -1, 1, 4)); + + t = c.differencedWith(a); + assert(t == c); + + t = c.differencedWith(e); + assert(t == KDRect(3, -2, 1, 1)); + + t = a.differencedWith(b); + assert(t == KDRect(0, 0, 10, 2)); + + t = a.differencedWith(c); + assert(t == a); + + t = a.differencedWith(d); + assert(t == KDRect(-1, 0, 8, 2)); +} From 96c24b1d63050a76ed5ea263992cfafce02f9cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 13:51:37 +0200 Subject: [PATCH 374/459] [kandinsky] Simplify code of Kandinsky tests Change-Id: Ib5c716a5c8ed8d1ef8849475f8bc71076f91c6bc --- kandinsky/test/rect.cpp | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/kandinsky/test/rect.cpp b/kandinsky/test/rect.cpp index 198adac2a..eb313a119 100644 --- a/kandinsky/test/rect.cpp +++ b/kandinsky/test/rect.cpp @@ -8,31 +8,17 @@ QUIZ_CASE(kandinsky_rect_intersect) { assert(a.intersects(b)); assert(b.intersects(a)); KDRect c = a.intersectedWith(b); - assert(c.x() == 0); - assert(c.y() == 0); - assert(c.width() == 5); - assert(c.height() == 5); + KDRect result(0, 0, 5, 5); + assert(c == result); c = b.intersectedWith(a); - assert(c.x() == 0); - assert(c.y() == 0); - assert(c.width() == 5); - assert(c.height() == 5); + assert(c == result); } QUIZ_CASE(kandinsky_rect_union) { KDRect a(-5, -5, 10, 10); KDRect b(0, 0, 10, 10); KDRect c = a.unionedWith(b); - assert(c.x() == -5); - assert(c.y() == -5); - assert(c.width() == 15); - assert(c.height() == 15); - - c = a.unionedWith(b); - assert(c.x() == -5); - assert(c.y() == -5); - assert(c.width() == 15); - assert(c.height() == 15); + assert(c == KDRect(-5, -5, 15, 15)); } QUIZ_CASE(kandinsky_rect_empty_union) { @@ -41,22 +27,13 @@ QUIZ_CASE(kandinsky_rect_empty_union) { KDRect c(-2, -1, 0, 1); KDRect t = a.unionedWith(b); - assert(t.x() == a.x()); - assert(t.y() == a.y()); - assert(t.width() == a.width()); - assert(t.height() == a.height()); + assert(t == a); t = b.unionedWith(a); - assert(t.x() == a.x()); - assert(t.y() == a.y()); - assert(t.width() == a.width()); - assert(t.height() == a.height()); + assert(t == a); t = a.unionedWith(c); - assert(t.x() == a.x()); - assert(t.y() == a.y()); - assert(t.width() == a.width()); - assert(t.height() == a.height()); + assert(t == a); } QUIZ_CASE(kandinsky_rect_difference) { From 61491fffe36a87463c22dea20fd0359575b2888e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:01:40 +0200 Subject: [PATCH 375/459] [poincare] Fix parser. Did not handle -1-2-3 (would give -1-(2-3)) Change-Id: I490bc95898cbd502b68ebb0817ff9d830946c9d1 --- poincare/src/expression_parser.y | 35 ++++++++------------------------ 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 153ce31c9..027239f87 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -91,12 +91,12 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char * one has the highest precedence. */ %nonassoc STO -%right UNARY_MINUS %left PLUS %left MINUS %left MULTIPLY %left DIVIDE %left IMPLICIT_MULTIPLY +%nonassoc UNARY_MINUS %right POW %left BANG %nonassoc LEFT_PARENTHESIS @@ -121,10 +121,6 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char %type bang; %type factor; %type pow; -%type div; -%type mul; -%type min; -%type unmin; %type exp; %type number; %type symb; @@ -137,7 +133,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char * have some heap-allocated data that need to be discarded. */ %destructor { delete $$; } FUNCTION -%destructor { delete $$; } UNDEFINED final_exp exp unmin min mul div pow factor bang term number EMPTY +%destructor { delete $$; } UNDEFINED final_exp exp pow factor bang term number EMPTY %destructor { delete $$; } lstData /* MATRICES_ARE_DEFINED */ %destructor { delete $$; } mtxData @@ -214,27 +210,12 @@ pow : factor { $$ = $1; } | bang POW MINUS pow { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Power(terms, false); } ; -div : pow { $$ = $1; } - | div DIVIDE pow { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); } - | div DIVIDE MINUS pow { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Division(terms, false); } - ; - -mul : div { $$ = $1; } - | mul MULTIPLY div { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } - | mul MULTIPLY MINUS div { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Multiplication(terms, 2, false); } - ; - -unmin : mul { $$ = $1; } - | MINUS mul %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } - ; - -min : unmin { $$ = $1; } - | unmin MINUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } - | unmin MINUS MINUS min { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Subtraction(terms, false); } - ; - -exp : min { $$ = $1; } - | exp PLUS min { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } +exp : pow { $$ = $1; } + | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); } + | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } + | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } + | MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } + | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } ; final_exp : exp { $$ = $1; } From 832f7c3c74d23e003ed9f4ac69307cf828c80575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:14:08 +0200 Subject: [PATCH 376/459] [escher] Only ExpressionLayoutField::reload calls eLFdidChangeSize Change-Id: I0e75c53750dfb2213b926b3d7e988bb6b37f9d05 --- escher/src/expression_layout_field.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 48a7543cb..725db70f1 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -38,7 +38,6 @@ Toolbox * ExpressionLayoutField::toolbox() { } bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { - KDSize previousSize = minimalSizeForOptimalDisplay(); bool didHandleEvent = false; bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded(); bool moveEventChangedLayout = false; @@ -54,12 +53,7 @@ bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { if (!shouldRecomputeLayout) { m_contentView.cursorPositionChanged(); scrollToCursor(); - return true; - } - reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->expressionLayoutFieldDidChangeSize(this); + } else { reload(); } return true; @@ -194,7 +188,6 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la return; } m_contentView.cursor()->showEmptyLayoutIfNeeded(); - KDSize previousSize = minimalSizeForOptimalDisplay(); if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { static_cast(layout)->addGreySquares(); } @@ -209,10 +202,6 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la } m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->expressionLayoutFieldDidChangeSize(this); - } } void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { @@ -233,9 +222,13 @@ void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { } void ExpressionLayoutField::reload() { + KDSize previousSize = minimalSizeForOptimalDisplay(); m_contentView.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); layoutSubviews(); - m_delegate->expressionLayoutFieldDidChangeSize(this); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->expressionLayoutFieldDidChangeSize(this); + } scrollToCursor(); m_contentView.cursorPositionChanged(); markRectAsDirty(bounds()); From 8778516fe2bcb401207d1f35b9050e3de0356d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:15:12 +0200 Subject: [PATCH 377/459] [escher] expressionLayoutFieldDidChangeSize reloads only the modalView Change-Id: Ib406c7d10e2befae9d660e025c84df58a2e9b70c --- escher/include/escher/modal_view_controller.h | 1 + escher/src/input_view_controller.cpp | 6 +++--- escher/src/modal_view_controller.cpp | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/escher/include/escher/modal_view_controller.h b/escher/include/escher/modal_view_controller.h index 83e4b3001..198e473b3 100644 --- a/escher/include/escher/modal_view_controller.h +++ b/escher/include/escher/modal_view_controller.h @@ -13,6 +13,7 @@ public: void didBecomeFirstResponder() override; void displayModalViewController(ViewController * vc, float verticalAlignment, float horizontalAlignment, KDCoordinate topMargin = 0, KDCoordinate leftMargin = 0, KDCoordinate bottomMargin = 0, KDCoordinate rightMargin = 0); + void reloadModalViewController(); void dismissModalViewController(); bool isDisplayingModal(); void viewWillAppear() override; diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index 4d0fdff73..c7bec3a3e 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -87,12 +87,12 @@ bool InputViewController::expressionLayoutFieldDidAbortEditing(ExpressionLayoutF } void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { - // Reload the view only if the ExpressionField height actually changes, - // i.e. not if the height is already maximal and stays maximal. + /* 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; - reloadView(); + reloadModalViewController(); } } diff --git a/escher/src/modal_view_controller.cpp b/escher/src/modal_view_controller.cpp index d589d061d..cd3ab4bd3 100644 --- a/escher/src/modal_view_controller.cpp +++ b/escher/src/modal_view_controller.cpp @@ -123,6 +123,10 @@ void ModalViewController::displayModalViewController(ViewController * vc, float app()->setFirstResponder(vc); } +void ModalViewController::reloadModalViewController() { + m_contentView.layoutSubviews(); +} + void ModalViewController::dismissModalViewController() { m_currentModalViewController->viewDidDisappear(); app()->setFirstResponder(m_previousResponder); From 43e81a6fb389ca45c93bec5d071974d55c2211a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:21:06 +0200 Subject: [PATCH 378/459] [escher] setFrame marks as dirty the olf frame minus the new frame. Change-Id: I0658551541971f9f36a60ef87380f55d7ff148b8 --- escher/src/view.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/escher/src/view.cpp b/escher/src/view.cpp index 46d3d9212..64cfcc62d 100644 --- a/escher/src/view.cpp +++ b/escher/src/view.cpp @@ -129,13 +129,12 @@ void View::setFrame(KDRect frame) { /* CAUTION: This code is not resilient to multiple consecutive setFrame() * calls without intermediate redraw() calls. */ - // TODO: Return if frame is equal to m_frame if (m_superview != nullptr) { /* We will move this view. This will leave a blank spot in its superview * were it previously was. - * At this point, we know that the only area that really needs to be redrawn - * in the superview is the value of m_frame at the start of that method. */ - m_superview->markRectAsDirty(m_frame); + * At this point, we know that the only area that needs to be redrawn in the + * superview is the old frame minus the part covered by the new frame.*/ + m_superview->markRectAsDirty(m_frame.differencedWith(frame)); } m_frame = frame; From 948efc54c6f8842084663ea3ceb223c92caf69a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:58:30 +0200 Subject: [PATCH 379/459] [poincare] Remove ELCursor::equivalentPointedSiblingLayout Change-Id: I6748a502e30efc8f047dcba58e5c50fcdd2fc2fc --- poincare/include/poincare/expression_layout.h | 3 + .../poincare/expression_layout_cursor.h | 1 - poincare/src/expression_layout_cursor.cpp | 78 +++++++------------ poincare/src/layout/expression_layout.cpp | 7 ++ 4 files changed, 37 insertions(+), 52 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index b1494dde4..16c478020 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -48,6 +48,9 @@ public: bool hasAncestor(const ExpressionLayout * e, bool includeSelf = false) const; ExpressionLayout * editableRoot(); + // Sibling + bool hasSibling(const ExpressionLayout * e) const; + /* Dynamic Layout */ // Collapse diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 74719f9b3..5ee003596 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -63,7 +63,6 @@ private: bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); KDCoordinate pointedLayoutHeight(); - ExpressionLayout * equivalentPointedSiblingLayout(); ExpressionLayout * m_pointedExpressionLayout; Position m_position; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 7348bf6f0..affc838ec 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -27,9 +27,9 @@ KDCoordinate ExpressionLayoutCursor::baseline() { } KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); KDCoordinate baseline2 = (KDCoordinate)0; - ExpressionLayout * equivalentSiblingLayout = equivalentPointedSiblingLayout(); - if (equivalentSiblingLayout != nullptr) { - baseline2 = equivalentSiblingLayout->baseline(); + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); + if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { + baseline2 = equivalentPointedLayout->baseline(); } return max(baseline1, baseline2); } @@ -215,40 +215,32 @@ void ExpressionLayoutCursor::clearLayout() { } bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { - /* Find Empty layouts adjacent to the cursor: Check the pointed layout and its - * neighbour in an Horizontal layout */ + /* Find Empty layouts adjacent to the cursor: Check the pointed layout and the + * equivalent cursor positions */ + ExpressionLayout * adjacentEmptyLayout = nullptr; // Check the pointed layout - if (m_pointedExpressionLayout->isEmpty() - || (m_position == Position::Left - && m_pointedExpressionLayout->isHorizontal() - && m_pointedExpressionLayout->numberOfChildren() > 0 - && m_pointedExpressionLayout->editableChild(0)->isEmpty())) - { - /* The cursor is next to an EmptyLayout if the pointed layout is an empty - * layout (either an EmptyLayout or HorizontalLayout with one child only, - * and this child is an EmptyLayout), or if the cursor points to the left of - * an HorizontalLayout that starts with an EmptyLayout (for instance, the - * emty base of a vertical offset layout). */ - if (m_pointedExpressionLayout->isHorizontal()) { - static_cast(m_pointedExpressionLayout->editableChild(0))->setVisible(show); - } else { - static_cast(m_pointedExpressionLayout)->setVisible(show); - } - return true; + if (m_pointedExpressionLayout->isEmpty()) { + adjacentEmptyLayout = m_pointedExpressionLayout; } else { - // Check the neighbour of the pointed layout in an HorizontalLayout - ExpressionLayout * equivalentPointedLayout = equivalentPointedSiblingLayout(); + // Check the equivalent cursor position + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); if (equivalentPointedLayout != nullptr && equivalentPointedLayout->isEmpty()) { - if (equivalentPointedLayout->isHorizontal()) { - static_cast(equivalentPointedLayout->editableChild(0))->setVisible(show); - } else { - static_cast(equivalentPointedLayout)->setVisible(show); - } - return true; + adjacentEmptyLayout = equivalentPointedLayout; } } - return false; + + if (adjacentEmptyLayout == nullptr) { + return false; + } + /* An EmptyLayout or HorizontalLayout with one child only, and this child is + * an EmptyLayout. */ + if (adjacentEmptyLayout->isHorizontal()) { + static_cast(adjacentEmptyLayout->editableChild(0))->setVisible(show); + } else { + static_cast(adjacentEmptyLayout)->setVisible(show); + } + return true; } bool ExpressionLayoutCursor::baseForNewPowerLayout() { @@ -266,32 +258,16 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { KDCoordinate height = pointedExpressionLayoutEquivalentChild()->size().height(); KDCoordinate height1 = height; - ExpressionLayout * equivalentSiblingLayout = equivalentPointedSiblingLayout(); - if (equivalentSiblingLayout != nullptr) { - KDCoordinate height2 = equivalentSiblingLayout->size().height(); + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); + if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { + KDCoordinate height2 = equivalentPointedLayout->size().height(); KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); - KDCoordinate baseline2 = equivalentSiblingLayout->baseline(); + KDCoordinate baseline2 = equivalentPointedLayout->baseline(); height = max(baseline1, baseline2) + max(height1 - baseline1, height2 - baseline2); } return height; } -ExpressionLayout * ExpressionLayoutCursor::equivalentPointedSiblingLayout() { - if (m_pointedExpressionLayout->parent() != nullptr - && m_pointedExpressionLayout->parent()->isHorizontal()) - { - ExpressionLayout * pointedLayoutParent = m_pointedExpressionLayout->editableParent(); - int indexOfPointedLayoutInParent = pointedLayoutParent->indexOfChild(m_pointedExpressionLayout); - if (m_position == Position::Left && indexOfPointedLayoutInParent > 0) { - return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent - 1); - } - if (m_position == Position::Right && indexOfPointedLayoutInParent < pointedLayoutParent->numberOfChildren() - 1) { - return pointedLayoutParent->editableChild(indexOfPointedLayoutInParent + 1); - } - } - return nullptr; -} - } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 45926669d..a86093d10 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -115,6 +115,13 @@ ExpressionLayout * ExpressionLayout::editableRoot() { return m_parent->editableRoot(); } +bool ExpressionLayout::hasSibling(const ExpressionLayout * e) const { + if (e == nullptr) { + return false; + } + return m_parent == e->parent(); +} + void ExpressionLayout::addSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling) { privateAddSibling(cursor, sibling, false); } From 590102115204aeac0cfc79fe7370569573b9c6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 15:59:15 +0200 Subject: [PATCH 380/459] [poincare] Fix ExpressionLayoutCursor::baseForNewPowerLayout Change-Id: I955479d62522d96a8fa18a9575f843107ff0e2ea --- poincare/src/expression_layout_cursor.cpp | 24 ++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index affc838ec..dca44189f 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -247,12 +247,26 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { /* Returns true if the layout on the left of the pointed layout is suitable to * be the base of a new power layout: the base layout should be anything but * an horizontal layout with no child. */ - if (m_pointedExpressionLayout->isHorizontal() - && m_pointedExpressionLayout->numberOfChildren() == 0) - { - return false; + if (m_position == Position::Right) { + if (m_pointedExpressionLayout->isHorizontal() && m_pointedExpressionLayout->numberOfChildren() == 0) { + return false; + } else { + return true; + } + } else { + assert(m_position == Position::Left); + if (m_pointedExpressionLayout->isHorizontal()) { + return false; + } + ExpressionLayoutCursor equivalentLayoutCursor = m_pointedExpressionLayout->equivalentCursor(this); + if (equivalentLayoutCursor.pointedExpressionLayout() != nullptr + && equivalentLayoutCursor.pointedExpressionLayout()->isHorizontal() + && equivalentLayoutCursor.position() == Position::Left) + { + return false; + } + return true; } - return true; } KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { From 728537c7ff29b50626dbdb61be1c896f609919ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 17:10:40 +0200 Subject: [PATCH 381/459] [escher/poincare] Remove ELCursor::pointedELEquivalentChild Change-Id: Iac459394b8743030243dc9e7e682c427f265a817 --- .../expression_layout_field_content_view.cpp | 10 ++++-- poincare/include/poincare/expression_layout.h | 1 + .../poincare/expression_layout_cursor.h | 1 - poincare/src/expression_layout_cursor.cpp | 36 ++++++++----------- poincare/src/layout/expression_layout.cpp | 7 ++++ 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index 1ef370293..ddb856fd9 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -58,10 +58,16 @@ void ExpressionLayoutField::ContentView::layoutCursorSubview() { return; } KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); - ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayoutEquivalentChild(); + ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayout(); + ExpressionLayoutCursor::Position cursorPosition = m_cursor.position(); + ExpressionLayoutCursor equivalentCursor = pointedLayout->equivalentCursor(&m_cursor); + if (pointedLayout->hasChild(equivalentCursor.pointedExpressionLayout())) { + pointedLayout = equivalentCursor.pointedExpressionLayout(); + cursorPosition = equivalentCursor.position(); + } KDPoint cursoredExpressionViewOrigin = pointedLayout->absoluteOrigin(); KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); - if (m_cursor.position() == ExpressionLayoutCursor::Position::Right) { + if (cursorPosition == ExpressionLayoutCursor::Position::Right) { cursorX += pointedLayout->size().width(); } KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayout->baseline() - m_cursor.baseline()); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 16c478020..facef85e5 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -39,6 +39,7 @@ public: const ExpressionLayout * child(int i) const; ExpressionLayout * editableChild(int i) { return const_cast(child(i)); } virtual int numberOfChildren() const = 0; + bool hasChild(const ExpressionLayout * child) const; int indexOfChild(const ExpressionLayout * child) const; // Parent diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 5ee003596..c6f31dcd4 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -24,7 +24,6 @@ public: /* Getters and setters */ ExpressionLayout * pointedExpressionLayout() { return m_pointedExpressionLayout; } - ExpressionLayout * pointedExpressionLayoutEquivalentChild(); void setPointedExpressionLayout(ExpressionLayout * expressionLayout) { m_pointedExpressionLayout = expressionLayout; } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index dca44189f..f19716714 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -9,13 +9,6 @@ namespace Poincare { static inline KDCoordinate max(KDCoordinate x, KDCoordinate y) { return (x>y ? x : y); } -ExpressionLayout * ExpressionLayoutCursor::pointedExpressionLayoutEquivalentChild() { - if (m_pointedExpressionLayout->isHorizontal() && m_pointedExpressionLayout->numberOfChildren() > 0) { - return m_position == Position::Left ? m_pointedExpressionLayout->editableChild(0) : m_pointedExpressionLayout->editableChild(m_pointedExpressionLayout->numberOfChildren()-1); - } - return m_pointedExpressionLayout; -} - KDCoordinate ExpressionLayoutCursor::cursorHeight() { KDCoordinate height = pointedLayoutHeight(); return height == 0 ? k_cursorHeight : height; @@ -25,13 +18,14 @@ KDCoordinate ExpressionLayoutCursor::baseline() { if (pointedLayoutHeight() == 0) { return k_cursorHeight / 2; } - KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); - KDCoordinate baseline2 = (KDCoordinate)0; + KDCoordinate pointedLayoutBaseline = m_pointedExpressionLayout->baseline(); ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); - if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { - baseline2 = equivalentPointedLayout->baseline(); + if (m_pointedExpressionLayout->hasChild(equivalentPointedLayout)) { + return equivalentPointedLayout->baseline(); + } else if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { + return max(pointedLayoutBaseline, equivalentPointedLayout->baseline()); } - return max(baseline1, baseline2); + return pointedLayoutBaseline; } bool ExpressionLayoutCursor::isEquivalentTo(ExpressionLayoutCursor cursor) { @@ -270,17 +264,17 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { } KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { - KDCoordinate height = pointedExpressionLayoutEquivalentChild()->size().height(); - KDCoordinate height1 = height; ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); - if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { - KDCoordinate height2 = equivalentPointedLayout->size().height(); - KDCoordinate baseline1 = pointedExpressionLayoutEquivalentChild()->baseline(); - KDCoordinate baseline2 = equivalentPointedLayout->baseline(); - height = max(baseline1, baseline2) - + max(height1 - baseline1, height2 - baseline2); + if (m_pointedExpressionLayout->hasChild(equivalentPointedLayout)) { + return equivalentPointedLayout->size().height(); + } else if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { + KDCoordinate pointedLayoutHeight = m_pointedExpressionLayout->size().height(); + KDCoordinate equivalentLayoutHeight = equivalentPointedLayout->size().height(); + KDCoordinate pointedLayoutBaseline = m_pointedExpressionLayout->baseline(); + KDCoordinate equivalentLayoutBaseline = equivalentPointedLayout->baseline(); + return max(pointedLayoutBaseline, equivalentLayoutBaseline) + + max(pointedLayoutHeight - pointedLayoutBaseline, equivalentLayoutHeight - equivalentLayoutBaseline); } - return height; } } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index a86093d10..6ebe5bfc2 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -83,6 +83,13 @@ const ExpressionLayout * ExpressionLayout::child(int i) const { return nullptr; } +bool ExpressionLayout::hasChild(const ExpressionLayout * child) const { + if (child == nullptr) { + return false; + } + return child->parent() == this; +} + int ExpressionLayout::indexOfChild(const ExpressionLayout * child) const { if (child == nullptr) { return -1; From 47cf7d3f355bcd3d7be4bd8f16e8aa8ddce189a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 18:00:28 +0200 Subject: [PATCH 382/459] [poincare] Fix missing return statement Change-Id: I56aa9bff457d150efc7c451d57155c9e0db8cec4 --- poincare/src/expression_layout_cursor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index f19716714..5495c1623 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -267,14 +267,16 @@ KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); if (m_pointedExpressionLayout->hasChild(equivalentPointedLayout)) { return equivalentPointedLayout->size().height(); - } else if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { - KDCoordinate pointedLayoutHeight = m_pointedExpressionLayout->size().height(); + } + KDCoordinate pointedLayoutHeight = m_pointedExpressionLayout->size().height(); + if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { KDCoordinate equivalentLayoutHeight = equivalentPointedLayout->size().height(); KDCoordinate pointedLayoutBaseline = m_pointedExpressionLayout->baseline(); KDCoordinate equivalentLayoutBaseline = equivalentPointedLayout->baseline(); return max(pointedLayoutBaseline, equivalentLayoutBaseline) + max(pointedLayoutHeight - pointedLayoutBaseline, equivalentLayoutHeight - equivalentLayoutBaseline); } + return pointedLayoutHeight; } } From cff95c2ac11f7e8b67ba3560b0348d7942ceb262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 18:00:53 +0200 Subject: [PATCH 383/459] [escher/poincare] Fix non ELField size change. When adding a big layout (e.g. SumLayout), the inputView did not change it size (in calculation and in Saquence for instance). Change-Id: Ic8604a4085c29e69d2aecc7ac8a88ca9889f34f1 --- escher/src/expression_layout_field.cpp | 1 - poincare/src/layout/dynamic_layout_hierarchy.cpp | 6 ------ poincare/src/layout/expression_layout.cpp | 6 ------ poincare/src/layout/grid_layout.cpp | 4 ---- 4 files changed, 17 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 725db70f1..0949e3e2b 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -224,7 +224,6 @@ void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { void ExpressionLayoutField::reload() { KDSize previousSize = minimalSizeForOptimalDisplay(); m_contentView.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines(); - layoutSubviews(); KDSize newSize = minimalSizeForOptimalDisplay(); if (m_delegate && previousSize.height() != newSize.height()) { m_delegate->expressionLayoutFieldDidChangeSize(this); diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index c5d11739b..848bd3fa3 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -71,9 +71,6 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * } m_children = newOperands; m_numberOfChildren = currentIndex; - m_sized = false; - m_positioned = false; - m_baselined = false; } bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index) { @@ -91,9 +88,6 @@ bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index delete[] m_children; m_children = newChildren; m_numberOfChildren += 1; - m_sized = false; - m_positioned = false; - m_baselined = false; return true; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 6ebe5bfc2..e5e834ac7 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -171,9 +171,6 @@ void ExpressionLayout::replaceChild(const ExpressionLayout * oldChild, Expressio break; } } - m_sized = false; - m_positioned = false; - m_baselined = false; } void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { @@ -331,9 +328,6 @@ void ExpressionLayout::detachChildAtIndex(int i) { const_cast(op[i])->setParent(nullptr); } op[i] = nullptr; - m_sized = false; - m_positioned = false; - m_baselined = false; } ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index ae3e7a1a5..b6ee2b201 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -192,7 +192,6 @@ void GridLayout::addEmptyRow(EmptyLayout::Color color) { } addChildrenAtIndex(const_cast(const_cast(newChildren)), m_numberOfColumns, numberOfChildren(), false); m_numberOfRows++; - invalidAllSizesPositionsAndBaselines(); } void GridLayout::addEmptyColumn(EmptyLayout::Color color) { @@ -200,7 +199,6 @@ void GridLayout::addEmptyColumn(EmptyLayout::Color color) { for (int i = 0; i < m_numberOfRows; i++) { addChildAtIndex(new EmptyLayout(color), i*m_numberOfColumns + m_numberOfColumns-1); } - invalidAllSizesPositionsAndBaselines(); } void GridLayout::deleteRowAtIndex(int index) { @@ -209,7 +207,6 @@ void GridLayout::deleteRowAtIndex(int index) { DynamicLayoutHierarchy::removeChildAtIndex(index * m_numberOfColumns, true); } m_numberOfRows--; - invalidAllSizesPositionsAndBaselines(); } void GridLayout::deleteColumnAtIndex(int index) { @@ -218,7 +215,6 @@ void GridLayout::deleteColumnAtIndex(int index) { DynamicLayoutHierarchy::removeChildAtIndex(i, true); } m_numberOfColumns--; - invalidAllSizesPositionsAndBaselines(); } bool GridLayout::childIsLeftOfGrid(int index) const { From ce81481922b325d578be5f558843a151bcb31735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 25 Apr 2018 18:08:35 +0200 Subject: [PATCH 384/459] [apps/calculation] Do not reload if the ELView is already maximal Change-Id: Id21cc71de7d5d83a30c6b7beea3c71108bed7197 --- apps/calculation/edit_expression_controller.cpp | 10 +++++++++- apps/calculation/edit_expression_controller.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 53c857809..e3bf905c8 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -110,7 +110,15 @@ bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::Expression } void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) { - reloadView(); + /* Reload the view only if the ExpressionField height actually changes, i.e. + * not if the height is already maximal and stays maximal. */ + if (view()) { + bool newInputViewHeightIsMaximal = static_cast(view())->expressionField()->heightIsMaximal(); + if (!m_inputViewHeightIsMaximal || !newInputViewHeightIsMaximal) { + m_inputViewHeightIsMaximal = newInputViewHeightIsMaximal; + reloadView(); + } + } } TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() { diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index e6aed04f5..1ad0b1c52 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -67,6 +67,7 @@ private: char m_cacheBuffer[TextField::maxBufferSize()]; HistoryController * m_historyController; CalculationStore * m_calculationStore; + bool m_inputViewHeightIsMaximal; }; } From b3d1f8975c3b126f2fa099714ac45ec305888952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 10:21:26 +0200 Subject: [PATCH 385/459] [poincare] cursorLeftOf, RightOf, etc., use a cursor object, not pointer Change-Id: If9a148e663cd7a18a303adc9175aab953d825945 --- .../expression_layout_field_content_view.cpp | 8 +-- poincare/include/poincare/expression_layout.h | 20 +++---- poincare/src/expression_layout_cursor.cpp | 16 ++--- .../layout/binomial_coefficient_layout.cpp | 36 ++++++------ .../src/layout/binomial_coefficient_layout.h | 8 +-- poincare/src/layout/bracket_layout.cpp | 16 ++--- poincare/src/layout/bracket_layout.h | 4 +- poincare/src/layout/bracket_pair_layout.cpp | 26 ++++----- poincare/src/layout/bracket_pair_layout.h | 4 +- poincare/src/layout/char_layout.cpp | 12 ++-- poincare/src/layout/char_layout.h | 4 +- poincare/src/layout/condensed_sum_layout.cpp | 8 +-- poincare/src/layout/condensed_sum_layout.h | 8 +-- poincare/src/layout/conjugate_layout.cpp | 24 ++++---- poincare/src/layout/conjugate_layout.h | 4 +- poincare/src/layout/empty_layout.cpp | 12 ++-- poincare/src/layout/empty_layout.h | 4 +- poincare/src/layout/expression_layout.cpp | 28 ++++----- poincare/src/layout/fraction_layout.cpp | 40 ++++++------- poincare/src/layout/fraction_layout.h | 8 +-- poincare/src/layout/grid_layout.cpp | 32 +++++----- poincare/src/layout/grid_layout.h | 8 +-- poincare/src/layout/horizontal_layout.cpp | 58 +++++++++---------- poincare/src/layout/horizontal_layout.h | 6 +- poincare/src/layout/integral_layout.cpp | 48 +++++++-------- poincare/src/layout/integral_layout.h | 8 +-- poincare/src/layout/matrix_layout.cpp | 36 ++++++------ poincare/src/layout/matrix_layout.h | 12 ++-- poincare/src/layout/nth_root_layout.cpp | 48 +++++++-------- poincare/src/layout/nth_root_layout.h | 8 +-- poincare/src/layout/sequence_layout.cpp | 48 +++++++-------- poincare/src/layout/sequence_layout.h | 8 +-- .../src/layout/vertical_offset_layout.cpp | 46 +++++++-------- poincare/src/layout/vertical_offset_layout.h | 8 +-- 34 files changed, 332 insertions(+), 332 deletions(-) diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index ddb856fd9..a236db7e1 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -60,10 +60,10 @@ void ExpressionLayoutField::ContentView::layoutCursorSubview() { KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayout(); ExpressionLayoutCursor::Position cursorPosition = m_cursor.position(); - ExpressionLayoutCursor equivalentCursor = pointedLayout->equivalentCursor(&m_cursor); - if (pointedLayout->hasChild(equivalentCursor.pointedExpressionLayout())) { - pointedLayout = equivalentCursor.pointedExpressionLayout(); - cursorPosition = equivalentCursor.position(); + ExpressionLayoutCursor eqCursor = pointedLayout->equivalentCursor(m_cursor); + if (pointedLayout->hasChild(eqCursor.pointedExpressionLayout())) { + pointedLayout = eqCursor.pointedExpressionLayout(); + cursorPosition = eqCursor.position(); } KDPoint cursoredExpressionViewOrigin = pointedLayout->absoluteOrigin(); KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index facef85e5..f58c62ca0 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -85,18 +85,18 @@ public: virtual void deleteBeforeCursor(ExpressionLayoutCursor * cursor); /* Tree navigation */ - virtual ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; - virtual ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); - virtual ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); - virtual ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); - virtual ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + virtual ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) = 0; + virtual ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) = 0; + virtual ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); + virtual ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; /* Cursor */ - virtual ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor * cursor); + virtual ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor cursor); /* Other */ virtual ExpressionLayout * layoutToPointWhenInserting(); @@ -135,7 +135,7 @@ protected: virtual KDPoint positionOfChild(ExpressionLayout * child) = 0; void scoreCursorInDescendantsVerticalOf ( VerticalDirection direction, - ExpressionLayoutCursor * cursor, + ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, ExpressionLayout ** childResult, void * resultPosition, @@ -152,8 +152,8 @@ protected: bool m_positioned; private: void detachChildAtIndex(int i); - ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); - ExpressionLayoutCursor cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + ExpressionLayoutCursor cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; }; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 5495c1623..11e4e4179 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -19,7 +19,7 @@ KDCoordinate ExpressionLayoutCursor::baseline() { return k_cursorHeight / 2; } KDCoordinate pointedLayoutBaseline = m_pointedExpressionLayout->baseline(); - ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(*this).pointedExpressionLayout(); if (m_pointedExpressionLayout->hasChild(equivalentPointedLayout)) { return equivalentPointedLayout->baseline(); } else if (m_pointedExpressionLayout->hasSibling(equivalentPointedLayout)) { @@ -42,19 +42,19 @@ KDPoint ExpressionLayoutCursor::middleLeftPoint() { } ExpressionLayoutCursor ExpressionLayoutCursor::cursorOnLeft(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->cursorLeftOf(this, shouldRecomputeLayout); + return m_pointedExpressionLayout->cursorLeftOf(*this, shouldRecomputeLayout); } ExpressionLayoutCursor ExpressionLayoutCursor::cursorOnRight(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->cursorRightOf(this, shouldRecomputeLayout); + return m_pointedExpressionLayout->cursorRightOf(*this, shouldRecomputeLayout); } ExpressionLayoutCursor ExpressionLayoutCursor::cursorAbove(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->cursorAbove(this, shouldRecomputeLayout); + return m_pointedExpressionLayout->cursorAbove(*this, shouldRecomputeLayout); } ExpressionLayoutCursor ExpressionLayoutCursor::cursorUnder(bool * shouldRecomputeLayout) { - return m_pointedExpressionLayout->cursorUnder(this, shouldRecomputeLayout); + return m_pointedExpressionLayout->cursorUnder(*this, shouldRecomputeLayout); } void ExpressionLayoutCursor::addLayoutAndMoveCursor(ExpressionLayout * layout) { @@ -218,7 +218,7 @@ bool ExpressionLayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { adjacentEmptyLayout = m_pointedExpressionLayout; } else { // Check the equivalent cursor position - ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(*this).pointedExpressionLayout(); if (equivalentPointedLayout != nullptr && equivalentPointedLayout->isEmpty()) { adjacentEmptyLayout = equivalentPointedLayout; } @@ -252,7 +252,7 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { if (m_pointedExpressionLayout->isHorizontal()) { return false; } - ExpressionLayoutCursor equivalentLayoutCursor = m_pointedExpressionLayout->equivalentCursor(this); + ExpressionLayoutCursor equivalentLayoutCursor = m_pointedExpressionLayout->equivalentCursor(*this); if (equivalentLayoutCursor.pointedExpressionLayout() != nullptr && equivalentLayoutCursor.pointedExpressionLayout()->isHorizontal() && equivalentLayoutCursor.position() == Position::Left) @@ -264,7 +264,7 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { } KDCoordinate ExpressionLayoutCursor::pointedLayoutHeight() { - ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(this).pointedExpressionLayout(); + ExpressionLayout * equivalentPointedLayout = m_pointedExpressionLayout->equivalentCursor(*this).pointedExpressionLayout(); if (m_pointedExpressionLayout->hasChild(equivalentPointedLayout)) { return equivalentPointedLayout->size().height(); } diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index a1599f5d4..e5216be40 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -18,46 +18,46 @@ ExpressionLayout * BinomialCoefficientLayout::clone() const { return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); } -ExpressionLayoutCursor BinomialCoefficientLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BinomialCoefficientLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the children. Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Left - && (cursor->pointedExpressionLayout() == nLayout() - || cursor->pointedExpressionLayout() == kLayout())) + if (cursor.position() == ExpressionLayoutCursor::Position::Left + && (cursor.pointedExpressionLayout() == nLayout() + || cursor.pointedExpressionLayout() == kLayout())) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go to the kLayout. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(kLayout() != nullptr); return ExpressionLayoutCursor(kLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor BinomialCoefficientLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BinomialCoefficientLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the children. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Right - && (cursor->pointedExpressionLayout() == nLayout() - || cursor->pointedExpressionLayout() == kLayout())) + if (cursor.position() == ExpressionLayoutCursor::Position::Right + && (cursor.pointedExpressionLayout() == nLayout() + || cursor.pointedExpressionLayout() == kLayout())) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go Left of the nLayout. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(nLayout() != nullptr); return ExpressionLayoutCursor(nLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); @@ -65,17 +65,17 @@ ExpressionLayoutCursor BinomialCoefficientLayout::cursorRightOf(ExpressionLayout return ExpressionLayoutCursor(); } -ExpressionLayoutCursor BinomialCoefficientLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor BinomialCoefficientLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: kLayout. Move to nLayout. - if (cursor->pointedExpressionLayout()->hasAncestor(kLayout(), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(kLayout(), true)) { return nLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor BinomialCoefficientLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor BinomialCoefficientLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: nLayout. Move to kLayout. - if (cursor->pointedExpressionLayout()->hasAncestor(nLayout(), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(nLayout(), true)) { return kLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index a2dcdf58d..44c666963 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -11,10 +11,10 @@ class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } diff --git a/poincare/src/layout/bracket_layout.cpp b/poincare/src/layout/bracket_layout.cpp index d3af81e41..5c92c029b 100644 --- a/poincare/src/layout/bracket_layout.cpp +++ b/poincare/src/layout/bracket_layout.cpp @@ -21,13 +21,13 @@ void BracketLayout::invalidAllSizesPositionsAndBaselines() { ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } -ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); // Case: Left. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -35,13 +35,13 @@ ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * curs return ExpressionLayoutCursor(); } -ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/bracket_layout.h b/poincare/src/layout/bracket_layout.h index 31de5e208..8cfed2a61 100644 --- a/poincare/src/layout/bracket_layout.h +++ b/poincare/src/layout/bracket_layout.h @@ -9,8 +9,8 @@ class BracketLayout : public StaticLayoutHierarchy<0> { public: BracketLayout(); void invalidAllSizesPositionsAndBaselines() override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; protected: void computeBaseline() override; KDCoordinate operandHeight(); diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index cb88a4d1b..f4471fcb0 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -34,21 +34,21 @@ void BracketPairLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor BracketPairLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BracketPairLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. Go Left of the brackets. if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == operandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right of the brackets. Go Right of the operand. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -56,23 +56,23 @@ ExpressionLayoutCursor BracketPairLayout::cursorLeftOf(ExpressionLayoutCursor * return ExpressionLayoutCursor(); } -ExpressionLayoutCursor BracketPairLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor BracketPairLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the operand. Go Right of the brackets. if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == operandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left of the brackets. Go Left of the operand. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right of the brackets. Ask the parent. - cursor->setPointedExpressionLayout(this); + cursor.setPointedExpressionLayout(this); if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index 81f522031..af194086d 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -13,8 +13,8 @@ public: ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: ExpressionLayout * operandLayout(); diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index fadaaa46a..b07d470ba 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -18,10 +18,10 @@ ExpressionLayout * CharLayout::clone() const { return layout; } -ExpressionLayoutCursor CharLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor CharLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } // Case: Left. Ask the parent. @@ -31,10 +31,10 @@ ExpressionLayoutCursor CharLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, return ExpressionLayoutCursor(); } -ExpressionLayoutCursor CharLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor CharLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } // Case: Right. Ask the parent. diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 3afce1439..6cb89ce4b 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -17,8 +17,8 @@ public: char character() { return m_char; } KDText::FontSize fontSize() const { return m_fontSize; } - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index ccde86ae1..882ac03c3 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -10,24 +10,24 @@ ExpressionLayout * CondensedSumLayout::clone() const { return layout; } -ExpressionLayoutCursor CondensedSumLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor CondensedSumLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { /* CondensedSumLayout is only used in apps/shared/sum_graph_controller.cpp, in * a view with no cursor. */ assert(false); return ExpressionLayoutCursor(); } -ExpressionLayoutCursor CondensedSumLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor CondensedSumLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { assert(false); return ExpressionLayoutCursor(); } -ExpressionLayoutCursor CondensedSumLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor CondensedSumLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { assert(false); return ExpressionLayoutCursor(); } -ExpressionLayoutCursor CondensedSumLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor CondensedSumLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { assert(false); return ExpressionLayoutCursor(); } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index d42aafc41..d0c082bc5 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -10,10 +10,10 @@ class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 4ae95a010..82a4f67eb 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -26,44 +26,44 @@ void ConjugateLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cur cursor->setPosition(ExpressionLayoutCursor::Position::Left); } -ExpressionLayoutCursor ConjugateLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ConjugateLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. Move Left. if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == operandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go to the operand. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(operandLayout() != nullptr); return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor ConjugateLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ConjugateLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the operand. Move Right. if (operandLayout() - && cursor->pointedExpressionLayout() == operandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == operandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go to the operand. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(operandLayout() != nullptr); return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left); } // Case: Right. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index 2146a3be1..e4f29f6d9 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -11,8 +11,8 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 84a811b6a..ba04f30d4 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -25,21 +25,21 @@ void EmptyLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { } } -ExpressionLayoutCursor EmptyLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor EmptyLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor.setPosition(ExpressionLayoutCursor::Position::Left); return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - assert(cursor->pointedExpressionLayout() == this); +ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + assert(cursor.pointedExpressionLayout() == this); // Ask the parent. if (m_parent) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor.setPosition(ExpressionLayoutCursor::Position::Right); return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index c73f7e8df..324d5ac67 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -15,8 +15,8 @@ public: EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index e5e834ac7..84cfe4ada 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -253,26 +253,26 @@ char ExpressionLayout::XNTChar() const { return m_parent->XNTChar(); } -ExpressionLayoutCursor ExpressionLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor ExpressionLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { return cursorVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { return cursorInDescendantsVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor ExpressionLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor ExpressionLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { return cursorVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { return cursorInDescendantsVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor ExpressionLayout::equivalentCursor(ExpressionLayoutCursor * cursor) { +ExpressionLayoutCursor ExpressionLayout::equivalentCursor(ExpressionLayoutCursor cursor) { // Only HorizontalLayout may not have a parent, and it overload this function assert(m_parent); - if (cursor->pointedExpressionLayout() == this) { + if (cursor.pointedExpressionLayout() == this) { return m_parent->equivalentCursor(cursor); } else { return ExpressionLayoutCursor(); @@ -330,7 +330,7 @@ void ExpressionLayout::detachChildAtIndex(int i) { op[i] = nullptr; } -ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { ExpressionLayout * chilResult = nullptr; ExpressionLayout ** childResultPtr = &chilResult; ExpressionLayoutCursor::Position resultPosition = ExpressionLayoutCursor::Position::Left; @@ -348,16 +348,16 @@ ExpressionLayoutCursor ExpressionLayout::cursorInDescendantsVerticalOf(VerticalD return ExpressionLayoutCursor(*childResultPtr, resultPosition); } -ExpressionLayoutCursor ExpressionLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor ExpressionLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (!equivalentPositionVisited) { ExpressionLayoutCursor cursorEquivalent = equivalentCursor(cursor); if (cursorEquivalent.isDefined()) { - cursor->setPointedExpressionLayout(cursorEquivalent.pointedExpressionLayout()); - cursor->setPosition(cursorEquivalent.position()); + cursor.setPointedExpressionLayout(cursorEquivalent.pointedExpressionLayout()); + cursor.setPosition(cursorEquivalent.position()); if (direction == VerticalDirection::Up) { - return cursor->pointedExpressionLayout()->cursorAbove(cursor, shouldRecomputeLayout, true); + return cursor.pointedExpressionLayout()->cursorAbove(cursor, shouldRecomputeLayout, true); } else { - return cursor->pointedExpressionLayout()->cursorUnder(cursor, shouldRecomputeLayout, true); + return cursor.pointedExpressionLayout()->cursorUnder(cursor, shouldRecomputeLayout, true); } } } @@ -373,14 +373,14 @@ ExpressionLayoutCursor ExpressionLayout::cursorVerticalOf(VerticalDirection dire void ExpressionLayout::scoreCursorInDescendantsVerticalOf ( VerticalDirection direction, - ExpressionLayoutCursor * cursor, + ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, ExpressionLayout ** childResult, void * resultPosition, int * resultScore) { ExpressionLayoutCursor::Position * castedResultPosition = static_cast(resultPosition); - KDPoint cursorMiddleLeft = cursor->middleLeftPoint(); + KDPoint cursorMiddleLeft = cursor.middleLeftPoint(); bool layoutIsUnderOrAbove = direction == VerticalDirection::Up ? m_frame.isAbove(cursorMiddleLeft) : m_frame.isUnder(cursorMiddleLeft); bool layoutContains = m_frame.contains(cursorMiddleLeft); diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 01bc6c18c..f29aed42e 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -89,72 +89,72 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor FractionLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor FractionLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the numerator or the denominator. Go Left of the fraction. - if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) - || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Left) + if (((numeratorLayout() && cursor.pointedExpressionLayout() == numeratorLayout()) + || (denominatorLayout() && cursor.pointedExpressionLayout() == denominatorLayout())) + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go to the denominator. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(denominatorLayout() != nullptr); return ExpressionLayoutCursor(denominatorLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor FractionLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor FractionLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the numerator or the denominator. Go Right of the fraction. - if (((numeratorLayout() && cursor->pointedExpressionLayout() == numeratorLayout()) - || (denominatorLayout() && cursor->pointedExpressionLayout() == denominatorLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Right) + if (((numeratorLayout() && cursor.pointedExpressionLayout() == numeratorLayout()) + || (denominatorLayout() && cursor.pointedExpressionLayout() == denominatorLayout())) + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go to the numerator. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(numeratorLayout() != nullptr); return ExpressionLayoutCursor(numeratorLayout(), ExpressionLayoutCursor::Position::Left); } // Case: Right. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor FractionLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor FractionLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside denominator, move it to the numerator. - if (denominatorLayout() && cursor->pointedExpressionLayout()->hasAncestor(denominatorLayout(), true)) { + if (denominatorLayout() && cursor.pointedExpressionLayout()->hasAncestor(denominatorLayout(), true)) { assert(numeratorLayout() != nullptr); return numeratorLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the numerator. - if (cursor->pointedExpressionLayout() == this){ + if (cursor.pointedExpressionLayout() == this){ assert(numeratorLayout() != nullptr); return numeratorLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor FractionLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor FractionLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside numerator, move it to the denominator. - if (numeratorLayout() && cursor->pointedExpressionLayout()->hasAncestor(numeratorLayout(), true)) { + if (numeratorLayout() && cursor.pointedExpressionLayout()->hasAncestor(numeratorLayout(), true)) { assert(denominatorLayout() != nullptr); return denominatorLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left or Right, move it to the denominator. - if (cursor->pointedExpressionLayout() == this){ + if (cursor.pointedExpressionLayout() == this){ assert(denominatorLayout() != nullptr); return denominatorLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 0a089cc71..6eb4e9fd0 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -12,10 +12,10 @@ public: ExpressionLayout * clone() const override; void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } diff --git a/poincare/src/layout/grid_layout.cpp b/poincare/src/layout/grid_layout.cpp index b6ee2b201..7f152288d 100644 --- a/poincare/src/layout/grid_layout.cpp +++ b/poincare/src/layout/grid_layout.cpp @@ -21,18 +21,18 @@ ExpressionLayout * GridLayout::clone() const { return layout; } -ExpressionLayoutCursor GridLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor GridLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right. Go to the last entry. - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) + if (cursor.pointedExpressionLayout() == this + && cursor.position() == ExpressionLayoutCursor::Position::Right) { ExpressionLayout * lastChild = editableChild(m_numberOfColumns*m_numberOfRows-1); assert(lastChild != nullptr); return ExpressionLayoutCursor(lastChild, ExpressionLayoutCursor::Position::Right); } // Case: The cursor points to a grid's child. - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); - if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Left) { + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); + if (childIndex >- 1 && cursor.position() == ExpressionLayoutCursor::Position::Left) { if (childIsLeftOfGrid(childIndex)) { // Case: Left of a child on the left of the grid. Go Left of the grid return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); @@ -40,7 +40,7 @@ ExpressionLayoutCursor GridLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, // Case: Left of another child. Go Right of its sibling on the left. return ExpressionLayoutCursor(editableChild(childIndex-1), ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -48,10 +48,10 @@ ExpressionLayoutCursor GridLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, return ExpressionLayoutCursor(); } -ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left. Go to the first entry. - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Left) + if (cursor.pointedExpressionLayout() == this + && cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(m_numberOfColumns*m_numberOfRows >= 1); ExpressionLayout * firstChild = editableChild(0); @@ -59,8 +59,8 @@ ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor * cursor return ExpressionLayoutCursor(firstChild, ExpressionLayoutCursor::Position::Left); } // Case: The cursor points to a grid's child. - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); - if (childIndex >- 1 && cursor->position() == ExpressionLayoutCursor::Position::Right) { + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); + if (childIndex >- 1 && cursor.position() == ExpressionLayoutCursor::Position::Right) { if (childIsRightOfGrid(childIndex)) { // Case: Right of a child on the right of the grid. Go Right of the grid. return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); @@ -68,7 +68,7 @@ ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor * cursor // Case: Right of another child. Go Left of its sibling on the right. return ExpressionLayoutCursor(editableChild(childIndex+1), ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); @@ -76,12 +76,12 @@ ExpressionLayoutCursor GridLayout::cursorRightOf(ExpressionLayoutCursor * cursor return ExpressionLayoutCursor(); } -ExpressionLayoutCursor GridLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor GridLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { /* If the cursor is child that is not on the top row, move it inside its upper * neighbour.*/ int childIndex = m_numberOfColumns; while (childIndex < numberOfChildren()) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { return editableChild(childIndex - m_numberOfColumns)->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } childIndex++; @@ -89,10 +89,10 @@ ExpressionLayoutCursor GridLayout::cursorAbove(ExpressionLayoutCursor * cursor, return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor GridLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor GridLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { int childIndex = 0; while (childIndex < numberOfChildren() - m_numberOfColumns) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { return editableChild(childIndex + m_numberOfColumns)->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } childIndex++; diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 379d44ff3..499aac12e 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -13,10 +13,10 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Dynamic layout */ void removeChildAtIndex(int index, bool deleteAfterRemoval) override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index ef3e9a9a4..8d0e4c6e9 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -171,21 +171,21 @@ void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, addChildAtIndex(eL, index); } -ExpressionLayoutCursor HorizontalLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor HorizontalLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left. Ask the parent. - if (cursor->pointedExpressionLayout() == this) { - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.pointedExpressionLayout() == this) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); /* Case: Right. * Go to the last child if there is one, and move Left. * Else go Left and ask the parent. */ if (numberOfChildren() < 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor.setPosition(ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } @@ -193,43 +193,43 @@ ExpressionLayoutCursor HorizontalLayout::cursorLeftOf(ExpressionLayoutCursor * c } ExpressionLayout * lastChild = editableChild(numberOfChildren()-1); assert(lastChild != nullptr); - cursor->setPointedExpressionLayout(lastChild); + cursor.setPointedExpressionLayout(lastChild); return lastChild->cursorLeftOf(cursor, shouldRecomputeLayout); } // Case: The cursor is Left of a child. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); assert(childIndex >= 0); if (childIndex == 0) { // Case: the child is the leftmost. Ask the parent. if (m_parent) { - cursor->setPointedExpressionLayout(this); + cursor.setPointedExpressionLayout(this); return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } // Case: the child is not the leftmost. Go to its left sibling and move Left. - cursor->setPointedExpressionLayout(editableChild(childIndex-1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor.setPointedExpressionLayout(editableChild(childIndex-1)); + cursor.setPosition(ExpressionLayoutCursor::Position::Right); return editableChild(childIndex-1)->cursorLeftOf(cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor HorizontalLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor HorizontalLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right. Ask the parent. - if (cursor->pointedExpressionLayout() == this) { - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.pointedExpressionLayout() == this) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); /* Case: Left. * Go to the first child if there is one, and move Right. * Else go Right and ask the parent. */ if (numberOfChildren() < 1) { - cursor->setPosition(ExpressionLayoutCursor::Position::Right); + cursor.setPosition(ExpressionLayoutCursor::Position::Right); if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } @@ -237,26 +237,26 @@ ExpressionLayoutCursor HorizontalLayout::cursorRightOf(ExpressionLayoutCursor * } ExpressionLayout * firstChild = editableChild(0); assert(firstChild != nullptr); - cursor->setPointedExpressionLayout(firstChild); + cursor.setPointedExpressionLayout(firstChild); return firstChild->cursorRightOf(cursor, shouldRecomputeLayout); } // Case: The cursor is Right of a child. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); assert(childIndex >= 0); if (childIndex == numberOfChildren() - 1) { // Case: the child is the rightmost. Ask the parent. if (m_parent) { - cursor->setPointedExpressionLayout(this); + cursor.setPointedExpressionLayout(this); return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } /* Case: the child is not the rightmost. Go to its right sibling and move * Right. */ - cursor->setPointedExpressionLayout(editableChild(childIndex+1)); - cursor->setPosition(ExpressionLayoutCursor::Position::Left); + cursor.setPointedExpressionLayout(editableChild(childIndex+1)); + cursor.setPosition(ExpressionLayoutCursor::Position::Left); return editableChild(childIndex+1)->cursorRightOf(cursor, shouldRecomputeLayout); } @@ -294,24 +294,24 @@ int HorizontalLayout::writeTextInBuffer(char * buffer, int bufferSize, int numbe return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); } -ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor * cursor) { +ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor cursor) { ExpressionLayoutCursor result; ExpressionLayout * newPointedLayout = nullptr; ExpressionLayoutCursor::Position newPosition = ExpressionLayoutCursor::Position::Left; - if (cursor->pointedExpressionLayout() == this) { + if (cursor.pointedExpressionLayout() == this) { // First or last child, if any if(numberOfChildren() == 0) { return result; } else { - newPointedLayout = editableChild(cursor->position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1); - newPosition = cursor->position(); + newPointedLayout = editableChild(cursor.position() == ExpressionLayoutCursor::Position::Left ? 0 : numberOfChildren() - 1); + newPosition = cursor.position(); } } else { // Left or right child - int indexOfPointedLayout = indexOfChild(cursor->pointedExpressionLayout()); + int indexOfPointedLayout = indexOfChild(cursor.pointedExpressionLayout()); if (indexOfPointedLayout < 0) { return result; - } else if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + } else if (cursor.position() == ExpressionLayoutCursor::Position::Left) { if (indexOfPointedLayout == 0) { newPointedLayout = this; newPosition = ExpressionLayoutCursor::Position::Left; @@ -320,7 +320,7 @@ ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor newPosition = ExpressionLayoutCursor::Position::Right; } } else { - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); if (indexOfPointedLayout == numberOfChildren() - 1) { newPointedLayout = this; newPosition = ExpressionLayoutCursor::Position::Right; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 8b4dcec35..cc7690c42 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -23,8 +23,8 @@ public: void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); /* Navigation */ - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) override; @@ -36,7 +36,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Cursor */ - ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor * cursor) override; + ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor cursor) override; /* Other */ bool isHorizontal() const override { return true; } diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index 2e66cca90..dca8acb70 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -36,31 +36,31 @@ void IntegralLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor IntegralLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor IntegralLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left the upper or lower bound. Go Left of the integral. if (((upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()) + && cursor.pointedExpressionLayout() == upperBoundLayout()) || (lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == lowerBoundLayout())) + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } // Case: Left the integrand. Go Right of the lower bound. if (integrandLayout() - && cursor->pointedExpressionLayout() == integrandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == integrandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(lowerBoundLayout() != nullptr); return ExpressionLayoutCursor(lowerBoundLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right of the integral. Go to the integrand. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); return ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); // Case: Left of the brackets. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -68,32 +68,32 @@ ExpressionLayoutCursor IntegralLayout::cursorLeftOf(ExpressionLayoutCursor * cur return ExpressionLayoutCursor(); } -ExpressionLayoutCursor IntegralLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor IntegralLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right the upper or lower bound. // Go Left of the integrand. if (((upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()) + && cursor.pointedExpressionLayout() == upperBoundLayout()) || (lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout())) - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == lowerBoundLayout())) + && cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(integrandLayout() != nullptr); return ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left); } // Case: Right the integrand. Go Right. if (integrandLayout() - && cursor->pointedExpressionLayout() == integrandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == integrandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left of the integral. Go to the upper bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); return ExpressionLayoutCursor(upperBoundLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); @@ -101,15 +101,15 @@ ExpressionLayoutCursor IntegralLayout::cursorRightOf(ExpressionLayoutCursor * cu return ExpressionLayoutCursor(); } -ExpressionLayoutCursor IntegralLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor IntegralLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { + if (lowerBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the upper bound. if (integrandLayout() - && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) + && cursor.isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); @@ -117,15 +117,15 @@ ExpressionLayoutCursor IntegralLayout::cursorAbove(ExpressionLayoutCursor * curs return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor IntegralLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor IntegralLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { + if (upperBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left of the integrand, move it to the lower bound. if (integrandLayout() - && cursor->isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) + && cursor.isEquivalentTo(ExpressionLayoutCursor(integrandLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index ca2333dca..d6c211124 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -17,10 +17,10 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 51890fffd..7ecdab87a 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -15,10 +15,10 @@ ExpressionLayout * MatrixLayout::clone() const { return layout; } -ExpressionLayoutCursor MatrixLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); +ExpressionLayoutCursor MatrixLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); if (childIndex >- 1 - && cursor->position() == ExpressionLayoutCursor::Position::Left + && cursor.position() == ExpressionLayoutCursor::Position::Left && childIsLeftOfGrid(childIndex)) { /* Case: Left of a child on the left of the grid. @@ -30,8 +30,8 @@ ExpressionLayoutCursor MatrixLayout::cursorLeftOf(ExpressionLayoutCursor * curso } /* Case: Right. Add the grey squares to the matrix, then move to the bottom * right non empty nor grey child. */ - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Right) + if (cursor.pointedExpressionLayout() == this + && cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(!hasGreySquares()); addGreySquares(); @@ -43,10 +43,10 @@ ExpressionLayoutCursor MatrixLayout::cursorLeftOf(ExpressionLayoutCursor * curso return GridLayout::cursorLeftOf(cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left. Add the grey squares to the matrix, then go to the first entry. - if (cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Left) + if (cursor.pointedExpressionLayout() == this + && cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(!hasGreySquares()); addGreySquares(); @@ -57,9 +57,9 @@ ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor * curs return ExpressionLayoutCursor(firstChild, ExpressionLayoutCursor::Position::Left); } // Case: The cursor points to a grid's child. - int childIndex = indexOfChild(cursor->pointedExpressionLayout()); + int childIndex = indexOfChild(cursor.pointedExpressionLayout()); if (childIndex >- 1 - && cursor->position() == ExpressionLayoutCursor::Position::Right + && cursor.position() == ExpressionLayoutCursor::Position::Right && childIsRightOfGrid(childIndex)) { /* Case: Right of a child on the right of the grid. Remove the grey squares @@ -73,10 +73,10 @@ ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor * curs return GridLayout::cursorRightOf(cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor MatrixLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor MatrixLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { // The cursor is leaving the matrix, so remove the grey squares. shouldRemoveGreySquares = true; break; @@ -91,10 +91,10 @@ ExpressionLayoutCursor MatrixLayout::cursorAbove(ExpressionLayoutCursor * cursor return resultCursor; } -ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { - if (cursor->pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { + if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { // The cursor is leaving the matrix, so remove the grey squares. shouldRemoveGreySquares = true; break; @@ -109,9 +109,9 @@ ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor * cursor return resultCursor; } -ExpressionLayoutCursor MatrixLayout::cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor MatrixLayout::cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { ExpressionLayoutCursor result = GridLayout::cursorInDescendantsAbove(cursor, shouldRecomputeLayout); - if (result.isDefined() && cursor->pointedExpressionLayout() != this) { + if (result.isDefined() && cursor.pointedExpressionLayout() != this) { // Add the grey squares if the cursor is pointing at a matrix descendant, // not at the matrix itself. assert(!hasGreySquares()); @@ -121,9 +121,9 @@ ExpressionLayoutCursor MatrixLayout::cursorInDescendantsAbove(ExpressionLayoutCu return result; } -ExpressionLayoutCursor MatrixLayout::cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor MatrixLayout::cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { ExpressionLayoutCursor result = GridLayout::cursorInDescendantsUnder(cursor, shouldRecomputeLayout); - if (result.isDefined() && cursor->pointedExpressionLayout() != this) { + if (result.isDefined() && cursor.pointedExpressionLayout() != this) { // Add the grey squares if the cursor is pointing at a matrix descendant, // not at the matrix itself. assert(!hasGreySquares()); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index 1765bf1ec..d5469fb81 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -11,12 +11,12 @@ public: ExpressionLayout * clone() const override; /* Navigation */ - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 1376c098b..598269d1f 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -50,11 +50,11 @@ void NthRootLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor NthRootLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor NthRootLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the radicand. Go the index if any, else go Left of the root. if (radicandLayout() - && cursor->pointedExpressionLayout() == radicandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == radicandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { if (indexLayout()) { return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right); @@ -63,18 +63,18 @@ ExpressionLayoutCursor NthRootLayout::cursorLeftOf(ExpressionLayoutCursor * curs } // Case: Left of the index. Go Left of the root. if (indexLayout() - && cursor->pointedExpressionLayout() == indexLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == indexLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go Right of the radicand. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(radicandLayout() != nullptr); return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); // Case: Left. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -82,32 +82,32 @@ ExpressionLayoutCursor NthRootLayout::cursorLeftOf(ExpressionLayoutCursor * curs return ExpressionLayoutCursor(); } -ExpressionLayoutCursor NthRootLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor NthRootLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the radicand. Go the Right of the root. if (radicandLayout() - && cursor->pointedExpressionLayout() == radicandLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == radicandLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } // Case: Right of the index. Go Left of the integrand. if (indexLayout() - && cursor->pointedExpressionLayout() == indexLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == indexLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(radicandLayout() != nullptr); return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go index if there is one, else go to the radicand. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { if (indexLayout()) { return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left); } assert(radicandLayout() != nullptr); return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); @@ -115,33 +115,33 @@ ExpressionLayoutCursor NthRootLayout::cursorRightOf(ExpressionLayoutCursor * cur return ExpressionLayoutCursor(); } -ExpressionLayoutCursor NthRootLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor NthRootLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is Left of the radicand, move it to the index. if (indexLayout() && radicandLayout() - && cursor->isEquivalentTo(ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left))) + && cursor.isEquivalentTo(ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left))) { return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right); } // If the cursor is Left, move it to the index. if (indexLayout() - && cursor->pointedExpressionLayout() == this - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == this + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left); } return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor NthRootLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - if (indexLayout() && cursor->pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { +ExpressionLayoutCursor NthRootLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (indexLayout() && cursor.pointedExpressionLayout()->hasAncestor(indexLayout(), true)) { // If the cursor is Right of the index, move it to the radicand. - if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Right))) { assert(radicandLayout() != nullptr); return ExpressionLayoutCursor(radicandLayout(), ExpressionLayoutCursor::Position::Left); } // If the cursor is Left of the index, move it Left . - if (cursor->isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(indexLayout(), ExpressionLayoutCursor::Position::Left))) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } } diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 6fb59077f..8954435e6 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -18,10 +18,10 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; /* Tree navigation */ - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Expression Engine */ int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 40856ec07..3f8a7cf35 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -17,31 +17,31 @@ void SequenceLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor SequenceLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor SequenceLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the bounds. Go Left of the sequence. - if (cursor->position() == ExpressionLayoutCursor::Position::Left + if (cursor.position() == ExpressionLayoutCursor::Position::Left && ((lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) + && cursor.pointedExpressionLayout() == lowerBoundLayout()) || (upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()))) + && cursor.pointedExpressionLayout() == upperBoundLayout()))) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } // Case: Left of the argument. Go Right of the lower bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left + if (cursor.position() == ExpressionLayoutCursor::Position::Left && argumentLayout() - && cursor->pointedExpressionLayout() == argumentLayout()) + && cursor.pointedExpressionLayout() == argumentLayout()) { assert(lowerBoundLayout() != nullptr); return ExpressionLayoutCursor(lowerBoundLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go to the argument and move Left. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(argumentLayout() != nullptr); return ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Right); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); // Case: Left. Ask the parent. if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); @@ -49,31 +49,31 @@ ExpressionLayoutCursor SequenceLayout::cursorLeftOf(ExpressionLayoutCursor * cur return ExpressionLayoutCursor(); } -ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the bounds. Go Left of the argument. - if (cursor->position() == ExpressionLayoutCursor::Position::Right + if (cursor.position() == ExpressionLayoutCursor::Position::Right && ((lowerBoundLayout() - && cursor->pointedExpressionLayout() == lowerBoundLayout()) + && cursor.pointedExpressionLayout() == lowerBoundLayout()) || (upperBoundLayout() - && cursor->pointedExpressionLayout() == upperBoundLayout()))) + && cursor.pointedExpressionLayout() == upperBoundLayout()))) { assert(argumentLayout() != nullptr); return ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left); } // Case: Right of the argument. Go Right. - if (cursor->position() == ExpressionLayoutCursor::Position::Right + if (cursor.position() == ExpressionLayoutCursor::Position::Right && argumentLayout() - && cursor->pointedExpressionLayout() == argumentLayout()) + && cursor.pointedExpressionLayout() == argumentLayout()) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go to the upper bound. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); return ExpressionLayoutCursor(upperBoundLayout(), ExpressionLayoutCursor::Position::Left); } - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); // Case: Right. Ask the parent. if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); @@ -81,15 +81,15 @@ ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor * cu return ExpressionLayoutCursor(); } -ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the lower bound, move it to the upper bound. - if (lowerBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { + if (lowerBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the upper bound. if (argumentLayout() - && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) + && cursor.isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); @@ -97,15 +97,15 @@ ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor * curs return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor SequenceLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor SequenceLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // If the cursor is inside the upper bound, move it to the lower bound. - if (upperBoundLayout() && cursor->pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { + if (upperBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } // If the cursor is Left of the argument, move it to the lower bound. if (argumentLayout() - && cursor->isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) + && cursor.isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index 327e97d49..ee0c57561 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -11,10 +11,10 @@ public: constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayout * layoutToPointWhenInserting() override; char XNTChar() const override { return 'n'; } protected: diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 5e51e94b5..2c0ff224e 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -63,62 +63,62 @@ void VerticalOffsetLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout::deleteBeforeCursor(cursor); } -ExpressionLayoutCursor VerticalOffsetLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the indice. Go Left. if (indiceLayout() - && cursor->pointedExpressionLayout() == indiceLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Left) + && cursor.pointedExpressionLayout() == indiceLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Left) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Right. Go to the indice. - if (cursor->position() == ExpressionLayoutCursor::Position::Right) { + if (cursor.position() == ExpressionLayoutCursor::Position::Right) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Left); + assert(cursor.position() == ExpressionLayoutCursor::Position::Left); if (m_parent) { return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor VerticalOffsetLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Right of the indice. Go Right. if (indiceLayout() - && cursor->pointedExpressionLayout() == indiceLayout() - && cursor->position() == ExpressionLayoutCursor::Position::Right) + && cursor.pointedExpressionLayout() == indiceLayout() + && cursor.position() == ExpressionLayoutCursor::Position::Right) { return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } - assert(cursor->pointedExpressionLayout() == this); + assert(cursor.pointedExpressionLayout() == this); // Case: Left. Go to the indice. - if (cursor->position() == ExpressionLayoutCursor::Position::Left) { + if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } // Case: Right. Ask the parent. - assert(cursor->position() == ExpressionLayoutCursor::Position::Right); + assert(cursor.position() == ExpressionLayoutCursor::Position::Right); if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } return ExpressionLayoutCursor(); } -ExpressionLayoutCursor VerticalOffsetLayout::cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Superscript. if (m_type == VerticalOffsetLayout::Type::Superscript) { // Case: Right. Move to the indice. - if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Move to the indice. - if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } @@ -127,24 +127,24 @@ ExpressionLayoutCursor VerticalOffsetLayout::cursorAbove(ExpressionLayoutCursor * position, pointing this. */ if (m_type == VerticalOffsetLayout::Type::Subscript && indiceLayout() != nullptr - && (cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left)) - || cursor->isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right)))) + && (cursor.isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left)) + || cursor.isEquivalentTo(ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right)))) { - return ExpressionLayoutCursor(this, cursor->position()); + return ExpressionLayoutCursor(this, cursor.position()); } return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayoutCursor VerticalOffsetLayout::cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor VerticalOffsetLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { // Case: Subscript. if (m_type == VerticalOffsetLayout::Type::Subscript) { // Case: Right. Move to the indice. - if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right))) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Right); } // Case: Left. Move to the indice. - if (cursor->isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { + if (cursor.isEquivalentTo(ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left))) { assert(indiceLayout() != nullptr); return ExpressionLayoutCursor(indiceLayout(), ExpressionLayoutCursor::Position::Left); } @@ -153,9 +153,9 @@ ExpressionLayoutCursor VerticalOffsetLayout::cursorUnder(ExpressionLayoutCursor * position, pointing this. */ if (m_type == VerticalOffsetLayout::Type::Superscript && indiceLayout() != nullptr - && cursor->pointedExpressionLayout() == indiceLayout()) + && cursor.pointedExpressionLayout() == indiceLayout()) { - return ExpressionLayoutCursor(this, cursor->position()); + return ExpressionLayoutCursor(this, cursor.position()); } return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index dbd1dd906..a78b3e880 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -15,10 +15,10 @@ public: Type type() const { return m_type; } ExpressionLayout * clone() const override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const override { return true; } From 7ce8b567ea5d4acd17b00333ba629b75977e0a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 10:37:48 +0200 Subject: [PATCH 386/459] [poincare] Change EmptyLayout height to prevent view jumps. When inserting 1 on an EmptyLayout, the view does not change its height now. Change-Id: I3f5c7ba13c6269f89d069f2ea60cf09abd8a496f --- poincare/src/layout/empty_layout.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 324d5ac67..d74767295 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -34,9 +34,9 @@ protected: void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; private: constexpr static KDCoordinate k_width = 7; - constexpr static KDCoordinate k_height = 13; + constexpr static KDCoordinate k_height = 12; constexpr static KDCoordinate k_marginWidth = 1; - constexpr static KDCoordinate k_marginHeight = 2; + constexpr static KDCoordinate k_marginHeight = 3; constexpr static KDCoordinate k_lineThickness = 1; bool m_isVisible; Color m_color; From 49c17f743a79fceb0bf19ea94126774af0483291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 11:47:10 +0200 Subject: [PATCH 387/459] [escher] Fix ExpressionLayoutFieldScrolling Change-Id: I6f8a265e01bce454732e53affa9ddd01f0e78f08 --- escher/src/expression_layout_field.cpp | 2 +- escher/src/expression_view.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 0949e3e2b..943ea22f4 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -228,8 +228,8 @@ void ExpressionLayoutField::reload() { if (m_delegate && previousSize.height() != newSize.height()) { m_delegate->expressionLayoutFieldDidChangeSize(this); } - scrollToCursor(); m_contentView.cursorPositionChanged(); + scrollToCursor(); markRectAsDirty(bounds()); } diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index a760f635a..48564708f 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -49,7 +49,7 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const { KDPoint ExpressionView::drawingOrigin() const { KDSize expressionSize = m_expressionLayout->size(); - return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), (m_frame.height() - expressionSize.height())/2); + return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), max(0, (m_frame.height() - expressionSize.height())/2)); } KDPoint ExpressionView::absoluteDrawingOrigin() const { From 30bffac99bfff7599e749d63c94ea1a37dfddbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 11:53:51 +0200 Subject: [PATCH 388/459] [escher] Move settings to initializer list Change-Id: I2e915e6290d2fc8a219898ab5369290d220f217d --- escher/src/expression_layout_field_content_view.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index a236db7e1..070c38687 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -5,13 +5,11 @@ using namespace Poincare; ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) : - m_cursor(), + m_cursor(expressionLayout, ExpressionLayoutCursor::Position::Right), m_expressionView(), m_cursorView(), m_isEditing(false) { - m_cursor.setPointedExpressionLayout(expressionLayout); - m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); m_expressionView.setExpressionLayout(expressionLayout); } From 19d5115eaa66cef7ee955e12071f9c653369f948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 16:31:09 +0200 Subject: [PATCH 389/459] [escher] Add margins in ExpressionField Change-Id: I51272682246403f0449be19ff6cc75fd5544ad9c --- escher/include/escher/expression_field.h | 4 +-- .../include/escher/expression_layout_field.h | 5 ++-- escher/include/escher/scroll_view.h | 3 +++ escher/include/escher/scrollable_view.h | 8 ++++-- escher/include/escher/text_field.h | 5 ++-- escher/include/escher/text_input.h | 2 +- escher/src/expression_field.cpp | 25 ++++++------------- escher/src/expression_layout_field.cpp | 10 +++++--- .../expression_layout_field_content_view.cpp | 10 +++----- escher/src/expression_view.cpp | 2 +- escher/src/scrollable_view.cpp | 4 +-- escher/src/text_field.cpp | 15 +++++------ escher/src/text_input.cpp | 5 ++-- poincare/src/layout/expression_layout.cpp | 4 ++- 14 files changed, 51 insertions(+), 51 deletions(-) diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index ae8238b6c..3146cecc9 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -34,8 +34,8 @@ public: private: static constexpr KDCoordinate k_textFieldHeight = 37; - static constexpr KDCoordinate k_leftMargin = 5; - static constexpr KDCoordinate k_verticalExpressionViewMargin = 5; + static constexpr KDCoordinate k_horizontalMargin = 5; + static constexpr KDCoordinate k_verticalMargin = 5; constexpr static int k_separatorThickness = 1; KDCoordinate inputViewHeight() const; KDCoordinate maximalHeight() const; diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index ef053e143..21d07dbdc 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -11,7 +11,7 @@ class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource { public: - ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr); + ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr, KDCoordinate leftMargin = 0, KDCoordinate rightMargin = 0, KDCoordinate topMargin = 0, KDCoordinate bottomMargin = 0, KDColor backgroundColor = KDColorWhite); void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; } bool isEditing() const; void setEditing(bool isEditing); @@ -42,7 +42,7 @@ protected: private: class ContentView : public View { public: - ContentView(Poincare::ExpressionLayout * expressionLayout); + ContentView(Poincare::ExpressionLayout * expressionLayout, KDColor backgroundColor); bool isEditing() const { return m_isEditing; } void setEditing(bool isEditing); void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } @@ -69,6 +69,7 @@ private: bool m_isEditing; }; ContentView m_contentView; + KDCoordinate m_verticalMargin; ExpressionLayoutFieldDelegate * m_delegate; }; diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 9589cfad3..c26342ea9 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -27,6 +27,9 @@ protected: KDRect visibleContentRect(); void layoutSubviews() override; void updateScrollIndicator(); + void setBackgroundColor(KDColor color) { + m_backgroundColor = color; + } KDSize contentSize(); KDCoordinate m_topMargin; #if ESCHER_VIEW_LOGGING diff --git a/escher/include/escher/scrollable_view.h b/escher/include/escher/scrollable_view.h index a6b08bf36..0d3cc844f 100644 --- a/escher/include/escher/scrollable_view.h +++ b/escher/include/escher/scrollable_view.h @@ -1,12 +1,16 @@ #ifndef ESCHER_SCROLLABLE_VIEW_H #define ESCHER_SCROLLABLE_VIEW_H -#include +#include #include +#include class ScrollableView : public Responder, public ScrollView { public: - ScrollableView(Responder * parentResponder, View * view, ScrollViewDataSource * dataSource); + ScrollableView(Responder * parentResponder, View * view, ScrollViewDataSource * dataSource, + KDCoordinate leftMargin = 0, KDCoordinate rightMargin = 0, KDCoordinate topMargin = 0, + KDCoordinate bottomMargin = 0, bool showIndicators = false, bool colorBackground = false, + KDColor backgroundColor = Palette::WallScreen); bool handleEvent(Ion::Events::Event event) override; void reloadScroll(bool forceRelayout = false); protected: diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index 99c0b6178..7c014b02f 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -8,8 +8,9 @@ class TextField : public TextInput { public: TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize, - TextFieldDelegate * delegate = nullptr, bool hasTwoBuffers = true, KDText::FontSize size = KDText::FontSize::Large, float horizontalAlignment = 0.0f, - float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite); + TextFieldDelegate * delegate = nullptr, bool hasTwoBuffers = true, KDText::FontSize size = KDText::FontSize::Large, + float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite, + KDCoordinate leftMargin = 0, KDCoordinate rightMargin = 0, KDCoordinate topMargin = 0, KDCoordinate bottomMargin = 0); void setDelegate(TextFieldDelegate * delegate) { m_delegate = delegate; } void setDraftTextBuffer(char * draftTextBuffer); bool isEditing() const; diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 136fb77b9..280839b3d 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -9,7 +9,7 @@ class TextInput : public ScrollableView, public ScrollViewDataSource { public: - TextInput(Responder * parentResponder, View * contentView); + TextInput(Responder * parentResponder, View * contentView, KDCoordinate leftMargin = 0, KDCoordinate rightMargin = 0, KDCoordinate topMargin = 0, KDCoordinate bottomMargin = 0, KDColor backgroundColor = KDColorWhite); Toolbox * toolbox() override; const char * text() const { return nonEditableContentView()->text(); } void setBackgroundColor(KDColor backgroundColor); diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 1420db5e0..1d92446be 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -5,8 +5,8 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : Responder(parentResponder), View(), - m_textField(parentResponder, textBuffer, textBuffer, textBufferLength, textFieldDelegate, false), - m_expressionLayoutField(parentResponder, layout, expressionLayoutFieldDelegate), + m_textField(parentResponder, textBuffer, textBuffer, textBufferLength, textFieldDelegate, false, KDText::FontSize::Large, 0.0f, 0.5f, KDColorBlack, KDColorWhite, k_horizontalMargin, k_horizontalMargin, 0, 0), + m_expressionLayoutField(parentResponder, layout, expressionLayoutFieldDelegate, k_horizontalMargin, k_horizontalMargin, k_verticalMargin, k_verticalMargin), m_textBuffer(textBuffer), m_textBufferLength(textBufferLength) { @@ -63,7 +63,7 @@ View * ExpressionField::subviewAtIndex(int index) { } void ExpressionField::layoutSubviews() { - KDRect inputViewFrame(k_leftMargin, k_separatorThickness, bounds().width() - k_leftMargin, bounds().height() - k_separatorThickness); + KDRect inputViewFrame(0, k_separatorThickness, bounds().width(), bounds().height() - k_separatorThickness); if (editionIsInTextField()) { m_textField.setFrame(inputViewFrame); m_expressionLayoutField.setFrame(KDRectZero); @@ -81,12 +81,6 @@ void ExpressionField::reload() { void ExpressionField::drawRect(KDContext * ctx, KDRect rect) const { // Draw the separator ctx->fillRect(KDRect(0, 0, bounds().width(), k_separatorThickness), Palette::GreyMiddle); - // Color the left margin - ctx->fillRect(KDRect(0, k_separatorThickness, k_leftMargin, bounds().height() - k_separatorThickness), m_textField.backgroundColor()); - if (!editionIsInTextField()) { - // Color the upper margin - ctx->fillRect(KDRect(0, k_separatorThickness, bounds().width(), k_verticalExpressionViewMargin), m_textField.backgroundColor()); - } } bool ExpressionField::handleEvent(Ion::Events::Event event) { @@ -106,7 +100,7 @@ bool ExpressionField::isEmpty() const { } bool ExpressionField::heightIsMaximal() const { - return inputViewHeight() == k_separatorThickness + k_verticalExpressionViewMargin + maximalHeight(); + return inputViewHeight() == k_separatorThickness + maximalHeight(); } bool ExpressionField::handleEventWithText(const char * text, bool indentation) { @@ -118,15 +112,10 @@ bool ExpressionField::handleEventWithText(const char * text, bool indentation) { } KDCoordinate ExpressionField::inputViewHeight() const { - if (editionIsInTextField()) { - return k_separatorThickness + k_textFieldHeight; - } return k_separatorThickness - + k_verticalExpressionViewMargin - + min(maximalHeight(), - max(k_textFieldHeight, - m_expressionLayoutField.minimalSizeForOptimalDisplay().height() - + k_verticalExpressionViewMargin)); + + (editionIsInTextField() ? k_textFieldHeight : + min(maximalHeight(), + max(k_textFieldHeight, m_expressionLayoutField.minimalSizeForOptimalDisplay().height()))); } KDCoordinate ExpressionField::maximalHeight() const { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 943ea22f4..905c7142a 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -7,9 +7,10 @@ #include #include -ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : - ScrollableView(parentResponder, &m_contentView, this), - m_contentView(expressionLayout), +ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate, KDCoordinate leftMargin, KDCoordinate rightMargin, KDCoordinate topMargin, KDCoordinate bottomMargin, KDColor backgroundColor) : + ScrollableView(parentResponder, &m_contentView, this, leftMargin, rightMargin, 0, 0, false, true, backgroundColor), + m_contentView(expressionLayout, backgroundColor), + m_verticalMargin(topMargin), //FIXME Find a way to add the margins to the scrollableView without un-cetring the ExpressionLayout. m_delegate(delegate) { } @@ -66,7 +67,8 @@ bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events } KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { - return m_contentView.minimalSizeForOptimalDisplay(); + KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); + return KDSize(contentViewSize.width(), contentViewSize.height() + m_verticalMargin); } bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index 070c38687..447f0aee3 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -4,9 +4,9 @@ using namespace Poincare; -ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) : +ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout, KDColor backgroundColor) : m_cursor(expressionLayout, ExpressionLayoutCursor::Position::Right), - m_expressionView(), + m_expressionView(0.0f, 0.5f, KDColorBlack, backgroundColor), m_cursorView(), m_isEditing(false) { @@ -32,11 +32,7 @@ void ExpressionLayoutField::ContentView::clearLayout() { } KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { - KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay(); - KDSize cursorSize = isEditing() ? m_cursorView.minimalSizeForOptimalDisplay() : KDSizeZero; - KDCoordinate resultWidth = expressionViewSize.width() + cursorSize.width(); - KDCoordinate resultHeight = expressionViewSize.height() + cursorSize.height()/2; - return KDSize(resultWidth, resultHeight); + return m_expressionView.minimalSizeForOptimalDisplay(); } View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) { diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 48564708f..a89c3f6bb 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -41,7 +41,7 @@ void ExpressionView::setAlignment(float horizontalAlignment, float verticalAlign } KDSize ExpressionView::minimalSizeForOptimalDisplay() const { - if (m_expressionLayout == nullptr) { + if (m_expressionLayout == nullptr) { return KDSizeZero; } return m_expressionLayout->size(); diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index 702ee0b81..6cc720cb8 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -2,9 +2,9 @@ #include #include -ScrollableView::ScrollableView(Responder * parentResponder, View * view, ScrollViewDataSource * dataSource) : +ScrollableView::ScrollableView(Responder * parentResponder, View * view, ScrollViewDataSource * dataSource, KDCoordinate leftMargin, KDCoordinate rightMargin, KDCoordinate topMargin, KDCoordinate bottomMargin, bool showIndicators, bool colorBackground, KDColor backgroundColor) : Responder(parentResponder), - ScrollView(view, dataSource, 0, 0, 0, 0, false, false), + ScrollView(view, dataSource, topMargin, rightMargin, bottomMargin, leftMargin, showIndicators, colorBackground, backgroundColor), m_manualScrollingOffset(KDPointZero) { } diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index a8374f65a..3af1e1023 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -24,12 +24,12 @@ void TextField::ContentView::setDraftTextBuffer(char * draftTextBuffer) { } void TextField::ContentView::drawRect(KDContext * ctx, KDRect rect) const { - KDColor bckCol = m_backgroundColor; + KDColor backgroundColor = m_backgroundColor; if (m_isEditing) { - bckCol = KDColorWhite; + backgroundColor = KDColorWhite; } - ctx->fillRect(rect, bckCol); - ctx->drawString(text(), characterFrameAtIndex(0).origin(), m_fontSize, m_textColor, bckCol); + ctx->fillRect(bounds(), backgroundColor); + ctx->drawString(text(), characterFrameAtIndex(0).origin(), m_fontSize, m_textColor, backgroundColor); } const char * TextField::ContentView::text() const { @@ -161,9 +161,10 @@ KDRect TextField::ContentView::characterFrameAtIndex(size_t index) const { TextField::TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize, TextFieldDelegate * delegate, bool hasTwoBuffers, KDText::FontSize size, - float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) : - TextInput(parentResponder, &m_contentView), - m_contentView(textBuffer, draftTextBuffer, textBufferSize, size,horizontalAlignment, verticalAlignment, textColor, backgroundColor), + float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor, + KDCoordinate leftMargin, KDCoordinate rightMargin, KDCoordinate topMargin, KDCoordinate bottomMargin) : + TextInput(parentResponder, &m_contentView, leftMargin, rightMargin, topMargin, bottomMargin), + m_contentView(textBuffer, draftTextBuffer, textBufferSize, size, horizontalAlignment, verticalAlignment, textColor, backgroundColor), m_hasTwoBuffers(hasTwoBuffers), m_delegate(delegate) { diff --git a/escher/src/text_input.cpp b/escher/src/text_input.cpp index 67ef0061a..4c24488ca 100644 --- a/escher/src/text_input.cpp +++ b/escher/src/text_input.cpp @@ -57,8 +57,8 @@ void TextInput::ContentView::reloadRectFromCursorPosition(size_t index, bool lin /* TextInput */ -TextInput::TextInput(Responder * parentResponder, View * contentView) : - ScrollableView(parentResponder, contentView, this) +TextInput::TextInput(Responder * parentResponder, View * contentView, KDCoordinate leftMargin, KDCoordinate rightMargin, KDCoordinate topMargin, KDCoordinate bottomMargin , KDColor backgroundColor) : + ScrollableView(parentResponder, contentView, this,leftMargin, rightMargin, topMargin, bottomMargin, false, true, backgroundColor) { } @@ -70,6 +70,7 @@ Toolbox * TextInput::toolbox() { } void TextInput::setBackgroundColor(KDColor backgroundColor) { + ScrollView::setBackgroundColor(backgroundColor); contentView()->setBackgroundColor(backgroundColor); } diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 84cfe4ada..f81c342c4 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -225,7 +225,9 @@ void ExpressionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { // Case: The pointed layout is a child. Move Left. assert(cursor->position() == ExpressionLayoutCursor::Position::Left); bool shouldRecomputeLayout = false; - cursor->cursorOnLeft(&shouldRecomputeLayout); + ExpressionLayoutCursor newCursor = cursor->cursorOnLeft(&shouldRecomputeLayout); + cursor->setPointedExpressionLayout(newCursor.pointedExpressionLayout()); + cursor->setPosition(newCursor.position()); return; } assert(cursor->pointedExpressionLayout() == this); From 4b79bd544e146f7af0ad42eb99eb61fe943efa46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 16:43:49 +0200 Subject: [PATCH 390/459] [escher/poincare] Insert ".10^()" in ELField on EE event. Change-Id: Ic30016c7cb7d2186b6e1b6f0ef1d676f1a512714 --- escher/src/expression_layout_field.cpp | 4 ++++ .../include/poincare/expression_layout_cursor.h | 1 + poincare/src/expression_layout_cursor.cpp | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 905c7142a..bd58ab665 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -151,6 +151,10 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { m_contentView.cursor()->addEmptySquarePowerLayout(); return true; } + if (event == Ion::Events::EE) { + m_contentView.cursor()->addEmptyTenPowerLayout(); + return true; + } if (event.hasText()) { const char * textToInsert = event.text(); if (textToInsert[1] == 0) { diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index c6f31dcd4..77115212f 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -50,6 +50,7 @@ public: void addEmptyPowerLayout(); void addEmptySquareRootLayout(); void addEmptySquarePowerLayout(); + void addEmptyTenPowerLayout(); void addXNTCharLayout(); void insertText(const char * text); void performBackspace(); diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 11e4e4179..c609ff7a3 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -144,6 +144,21 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { setPosition(ExpressionLayoutCursor::Position::Right); } +void ExpressionLayoutCursor::addEmptyTenPowerLayout() { + HorizontalLayout * newSibling = new HorizontalLayout(); + EmptyLayout * powerLayout = new EmptyLayout(); + int numberOfChildren = 4; + ExpressionLayout * childLayouts[numberOfChildren] = { + new CharLayout(Ion::Charset::MiddleDot), + new CharLayout('1'), + new CharLayout('0'), + new VerticalOffsetLayout(powerLayout, VerticalOffsetLayout::Type::Superscript, false)}; + newSibling->addChildrenAtIndex(childLayouts, numberOfChildren, 0, false); + m_pointedExpressionLayout->addSibling(this, newSibling); + setPointedExpressionLayout(powerLayout); + setPosition(ExpressionLayoutCursor::Position::Right); +} + void ExpressionLayoutCursor::addXNTCharLayout() { CharLayout * newChild = new CharLayout(m_pointedExpressionLayout->XNTChar()); m_pointedExpressionLayout->addSibling(this, newChild); From 7244eabd5151cdbe9be3a1df354b35456448c081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 17:17:44 +0200 Subject: [PATCH 391/459] [poincare] Fix cursorAbove/Under in EmptyLayout. Change-Id: I9e5ac6eb557d07644310e391d5cc7bc75408c628 --- poincare/src/layout/empty_layout.cpp | 23 +++++++++++++++++++++++ poincare/src/layout/empty_layout.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index ba04f30d4..d68a86e33 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -45,6 +45,29 @@ ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor cursor, return ExpressionLayoutCursor(); } +ExpressionLayoutCursor EmptyLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return cursorVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +ExpressionLayoutCursor EmptyLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + return cursorVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +ExpressionLayoutCursor EmptyLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + assert(cursor.pointedExpressionLayout() == this); + ExpressionLayoutCursor cursorResult = direction == VerticalDirection::Up ? + ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : + ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + if (cursorResult.isDefined()) { + return cursorResult; + } + ExpressionLayoutCursor::Position newPosition = cursor.position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left; + cursor.setPosition(newPosition); + return direction == VerticalDirection::Up ? + ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : + ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index d74767295..70f48333a 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -17,6 +17,8 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } @@ -38,6 +40,7 @@ private: constexpr static KDCoordinate k_marginWidth = 1; constexpr static KDCoordinate k_marginHeight = 3; constexpr static KDCoordinate k_lineThickness = 1; + ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); bool m_isVisible; Color m_color; }; From 87becaa854a0254ccdd06dc04d0c9394cbaebcd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 17:34:48 +0200 Subject: [PATCH 392/459] [escher] The layout should not change if ELField cannot handle event. Change-Id: Ie3a59400a054680aa8cc42ab755708aa2fa19e2d --- escher/src/expression_layout_field.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index bd58ab665..f435d54e9 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -59,6 +59,7 @@ bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { } return true; } + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); return false; } From 8801b9f383ea7f53c81b8438f701c9600a0f769b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 17:52:11 +0200 Subject: [PATCH 393/459] [apps/code] Fix cursor position when inserting Python commands Change-Id: I2f5cdc72220cc61b0c8830d746c63f705a7c928e --- apps/code/catalog.universal.i18n | 12 ++++++------ apps/code/python_toolbox.cpp | 2 +- apps/code/toolbox.universal.i18n | 20 ++++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/code/catalog.universal.i18n b/apps/code/catalog.universal.i18n index bcb3233f1..afeeb6310 100644 --- a/apps/code/catalog.universal.i18n +++ b/apps/code/catalog.universal.i18n @@ -19,7 +19,7 @@ PythonCommandBin = "bin(x)" PythonCommandCeil = "ceil(x)" PythonCommandChoice = "choice(list)" PythonCommandCmathFunction = "cmath.function" -PythonCommandCmathFunctionWithoutArg = "cmath." +PythonCommandCmathFunctionWithoutArg = "cmath.•" PythonCommandColor = "color(r,g,b)" PythonCommandComplex = "complex(a,b)" PythonCommandCopySign = "copysign(x,y)" @@ -57,7 +57,7 @@ PythonCommandIsFinite = "isfinite(x)" PythonCommandIsInfinite = "isinf(x)" PythonCommandIsNaN = "isnan(x)" PythonCommandKandinskyFunction = "kandinsky.function" -PythonCommandKandinskyFunctionWithoutArg = "kandinsky." +PythonCommandKandinskyFunctionWithoutArg = "kandinsky.•" PythonCommandLdexp = "ldexp(x,i)" PythonCommandLgamma = "lgamma(x)" PythonCommandLength = "len(object)" @@ -66,7 +66,7 @@ PythonCommandLog10 = "log10(x)" PythonCommandLog2 = "log2(x)" PythonCommandLogComplex = "log(z,a)" PythonCommandMathFunction = "math.function" -PythonCommandMathFunctionWithoutArg = "math." +PythonCommandMathFunctionWithoutArg = "math.•" PythonCommandMax = "max(list)" PythonCommandMin = "min(list)" PythonCommandModf = "modf(x)" @@ -80,7 +80,7 @@ PythonCommandRadians = "radians(x)" PythonCommandRandom = "random()" PythonCommandRandint = "randint(a,b)" PythonCommandRandomFunction = "random.function" -PythonCommandRandomFunctionWithoutArg = "random." +PythonCommandRandomFunctionWithoutArg = "random.•" PythonCommandRandrange = "randrange(start, stop)" PythonCommandRangeStartStop = "range(start, stop)" PythonCommandRangeStop = "range(stop)" @@ -100,6 +100,6 @@ PythonCommandTanh = "tanh(x)" PythonCommandTrunc = "trunc(x)" PythonCommandImag = "z.imag" PythonCommandReal = "z.real" -PythonCommandImagWithoutArg = "().imag" -PythonCommandRealWithoutArg = "().real" +PythonCommandImagWithoutArg = "•.imag" +PythonCommandRealWithoutArg = "•.real" PythonCommandUniform = "uniform(a,b)" diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp index 3ceeaf2ad..85b6d0a93 100644 --- a/apps/code/python_toolbox.cpp +++ b/apps/code/python_toolbox.cpp @@ -293,7 +293,7 @@ bool PythonToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { const char * editedText = I18n::translate(node->insertedText()); int strippedEditedTextMaxLength = strlen(editedText)+1; char strippedEditedText[strippedEditedTextMaxLength]; - Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength); + Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength, true); sender()->handleEventWithText(strippedEditedText, true); app()->dismissModalViewController(); return true; diff --git a/apps/code/toolbox.universal.i18n b/apps/code/toolbox.universal.i18n index 86b596a02..680a88d50 100644 --- a/apps/code/toolbox.universal.i18n +++ b/apps/code/toolbox.universal.i18n @@ -20,25 +20,25 @@ NonEqualityCondition = "!=" NonEqualityConditionWithArg = "x!=y" EqualityCondition = "==" EqualityConditionWithArg = "x==y" -WhileLoop = "while ():\n " +WhileLoop = "while •:\n " WhileLoopWithArg = "while condition:\n instruction" -IfOrIfElseStatement = "if () or ():\n \nelse:\n " +IfOrIfElseStatement = "if • or :\n \nelse:\n " IfOrIfElseStatementWithArg = "if condition1 or condition2:\n instruction1\nelse:\n instruction2" -IfAndIfElseStatement = "if () and ():\n \nelse:\n " +IfAndIfElseStatement = "if • and :\n \nelse:\n " IfAndIfElseStatementWithArg = "if condition1 and condition2:\n instruction1\nelse:\n instruction2" -IfElifElseStatement = "if ():\n \nelif ():\n \nelse:\n " +IfElifElseStatement = "if •:\n \nelif :\n \nelse:\n " IfElifElseStatementWithArg = "if condition1:\n instruction1\nelif condition2:\n instruction2\nelse:\n instruction3" -IfThenStatement= "if ():\n " +IfThenStatement= "if •:\n " IfThenStatementWithArg = "if condition:\n instruction" -IfElseStatement = "if ():\n \nelse:\n " +IfElseStatement = "if •:\n \nelse:\n " IfElseStatementWithArg = "if condition:\n instruction1\nelse:\n instruction2" -ForInListLoop = "for i in ():\n " +ForInListLoop = "for i in •:\n " ForInListLoopWithArg = "for i in list:\n instruction" -ForInRange3ArgsLoop = "for i in range(,,):\n " +ForInRange3ArgsLoop = "for i in range(•,,):\n " ForInRange3ArgsLoopWithArg = "for i in range(start, stop, step):\n instruction" -ForInRange2ArgsLoop = "for i in range(,):\n " +ForInRange2ArgsLoop = "for i in range(•,):\n " ForInRange2ArgsLoopWithArg = "for i in range(start, stop):\n instruction" -ForInRange1ArgLoop = "for i in range():\n " +ForInRange1ArgLoop = "for i in range(•):\n " ForInRange1ArgLoopWithArg = "for i in range(size):\n instruction" PythonCommandDef = "def •():\n " PythonCommandDefWithArg = "def function(x):" From acf79de1d49456992cbe3490403ddb10178ac2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 26 Apr 2018 18:11:10 +0200 Subject: [PATCH 394/459] [escher] Better cursor scroll (scroll to see the cursor baseline) Change-Id: I4ddd1818d783d6f5f22c8b6f1e17ad09aea77527 --- escher/src/expression_layout_field.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index f435d54e9..f1699d877 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -28,7 +28,16 @@ void ExpressionLayoutField::clearLayout() { } void ExpressionLayoutField::scrollToCursor() { + // Show the whole cursor scrollToContentRect(m_contentView.cursorRect(), true); + // Show the cursor area around its baseline + Poincare::ExpressionLayoutCursor * cursor = m_contentView.cursor(); + KDCoordinate cursorBaseline = cursor->baseline(); + KDCoordinate underBaseline = m_contentView.cursorRect().height() - cursorBaseline; + KDCoordinate minAroundBaseline = min(cursorBaseline, underBaseline); + minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); + KDRect balancedRect(0, m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, 1, 2 * minAroundBaseline); + scrollToContentRect(balancedRect, true); } Toolbox * ExpressionLayoutField::toolbox() { From bc40c21f6892b1e627b51f98e98ff974f8a9df06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 27 Apr 2018 09:47:26 +0200 Subject: [PATCH 395/459] [poincare] Fix Fraction layout navigation. Change-Id: I22bf36367c68c8b457bd224f02a6106f53da0146 --- poincare/src/layout/fraction_layout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index f29aed42e..044aed5bb 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -142,7 +142,7 @@ ExpressionLayoutCursor FractionLayout::cursorAbove(ExpressionLayoutCursor cursor // If the cursor is Left or Right, move it to the numerator. if (cursor.pointedExpressionLayout() == this){ assert(numeratorLayout() != nullptr); - return numeratorLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); + return ExpressionLayoutCursor(numeratorLayout(), cursor.position()); } return ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); } @@ -156,7 +156,7 @@ ExpressionLayoutCursor FractionLayout::cursorUnder(ExpressionLayoutCursor cursor // If the cursor is Left or Right, move it to the denominator. if (cursor.pointedExpressionLayout() == this){ assert(denominatorLayout() != nullptr); - return denominatorLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); + return ExpressionLayoutCursor(denominatorLayout(), cursor.position()); } return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } From c8a95b6acd917099fcd8bd817a98b60f3df195d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 30 Apr 2018 17:50:17 +0200 Subject: [PATCH 396/459] [escher] ELField size should take into account the cursor. Else, when it is on the extrema, it does not appear. Change-Id: I2a8620ef38773e51d2087f842ec2dade2d8e0bac --- escher/src/expression_layout_field.cpp | 2 +- escher/src/expression_layout_field_content_view.cpp | 5 +++-- poincare/include/poincare/expression_layout_cursor.h | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index f1699d877..ed6573fb3 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -36,7 +36,7 @@ void ExpressionLayoutField::scrollToCursor() { KDCoordinate underBaseline = m_contentView.cursorRect().height() - cursorBaseline; KDCoordinate minAroundBaseline = min(cursorBaseline, underBaseline); minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); - KDRect balancedRect(0, m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, 1, 2 * minAroundBaseline); + KDRect balancedRect(0, m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, Poincare::ExpressionLayoutCursor::k_cursorWidth, 2 * minAroundBaseline); scrollToContentRect(balancedRect, true); } diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index 447f0aee3..f8a76b53b 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -32,7 +32,8 @@ void ExpressionLayoutField::ContentView::clearLayout() { } KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { - return m_expressionView.minimalSizeForOptimalDisplay(); + KDSize evSize = m_expressionView.minimalSizeForOptimalDisplay(); + return KDSize(evSize.width(), evSize.height() + ExpressionLayoutCursor::k_cursorWidth); } View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) { @@ -65,5 +66,5 @@ void ExpressionLayoutField::ContentView::layoutCursorSubview() { cursorX += pointedLayout->size().width(); } KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayout->baseline() - m_cursor.baseline()); - m_cursorView.setFrame(KDRect(cursorTopLeftPosition, 1, m_cursor.cursorHeight())); + m_cursorView.setFrame(KDRect(cursorTopLeftPosition, ExpressionLayoutCursor::k_cursorWidth, m_cursor.cursorHeight())); } diff --git a/poincare/include/poincare/expression_layout_cursor.h b/poincare/include/poincare/expression_layout_cursor.h index 77115212f..902062e68 100644 --- a/poincare/include/poincare/expression_layout_cursor.h +++ b/poincare/include/poincare/expression_layout_cursor.h @@ -9,6 +9,8 @@ class ExpressionLayout; class ExpressionLayoutCursor { public: + constexpr static KDCoordinate k_cursorWidth = 1; + enum class Position { Left, Right From 80d50d2a79973b77ac238e33e09bd58f66047abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 30 Apr 2018 18:04:33 +0200 Subject: [PATCH 397/459] [escher] Fix horizontal scroll in ELField Change-Id: Id2502f84514a1aeb76c84f7648dea110b0676ee4 --- escher/src/expression_layout_field.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index ed6573fb3..f67558707 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -36,7 +36,7 @@ void ExpressionLayoutField::scrollToCursor() { KDCoordinate underBaseline = m_contentView.cursorRect().height() - cursorBaseline; KDCoordinate minAroundBaseline = min(cursorBaseline, underBaseline); minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); - KDRect balancedRect(0, m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, Poincare::ExpressionLayoutCursor::k_cursorWidth, 2 * minAroundBaseline); + KDRect balancedRect(m_contentView.cursorRect().x(), m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, Poincare::ExpressionLayoutCursor::k_cursorWidth, 2 * minAroundBaseline); scrollToContentRect(balancedRect, true); } From 951f31e951d56b1c974d6dc9d0057754bf0c56c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 2 May 2018 10:16:52 +0200 Subject: [PATCH 398/459] [escher] Fix bug in CursorIndexInCommand (when bufferSize = 0) Change-Id: I3494ce7faeb6925e7ed6c7b532d34172420c4620 --- escher/src/text_input_helpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/escher/src/text_input_helpers.cpp b/escher/src/text_input_helpers.cpp index dd0307d42..3a878afbe 100644 --- a/escher/src/text_input_helpers.cpp +++ b/escher/src/text_input_helpers.cpp @@ -5,8 +5,8 @@ namespace TextInputHelpers { int CursorIndexInCommand(const char * text) { - size_t textLength = strlen(text); - for (size_t i = 0; i < textLength - 1; i++) { + int textLength = strlen(text); + for (int i = 0; i < textLength - 1; i++) { if (text[i] == '\'' && text[i+1] == '\'') { return i + 1; } else if (text[i] == Ion::Charset::Empty) { From 21f083d926ba0532721c7ab9c27b6d1c81991d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 2 May 2018 10:56:32 +0200 Subject: [PATCH 399/459] [escher] Fix Graph/Sequence cursor display in 2D edition. When inserting a layout, the ELField was not put in Edition mode and the cursor did not appear. Change-Id: I47154829bda4a51201a4b1417ce86cae4099c1b9 --- escher/src/expression_layout_field.cpp | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index f67558707..d4eb36739 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -52,6 +52,9 @@ bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded(); bool moveEventChangedLayout = false; if (privateHandleMoveEvent(event, &moveEventChangedLayout)) { + if (!isEditing()) { + setEditing(true); + } shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout; didHandleEvent = true; } else if (privateHandleEvent(event)) { @@ -137,35 +140,57 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { return true; } if (event == Ion::Events::Back && isEditing()) { + clearLayout(); setEditing(false); m_delegate->expressionLayoutFieldDidAbortEditing(this); return true; } if (event == Ion::Events::Division) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addFractionLayoutAndCollapseSiblings(); return true; } if (event == Ion::Events::Exp) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addEmptyExponentialLayout(); return true; } if (event == Ion::Events::Power) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addEmptyPowerLayout(); return true; } if (event == Ion::Events::Sqrt) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addEmptySquareRootLayout(); return true; } if (event == Ion::Events::Square) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addEmptySquarePowerLayout(); return true; } if (event == Ion::Events::EE) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->addEmptyTenPowerLayout(); return true; } if (event.hasText()) { + if (!isEditing()) { + setEditing(true); + } const char * textToInsert = event.text(); if (textToInsert[1] == 0) { if (textToInsert[0] == Ion::Charset::MultiplicationSign) { @@ -182,6 +207,9 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { return true; } if (event == Ion::Events::Backspace) { + if (!isEditing()) { + setEditing(true); + } m_contentView.cursor()->performBackspace(); return true; } From 7ea0ddb2a7ced5424a960490731a07ed22c4a2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 2 May 2018 11:05:08 +0200 Subject: [PATCH 400/459] [escher] OnFinishEditing, clear the layout. The layout should never be deleted + this fixes the ELField size that might stay big once emptied (e.g. 1 / 2 OK would leave an empty ELField, but with a big vertical size). Change-Id: I3971115d3bad48ce36a449e01bd12d5d8229ca4c --- escher/src/expression_layout_field.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index d4eb36739..996463971 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -126,10 +126,7 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { char buffer[bufferSize]; m_contentView.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize); if (m_delegate->expressionLayoutFieldDidFinishEditing(this, buffer, event)) { - delete m_contentView.expressionView()->expressionLayout(); - Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout(); - m_contentView.editableExpressionView()->setExpressionLayout(newLayout); - m_contentView.cursor()->setPointedExpressionLayout(newLayout); + clearLayout(); } return true; } From 4576b88f81071f00de0199079965571fedfb4106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 2 May 2018 14:46:10 +0200 Subject: [PATCH 401/459] [escher] Fix cursor display in ELField, when the cursor is on the right Change-Id: I44e9bc53440b4ce7b074a94b733a636d3582ac3c --- escher/src/expression_layout_field_content_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index f8a76b53b..1a75ec09b 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -33,7 +33,7 @@ void ExpressionLayoutField::ContentView::clearLayout() { KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { KDSize evSize = m_expressionView.minimalSizeForOptimalDisplay(); - return KDSize(evSize.width(), evSize.height() + ExpressionLayoutCursor::k_cursorWidth); + return KDSize(evSize.width() + ExpressionLayoutCursor::k_cursorWidth, evSize.height()); } View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) { From f660c7750c8fe54f0073441afe98d9b98a17a9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 May 2018 14:14:02 +0200 Subject: [PATCH 402/459] [ion] Fix linear mode cursor position when pressing "cos" for instance Change-Id: I7a39f875cc85eedc336818fcfe5b125c74a8960c --- ion/src/shared/events.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/ion/src/shared/events.cpp b/ion/src/shared/events.cpp index 150cecdc6..5c29bb1b6 100644 --- a/ion/src/shared/events.cpp +++ b/ion/src/shared/events.cpp @@ -25,21 +25,32 @@ private: #define U() EventData::Undefined() #define T(x) EventData::Text(x) -static constexpr const char k_pi[2] = {Ion::Charset::SmallPi, 0}; -static constexpr const char k_root[4] = {Ion::Charset::Root, '(', ')', 0}; +static constexpr const char k_exponential[6] = {Ion::Charset::Exponential, '^', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_naperianLogarithm[6] = {'l', 'n', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_logarithm[7] = {'l', 'o', 'g', '(', Ion::Charset::Empty, ')', 0}; static constexpr const char k_complexI[2] = {Ion::Charset::IComplex, 0}; -static constexpr const char k_exponential[5] = {Ion::Charset::Exponential, '^', '(', ')', 0}; -static constexpr const char k_sto[2] = {Ion::Charset::Sto, 0}; -static constexpr const char k_exponent[2] = {Ion::Charset::Exponent, 0}; + +static constexpr const char k_sine[7] = {'s', 'i', 'n', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_cosine[7] = {'c', 'o', 's', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_tangent[7] = {'t', 'a', 'n', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_pi[2] = {Ion::Charset::SmallPi, 0}; +static constexpr const char k_root[5] = {Ion::Charset::Root, '(', Ion::Charset::Empty, ')', 0}; + static constexpr const char k_multiplicationSign[2] = {Ion::Charset::MultiplicationSign, 0}; +static constexpr const char k_exponent[2] = {Ion::Charset::Exponent, 0}; +static constexpr const char k_sto[2] = {Ion::Charset::Sto, 0}; + +static constexpr const char k_arcSine[8] = {'a', 's', 'i', 'n', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_arcCosine[8] = {'a', 'c', 'o', 's', '(', Ion::Charset::Empty, ')', 0}; +static constexpr const char k_arcTangent[8] = {'a', 't', 'a', 'n', '(', Ion::Charset::Empty, ')', 0}; static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Plain TL(), TL(), TL(), TL(), TL(), TL(), TL(), TL(), U(), U(), U(), U(), TL(), TL(), TL(), TL(), TL(), TL(), - T(k_exponential), T("ln()"), T("log()"), T(k_complexI), T(","), T("^"), - T("sin()"), T("cos()"), T("tan()"), T(k_pi), T(k_root), T("^2"), + T(k_exponential), T(k_naperianLogarithm), T(k_logarithm), T(k_complexI), T(","), T("^"), + T(k_sine), T(k_cosine), T(k_tangent), T(k_pi), T(k_root), T("^2"), T("7"), T("8"), T("9"), T("("), T(")"), U(), T("4"), T("5"), T("6"), T(k_multiplicationSign), T("/"), U(), T("1"), T("2"), T("3"), T("+"), T("-"), U(), @@ -49,7 +60,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), U(), U(), U(), U(), U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T(k_sto), - T("asin()"), T("acos()"), T("atan()"), T("="), T("<"), T(">"), + T(k_arcSine), T(k_arcCosine), T(k_arcTangent), T("="), T("<"), T(">"), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), From 6e409cace68579a1479de0cc52169ca826c97084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 May 2018 14:22:34 +0200 Subject: [PATCH 403/459] [poincare] Handle Charset::Empty during 2D text insertion Change-Id: Ie3aee986045d0e4eced06b909ab3bcf22f31ec59 --- poincare/src/expression_layout_cursor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index c609ff7a3..9733294e6 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -174,6 +174,9 @@ void ExpressionLayoutCursor::insertText(const char * text) { ExpressionLayout * newChild = nullptr; ExpressionLayout * pointedChild = nullptr; for (int i = 0; i < textLength; i++) { + if (text[i] == Ion::Charset::Empty) { + continue; + } if (text[i] == '(') { newChild = new LeftParenthesisLayout(); if (pointedChild == nullptr) { From 66d2eb0e7a844624ca3eecca0197d37f5daa8c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 7 May 2018 14:24:44 +0200 Subject: [PATCH 404/459] [poincare] Handle MultiplicationSign in ExpressionLayoutCursor::insertText Change-Id: Ie2dd1c48cedbb3f80eac4db1ff9ffeeefb1ede71 --- escher/src/expression_layout_field.cpp | 13 +++---------- poincare/src/expression_layout_cursor.cpp | 4 +++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 996463971..bad46ef9a 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -189,16 +189,9 @@ bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { setEditing(true); } const char * textToInsert = event.text(); - if (textToInsert[1] == 0) { - if (textToInsert[0] == Ion::Charset::MultiplicationSign) { - const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; - m_contentView.cursor()->insertText(middleDotString); - return true; - } - if (textToInsert[0] == '[' || textToInsert[0] == ']') { - m_contentView.cursor()->addEmptyMatrixLayout(); - return true; - } + if (textToInsert[1] == 0 && (textToInsert[0] == '[' || textToInsert[0] == ']')) { + m_contentView.cursor()->addEmptyMatrixLayout(); + return true; } m_contentView.cursor()->insertText(textToInsert); return true; diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 9733294e6..e68f6762a 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -177,7 +177,9 @@ void ExpressionLayoutCursor::insertText(const char * text) { if (text[i] == Ion::Charset::Empty) { continue; } - if (text[i] == '(') { + if (text[i] == Ion::Charset::MultiplicationSign) { + newChild = new CharLayout(Ion::Charset::MiddleDot); + } else if (text[i] == '(') { newChild = new LeftParenthesisLayout(); if (pointedChild == nullptr) { pointedChild = newChild; From 3fcfbcf8335cd25870359a81eae6366880f4e0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 12:02:21 +0200 Subject: [PATCH 405/459] [poincare] Fix DynamicLayoutHierarchy::mergeChildrenAtIndex Change-Id: I579d3daf9791e06474a66071b2b2be0908a8cf02 --- poincare/src/layout/dynamic_layout_hierarchy.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 848bd3fa3..39f48e64f 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -37,11 +37,15 @@ DynamicLayoutHierarchy::~DynamicLayoutHierarchy() { } void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { + int indexForInsertion = index; int indexOfEL = indexOfChild(eL); if (indexOfEL >= 0) { removeChildAtIndex(indexOfEL, false); + if (indexOfEL < index) { + indexForInsertion--; + } } - addChildrenAtIndex(eL->children(), eL->numberOfChildren(), index, removeEmptyChildren); + addChildrenAtIndex(eL->children(), eL->numberOfChildren(), indexForInsertion, removeEmptyChildren); eL->detachChildren(); delete eL; } From bf3b26439d9bfe10dad2bfd25f8759c04e1e2cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 12:03:33 +0200 Subject: [PATCH 406/459] [poincare] Coding style Change-Id: I0de1e558b3b9483456ccca5b8d42b6d0b9f2e30e --- poincare/src/layout/binomial_coefficient_layout.cpp | 3 ++- poincare/src/layout/dynamic_layout_hierarchy.cpp | 10 +++++----- poincare/src/layout/static_layout_hierarchy.cpp | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index e5216be40..fa097578f 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -15,7 +15,8 @@ extern "C" { namespace Poincare { ExpressionLayout * BinomialCoefficientLayout::clone() const { - return new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); + BinomialCoefficientLayout * layout = new BinomialCoefficientLayout(const_cast(this)->nLayout(), const_cast(this)->kLayout(), true); + return layout; } ExpressionLayoutCursor BinomialCoefficientLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 39f48e64f..5e0b9a57c 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -21,7 +21,7 @@ DynamicLayoutHierarchy::DynamicLayoutHierarchy(const ExpressionLayout * const * { assert(children != nullptr); m_children = new const ExpressionLayout * [numberOfChildren]; - for (int i=0; iclone(); @@ -55,10 +55,10 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * const ExpressionLayout ** newOperands = new const ExpressionLayout * [m_numberOfChildren+numberOfOperands]; int currentIndex = 0; assert(indexForInsertion <= m_numberOfChildren); - for (int i=0; iisEmpty() || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftSibling())) @@ -67,7 +67,7 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * newOperands[currentIndex++] = operands[i]; } } - for (int i=indexForInsertion; i= 0 && index <= m_numberOfChildren); const ExpressionLayout ** newChildren = new const ExpressionLayout * [m_numberOfChildren+1]; int j = 0; - for (int i=0; i<=m_numberOfChildren; i++) { + for (int i = 0; i <= m_numberOfChildren; i++) { if (i == index) { child->setParent(this); newChildren[i] = child; diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp index 224902945..3d69b4384 100644 --- a/poincare/src/layout/static_layout_hierarchy.cpp +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -51,7 +51,7 @@ template void StaticLayoutHierarchy::build(const ExpressionLayout * const * operands, int numberOfOperands, bool cloneOperands) { assert(operands != nullptr); assert(numberOfOperands <= T); - for (int i=0; i < numberOfOperands; i++) { + for (int i = 0; i < numberOfOperands; i++) { if (cloneOperands && operands[i] != nullptr) { m_children[i] = operands[i]->clone(); } else { From 8d5c83fef3993bc62c009496e313961355f4c9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 12:03:55 +0200 Subject: [PATCH 407/459] [poincare] Fix/add assertions Change-Id: I642bf20ae2bb75ea5a65898e11390f5337363b3b --- poincare/src/layout/dynamic_layout_hierarchy.cpp | 3 ++- poincare/src/layout/expression_layout.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 5e0b9a57c..dac5cf894 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -54,7 +54,7 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * assert(numberOfOperands > 0); const ExpressionLayout ** newOperands = new const ExpressionLayout * [m_numberOfChildren+numberOfOperands]; int currentIndex = 0; - assert(indexForInsertion <= m_numberOfChildren); + assert(indexForInsertion >= 0 && indexForInsertion <= m_numberOfChildren); for (int i = 0; i < indexForInsertion; i++) { newOperands[currentIndex++] = m_children[i]; } @@ -96,6 +96,7 @@ bool DynamicLayoutHierarchy::addChildAtIndex(ExpressionLayout * child, int index } void DynamicLayoutHierarchy::removeChildAtIndex(int index, bool deleteAfterRemoval) { + assert(index >= 0 && index < m_numberOfChildren); if (deleteAfterRemoval) { delete m_children[index]; } else { diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index f81c342c4..bee2a81db 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -183,7 +183,7 @@ void ExpressionLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChi } void ExpressionLayout::detachChild(const ExpressionLayout * e) { - assert(indexOfChild(e) >= 0); + assert(hasChild(e)); detachChildAtIndex(indexOfChild(e)); } From 9b1d0e67c0bfcbf9d6274f61e08f348e0d906d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 12:04:31 +0200 Subject: [PATCH 408/459] [poincare] Clearer ExpressionLayout::indexOfChild Change-Id: Ibe7f1b616ccd3b7951e6334682d28116d3234f77 --- poincare/src/layout/expression_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index bee2a81db..21c6e64b8 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -91,7 +91,7 @@ bool ExpressionLayout::hasChild(const ExpressionLayout * child) const { } int ExpressionLayout::indexOfChild(const ExpressionLayout * child) const { - if (child == nullptr) { + if (child == nullptr || !hasChild(child)) { return -1; } for (int i = 0; i < numberOfChildren(); i++) { @@ -99,6 +99,7 @@ int ExpressionLayout::indexOfChild(const ExpressionLayout * child) const { return i; } } + assert(false); return -1; } From 2fd332fba52c792e3e10799f61a24de04c6c94c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 15:43:41 +0200 Subject: [PATCH 409/459] [poincare] Fix background fill in ExpressionField. Change-Id: If12a043525cafe7b98015df88ad144057a5ffdcb --- escher/include/escher/expression_layout_field.h | 6 ++++-- escher/include/escher/scroll_view.h | 2 +- escher/src/expression_field.cpp | 5 +++++ escher/src/expression_layout_field.cpp | 9 +++++++-- escher/src/expression_layout_field_content_view.cpp | 8 ++++++-- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 6ca307243..51692bf45 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -11,7 +11,7 @@ class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource { public: - ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr, KDColor backgroundColor = KDColorWhite); + ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr); void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; } bool isEditing() const; void setEditing(bool isEditing); @@ -23,6 +23,7 @@ public: bool handleEventWithText(const char * text, bool indentation = false) override; Poincare::ExpressionLayout * expressionLayout(); char XNTChar(); + void setBackgroundColor(KDColor c) override; /* Responder */ Toolbox * toolbox() override; @@ -42,9 +43,10 @@ protected: private: class ContentView : public View { public: - ContentView(Poincare::ExpressionLayout * expressionLayout, KDColor backgroundColor); + ContentView(Poincare::ExpressionLayout * expressionLayout); bool isEditing() const { return m_isEditing; } void setEditing(bool isEditing); + void setBackgroundColor(KDColor c); void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } void cursorPositionChanged(); KDRect cursorRect(); diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index d8b27e61d..097913aa1 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -29,7 +29,7 @@ public: bool showsIndicators() const { return m_showsIndicators; } void setColorsBackground(bool c) { m_colorsBackground = c; } bool colorsBackground() const { return m_colorsBackground; } - void setBackgroundColor(KDColor c) { m_backgroundColor = c; } + virtual void setBackgroundColor(KDColor c) { m_backgroundColor = c; } KDColor backgroundColor() const { return m_backgroundColor; } ScrollViewIndicator * verticalScrollIndicator() { return &m_verticalScrollIndicator; } diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 89ce0add0..e3512576c 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -10,9 +10,14 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, m_textBuffer(textBuffer), m_textBufferLength(textBufferLength) { + // Initialize text field m_textField.setMargins(0, k_horizontalMargin, 0, k_horizontalMargin); + m_textField.setBackgroundColor(KDColorWhite); + m_textField.setColorsBackground(true); + // Initialize layout field m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); m_expressionLayoutField.setBackgroundColor(KDColorWhite); + m_expressionLayoutField.setColorsBackground(true); } void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index c4bff58db..e7e6e0985 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -7,9 +7,9 @@ #include #include -ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate, KDColor backgroundColor) : +ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : ScrollableView(parentResponder, &m_contentView, this), - m_contentView(expressionLayout, backgroundColor), + m_contentView(expressionLayout), m_delegate(delegate) { } @@ -322,3 +322,8 @@ Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() { char ExpressionLayoutField::XNTChar() { return m_contentView.cursor()->pointedExpressionLayout()->XNTChar(); } + +void ExpressionLayoutField::setBackgroundColor(KDColor c) { + ScrollableView::setBackgroundColor(c); + m_contentView.setBackgroundColor(c); +} diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp index 1a75ec09b..8b4c5b0d6 100644 --- a/escher/src/expression_layout_field_content_view.cpp +++ b/escher/src/expression_layout_field_content_view.cpp @@ -4,9 +4,9 @@ using namespace Poincare; -ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout, KDColor backgroundColor) : +ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) : m_cursor(expressionLayout, ExpressionLayoutCursor::Position::Right), - m_expressionView(0.0f, 0.5f, KDColorBlack, backgroundColor), + m_expressionView(0.0f, 0.5f, KDColorBlack, KDColorWhite), m_cursorView(), m_isEditing(false) { @@ -19,6 +19,10 @@ void ExpressionLayoutField::ContentView::setEditing(bool isEditing) { layoutSubviews(); } +void ExpressionLayoutField::ContentView::setBackgroundColor(KDColor c) { + m_expressionView.setBackgroundColor(c); +} + void ExpressionLayoutField::ContentView::cursorPositionChanged() { layoutCursorSubview(); } From 3aeb5b9eef10dd07ad750b091e25d554e9f85609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 16:24:13 +0200 Subject: [PATCH 410/459] [poincare] Fix Layout Field vertical margins. Change-Id: I36c90574aca915d0f1cb803948b8c85cd28852ab --- escher/include/escher/expression_layout_field.h | 3 ++- escher/include/escher/scroll_view.h | 2 +- escher/src/expression_field.cpp | 2 +- escher/src/expression_layout_field.cpp | 7 ++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 51692bf45..89de691c0 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -24,6 +24,7 @@ public: Poincare::ExpressionLayout * expressionLayout(); char XNTChar(); void setBackgroundColor(KDColor c) override; + void setTopMargin(KDCoordinate m) override; /* Responder */ Toolbox * toolbox() override; @@ -71,7 +72,7 @@ private: bool m_isEditing; }; ContentView m_contentView; - KDCoordinate m_verticalMargin; + KDCoordinate m_verticalTopMargin; ExpressionLayoutFieldDelegate * m_delegate; }; diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index 097913aa1..f0f54347a 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -10,7 +10,7 @@ public: ScrollView(View * contentView, ScrollViewDataSource * dataSource); void drawRect(KDContext * ctx, KDRect rect) const override; - void setTopMargin(KDCoordinate m) { m_topMargin = m; } + virtual void setTopMargin(KDCoordinate m) { m_topMargin = m; } KDCoordinate topMargin() const { return m_topMargin; } void setRightMargin(KDCoordinate m) { m_rightMargin = m; } KDCoordinate rightMargin() const { return m_rightMargin; } diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index e3512576c..7e6657076 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -15,7 +15,7 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, m_textField.setBackgroundColor(KDColorWhite); m_textField.setColorsBackground(true); // Initialize layout field - m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); + m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, 0, k_horizontalMargin); m_expressionLayoutField.setBackgroundColor(KDColorWhite); m_expressionLayoutField.setColorsBackground(true); } diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index e7e6e0985..19d949662 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -10,6 +10,7 @@ ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : ScrollableView(parentResponder, &m_contentView, this), m_contentView(expressionLayout), + m_verticalTopMargin(0), m_delegate(delegate) { } @@ -80,7 +81,7 @@ bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); - return KDSize(contentViewSize.width(), contentViewSize.height() + m_verticalMargin); + return KDSize(contentViewSize.width(), contentViewSize.height() + m_verticalTopMargin); } bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { @@ -327,3 +328,7 @@ void ExpressionLayoutField::setBackgroundColor(KDColor c) { ScrollableView::setBackgroundColor(c); m_contentView.setBackgroundColor(c); } + +void ExpressionLayoutField::setTopMargin(KDCoordinate m) { + m_verticalTopMargin = m; +} From 7b6fdf6a1ce673e2b4d55b01f54b55be715ca58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 17:32:55 +0200 Subject: [PATCH 411/459] [escher] Fix ScrollableView content view size. Change-Id: I531236e7527b3922dac81067d41024e0c5d6bf88 --- escher/include/escher/expression_layout_field.h | 2 -- escher/src/expression_field.cpp | 4 ++-- escher/src/expression_layout_field.cpp | 7 +------ escher/src/scrollable_view.cpp | 4 ++-- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 89de691c0..83e8f4f95 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -24,7 +24,6 @@ public: Poincare::ExpressionLayout * expressionLayout(); char XNTChar(); void setBackgroundColor(KDColor c) override; - void setTopMargin(KDCoordinate m) override; /* Responder */ Toolbox * toolbox() override; @@ -72,7 +71,6 @@ private: bool m_isEditing; }; ContentView m_contentView; - KDCoordinate m_verticalTopMargin; ExpressionLayoutFieldDelegate * m_delegate; }; diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 7e6657076..5e9766583 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -15,7 +15,7 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, m_textField.setBackgroundColor(KDColorWhite); m_textField.setColorsBackground(true); // Initialize layout field - m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, 0, k_horizontalMargin); + m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); m_expressionLayoutField.setBackgroundColor(KDColorWhite); m_expressionLayoutField.setColorsBackground(true); } @@ -123,7 +123,7 @@ KDCoordinate ExpressionField::inputViewHeight() const { return k_separatorThickness + (editionIsInTextField() ? k_textFieldHeight : min(maximalHeight(), - max(k_textFieldHeight, m_expressionLayoutField.minimalSizeForOptimalDisplay().height()))); + max(k_textFieldHeight, m_expressionLayoutField.minimalSizeForOptimalDisplay().height() + 2*k_verticalMargin ))); } KDCoordinate ExpressionField::maximalHeight() const { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 19d949662..b27a9bff0 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -10,7 +10,6 @@ ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : ScrollableView(parentResponder, &m_contentView, this), m_contentView(expressionLayout), - m_verticalTopMargin(0), m_delegate(delegate) { } @@ -81,7 +80,7 @@ bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); - return KDSize(contentViewSize.width(), contentViewSize.height() + m_verticalTopMargin); + return KDSize(contentViewSize.width(), contentViewSize.height()); } bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { @@ -328,7 +327,3 @@ void ExpressionLayoutField::setBackgroundColor(KDColor c) { ScrollableView::setBackgroundColor(c); m_contentView.setBackgroundColor(c); } - -void ExpressionLayoutField::setTopMargin(KDCoordinate m) { - m_verticalTopMargin = m; -} diff --git a/escher/src/scrollable_view.cpp b/escher/src/scrollable_view.cpp index 6db6475fc..bc9048715 100644 --- a/escher/src/scrollable_view.cpp +++ b/escher/src/scrollable_view.cpp @@ -52,8 +52,8 @@ void ScrollableView::reloadScroll(bool forceReLayout) { void ScrollableView::layoutSubviews() { KDSize viewSize = contentSize(); - KDCoordinate viewWidth = viewSize.width() < bounds().width() ? bounds().width() : viewSize.width(); - KDCoordinate viewHeight = viewSize.height() < bounds().height() ? bounds().height() : viewSize.height(); + KDCoordinate viewWidth = max(viewSize.width(), bounds().width() - leftMargin() - rightMargin()); + KDCoordinate viewHeight = max(viewSize.height(), bounds().height() - topMargin() - bottomMargin()); m_contentView->setSize(KDSize(viewWidth, viewHeight)); ScrollView::layoutSubviews(); } From 1e78f02ffc6cb05cd42421a771a0017f3c3d371c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 17:48:47 +0200 Subject: [PATCH 412/459] [poincare] Fix blackbox bug about variable initialization Change-Id: I8538ce9aa75ecee5f9e7f572be13fc590c994db7 --- poincare/src/expression_layout_cursor.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index e68f6762a..9b2cafaa7 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -147,13 +147,12 @@ void ExpressionLayoutCursor::addEmptySquarePowerLayout() { void ExpressionLayoutCursor::addEmptyTenPowerLayout() { HorizontalLayout * newSibling = new HorizontalLayout(); EmptyLayout * powerLayout = new EmptyLayout(); - int numberOfChildren = 4; - ExpressionLayout * childLayouts[numberOfChildren] = { + ExpressionLayout * childLayouts[] = { new CharLayout(Ion::Charset::MiddleDot), new CharLayout('1'), new CharLayout('0'), new VerticalOffsetLayout(powerLayout, VerticalOffsetLayout::Type::Superscript, false)}; - newSibling->addChildrenAtIndex(childLayouts, numberOfChildren, 0, false); + newSibling->addChildrenAtIndex(childLayouts, 4, 0, false); m_pointedExpressionLayout->addSibling(this, newSibling); setPointedExpressionLayout(powerLayout); setPosition(ExpressionLayoutCursor::Position::Right); From 4de2ae5353042f4f610e78bb7e6e89b0051b6b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 8 May 2018 17:50:35 +0200 Subject: [PATCH 413/459] [poincare] Fix virtualty of ScrollView::setBackgroundColor and TopMargin Change-Id: Id15d2b233b0a0f11435ab8f41a142eeca4fcec05 --- apps/calculation/scrollable_expression_view.cpp | 1 + apps/calculation/scrollable_expression_view.h | 2 +- escher/include/escher/scroll_view.h | 2 +- escher/include/escher/text_input.h | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index 4fd7572df..70e10b526 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -17,6 +17,7 @@ void ScrollableExpressionView::setExpressionLayout(ExpressionLayout * expression void ScrollableExpressionView::setBackgroundColor(KDColor backgroundColor) { m_expressionView.setBackgroundColor(backgroundColor); + ScrollableView::setBackgroundColor(backgroundColor); } KDSize ScrollableExpressionView::minimalSizeForOptimalDisplay() const { diff --git a/apps/calculation/scrollable_expression_view.h b/apps/calculation/scrollable_expression_view.h index fb156fbc9..38ae2d8d4 100644 --- a/apps/calculation/scrollable_expression_view.h +++ b/apps/calculation/scrollable_expression_view.h @@ -9,7 +9,7 @@ class ScrollableExpressionView : public ScrollableView, public ScrollViewDataSou public: ScrollableExpressionView(Responder * parentResponder); void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); - void setBackgroundColor(KDColor backgroundColor); + void setBackgroundColor(KDColor backgroundColor) override; KDSize minimalSizeForOptimalDisplay() const override; private: ExpressionView m_expressionView; diff --git a/escher/include/escher/scroll_view.h b/escher/include/escher/scroll_view.h index f0f54347a..097913aa1 100644 --- a/escher/include/escher/scroll_view.h +++ b/escher/include/escher/scroll_view.h @@ -10,7 +10,7 @@ public: ScrollView(View * contentView, ScrollViewDataSource * dataSource); void drawRect(KDContext * ctx, KDRect rect) const override; - virtual void setTopMargin(KDCoordinate m) { m_topMargin = m; } + void setTopMargin(KDCoordinate m) { m_topMargin = m; } KDCoordinate topMargin() const { return m_topMargin; } void setRightMargin(KDCoordinate m) { m_rightMargin = m; } KDCoordinate rightMargin() const { return m_rightMargin; } diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 136fb77b9..513386659 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -12,8 +12,7 @@ public: TextInput(Responder * parentResponder, View * contentView); Toolbox * toolbox() override; const char * text() const { return nonEditableContentView()->text(); } - void setBackgroundColor(KDColor backgroundColor); - KDColor backgroundColor() const { return nonEditableContentView()->backgroundColor(); } + void setBackgroundColor(KDColor backgroundColor) override; void setTextColor(KDColor textColor); bool removeChar(); size_t cursorLocation() const { return nonEditableContentView()->cursorLocation(); } From 9af3d378d174fbbf00082f9f9b8affcde57e7b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 09:55:58 +0200 Subject: [PATCH 414/459] [apps] Fix CondensedSumLayout created with a nullptr child Change-Id: Ie6d4c6408a45a9cdf617b8cba988667c17f4cc36 --- apps/shared/sum_graph_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 5244263a7..c7db7491e 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -251,7 +251,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl m_sumLayout = new CondensedSumLayout( LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), - nullptr, + new EmptyLayout(EmptyLayout::Color::Yellow, false), false); } else { char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; From d56f94224feed1bb5a8267887a55d264472639a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 11:10:35 +0200 Subject: [PATCH 415/459] [escher] Fix cursor position when copy pasting in ELField Change-Id: I7408e89ceb6ef6e7bce7e47dc6b3d2a4945cfdbf --- escher/src/expression_layout_field.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index b27a9bff0..6ab736437 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -226,7 +226,7 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la } bool layoutWillBeMerged = layout->isHorizontal(); m_contentView.cursor()->addLayoutAndMoveCursor(layout); - if (pointedLayout != nullptr) { + if (pointedLayout != nullptr && (pointedLayout != layout || !layoutWillBeMerged)) { m_contentView.cursor()->setPointedExpressionLayout(pointedLayout); m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } else if (!layoutWillBeMerged) { @@ -243,7 +243,7 @@ void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { Poincare::ExpressionLayout * layout = expression->createLayout(); delete expression; m_contentView.cursor()->showEmptyLayoutIfNeeded(); - insertLayoutAtCursor(layout, nullptr); + insertLayoutAtCursor(layout, layout); m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); return; From 0ea3d488f1a3c0e0a3592f89a7e00af3032d1064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 11:12:30 +0200 Subject: [PATCH 416/459] [escher] Clean code in expression_layout_field.cpp Change-Id: I80a7d8445209efece8c0f293d5761b04d087b884 --- escher/src/expression_layout_field.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 6ab736437..f96dc55f9 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -238,18 +238,15 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la } void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { + m_contentView.cursor()->showEmptyLayoutIfNeeded(); Poincare::Expression * expression = Poincare::Expression::parse(text); if (expression != nullptr) { Poincare::ExpressionLayout * layout = expression->createLayout(); delete expression; - m_contentView.cursor()->showEmptyLayoutIfNeeded(); insertLayoutAtCursor(layout, layout); - m_contentView.cursor()->hideEmptyLayoutIfNeeded(); - reload(); - return; + } else { + m_contentView.cursor()->insertText(text); } - m_contentView.cursor()->showEmptyLayoutIfNeeded(); - m_contentView.cursor()->insertText(text); m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); } From 4692f0a6f4acde63d5769d1f5de4db3d08d1497c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 11:35:58 +0200 Subject: [PATCH 417/459] [poincare] Fix collapsing layout bug. Change-Id: I6b1763e54e44645ab83c8be82ed6d5fcfc29fc91 --- poincare/src/layout/bracket_pair_layout.cpp | 5 +++-- poincare/src/layout/conjugate_layout.cpp | 5 +++-- poincare/src/layout/fraction_layout.cpp | 10 ++++++---- poincare/src/layout/nth_root_layout.cpp | 5 +++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index f4471fcb0..fcb4fba90 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -17,8 +17,9 @@ ExpressionLayout * BracketPairLayout::clone() const { void BracketPairLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the operand layout is not an HorizontalLayout, replace it with one. if (!operandLayout()->isHorizontal()) { - HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); - replaceChild(operandLayout(), horizontalOperandLayout, false); + ExpressionLayout * previousOperand = operandLayout(); + HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(previousOperand, false); + replaceChild(previousOperand, horizontalOperandLayout, false); } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); cursor->setPointedExpressionLayout(operandLayout()); diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 82a4f67eb..2b9cc9b26 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -18,8 +18,9 @@ ExpressionLayout * ConjugateLayout::clone() const { void ConjugateLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the operand layouts is not HorizontalLayouts, replace it with one. if (!operandLayout()->isHorizontal()) { - HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(operandLayout(), false); - replaceChild(operandLayout(), horizontalOperandLayout, false); + ExpressionLayout * previousOperand = operandLayout(); + HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(previousOperand, false); + replaceChild(previousOperand, horizontalOperandLayout, false); } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); cursor->setPointedExpressionLayout(operandLayout()); diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 044aed5bb..790bd0231 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -18,12 +18,14 @@ void FractionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curs /* If the numerator or denominator layouts are not HorizontalLayouts, replace * them with one. */ if (!numeratorLayout()->isHorizontal()) { - HorizontalLayout * horizontalNumeratorLayout = new HorizontalLayout(numeratorLayout(), false); - replaceChild(numeratorLayout(), horizontalNumeratorLayout, false); + ExpressionLayout * previousNumerator = numeratorLayout(); + HorizontalLayout * horizontalNumeratorLayout = new HorizontalLayout(previousNumerator, false); + replaceChild(previousNumerator, horizontalNumeratorLayout, false); } if (!denominatorLayout()->isHorizontal()) { - HorizontalLayout * horizontalDenominatorLayout = new HorizontalLayout(denominatorLayout(), false); - replaceChild(denominatorLayout(), horizontalDenominatorLayout, false); + ExpressionLayout * previousDenominator = denominatorLayout(); + HorizontalLayout * horizontalDenominatorLayout = new HorizontalLayout(previousDenominator, false); + replaceChild(previousDenominator, horizontalDenominatorLayout, false); } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 1); ExpressionLayout::collapseOnDirection(HorizontalDirection::Left, 0); diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index 598269d1f..bc3532811 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -31,8 +31,9 @@ ExpressionLayout * NthRootLayout::clone() const { void NthRootLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) { // If the radicand layout is not an HorizontalLayout, replace it with one. if (!radicandLayout()->isHorizontal()) { - HorizontalLayout * horizontalRadicandLayout = new HorizontalLayout(radicandLayout(), false); - replaceChild(radicandLayout(), horizontalRadicandLayout, false); + ExpressionLayout * previousRadicand = radicandLayout(); + HorizontalLayout * horizontalRadicandLayout = new HorizontalLayout(previousRadicand, false); + replaceChild(previousRadicand, horizontalRadicandLayout, false); } ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0); cursor->setPointedExpressionLayout(radicandLayout()); From dcc75dbc7d2c8b9266a51a51a347a864f7af3a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 12:01:34 +0200 Subject: [PATCH 418/459] [poincare] Remove overriding method in Matrix. Adding GreySquares when moving the cursor inside a matrix is already handled by ExpressionLayout. Change-Id: I6e8b4b5dab54c5f6f3528509fd52e9694991e3fb --- poincare/src/layout/matrix_layout.cpp | 24 ------------------------ poincare/src/layout/matrix_layout.h | 2 -- 2 files changed, 26 deletions(-) diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index 7ecdab87a..bde566c4c 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -109,30 +109,6 @@ ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor cursor, return resultCursor; } -ExpressionLayoutCursor MatrixLayout::cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { - ExpressionLayoutCursor result = GridLayout::cursorInDescendantsAbove(cursor, shouldRecomputeLayout); - if (result.isDefined() && cursor.pointedExpressionLayout() != this) { - // Add the grey squares if the cursor is pointing at a matrix descendant, - // not at the matrix itself. - assert(!hasGreySquares()); - addGreySquares(); - *shouldRecomputeLayout = true; - } - return result; -} - -ExpressionLayoutCursor MatrixLayout::cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { - ExpressionLayoutCursor result = GridLayout::cursorInDescendantsUnder(cursor, shouldRecomputeLayout); - if (result.isDefined() && cursor.pointedExpressionLayout() != this) { - // Add the grey squares if the cursor is pointing at a matrix descendant, - // not at the matrix itself. - assert(!hasGreySquares()); - addGreySquares(); - *shouldRecomputeLayout = true; - } - return result; -} - void MatrixLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) { int oldChildIndex = indexOfChild(oldChild); GridLayout::replaceChild(oldChild, newChild, deleteOldChild); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index d5469fb81..a5fa5c85f 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -15,8 +15,6 @@ public: ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; From 7e9bbe3aeab0fd7333ac9f035135dfdea1d624d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 12:17:30 +0200 Subject: [PATCH 419/459] [ion] Add event names for Shift+Up/Down/Left/Right Change-Id: I03cd5707ea2d9e460ed925009442e15d38572798 --- ion/src/shared/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/src/shared/events.cpp b/ion/src/shared/events.cpp index 5c29bb1b6..b5300ec37 100644 --- a/ion/src/shared/events.cpp +++ b/ion/src/shared/events.cpp @@ -156,7 +156,7 @@ static constexpr const char * s_nameForEvent[255] = { "One", "Two", "Three", "Plus", "Minus", nullptr, "Zero", "Dot", "EE", "Ans", "EXE", nullptr, //Shift, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "ShiftLeft", "ShiftUp", "ShiftDown", "ShiftRight", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear", "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto", From b5f4a7b3f049876adc9c8d2cc3b06dfa69e2da42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:32:27 +0200 Subject: [PATCH 420/459] [poincare] Simplify MatrixLayout code Change-Id: I4bfcf3da94296b8314ff47a1a71dbc79150a4027 --- poincare/include/poincare/expression_layout.h | 6 ++--- poincare/src/layout/matrix_layout.cpp | 26 ++++--------------- poincare/src/layout/matrix_layout.h | 3 +-- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index f58c62ca0..411dae424 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -89,8 +89,8 @@ public: virtual ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) = 0; virtual ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); virtual ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); - virtual ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); - virtual ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorInDescendantsAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); + ExpressionLayoutCursor cursorInDescendantsUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); /* Expression Engine */ virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; @@ -142,6 +142,7 @@ protected: int * resultScore); virtual void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor); void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); + virtual ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); ExpressionLayout * m_parent; KDCoordinate m_baseline; /* m_baseline is the signed vertical distance from the top of the layout to @@ -152,7 +153,6 @@ protected: bool m_positioned; private: void detachChildAtIndex(int i); - ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); ExpressionLayoutCursor cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); KDRect m_frame; diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index bde566c4c..db5b20791 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -73,34 +73,18 @@ ExpressionLayoutCursor MatrixLayout::cursorRightOf(ExpressionLayoutCursor cursor return GridLayout::cursorRightOf(cursor, shouldRecomputeLayout); } -ExpressionLayoutCursor MatrixLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +ExpressionLayoutCursor MatrixLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { bool shouldRemoveGreySquares = false; - for (int childIndex = 0; childIndex < m_numberOfColumns; childIndex++) { + int firstIndex = direction == VerticalDirection::Up ? 0 : numberOfChildren() - m_numberOfColumns; + int lastIndex = direction == VerticalDirection::Up ? m_numberOfColumns : numberOfChildren(); + for (int childIndex = firstIndex; childIndex < lastIndex; childIndex++) { if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { // The cursor is leaving the matrix, so remove the grey squares. shouldRemoveGreySquares = true; break; } } - ExpressionLayoutCursor resultCursor = GridLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited); - if (resultCursor.isDefined() && shouldRemoveGreySquares) { - assert(hasGreySquares()); - removeGreySquares(); - *shouldRecomputeLayout = true; - } - return resultCursor; -} - -ExpressionLayoutCursor MatrixLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - bool shouldRemoveGreySquares = false; - for (int childIndex = numberOfChildren() - m_numberOfColumns; childIndex < m_numberOfChildren; childIndex++) { - if (cursor.pointedExpressionLayout()->hasAncestor(child(childIndex), true)) { - // The cursor is leaving the matrix, so remove the grey squares. - shouldRemoveGreySquares = true; - break; - } - } - ExpressionLayoutCursor resultCursor = GridLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + ExpressionLayoutCursor resultCursor = GridLayout::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, equivalentPositionVisited); if (resultCursor.isDefined() && shouldRemoveGreySquares) { assert(hasGreySquares()); removeGreySquares(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index a5fa5c85f..e2cf2f4e2 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -13,8 +13,6 @@ public: /* Navigation */ ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; /* Dynamic layout */ void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; @@ -35,6 +33,7 @@ protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * child) override; + ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; private: void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; From 695e189836eccfeb5b53c3b02f900af489dcac1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:42:31 +0200 Subject: [PATCH 421/459] [poincare] Add method removeGreySquaresFromAllMatrixAncestors Change-Id: I1351138fde688be3cba57b8f7ba1cd7b3010b0bc --- poincare/include/poincare/expression_layout.h | 2 ++ poincare/src/layout/expression_layout.cpp | 32 +++++++++++++------ poincare/src/layout/matrix_layout.h | 2 +- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 411dae424..57a31feb9 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -101,6 +101,7 @@ public: /* Other */ virtual ExpressionLayout * layoutToPointWhenInserting(); bool addGreySquaresToAllMatrixAncestors(); + bool removeGreySquaresFromAllMatrixAncestors(); bool hasText() const; virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a sibling fraction: should the layout be @@ -155,6 +156,7 @@ private: void detachChildAtIndex(int i); ExpressionLayoutCursor cursorInDescendantsVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout); ExpressionLayout * replaceWithJuxtapositionOf(ExpressionLayout * leftChild, ExpressionLayout * rightChild, bool deleteAfterReplace); + bool changeGreySquaresOfAllMatrixAncestors(bool add); KDRect m_frame; }; diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 21c6e64b8..ed9cad3a5 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -290,16 +290,11 @@ ExpressionLayout * ExpressionLayout::layoutToPointWhenInserting() { } bool ExpressionLayout::addGreySquaresToAllMatrixAncestors() { - bool addedSquares = false; - ExpressionLayout * currentAncestor = m_parent; - while (currentAncestor != nullptr) { - if (currentAncestor->isMatrix()) { - static_cast(currentAncestor)->addGreySquares(); - addedSquares = true; - } - currentAncestor = currentAncestor->editableParent(); - } - return addedSquares; + return changeGreySquaresOfAllMatrixAncestors(true); +} + +bool ExpressionLayout::removeGreySquaresFromAllMatrixAncestors() { + return changeGreySquaresOfAllMatrixAncestors(false); } bool ExpressionLayout::hasText() const { @@ -517,4 +512,21 @@ ExpressionLayout * ExpressionLayout::replaceWithJuxtapositionOf(ExpressionLayout return layout; } +bool ExpressionLayout::changeGreySquaresOfAllMatrixAncestors(bool add) { + bool changedSquares = false; + ExpressionLayout * currentAncestor = m_parent; + while (currentAncestor != nullptr) { + if (currentAncestor->isMatrix()) { + if (add) { + static_cast(currentAncestor)->addGreySquares(); + } else { + static_cast(currentAncestor)->removeGreySquares(); + } + changedSquares = true; + } + currentAncestor = currentAncestor->editableParent(); + } + return changedSquares; +} + } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index e2cf2f4e2..e4b17f582 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -28,6 +28,7 @@ public: /* Special matrix method */ void newRowOrColumnAtIndex(int index); void addGreySquares(); + void removeGreySquares(); protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; @@ -38,7 +39,6 @@ private: void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; - void removeGreySquares(); bool hasGreySquares() const; }; From 30007a357476b021995606c93ccc589c5970b578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:43:00 +0200 Subject: [PATCH 422/459] [poincare] Handle Matrix GreySquares on ShiftLeft/Right events. Change-Id: Id0b0b6c99c683808d3b21123e208da8b6e8e1175 --- escher/src/expression_layout_field.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index f96dc55f9..c1033841c 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -94,9 +94,16 @@ bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, boo } else if (event == Ion::Events::Down) { result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout); } else if (event == Ion::Events::ShiftLeft) { + *shouldRecomputeLayout = true; + if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) { + *shouldRecomputeLayout = true; + } result.setPointedExpressionLayout(m_contentView.expressionView()->expressionLayout()); result.setPosition(Poincare::ExpressionLayoutCursor::Position::Left); } else if (event == Ion::Events::ShiftRight) { + if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) { + *shouldRecomputeLayout = true; + } result.setPointedExpressionLayout(m_contentView.expressionView()->expressionLayout()); result.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } From 790c9c7be322323376c94ff69c2bf72ee2e9cfc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:50:35 +0200 Subject: [PATCH 423/459] [poincare] Clean EmptyLayout Change-Id: I880a66c79c440912ff6bbcc86c6f22d3bdb8a5ad --- poincare/src/layout/empty_layout.cpp | 10 ++-------- poincare/src/layout/empty_layout.h | 4 +--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index d68a86e33..6d1acc880 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -45,15 +45,9 @@ ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor cursor, return ExpressionLayoutCursor(); } -ExpressionLayoutCursor EmptyLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - return cursorVerticalOf(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); -} - -ExpressionLayoutCursor EmptyLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - return cursorVerticalOf(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); -} - ExpressionLayoutCursor EmptyLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + /* The two cursor positions around an EmptyLayout are equivalent, so both + * should be checked. */ assert(cursor.pointedExpressionLayout() == this); ExpressionLayoutCursor cursorResult = direction == VerticalDirection::Up ? ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 70f48333a..4f72e5b7f 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -17,8 +17,6 @@ public: void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isEmpty() const override { return true; } Color color() const { return m_color; } @@ -40,7 +38,7 @@ private: constexpr static KDCoordinate k_marginWidth = 1; constexpr static KDCoordinate k_marginHeight = 3; constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; bool m_isVisible; Color m_color; }; From a09c671cc57f7a1e06e1940ea4fbd42fb8057edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:55:12 +0200 Subject: [PATCH 424/459] [poincare] EmptyLayout reorganization. Change-Id: Ie575bd4f022058316ba18504666b70c10786d1a7 --- poincare/src/layout/empty_layout.cpp | 34 ++++++++++++++-------------- poincare/src/layout/empty_layout.h | 26 +++++++++++++++------ 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 6d1acc880..867814b3c 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -45,23 +45,6 @@ ExpressionLayoutCursor EmptyLayout::cursorRightOf(ExpressionLayoutCursor cursor, return ExpressionLayoutCursor(); } -ExpressionLayoutCursor EmptyLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - /* The two cursor positions around an EmptyLayout are equivalent, so both - * should be checked. */ - assert(cursor.pointedExpressionLayout() == this); - ExpressionLayoutCursor cursorResult = direction == VerticalDirection::Up ? - ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : - ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); - if (cursorResult.isDefined()) { - return cursorResult; - } - ExpressionLayoutCursor::Position newPosition = cursor.position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left; - cursor.setPosition(newPosition); - return direction == VerticalDirection::Up ? - ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : - ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); -} - int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (bufferSize == 0) { return -1; @@ -108,4 +91,21 @@ void EmptyLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionL } } +ExpressionLayoutCursor EmptyLayout::cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + /* The two cursor positions around an EmptyLayout are equivalent, so both + * should be checked. */ + assert(cursor.pointedExpressionLayout() == this); + ExpressionLayoutCursor cursorResult = direction == VerticalDirection::Up ? + ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : + ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + if (cursorResult.isDefined()) { + return cursorResult; + } + ExpressionLayoutCursor::Position newPosition = cursor.position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left; + cursor.setPosition(newPosition); + return direction == VerticalDirection::Up ? + ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : + ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 4f72e5b7f..b141425f4 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -12,20 +12,32 @@ public: Yellow, Grey }; + // Constructor EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; - void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - bool isEmpty() const override { return true; } + + // EmptyLayout Color color() const { return m_color; } void setColor(Color color) { m_color = color; } bool isVisible() const { return m_isVisible; } void setVisible(bool visible) { m_isVisible = visible; } + + // User input + void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; + + // Tree navigation + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + + // Serialization + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + + // Other + bool isEmpty() const override { return true; } + protected: - virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - virtual KDSize computeSize() override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override { assert(false); From c1fbaab4520d2f5aa2abad336ee6b29f95ede1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 13:56:22 +0200 Subject: [PATCH 425/459] [coding style] Remove white line Change-Id: I1c5baffdbe0727eb814158a872db3cbb9ac131bf --- poincare/include/poincare/expression_layout.h | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 57a31feb9..c4af5a2c2 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -5,7 +5,6 @@ #include #include - namespace Poincare { class ExpressionLayout { From 029e46ce3932e6e4330e0f1361f6c2d47a5217ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 14:10:32 +0200 Subject: [PATCH 426/459] [poincare] Fix bug in EmptyLayout::cursorVerticalOf Change-Id: I1f95fa90641f90edbc751c5a36c139f55f3c42c4 --- poincare/src/layout/empty_layout.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 867814b3c..6744aec61 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -95,17 +95,13 @@ ExpressionLayoutCursor EmptyLayout::cursorVerticalOf(VerticalDirection direction /* The two cursor positions around an EmptyLayout are equivalent, so both * should be checked. */ assert(cursor.pointedExpressionLayout() == this); - ExpressionLayoutCursor cursorResult = direction == VerticalDirection::Up ? - ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : - ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + ExpressionLayoutCursor cursorResult = ExpressionLayout::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, equivalentPositionVisited); if (cursorResult.isDefined()) { return cursorResult; } ExpressionLayoutCursor::Position newPosition = cursor.position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left; cursor.setPosition(newPosition); - return direction == VerticalDirection::Up ? - ExpressionLayout::cursorAbove(cursor, shouldRecomputeLayout, equivalentPositionVisited) : - ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); + return ExpressionLayout::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, false); } } From 8e6b1f4c457b1606abaff14137bdd945e26752e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 14:27:12 +0200 Subject: [PATCH 427/459] [poincare] Fix ExpressionLayoutCursor::baseForNewPowerLayout If the cursor is on the left of an empty layout, move it to its right and this empty layout will be the base of the new power layout. Change-Id: I81be3787ca1d279fc370fcbe86e558ec078b7b44 --- poincare/src/expression_layout_cursor.cpp | 19 ++++++++++++++++--- poincare/src/layout/matrix_layout.cpp | 3 +-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/poincare/src/expression_layout_cursor.cpp b/poincare/src/expression_layout_cursor.cpp index 9b2cafaa7..dff7a5fc5 100644 --- a/poincare/src/expression_layout_cursor.cpp +++ b/poincare/src/expression_layout_cursor.cpp @@ -271,10 +271,23 @@ bool ExpressionLayoutCursor::baseForNewPowerLayout() { if (m_pointedExpressionLayout->isHorizontal()) { return false; } + if (m_pointedExpressionLayout->isEmpty()) { + /* If the cursor is on the right of an EmptyLayout, move it to its right, + * make sure it is yellow, and this EmptyLayout will be the base of the + * new power layout. */ + m_position = Position::Right; + if (static_cast(m_pointedExpressionLayout)->color() == EmptyLayout::Color::Grey) { + static_cast(m_pointedExpressionLayout)->setColor(EmptyLayout::Color::Yellow); + int indexInParent = m_pointedExpressionLayout->parent()->indexOfChild(m_pointedExpressionLayout); + assert(indexInParent >= 0); + static_cast(m_pointedExpressionLayout->editableParent())->newRowOrColumnAtIndex(indexInParent); + } + return true; + } ExpressionLayoutCursor equivalentLayoutCursor = m_pointedExpressionLayout->equivalentCursor(*this); - if (equivalentLayoutCursor.pointedExpressionLayout() != nullptr - && equivalentLayoutCursor.pointedExpressionLayout()->isHorizontal() - && equivalentLayoutCursor.position() == Position::Left) + if (equivalentLayoutCursor.pointedExpressionLayout() == nullptr + || ( equivalentLayoutCursor.pointedExpressionLayout()->isHorizontal() + && equivalentLayoutCursor.position() == Position::Left)) { return false; } diff --git a/poincare/src/layout/matrix_layout.cpp b/poincare/src/layout/matrix_layout.cpp index db5b20791..903ff6b45 100644 --- a/poincare/src/layout/matrix_layout.cpp +++ b/poincare/src/layout/matrix_layout.cpp @@ -152,8 +152,7 @@ void MatrixLayout::newRowOrColumnAtIndex(int index) { assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows); bool shouldAddNewRow = GridLayout::childIsBottomOfGrid(index); int correspondingRow = rowAtChildIndex(index); - // We need to compute this bool before modifying the layout.:w - // + // We need to compute this boolean before modifying the layout if (GridLayout::childIsRightOfGrid(index)) { // Color the grey EmptyLayouts of the column in yellow. int correspondingColumn = m_numberOfColumns - 1; From 31af7f9e1233ccc96c9235569f38253a04b72b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 15:04:07 +0200 Subject: [PATCH 428/459] [poincare] Fix HorizontalLayout::privateAddSibling If an OffsetLayout is added on the right of an HorizontalLayout whose last child is Empty, this empty child should not be removed. Change-Id: I72ae2fe52385fa65b8c5fb43ca519a2049c9fe1b --- poincare/src/layout/horizontal_layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 8d0e4c6e9..691501bdc 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -416,7 +416,7 @@ void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres assert(cursor->position() == ExpressionLayoutCursor::Position::Right); // If the last child is empty, remove it before adding the layout. int childrenCount = numberOfChildren(); - if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty()) { + if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { removeChildAtIndex(childrenCount - 1, true); } addOrMergeChildAtIndex(sibling, numberOfChildren(), false); From c9c216c071b3637a9fa7ef5fce140ac69124c854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 15:26:44 +0200 Subject: [PATCH 429/459] [poincare] Fix HorizontalLayout::privateAddSibling Change-Id: I0cebcaedc4d36749f79293c8bd8acc289522dbc2 --- poincare/src/layout/horizontal_layout.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 691501bdc..dfce7509a 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -398,19 +398,25 @@ KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) { // Add the "sibling" as a child. if (cursor->position() == ExpressionLayoutCursor::Position::Left) { - // If the first child is empty, remove it before adding the layout. + int indexForInsertion = 0; + /* If the first child is empty, remove it before adding the layout, unless + * the new sibling needs the empty layout as a base. */ if (numberOfChildren() > 0 && editableChild(0)->isEmpty()) { - removeChildAtIndex(0, true); + if (sibling->mustHaveLeftSibling()) { + indexForInsertion = 1; + } else { + removeChildAtIndex(0, true); + } } if (moveCursor) { - if (numberOfChildren() > 0) { - cursor->setPointedExpressionLayout(editableChild(0)); + if (numberOfChildren() > indexForInsertion) { + cursor->setPointedExpressionLayout(editableChild(indexForInsertion)); } else { cursor->setPointedExpressionLayout(this); cursor->setPosition(ExpressionLayoutCursor::Position::Right); } } - addOrMergeChildAtIndex(sibling, 0, false); + addOrMergeChildAtIndex(sibling, indexForInsertion, false); return; } assert(cursor->position() == ExpressionLayoutCursor::Position::Right); From d63ad7e42d67c56733a91b8da87840d0b7d16f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 15:46:32 +0200 Subject: [PATCH 430/459] [poincare] Handle pressing "Divide" when the cursor is (^2|) Change-Id: If05116852e037bd22c91725e8ced9b2958da33a8 --- poincare/src/layout/expression_layout.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index ed9cad3a5..a89d27a4c 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -477,6 +477,7 @@ void ExpressionLayout::collapseOnDirection(HorizontalDirection direction, int ab canCollapse = !(editableParent()->editableChild(indexInParent+1)->mustHaveLeftSibling()); } ExpressionLayout * sibling = nullptr; + bool forceCollapse = false; while (canCollapse) { if (direction == HorizontalDirection::Right && indexInParent == numberOfSiblings - 1) { break; @@ -486,7 +487,11 @@ void ExpressionLayout::collapseOnDirection(HorizontalDirection direction, int ab } int siblingIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; sibling = editableParent()->editableChild(siblingIndex); - if (sibling->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left)) { + if (forceCollapse || sibling->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left)) { + /* If the collapse direction is Left and the next sibling to be collapsed + * must have a left sibling, force the collapsing of this needed left + * sibling. */ + forceCollapse = direction == HorizontalDirection::Left && sibling->mustHaveLeftSibling(); editableParent()->removeChildAtIndex(siblingIndex, false); int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; horizontalAbsorbingChild->addOrMergeChildAtIndex(sibling, newIndex, true); From 68b1ddf05857e7e83665920ebecaa1ed1c50cd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 16:09:32 +0200 Subject: [PATCH 431/459] [poincare] Code cleaning Change-Id: Icc60c8ec81fbe8ed01ed3afc776b60d760975d63 --- .../layout/binomial_coefficient_layout.cpp | 8 ------- .../src/layout/binomial_coefficient_layout.h | 10 +++++++-- poincare/src/layout/bracket_pair_layout.cpp | 4 ---- poincare/src/layout/bracket_pair_layout.h | 11 +++++++++- poincare/src/layout/char_layout.cpp | 5 ----- poincare/src/layout/char_layout.h | 22 ++++++++++++++----- 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/poincare/src/layout/binomial_coefficient_layout.cpp b/poincare/src/layout/binomial_coefficient_layout.cpp index fa097578f..1ac2f96ae 100644 --- a/poincare/src/layout/binomial_coefficient_layout.cpp +++ b/poincare/src/layout/binomial_coefficient_layout.cpp @@ -116,12 +116,4 @@ KDPoint BinomialCoefficientLayout::positionOfChild(ExpressionLayout * child) { return dummyGridLayout->positionOfChild(dummyGridLayout->editableChild(1)).translatedBy(dummyLayout.positionOfChild(dummyGridLayout)); } -ExpressionLayout * BinomialCoefficientLayout::nLayout() { - return editableChild(0); -} - -ExpressionLayout * BinomialCoefficientLayout::kLayout() { - return editableChild(1); -} - } diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 44c666963..8f9f5ac41 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -9,23 +9,29 @@ namespace Poincare { class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: + // Constructor using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - ExpressionLayout * kLayout(); - ExpressionLayout * nLayout(); + ExpressionLayout * nLayout() { return editableChild(0); } + ExpressionLayout * kLayout() { return editableChild(1); } }; } diff --git a/poincare/src/layout/bracket_pair_layout.cpp b/poincare/src/layout/bracket_pair_layout.cpp index fcb4fba90..96a6c97ec 100644 --- a/poincare/src/layout/bracket_pair_layout.cpp +++ b/poincare/src/layout/bracket_pair_layout.cpp @@ -101,10 +101,6 @@ int BracketPairLayout::writeTextInBuffer(char * buffer, int bufferSize, int numb return numberOfChar; } -ExpressionLayout * BracketPairLayout::operandLayout() { - return editableChild(0); -} - void BracketPairLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { const KDCoordinate k_widthMargin = widthMargin(); const KDCoordinate k_externWidthMargin = externWidthMargin(); diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index af194086d..3d3574f62 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -9,15 +9,24 @@ namespace Poincare { class BracketPairLayout : public StaticLayoutHierarchy<1> { friend class MatrixLayout; public: + // Constructor using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + // Collapse void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; + + // User input void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; protected: - ExpressionLayout * operandLayout(); + ExpressionLayout * operandLayout() { return editableChild(0); } KDCoordinate externWidthMargin() const { return 2; } virtual KDCoordinate widthMargin() const { return 5; } virtual KDCoordinate verticalExternMargin() const { return 0; } diff --git a/poincare/src/layout/char_layout.cpp b/poincare/src/layout/char_layout.cpp index b07d470ba..0a4cd9018 100644 --- a/poincare/src/layout/char_layout.cpp +++ b/poincare/src/layout/char_layout.cpp @@ -63,11 +63,6 @@ void CharLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDC ctx->drawString(string, p, m_fontSize, expressionColor, backgroundColor); } -KDPoint CharLayout::positionOfChild(ExpressionLayout * child) { - assert(false); - return KDPointZero; -} - KDSize CharLayout::computeSize() { return KDText::charSize(m_fontSize); } diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 6cb89ce4b..11439aa0a 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -4,25 +4,37 @@ #include #include #include +#include namespace Poincare { class CharLayout : public StaticLayoutHierarchy<0> { public: + // Constructor CharLayout(char c, KDText::FontSize fontSize = KDText::FontSize::Large); ExpressionLayout * clone() const override; + + // CharLayout + char character() const { return m_char; } + KDText::FontSize fontSize() const { return m_fontSize; } + + // Tree navigation + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); } - char character() { return m_char; } - KDText::FontSize fontSize() const { return m_fontSize; } - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; + // Other bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - KDPoint positionOfChild(ExpressionLayout * child) override; + KDPoint positionOfChild(ExpressionLayout * child) override { + assert(false); + return KDPointZero; + } KDSize computeSize() override; void computeBaseline() override; char m_char; From f75fdbda12971285402da575dd9b6beecca9298d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 16:37:54 +0200 Subject: [PATCH 432/459] [poincare] Fix Exp SquarePower SquarePower Change-Id: I2c378728fe99096497d396dd6ae526867326ace5 --- poincare/src/layout/vertical_offset_layout.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 2c0ff224e..48cd88df1 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -254,7 +254,6 @@ void VerticalOffsetLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Ex VerticalOffsetLayout * verticalOffsetSibling = static_cast(sibling); if (verticalOffsetSibling->type() == Type::Superscript) { assert(m_parent->isHorizontal()); - // Add the Left parenthesis int indexInParent = m_parent->indexOfChild(this); int leftParenthesisIndex = indexInParent; @@ -266,7 +265,7 @@ void VerticalOffsetLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Ex leftParenthesisIndex--; } m_parent->addChildAtIndex(leftParenthesis, leftParenthesisIndex); - indexInParent++; + indexInParent = m_parent->indexOfChild(this); // Add the Right parenthesis RightParenthesisLayout * rightParenthesis = new RightParenthesisLayout(); From eaca1d7028e6e0528552f6875828269daff5a67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 17:09:18 +0200 Subject: [PATCH 433/459] [poincare] Code cleaning Change-Id: I4b11c119938eeee9c9dd6ded370ef5f458faaa15 --- .../src/layout/binomial_coefficient_layout.h | 1 - poincare/src/layout/bracket_pair_layout.h | 1 - poincare/src/layout/char_layout.h | 1 - poincare/src/layout/condensed_sum_layout.cpp | 43 ------------------- poincare/src/layout/condensed_sum_layout.h | 42 ++++++++++++++---- poincare/src/layout/conjugate_layout.cpp | 40 ++++++++--------- poincare/src/layout/conjugate_layout.h | 14 ++++-- poincare/src/layout/empty_layout.h | 1 - poincare/src/layout/fraction_layout.cpp | 8 ---- poincare/src/layout/fraction_layout.h | 14 +++++- poincare/src/layout/grid_layout.h | 10 ++--- poincare/src/layout/horizontal_layout.cpp | 19 -------- poincare/src/layout/horizontal_layout.h | 19 ++++---- poincare/src/layout/integral_layout.cpp | 17 -------- poincare/src/layout/integral_layout.h | 20 +++++---- poincare/src/layout/matrix_layout.h | 18 ++++---- poincare/src/layout/nth_root_layout.cpp | 11 ----- poincare/src/layout/nth_root_layout.h | 13 +++--- poincare/src/layout/sequence_layout.cpp | 33 ++++---------- poincare/src/layout/sequence_layout.h | 18 ++++++-- .../src/layout/vertical_offset_layout.cpp | 8 ---- poincare/src/layout/vertical_offset_layout.h | 16 +++++-- 22 files changed, 153 insertions(+), 214 deletions(-) diff --git a/poincare/src/layout/binomial_coefficient_layout.h b/poincare/src/layout/binomial_coefficient_layout.h index 8f9f5ac41..f53ac8baf 100644 --- a/poincare/src/layout/binomial_coefficient_layout.h +++ b/poincare/src/layout/binomial_coefficient_layout.h @@ -9,7 +9,6 @@ namespace Poincare { class BinomialCoefficientLayout : public StaticLayoutHierarchy<2> { public: - // Constructor using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/bracket_pair_layout.h b/poincare/src/layout/bracket_pair_layout.h index 3d3574f62..25fbef9b9 100644 --- a/poincare/src/layout/bracket_pair_layout.h +++ b/poincare/src/layout/bracket_pair_layout.h @@ -9,7 +9,6 @@ namespace Poincare { class BracketPairLayout : public StaticLayoutHierarchy<1> { friend class MatrixLayout; public: - // Constructor using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/char_layout.h b/poincare/src/layout/char_layout.h index 11439aa0a..79da87bd2 100644 --- a/poincare/src/layout/char_layout.h +++ b/poincare/src/layout/char_layout.h @@ -10,7 +10,6 @@ namespace Poincare { class CharLayout : public StaticLayoutHierarchy<0> { public: - // Constructor CharLayout(char c, KDText::FontSize fontSize = KDText::FontSize::Large); ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/condensed_sum_layout.cpp b/poincare/src/layout/condensed_sum_layout.cpp index 882ac03c3..1be4db0b5 100644 --- a/poincare/src/layout/condensed_sum_layout.cpp +++ b/poincare/src/layout/condensed_sum_layout.cpp @@ -10,37 +10,6 @@ ExpressionLayout * CondensedSumLayout::clone() const { return layout; } -ExpressionLayoutCursor CondensedSumLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { - /* CondensedSumLayout is only used in apps/shared/sum_graph_controller.cpp, in - * a view with no cursor. */ - assert(false); - return ExpressionLayoutCursor(); -} - -ExpressionLayoutCursor CondensedSumLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { - assert(false); - return ExpressionLayoutCursor(); -} - -ExpressionLayoutCursor CondensedSumLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - assert(false); - return ExpressionLayoutCursor(); -} - -ExpressionLayoutCursor CondensedSumLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - assert(false); - return ExpressionLayoutCursor(); -} - -ExpressionLayout * CondensedSumLayout::layoutToPointWhenInserting() { - assert(false); - return nullptr; -} - -void CondensedSumLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - // Nothing to draw -} - KDSize CondensedSumLayout::computeSize() { KDSize baseSize = baseLayout()->size(); KDSize subscriptSize = subscriptLayout()->size(); @@ -72,17 +41,5 @@ KDPoint CondensedSumLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x,y); } -ExpressionLayout * CondensedSumLayout::baseLayout() { - return editableChild(0); -} - -ExpressionLayout * CondensedSumLayout::subscriptLayout() { - return editableChild(1); -} - -ExpressionLayout * CondensedSumLayout::superscriptLayout() { - return editableChild(2); -} - } diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index d0c082bc5..9caa64345 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -10,23 +11,46 @@ class CondensedSumLayout : public StaticLayoutHierarchy<3> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + + /* Tree navigation + * CondensedSumLayout is only used in apps/shared/sum_graph_controller.cpp, in + * a view with no cursor. */ + ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override { + assert(false); + return ExpressionLayoutCursor(); + } + ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override { + assert(false); + return ExpressionLayoutCursor(); + } + ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override { + assert(false); + return ExpressionLayoutCursor(); + } + ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override { + assert(false); + return ExpressionLayoutCursor(); + } + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "sum"); } - ExpressionLayout * layoutToPointWhenInserting() override; + + // Other + ExpressionLayout * layoutToPointWhenInserting() override { + assert(false); + return nullptr; + } protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - ExpressionLayout * baseLayout(); - ExpressionLayout * subscriptLayout(); - ExpressionLayout * superscriptLayout(); + ExpressionLayout * baseLayout() { return editableChild(0); } + ExpressionLayout * subscriptLayout() { return editableChild(1); } + ExpressionLayout * superscriptLayout() { return editableChild(2); } }; } diff --git a/poincare/src/layout/conjugate_layout.cpp b/poincare/src/layout/conjugate_layout.cpp index 2b9cc9b26..135fb5150 100644 --- a/poincare/src/layout/conjugate_layout.cpp +++ b/poincare/src/layout/conjugate_layout.cpp @@ -27,6 +27,24 @@ void ConjugateLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cur cursor->setPosition(ExpressionLayoutCursor::Position::Left); } +void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { + assert(oldChild == operandLayout()); + if (newChild->isEmpty()) { + if (!deleteOldChild) { + detachChild(oldChild); + } + replaceWithAndMoveCursor(newChild, true, cursor); + return; + } + ExpressionLayout::replaceChildAndMoveCursor(oldChild, newChild, deleteOldChild, cursor); +} + +void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { + assert(index >= 0 && index < numberOfChildren()); + assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); + replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); +} + ExpressionLayoutCursor ConjugateLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { // Case: Left of the operand. Move Left. if (operandLayout() @@ -71,24 +89,6 @@ ExpressionLayoutCursor ConjugateLayout::cursorRightOf(ExpressionLayoutCursor cur return ExpressionLayoutCursor(); } -void ConjugateLayout::replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) { - assert(oldChild == operandLayout()); - if (newChild->isEmpty()) { - if (!deleteOldChild) { - detachChild(oldChild); - } - replaceWithAndMoveCursor(newChild, true, cursor); - return; - } - ExpressionLayout::replaceChildAndMoveCursor(oldChild, newChild, deleteOldChild, cursor); -} - -void ConjugateLayout::removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) { - assert(index >= 0 && index < numberOfChildren()); - assert(cursor->pointedExpressionLayout()->hasAncestor(child(index), true)); - replaceChildAndMoveCursor(child(index), new EmptyLayout(), deleteAfterRemoval, cursor); -} - void ConjugateLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, p.y(), operandLayout()->size().width()+2*Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth), expressionColor); } @@ -107,9 +107,5 @@ KDPoint ConjugateLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(Metric::FractionAndConjugateHorizontalMargin+Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth+k_overlineVerticalMargin); } -ExpressionLayout * ConjugateLayout::operandLayout() { - return editableChild(0); -} - } diff --git a/poincare/src/layout/conjugate_layout.h b/poincare/src/layout/conjugate_layout.h index e4f29f6d9..e29f3fc8a 100644 --- a/poincare/src/layout/conjugate_layout.h +++ b/poincare/src/layout/conjugate_layout.h @@ -10,11 +10,19 @@ class ConjugateLayout : public StaticLayoutHierarchy<1> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + // Collapse void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; + // Replace + void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; + // Remove + void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; - void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "conj"); } @@ -26,7 +34,7 @@ protected: private: constexpr static KDCoordinate k_overlineWidth = 1; constexpr static KDCoordinate k_overlineVerticalMargin = 1; - ExpressionLayout * operandLayout(); + ExpressionLayout * operandLayout() { return editableChild(0); } }; } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index b141425f4..16d98a9fc 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -12,7 +12,6 @@ public: Yellow, Grey }; - // Constructor EmptyLayout(Color color = Color::Yellow, bool visible = true); ExpressionLayout * clone() const override; diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 790bd0231..3c2682621 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -254,12 +254,4 @@ KDPoint FractionLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x, y); } -ExpressionLayout * FractionLayout::numeratorLayout() { - return editableChild(0); -} - -ExpressionLayout * FractionLayout::denominatorLayout() { - return editableChild(1); -} - } diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 6eb4e9fd0..31562945f 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -10,13 +10,23 @@ class FractionLayout : public StaticLayoutHierarchy<2> { public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; + + // Collapse void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; + + // User input void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + + // Other ExpressionLayout * layoutToPointWhenInserting() override; bool canBeOmittedMultiplicationRightFactor() const override { return false; } /* WARNING: We need to override this function, else 1/2 3/4 would be @@ -32,8 +42,8 @@ protected: private: constexpr static KDCoordinate k_fractionLineMargin = 2; constexpr static KDCoordinate k_fractionLineHeight = 1; - ExpressionLayout * numeratorLayout(); - ExpressionLayout * denominatorLayout(); + ExpressionLayout * numeratorLayout() { return editableChild(0); } + ExpressionLayout * denominatorLayout() { return editableChild(1); } }; } diff --git a/poincare/src/layout/grid_layout.h b/poincare/src/layout/grid_layout.h index 499aac12e..7dd23a0e1 100644 --- a/poincare/src/layout/grid_layout.h +++ b/poincare/src/layout/grid_layout.h @@ -12,18 +12,18 @@ public: GridLayout(const ExpressionLayout * const * entryLayouts, int numberOfRows, int numberOfColumns, bool cloneOperands); ExpressionLayout * clone() const override; - /* Navigation */ + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - /* Dynamic layout */ + // Remove void removeChildAtIndex(int index, bool deleteAfterRemoval) override; - // This function replaces the child with an EmptyLayout. To delete the - // grid's children, do not call this function. + /* This function replaces the child with an EmptyLayout. To delete the grid's + * children, do not call this function. */ - /* Expression engine */ + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return 0; } protected: diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index dfce7509a..8dad484d6 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -335,25 +335,6 @@ ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor return result; } -bool HorizontalLayout::isEmpty() const { - if (m_numberOfChildren == 1 && child(0)->isEmpty()) - { - return true; - } - return false; -} - -bool HorizontalLayout::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { - if (m_numberOfChildren == 0) { - return false; - } else { - return true; - } -} - -void HorizontalLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { -} - KDSize HorizontalLayout::computeSize() { KDCoordinate totalWidth = 0; int i = 0; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index cc7690c42..b784a1547 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -17,33 +17,34 @@ public: ExpressionLayout * clone() const override; void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - /* Hierarchy */ + // Replace void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren); - /* Navigation */ + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - /* Dynamic layout */ + // Dynamic layout void addChildrenAtIndex(const ExpressionLayout * const * operands, int numberOfOperands, int indexForInsertion, bool removeEmptyChildren) override; bool addChildAtIndex(ExpressionLayout * operand, int index) override; void removeChildAtIndex(int index, bool deleteAfterRemoval) override; void mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) override; - /* Expression Engine */ + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - /* Cursor */ + // Cursor ExpressionLayoutCursor equivalentCursor(ExpressionLayoutCursor cursor) override; - /* Other */ + // Other bool isHorizontal() const override { return true; } - bool isEmpty() const override; - bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; + bool isEmpty() const override { return m_numberOfChildren == 1 && child(0)->isEmpty(); } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return m_numberOfChildren != 0; } +} protected: - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; diff --git a/poincare/src/layout/integral_layout.cpp b/poincare/src/layout/integral_layout.cpp index dca8acb70..81d4b91b0 100644 --- a/poincare/src/layout/integral_layout.cpp +++ b/poincare/src/layout/integral_layout.cpp @@ -177,11 +177,6 @@ int IntegralLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberO return numberOfChar; } -ExpressionLayout * IntegralLayout::layoutToPointWhenInserting() { - assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout(); -} - void IntegralLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { KDSize integrandSize = integrandLayout()->size(); KDSize upperBoundSize = upperBoundLayout()->size(); @@ -241,16 +236,4 @@ KDPoint IntegralLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x,y); } -ExpressionLayout * IntegralLayout::upperBoundLayout() { - return editableChild(2); -} - -ExpressionLayout * IntegralLayout::lowerBoundLayout() { - return editableChild(1); -} - -ExpressionLayout * IntegralLayout::integrandLayout() { - return editableChild(0); -} - } diff --git a/poincare/src/layout/integral_layout.h b/poincare/src/layout/integral_layout.h index d6c211124..f577fb382 100644 --- a/poincare/src/layout/integral_layout.h +++ b/poincare/src/layout/integral_layout.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -13,20 +14,23 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; ExpressionLayout * clone() const override; - /* Dynamic Layout*/ + // Dynamic Layout void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - /* Tree navigation */ + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - /* Expression Engine */ + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - /* Other */ - ExpressionLayout * layoutToPointWhenInserting() override; + // Other + ExpressionLayout * layoutToPointWhenInserting() override { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout(); + } char XNTChar() const override { return 'x'; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; @@ -39,9 +43,9 @@ private: constexpr static KDCoordinate k_integrandWidthMargin = 2; constexpr static KDCoordinate k_integrandHeigthMargin = 2; constexpr static KDCoordinate k_lineThickness = 1; - ExpressionLayout * lowerBoundLayout(); - ExpressionLayout * upperBoundLayout(); - ExpressionLayout * integrandLayout(); + ExpressionLayout * integrandLayout() { return editableChild(0); } + ExpressionLayout * lowerBoundLayout() { return editableChild(1); } + ExpressionLayout * upperBoundLayout() { return editableChild(2); } }; } diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index e4b17f582..91b74fbf3 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -10,26 +10,26 @@ public: using GridLayout::GridLayout; ExpressionLayout * clone() const override; - /* Navigation */ + // MatrixLayout + void newRowOrColumnAtIndex(int index); + void addGreySquares(); + void removeGreySquares(); + + // Tree Navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; - /* Dynamic layout */ + // Replace & remove void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) override; void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override; void removePointedChildAtIndexAndMoveCursor(int index, bool deleteAfterRemoval, ExpressionLayoutCursor * cursor) override; - /* Expression engine */ + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - /* Other */ + // Other bool isMatrix() const override { return true; } - /* Special matrix method */ - void newRowOrColumnAtIndex(int index); - void addGreySquares(); - void removeGreySquares(); - protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp index bc3532811..987862239 100644 --- a/poincare/src/layout/nth_root_layout.cpp +++ b/poincare/src/layout/nth_root_layout.cpp @@ -266,17 +266,6 @@ KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { return KDPoint(x,y); } -ExpressionLayout * NthRootLayout::radicandLayout() { - return editableChild(0); -} - -ExpressionLayout * NthRootLayout::indexLayout() { - if (numberOfChildren() > 1) { - return editableChild(1); - } - return nullptr; -} - KDSize NthRootLayout::adjustedIndexSize() { return indexLayout() != nullptr ? KDSize(max(k_leftRadixWidth, indexLayout()->size().width()), indexLayout()->size().height()) : KDSize(k_leftRadixWidth,0); } diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h index 8954435e6..4af03b082 100644 --- a/poincare/src/layout/nth_root_layout.h +++ b/poincare/src/layout/nth_root_layout.h @@ -13,19 +13,22 @@ public: using BoundedStaticLayoutHierarchy::BoundedStaticLayoutHierarchy; ExpressionLayout * clone() const override; - /* Dynamic Layout*/ + // Collapse void collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) override; + + // User input void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; - /* Tree navigation */ + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - /* Expression Engine */ + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + // Other bool hasUpperLeftIndex() const override { return numberOfChildren() > 1; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; @@ -39,9 +42,9 @@ private: constexpr static KDCoordinate k_heightMargin = 2; constexpr static KDCoordinate k_widthMargin = 2; constexpr static KDCoordinate k_radixLineThickness = 1; - ExpressionLayout * radicandLayout(); - ExpressionLayout * indexLayout(); KDSize adjustedIndexSize(); + ExpressionLayout * radicandLayout() { return editableChild(0); } + ExpressionLayout * indexLayout() { return numberOfChildren() > 1 ? editableChild(1) : nullptr; } }; } diff --git a/poincare/src/layout/sequence_layout.cpp b/poincare/src/layout/sequence_layout.cpp index 3f8a7cf35..b95f2191a 100644 --- a/poincare/src/layout/sequence_layout.cpp +++ b/poincare/src/layout/sequence_layout.cpp @@ -68,13 +68,13 @@ ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor curs return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right); } assert(cursor.pointedExpressionLayout() == this); - // Case: Left. Go to the upper bound. + // Case: Left. Go to the upper bound if (cursor.position() == ExpressionLayoutCursor::Position::Left) { assert(upperBoundLayout() != nullptr); return ExpressionLayoutCursor(upperBoundLayout(), ExpressionLayoutCursor::Position::Left); } assert(cursor.position() == ExpressionLayoutCursor::Position::Right); - // Case: Right. Ask the parent. + // Case: Right. Ask the parent if (m_parent) { return m_parent->cursorRightOf(cursor, shouldRecomputeLayout); } @@ -82,12 +82,12 @@ ExpressionLayoutCursor SequenceLayout::cursorRightOf(ExpressionLayoutCursor curs } ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // If the cursor is inside the lower bound, move it to the upper bound. + // If the cursor is inside the lower bound, move it to the upper bound if (lowerBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(lowerBoundLayout(), true)) { assert(upperBoundLayout() != nullptr); return upperBoundLayout()->cursorInDescendantsAbove(cursor, shouldRecomputeLayout); } - // If the cursor is Left of the argument, move it to the upper bound. + // If the cursor is Left of the argument, move it to the upper bound if (argumentLayout() && cursor.isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { @@ -98,12 +98,12 @@ ExpressionLayoutCursor SequenceLayout::cursorAbove(ExpressionLayoutCursor cursor } ExpressionLayoutCursor SequenceLayout::cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { - // If the cursor is inside the upper bound, move it to the lower bound. + // If the cursor is inside the upper bound, move it to the lower bound if (upperBoundLayout() && cursor.pointedExpressionLayout()->hasAncestor(upperBoundLayout(), true)) { assert(lowerBoundLayout() != nullptr); return lowerBoundLayout()->cursorInDescendantsUnder(cursor, shouldRecomputeLayout); } - // If the cursor is Left of the argument, move it to the lower bound. + // If the cursor is Left of the argument, move it to the lower bound if (argumentLayout() && cursor.isEquivalentTo(ExpressionLayoutCursor(argumentLayout(), ExpressionLayoutCursor::Position::Left))) { @@ -113,11 +113,6 @@ ExpressionLayoutCursor SequenceLayout::cursorUnder(ExpressionLayoutCursor cursor return ExpressionLayout::cursorUnder(cursor, shouldRecomputeLayout, equivalentPositionVisited); } -ExpressionLayout * SequenceLayout::layoutToPointWhenInserting() { - assert(lowerBoundLayout() != nullptr); - return lowerBoundLayout(); -} - int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits) const { assert(operatorName != nullptr); if (bufferSize == 0) { @@ -159,18 +154,6 @@ int SequenceLayout::writeDerivedClassInBuffer(const char * operatorName, char * return numberOfChar; } -ExpressionLayout * SequenceLayout::upperBoundLayout() { - return editableChild(2); -} - -ExpressionLayout * SequenceLayout::lowerBoundLayout() { - return editableChild(1); -} - -ExpressionLayout * SequenceLayout::argumentLayout() { - return editableChild(0); -} - KDSize SequenceLayout::computeSize() { KDSize lowerBoundSizeWithNEquals = HorizontalLayout(new CharLayout('n'), new CharLayout('='), lowerBoundLayout()->clone(), false).size(); LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); @@ -211,14 +194,14 @@ KDPoint SequenceLayout::positionOfChild(ExpressionLayout * eL) { } void SequenceLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - // Render the "n=". + // Render the "n=" CharLayout * dummyN = new CharLayout('n'); ExpressionLayout * lowerBoundClone = lowerBoundLayout()->clone(); HorizontalLayout dummyLayout(dummyN, new CharLayout('='), lowerBoundClone, false); KDPoint nEqualsPosition = positionOfChild(lowerBoundLayout()).translatedBy((dummyLayout.positionOfChild(lowerBoundClone)).opposite()).translatedBy(dummyLayout.positionOfChild(dummyN)); ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN->fontSize(), expressionColor, backgroundColor); - // Render the parentheses. + // Render the parentheses LeftParenthesisLayout * dummyLeftParenthesis = new LeftParenthesisLayout(); RightParenthesisLayout * dummyRightParenthesis = new RightParenthesisLayout(); HorizontalLayout dummyLayout2(dummyLeftParenthesis, argumentLayout()->clone(), dummyRightParenthesis, false); diff --git a/poincare/src/layout/sequence_layout.h b/poincare/src/layout/sequence_layout.h index ee0c57561..da9f619a6 100644 --- a/poincare/src/layout/sequence_layout.h +++ b/poincare/src/layout/sequence_layout.h @@ -2,6 +2,7 @@ #define POINCARE_SEQUENCE_LAYOUT_H #include +#include namespace Poincare { @@ -10,23 +11,32 @@ public: using StaticLayoutHierarchy::StaticLayoutHierarchy; constexpr static KDCoordinate k_symbolHeight = 15; constexpr static KDCoordinate k_symbolWidth = 9; + + // User input void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; - ExpressionLayout * layoutToPointWhenInserting() override; + + // Other + ExpressionLayout * layoutToPointWhenInserting() override { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout(); + } char XNTChar() const override { return 'n'; } protected: constexpr static KDCoordinate k_boundHeightMargin = 2; constexpr static KDCoordinate k_argumentWidthMargin = 2; int writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; - ExpressionLayout * lowerBoundLayout(); - ExpressionLayout * upperBoundLayout(); - ExpressionLayout * argumentLayout(); KDSize computeSize() override; KDPoint positionOfChild(ExpressionLayout * eL) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + ExpressionLayout * upperBoundLayout() { return editableChild(2); } + ExpressionLayout * lowerBoundLayout() { return editableChild(1); } + ExpressionLayout * argumentLayout() { return editableChild(0); } private: void computeBaseline() override; }; diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 48cd88df1..39c2466a4 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -201,20 +201,12 @@ int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int n return numberOfChar; } -ExpressionLayout * VerticalOffsetLayout::indiceLayout() { - return editableChild(0); -} - ExpressionLayout * VerticalOffsetLayout::baseLayout() { int indexInParent = parent()->indexOfChild(this); assert(indexInParent > 0); return editableParent()->editableChild(indexInParent - 1); } -void VerticalOffsetLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - // There is nothing to draw for a subscript/superscript, only the position of the child matters -} - KDSize VerticalOffsetLayout::computeSize() { KDSize indiceSize = indiceLayout()->size(); KDCoordinate width = indiceSize.width(); diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index a78b3e880..02bb3f935 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -12,20 +12,30 @@ public: Superscript }; VerticalOffsetLayout(ExpressionLayout * indice, Type type, bool cloneOperands); - Type type() const { return m_type; } ExpressionLayout * clone() const override; + + // VerticalOffsetLayout + Type type() const { return m_type; } + + // User input void deleteBeforeCursor(ExpressionLayoutCursor * cursor) override; + + // Tree navigation ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) override; ExpressionLayoutCursor cursorAbove(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; ExpressionLayoutCursor cursorUnder(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + + // Serialization int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + + // Other bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const override { return true; } protected: - ExpressionLayout * indiceLayout(); + ExpressionLayout * indiceLayout() { return editableChild(0);} ExpressionLayout * baseLayout(); - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} KDSize computeSize() override; void computeBaseline() override; KDPoint positionOfChild(ExpressionLayout * child) override; From a5d65deb3e06a04d414282704827a137632f2b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 17:39:43 +0200 Subject: [PATCH 434/459] [poincare] Remove empty base of VerticalOffset in addChildrenAtIndexLayout Change-Id: I5bd3763df7452b6994bc1d7f7471d342964e86a9 --- poincare/src/layout/condensed_sum_layout.h | 2 +- poincare/src/layout/dynamic_layout_hierarchy.cpp | 11 +++++++++++ poincare/src/layout/horizontal_layout.cpp | 8 +++++--- poincare/src/layout/horizontal_layout.h | 1 - 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/condensed_sum_layout.h b/poincare/src/layout/condensed_sum_layout.h index 9caa64345..372c9d6e8 100644 --- a/poincare/src/layout/condensed_sum_layout.h +++ b/poincare/src/layout/condensed_sum_layout.h @@ -3,7 +3,7 @@ #include #include -#include +#include namespace Poincare { diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index dac5cf894..409a0b2a3 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -59,6 +59,17 @@ void DynamicLayoutHierarchy::addChildrenAtIndex(const ExpressionLayout * const * newOperands[currentIndex++] = m_children[i]; } for (int i = 0; i < numberOfOperands; i++) { + if (i == 0 + && operands[0]->isEmpty() + && numberOfOperands > 1 + && operands[1]->mustHaveLeftSibling() + && indexForInsertion > 0) + { + /* If the first added operand is Empty because its right sibling needs a + * left sibling, remove it if any previous child could be such a left + * sibling. */ + continue; + } if (!removeEmptyChildren || !operands[i]->isEmpty() || (i < numberOfOperands-1 && operands[i+1]->mustHaveLeftSibling())) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 8dad484d6..263299ba4 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -275,9 +275,11 @@ void HorizontalLayout::removeChildAtIndex(int index, bool deleteAfterRemoval) { } void HorizontalLayout::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, int index, bool removeEmptyChildren) { - /* If the layout to insert starts with a vertical offset layout, the child - * empty layout on the left of the inserted layout (if there is one) shoul not - * be reomved, as it wil be the base for the VerticalOffsetLayout. */ + /* Before the merge, remove ay empty child that would be on the left or on the + * right of the inserted layout. + * If the layout to insert starts with a vertical offset layout, any empty + * layout child directly on the left of the inserted layout (if there is one) + * should not be removed: it will be the base for the VerticalOffsetLayout. */ bool shouldRemoveOnLeft = eL->numberOfChildren() > 0 ? !(eL->child(0)->mustHaveLeftSibling()) : true; int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); DynamicLayoutHierarchy::mergeChildrenAtIndex(eL, newIndex, removeEmptyChildren); diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index b784a1547..622ca91fa 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -42,7 +42,6 @@ public: bool isHorizontal() const override { return true; } bool isEmpty() const override { return m_numberOfChildren == 1 && child(0)->isEmpty(); } bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return m_numberOfChildren != 0; } -} protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} KDSize computeSize() override; From 31dae66dfb08989d813db1016f2f76a9bc3ffd8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 18:03:30 +0200 Subject: [PATCH 435/459] [poincare] DynLayout: Do not detach children needing to be deleted Change-Id: Id46afd541c8090268e7f48f09a07e6cb6240f445 --- poincare/include/poincare/dynamic_layout_hierarchy.h | 2 ++ poincare/src/layout/dynamic_layout_hierarchy.cpp | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/dynamic_layout_hierarchy.h b/poincare/include/poincare/dynamic_layout_hierarchy.h index 573e5be64..9d5830f11 100644 --- a/poincare/include/poincare/dynamic_layout_hierarchy.h +++ b/poincare/include/poincare/dynamic_layout_hierarchy.h @@ -35,6 +35,8 @@ public: protected: const ExpressionLayout ** m_children; int m_numberOfChildren; +private: + void removeDetachedChildren(); }; } diff --git a/poincare/src/layout/dynamic_layout_hierarchy.cpp b/poincare/src/layout/dynamic_layout_hierarchy.cpp index 409a0b2a3..ba55192b8 100644 --- a/poincare/src/layout/dynamic_layout_hierarchy.cpp +++ b/poincare/src/layout/dynamic_layout_hierarchy.cpp @@ -46,7 +46,7 @@ void DynamicLayoutHierarchy::mergeChildrenAtIndex(DynamicLayoutHierarchy * eL, i } } addChildrenAtIndex(eL->children(), eL->numberOfChildren(), indexForInsertion, removeEmptyChildren); - eL->detachChildren(); + eL->removeDetachedChildren(); delete eL; } @@ -160,4 +160,14 @@ void DynamicLayoutHierarchy::removeAndDeleteChildren() { m_numberOfChildren = 0; } +void DynamicLayoutHierarchy::removeDetachedChildren() { + int currentIndex = 0; + for (int i = 0; i < m_numberOfChildren; i++) { + if (m_children[i] != nullptr && m_children[i]->parent() == this) { + m_children[currentIndex++] = m_children[i]; + } + } + m_numberOfChildren = currentIndex; +} + } From 69414998e84cb963871bed604843a9fbc6af54a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 9 May 2018 18:22:33 +0200 Subject: [PATCH 436/459] [poincare] Fix FractionLayout::deleteBeforeCursor Change-Id: I4e09fe1203df1c67e3146912f3f3907088674f1f --- poincare/src/layout/fraction_layout.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index 3c2682621..fcb98afe9 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -71,9 +71,13 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { detachChild(numerator); detachChild(denominator); HorizontalLayout * newLayout = new HorizontalLayout(); - newLayout->addOrMergeChildAtIndex(denominator, 0, true); - newLayout->addOrMergeChildAtIndex(numerator, 0, true); // Add the denominator before the numerator to have the right order. + if (!denominator->isEmpty()) { + newLayout->addOrMergeChildAtIndex(denominator, 0, true); + } + if (!numerator->isEmpty()) { + newLayout->addOrMergeChildAtIndex(numerator, 0, true); + } replaceWith(newLayout, true); cursor->setPointedExpressionLayout(nextPointedLayout); cursor->setPosition(nextPosition); From 8276e99b1e0b80c5380343e20d5a56a2d69a9ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 11 May 2018 14:12:40 +0200 Subject: [PATCH 437/459] [calculation] Conditional jump on uninitialized boolean --- apps/calculation/edit_expression_controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index e3bf905c8..561f6bb48 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -47,7 +47,8 @@ void EditExpressionController::ContentView::reload() { EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) : DynamicViewController(parentResponder), m_historyController(historyController), - m_calculationStore(calculationStore) + m_calculationStore(calculationStore), + m_inputViewHeightIsMaximal(false) { m_cacheBuffer[0] = 0; } From 3a97776c837a2a5fbe75f9a9430b9277e570d120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 11 May 2018 14:18:32 +0200 Subject: [PATCH 438/459] [poincare] Fix bug: removing a fraction layout inside a matrix should not set the cursor outside of the matrix Example: 'Backspace' with cursor to the left of 2 (O = empty char) ------------------ ------------------ | O | | | | --- O | | |2 O | | |2 |------> | | | | | | | | | O O | | O O | | | ------------------ ------------------ instead of --------> | [2] (with bug on the grey rectangle!) --- poincare/src/layout/fraction_layout.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index fcb98afe9..d0bda642c 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -54,6 +54,14 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { ExpressionLayout * nextPointedLayout = numeratorLayout(); ExpressionLayoutCursor::Position nextPosition = ExpressionLayoutCursor::Position::Right; if (numeratorLayout()->isEmpty()) { + /* If no numeratorLayout, place the cursor to the left of denominator (as + * both cannot be empty - case handled before). */ + nextPointedLayout = denominatorLayout(); + nextPosition = ExpressionLayoutCursor::Position::Left; + if (denominatorLayout()->isHorizontal()) { + nextPointedLayout = denominatorLayout()->editableChild(0); + } +#if 0 // TODO: discard me if agreed int indexInParent = m_parent->indexOfChild(this); if (indexInParent > 0) { nextPointedLayout = m_parent->editableChild(indexInParent - 1); @@ -61,6 +69,7 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { nextPointedLayout = m_parent; nextPosition = ExpressionLayoutCursor::Position::Left; } +#endif } else if (numeratorLayout()->isHorizontal()) { nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); } From e16f24f69ea0ba8d58d1e39d82b4c91218ab8931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 11 May 2018 14:35:41 +0200 Subject: [PATCH 439/459] [poincare] Fix bug: O^O|^x --'Backspace' --> O|^x with O = Empty Layout --- poincare/src/layout/horizontal_layout.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 263299ba4..31c2f5465 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -388,7 +388,10 @@ void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres if (sibling->mustHaveLeftSibling()) { indexForInsertion = 1; } else { - removeChildAtIndex(0, true); + /* We force the removing of the child even followed by a neighbourg + * requiring a left sibling as we are about to add a sibling in first + * position anyway. */ + privateRemoveChildAtIndex(0, true, true); } } if (moveCursor) { @@ -406,7 +409,8 @@ void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres // If the last child is empty, remove it before adding the layout. int childrenCount = numberOfChildren(); if (childrenCount > 0 && editableChild(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { - removeChildAtIndex(childrenCount - 1, true); + /* Force remove the last child. */ + privateRemoveChildAtIndex(childrenCount - 1, true, true); } addOrMergeChildAtIndex(sibling, numberOfChildren(), false); if (moveCursor) { @@ -415,13 +419,17 @@ void HorizontalLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres } void HorizontalLayout::privateRemoveChildAtIndex(int index, bool deleteAfterRemoval, bool forceRemove) { + /* Remove the child before potentially adding an EmptyLayout. Indeed, adding + * a new child would remove any EmptyLayout surrounding the new child and in + * the case the child to be removed was an Empty layout, it would result in + * removing it twice if we remove it afterwards. */ + DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); /* If the child to remove is at index 0 and its right sibling must have a left * sibling (e.g. it is a VerticalOffsetLayout), replace the child with an * EmptyLayout instead of removing it. */ - if (!forceRemove && index == 0 && numberOfChildren() > 1 && child(1)->mustHaveLeftSibling()) { - addChildAtIndex(new EmptyLayout(), index + 1); + if (!forceRemove && index == 0 && numberOfChildren() > 0 && child(0)->mustHaveLeftSibling()) { + addChildAtIndex(new EmptyLayout(), 0); } - DynamicLayoutHierarchy::removeChildAtIndex(index, deleteAfterRemoval); } int HorizontalLayout::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { From 246afc26da5c625c1c7fd1d45283cab7ae88e680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 11 May 2018 16:21:07 +0200 Subject: [PATCH 440/459] [poincare] Fix infinite loop: when adding a sibling between 2 VerticalOffsets --- poincare/src/layout/expression_layout.cpp | 33 ++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index a89d27a4c..18dd90ed1 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -416,22 +416,25 @@ void ExpressionLayout::privateAddSibling(ExpressionLayoutCursor * cursor, Expres int siblingIndex = cursor->position() == ExpressionLayoutCursor::Position::Left ? indexInParent : indexInParent + 1; /* Special case: If the neighbour sibling is a VerticalOffsetLayout, let it - * handle the insertion of the new sibling. */ - ExpressionLayout * neighbour = nullptr; - if (cursor->position() == ExpressionLayoutCursor::Position::Left && indexInParent > 0) { - neighbour = m_parent->editableChild(indexInParent - 1); - } else if (cursor->position() == ExpressionLayoutCursor::Position::Right && indexInParent < m_parent->numberOfChildren() - 1) { - neighbour = m_parent->editableChild(indexInParent + 1); - } - if (neighbour != nullptr && neighbour->isVerticalOffset()) { - cursor->setPointedExpressionLayout(neighbour); - cursor->setPosition(cursor->position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left); - if (moveCursor) { - neighbour->addSiblingAndMoveCursor(cursor, sibling); - } else { - neighbour->addSibling(cursor, sibling); + * handle the insertion of the new sibling. Jump special case if this is a + * VerticalOffsetLayout to avoid infinite loop.*/ + if (!isVerticalOffset()) { + ExpressionLayout * neighbour = nullptr; + if (cursor->position() == ExpressionLayoutCursor::Position::Left && indexInParent > 0) { + neighbour = m_parent->editableChild(indexInParent - 1); + } else if (cursor->position() == ExpressionLayoutCursor::Position::Right && indexInParent < m_parent->numberOfChildren() - 1) { + neighbour = m_parent->editableChild(indexInParent + 1); + } + if (neighbour != nullptr && neighbour->isVerticalOffset()) { + cursor->setPointedExpressionLayout(neighbour); + cursor->setPosition(cursor->position() == ExpressionLayoutCursor::Position::Left ? ExpressionLayoutCursor::Position::Right : ExpressionLayoutCursor::Position::Left); + if (moveCursor) { + neighbour->addSiblingAndMoveCursor(cursor, sibling); + } else { + neighbour->addSibling(cursor, sibling); + } + return; } - return; } // Else, let the parent add the sibling. From db38f027d4e14066c4dcd62689400360e57baa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 11 May 2018 17:58:18 +0200 Subject: [PATCH 441/459] [poincare] Fix memory leak: parsed expression must be delete --- escher/src/expression_layout_field.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index c1033841c..552fe27bd 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -301,6 +301,7 @@ bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentat return false; } Poincare::ExpressionLayout * resultLayout = resultExpression->createLayout(); + delete resultExpression; // Find the pointed layout. Poincare::ExpressionLayout * pointedLayout = nullptr; if (resultLayout->isHorizontal()) { From aa13e7bc952f72f220f9dc896d36d7a953c1def3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 14 May 2018 10:36:21 +0200 Subject: [PATCH 442/459] [poincare] Fraction layout: removing a fraction layout triggered bug when cursor pointed to Empty layout which where then deleted. --- poincare/src/layout/fraction_layout.cpp | 45 ++++++++++++------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index d0bda642c..e46989131 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -50,42 +50,39 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { // denominator. Place the cursor in the middle of the juxtaposition, which // is right of the numerator. - // Prepare the cursor position. - ExpressionLayout * nextPointedLayout = numeratorLayout(); - ExpressionLayoutCursor::Position nextPosition = ExpressionLayoutCursor::Position::Right; - if (numeratorLayout()->isEmpty()) { - /* If no numeratorLayout, place the cursor to the left of denominator (as - * both cannot be empty - case handled before). */ - nextPointedLayout = denominatorLayout(); - nextPosition = ExpressionLayoutCursor::Position::Left; - if (denominatorLayout()->isHorizontal()) { - nextPointedLayout = denominatorLayout()->editableChild(0); - } -#if 0 // TODO: discard me if agreed - int indexInParent = m_parent->indexOfChild(this); - if (indexInParent > 0) { - nextPointedLayout = m_parent->editableChild(indexInParent - 1); - } else { - nextPointedLayout = m_parent; - nextPosition = ExpressionLayoutCursor::Position::Left; - } -#endif - } else if (numeratorLayout()->isHorizontal()) { - nextPointedLayout = numeratorLayout()->editableChild(numeratorLayout()->numberOfChildren() - 1); - } - // Juxtapose. ExpressionLayout * numerator = numeratorLayout(); ExpressionLayout * denominator = denominatorLayout(); detachChild(numerator); detachChild(denominator); HorizontalLayout * newLayout = new HorizontalLayout(); + // Prepare the cursor position. + ExpressionLayout * nextPointedLayout = nullptr; + ExpressionLayoutCursor::Position nextPosition = ExpressionLayoutCursor::Position::Left; // Add the denominator before the numerator to have the right order. if (!denominator->isEmpty()) { newLayout->addOrMergeChildAtIndex(denominator, 0, true); + /* The cursor should point to the left of denominator. However, if the + * pointed expression is an empty layout, it might disappear when merging + * the numerator, we therefore point to the next child which is visually + * equivalent. */ + int indexPointedLayout = newLayout->editableChild(0)->isEmpty() ? 1 : 0; + assert(newLayout->numberOfChildren() > indexPointedLayout); + nextPointedLayout = newLayout->editableChild(indexPointedLayout); } if (!numerator->isEmpty()) { newLayout->addOrMergeChildAtIndex(numerator, 0, true); + if (nextPointedLayout == nullptr) { + /* If nextPointedLayout is not defined yet, the denominator was empty + * and we want to point to the right of the numerator. It is asserted + * not to be empty because we previously handled the case of both + * numerator and denominator empty and the rightest child of a + * horizontal layout cannot be empty. */ + assert(newLayout->numberOfChildren() > 0); + nextPointedLayout = newLayout->editableChild(newLayout->numberOfChildren() - 1); + nextPosition = ExpressionLayoutCursor::Position::Right; + assert(!nextPointedLayout->isEmpty()); + } } replaceWith(newLayout, true); cursor->setPointedExpressionLayout(nextPointedLayout); From 203311f81beedfed07eaf6539df7419e618c9221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 14 May 2018 13:38:28 +0200 Subject: [PATCH 443/459] [escher] Fix reading garbage memory in TextField --- escher/src/text_field.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index d4bca8daa..ae3ff78c5 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -318,18 +318,19 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation) { buffer[bufferIndex++] = '('; } else if (eventText[i] == '}') { buffer[bufferIndex++] = ')'; - } else if (eventText[i] != '_') { + } else if (eventText[i] == '_') { + } else { buffer[bufferIndex++] = eventText[i]; } } int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(buffer); - bufferIndex = 0; + int newBufferIndex = 0; // Remove EmptyChars - for (size_t i = bufferIndex; i < eventTextSize; i++) { + for (size_t i = newBufferIndex; i < bufferIndex; i++) { if (buffer[i] != Ion::Charset::Empty) { - buffer[bufferIndex++] = buffer[i]; + buffer[newBufferIndex++] = buffer[i]; } } From d49f5e8f3aefaf5f0c42d72a1a204385b130106f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 14 May 2018 13:39:04 +0200 Subject: [PATCH 444/459] [poincare] Fix potential deferencing nullptr --- poincare/src/layout/static_layout_hierarchy.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/layout/static_layout_hierarchy.cpp b/poincare/src/layout/static_layout_hierarchy.cpp index 3d69b4384..0a2df93ae 100644 --- a/poincare/src/layout/static_layout_hierarchy.cpp +++ b/poincare/src/layout/static_layout_hierarchy.cpp @@ -52,7 +52,8 @@ void StaticLayoutHierarchy::build(const ExpressionLayout * const * operands, assert(operands != nullptr); assert(numberOfOperands <= T); for (int i = 0; i < numberOfOperands; i++) { - if (cloneOperands && operands[i] != nullptr) { + assert(operands[i] != nullptr); + if (cloneOperands) { m_children[i] = operands[i]->clone(); } else { m_children[i] = operands[i]; From 7d484dbd7fe1d066239285e5365f6ee48a7edb07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 14:16:17 +0200 Subject: [PATCH 445/459] [poincare] Fraction layout: backspace caused memory leak Empty numerator/denominator was detached from the fraction, not added to the new juxtaposition of layouts, and neither deleted. Hence, when the fraction layout was deleted, it did not delete the empty numerator/denominator. Change-Id: I453c7bb42c392fff3efa2a2fbd5f1eeeb53dad7e --- poincare/src/layout/fraction_layout.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index e46989131..b2c7632e3 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -69,6 +69,8 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { int indexPointedLayout = newLayout->editableChild(0)->isEmpty() ? 1 : 0; assert(newLayout->numberOfChildren() > indexPointedLayout); nextPointedLayout = newLayout->editableChild(indexPointedLayout); + } else { + delete denominator; } if (!numerator->isEmpty()) { newLayout->addOrMergeChildAtIndex(numerator, 0, true); @@ -83,6 +85,8 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { nextPosition = ExpressionLayoutCursor::Position::Right; assert(!nextPointedLayout->isEmpty()); } + } else { + delete numerator; } replaceWith(newLayout, true); cursor->setPointedExpressionLayout(nextPointedLayout); From 4c0273fcd2cd55c7793aa7405da4edc0e02cfcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 14:22:14 +0200 Subject: [PATCH 446/459] [poincare] Coding style Change-Id: Ia3d073038503fde758c5cc67aa485a53aafe5816 --- poincare/src/layout/fraction_layout.cpp | 20 ++++++++++---------- poincare/src/layout/horizontal_layout.cpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/poincare/src/layout/fraction_layout.cpp b/poincare/src/layout/fraction_layout.cpp index b2c7632e3..8782aafb5 100644 --- a/poincare/src/layout/fraction_layout.cpp +++ b/poincare/src/layout/fraction_layout.cpp @@ -34,21 +34,21 @@ void FractionLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * curs } void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { - // Case: Left of the denominator. - // Replace the fraction with a horizontal juxtaposition of the numerator and - // the denominator. + /* Case: Left of the denominator. + * Replace the fraction with a horizontal juxtaposition of the numerator and + * the denominator. */ if (cursor->pointedExpressionLayout() == denominatorLayout()) { assert(cursor->position() == ExpressionLayoutCursor::Position::Left); if (numeratorLayout()->isEmpty() && denominatorLayout()->isEmpty()) { - // Case: Numerator and denominator are empty. - // Move the cursor then replace the fraction with an empty layout. + /* Case: Numerator and denominator are empty. + * Move the cursor then replace the fraction with an empty layout. */ replaceWithAndMoveCursor(new EmptyLayout(), true, cursor); return; } - // Else, replace the fraction with a juxtaposition of the numerator and - // denominator. Place the cursor in the middle of the juxtaposition, which - // is right of the numerator. + /* Else, replace the fraction with a juxtaposition of the numerator and + * denominator. Place the cursor in the middle of the juxtaposition, which + * is right of the numerator. */ // Juxtapose. ExpressionLayout * numerator = numeratorLayout(); @@ -94,8 +94,8 @@ void FractionLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) { return; } - // Case: Right. - // Move Right of the denominator. + /* Case: Right. + * Move Right of the denominator. */ if (cursor->pointedExpressionLayout() == this && cursor->position() == ExpressionLayoutCursor::Position::Right) { diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 31c2f5465..139c664f5 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -166,9 +166,9 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex void HorizontalLayout::addOrMergeChildAtIndex(ExpressionLayout * eL, int index, bool removeEmptyChildren) { if (eL->isHorizontal()) { mergeChildrenAtIndex(static_cast(eL), index, removeEmptyChildren); - return; + } else { + addChildAtIndex(eL, index); } - addChildAtIndex(eL, index); } ExpressionLayoutCursor HorizontalLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) { From 83024c43a8bd9b4c304de79b25513e565b0b42c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 14:29:46 +0200 Subject: [PATCH 447/459] [apps/math_toolbox] Fix cursor position in new matrix in 1D This also fixes the creation of a matrix in 2D, when selecting the new matrix toolbox item Change-Id: I3ace2e78450b86d924c875de015a5a24c12a6374 --- apps/shared.universal.i18n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 0b4a7235a..6ee024d51 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -35,7 +35,7 @@ LcmCommandWithArg = "lcm(p,q)" LeftIntegralFirstLegend = "P(X≤" LeftIntegralSecondLegend = ")=" LogCommandWithArg = "log(x,a)" -MatrixCommand = "[[]]" +MatrixCommand = "[[•]]" MatrixCommandWithArg = "[[1,2][3,4]]" MaxCommandWithArg = "max(L)" MinCommandWithArg = "min(L)" From de799a132314d7950bc4f37dce0e58ad9d6f27d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 14:58:57 +0200 Subject: [PATCH 448/459] [escher] Remove superfluous code Change-Id: I5d0718195592c6223795c94069da7a3c345b242d --- escher/src/expression_layout_field.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 552fe27bd..dee85dadc 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -279,24 +279,7 @@ void ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) { } bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentation) { - size_t textLength = strlen(text) + 1; - size_t textToInsertMaxLength = 2*textLength; - char textToInsert[textToInsertMaxLength]; - - size_t textToInsertIndex = 0; - // Add empty chars where arguments are needed - for (size_t i = textToInsertIndex; i < textLength; i++) { - textToInsert[textToInsertIndex++] = text[i]; - if (((text[i] == '(' || text[i] == '[') - && text[i+1] == ',') - || (text[i] == ',' - && (text[i+1] == ')' || text[i+1] == ']'))) - { - textToInsert[textToInsertIndex++] = Ion::Charset::Empty; - } - } - - Poincare::Expression * resultExpression = Poincare::Expression::parse(textToInsert); + Poincare::Expression * resultExpression = Poincare::Expression::parse(text); if (resultExpression == nullptr) { return false; } From 2f55660ce4dd53108f3861fb4db550a436d442ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 15:08:02 +0200 Subject: [PATCH 449/459] [escher] Fix addding Grey Squares when adding matrix from toolbox Change-Id: Ie96122033de7ae80ddf5378f0f3fe07d52c3453e --- escher/src/expression_layout_field.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index dee85dadc..1d3afc144 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -228,9 +228,6 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la return; } m_contentView.cursor()->showEmptyLayoutIfNeeded(); - if (layout->isMatrix() && pointedLayout && pointedLayout->hasAncestor(layout)) { - static_cast(layout)->addGreySquares(); - } bool layoutWillBeMerged = layout->isHorizontal(); m_contentView.cursor()->addLayoutAndMoveCursor(layout); if (pointedLayout != nullptr && (pointedLayout != layout || !layoutWillBeMerged)) { @@ -240,6 +237,7 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la m_contentView.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); } + m_contentView.cursor()->pointedExpressionLayout()->addGreySquaresToAllMatrixAncestors(); m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); } From 9a94cbe934a0cdcf186d35c3b4bb3648afd6d622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 16:53:40 +0200 Subject: [PATCH 450/459] [poincare] Scroll to show whole layout inserted from toolbox Change-Id: If3e39659bdfc36b5e52a29845dfd213424233ab4 --- .../include/escher/expression_layout_field.h | 3 ++ escher/src/expression_layout_field.cpp | 34 +++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h index 83e8f4f95..f87e53af6 100644 --- a/escher/include/escher/expression_layout_field.h +++ b/escher/include/escher/expression_layout_field.h @@ -41,6 +41,9 @@ protected: virtual bool privateHandleEvent(Ion::Events::Event event); bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); private: + void scrollRightOfLayout(Poincare::ExpressionLayout * layout); + void scrollToBaselinedRect(KDRect rect, KDCoordinate baseline); + class ContentView : public View { public: ContentView(Poincare::ExpressionLayout * expressionLayout); diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index 1d3afc144..dd5674974 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -27,16 +27,7 @@ void ExpressionLayoutField::clearLayout() { } void ExpressionLayoutField::scrollToCursor() { - // Show the whole cursor - scrollToContentRect(m_contentView.cursorRect(), true); - // Show the cursor area around its baseline - Poincare::ExpressionLayoutCursor * cursor = m_contentView.cursor(); - KDCoordinate cursorBaseline = cursor->baseline(); - KDCoordinate underBaseline = m_contentView.cursorRect().height() - cursorBaseline; - KDCoordinate minAroundBaseline = min(cursorBaseline, underBaseline); - minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); - KDRect balancedRect(m_contentView.cursorRect().x(), m_contentView.cursorRect().y() + cursorBaseline - minAroundBaseline, Poincare::ExpressionLayoutCursor::k_cursorWidth, 2 * minAroundBaseline); - scrollToContentRect(balancedRect, true); + scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline()); } Toolbox * ExpressionLayoutField::toolbox() { @@ -229,6 +220,7 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la } m_contentView.cursor()->showEmptyLayoutIfNeeded(); bool layoutWillBeMerged = layout->isHorizontal(); + Poincare::ExpressionLayout * lastMergedLayoutChild = layoutWillBeMerged ? layout->editableChild(layout->numberOfChildren()-1) : nullptr; m_contentView.cursor()->addLayoutAndMoveCursor(layout); if (pointedLayout != nullptr && (pointedLayout != layout || !layoutWillBeMerged)) { m_contentView.cursor()->setPointedExpressionLayout(pointedLayout); @@ -240,6 +232,13 @@ void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * la m_contentView.cursor()->pointedExpressionLayout()->addGreySquaresToAllMatrixAncestors(); m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); + if (!layoutWillBeMerged) { + scrollRightOfLayout(layout); + } else { + assert(lastMergedLayoutChild != nullptr); + scrollRightOfLayout(lastMergedLayoutChild); + } + scrollToCursor(); } void ExpressionLayoutField::insertLayoutFromTextAtCursor(const char * text) { @@ -313,3 +312,18 @@ void ExpressionLayoutField::setBackgroundColor(KDColor c) { ScrollableView::setBackgroundColor(c); m_contentView.setBackgroundColor(c); } + +void ExpressionLayoutField::scrollRightOfLayout(Poincare::ExpressionLayout * layout) { + KDRect layoutRect(layout->absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layout->size()); + scrollToBaselinedRect(layoutRect, layout->baseline()); +} + +void ExpressionLayoutField::scrollToBaselinedRect(KDRect rect, KDCoordinate baseline) { + scrollToContentRect(rect, true); + // Show the rect area around its baseline + KDCoordinate underBaseline = rect.height() - baseline; + KDCoordinate minAroundBaseline = min(baseline, underBaseline); + minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); + KDRect balancedRect(rect.x(), rect.y() + baseline - minAroundBaseline, rect.width(), 2 * minAroundBaseline); + scrollToContentRect(balancedRect, true); +} From 87194941da033df3c5766d630231ca0f13a409e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 14 May 2018 17:55:16 +0200 Subject: [PATCH 451/459] [poincare] Comment: HorizontalLayout should not have Horizontal children Change-Id: I35186fe09d169ff9aeadc9b903f16d2f046f27a0 --- poincare/src/layout/horizontal_layout.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 622ca91fa..f4f0b03b9 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -7,6 +7,9 @@ namespace Poincare { +/* WARNING: A Horizontal Layout should never have a Horizontal Layout child. + * For instance, use addOrMergeChildAtIndex to add an ExpressionLayout safely. */ + class HorizontalLayout : public DynamicLayoutHierarchy { friend class BinomialCoefficientLayout; friend class IntegralLayout; From 2c16a57ef73dc6d2b5deb3109b82e923a82548e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 10:37:09 +0200 Subject: [PATCH 452/459] [poincare] Fix PowerLayout::privateCreateLayout A HorizontalLayout should not have a HorizontalLayout child Change-Id: I300e71103a1f72f8ab8293adfb0d1a0b86059f7a --- poincare/src/power.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 412ead979..c5c2ef32c 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -151,13 +151,14 @@ ExpressionLayout * Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = m_operands[1]->operand(0); } - return new HorizontalLayout( - m_operands[0]->createLayout(floatDisplayMode, complexFormat), - new VerticalOffsetLayout( + HorizontalLayout * result = new HorizontalLayout(); + result->addOrMergeChildAtIndex(m_operands[0]->createLayout(floatDisplayMode, complexFormat), 0, false); + result->addChildAtIndex(new VerticalOffsetLayout( indiceOperand->createLayout(floatDisplayMode, complexFormat), VerticalOffsetLayout::Type::Superscript, false), - false); + result->numberOfChildren()); + return result; } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { From 0c7cd1fe6bda8cafc6de1f4b35528848ad740cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 10:37:56 +0200 Subject: [PATCH 453/459] [poincare] Coding style Change-Id: Ie08fa0fa4eb6098d089e0919b35cc1dcd7a86409 --- poincare/src/opposite.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 3d307a086..249ad84ce 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -72,9 +72,9 @@ ExpressionLayout * Opposite::privateCreateLayout(PrintFloat::Mode floatDisplayMo HorizontalLayout * result = new HorizontalLayout(new CharLayout('-'), false); if (operand(0)->type() == Type::Opposite) { result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1, false); - return result; + } else { + result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); } - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); return result; } From 48d1d248eaabec917cff5db1a56666661d8df5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 11:03:07 +0200 Subject: [PATCH 454/459] [poincare] Fix cursor position in 2D when inserting "random()" Change-Id: I3851e79cd7b0a1f2b1b13c4cf7c604ad0d95d6d3 --- escher/src/expression_layout_field.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp index dd5674974..1cd523a86 100644 --- a/escher/src/expression_layout_field.cpp +++ b/escher/src/expression_layout_field.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -284,7 +285,11 @@ bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentat delete resultExpression; // Find the pointed layout. Poincare::ExpressionLayout * pointedLayout = nullptr; - if (resultLayout->isHorizontal()) { + if (strcmp(text, I18n::translate(I18n::Message::RandomCommandWithArg)) == 0) { + /* Special case: if the text is "random()", the cursor should not be set + * inside the parentheses. */ + pointedLayout = resultLayout; + } else if (resultLayout->isHorizontal()) { /* If the layout is horizontal, pick the first open parenthesis. For now, * all horizontal layouts in MathToolbox have parentheses. */ for (int i = 0; i < resultLayout->numberOfChildren(); i++) { From c70feb9a46d4aa78868ef09b0dc6588f7e1309bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 11:33:51 +0200 Subject: [PATCH 455/459] [poincare] Fix SumGraphController CondensSumLayout size on second step Change-Id: Ia9608ccf6b556183ed8def852d35a9096aeaac19 --- apps/shared/sum_graph_controller.cpp | 2 +- poincare/src/layout/empty_layout.cpp | 18 ++++++++++-------- poincare/src/layout/empty_layout.h | 9 ++++++--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index c7db7491e..49a31a458 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -251,7 +251,7 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl m_sumLayout = new CondensedSumLayout( LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), - new EmptyLayout(EmptyLayout::Color::Yellow, false), + new EmptyLayout(EmptyLayout::Color::Yellow, false, KDText::FontSize::Small, false), false); } else { char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; diff --git a/poincare/src/layout/empty_layout.cpp b/poincare/src/layout/empty_layout.cpp index 6744aec61..535599ec5 100644 --- a/poincare/src/layout/empty_layout.cpp +++ b/poincare/src/layout/empty_layout.cpp @@ -6,15 +6,17 @@ namespace Poincare { -EmptyLayout::EmptyLayout(Color color, bool visible) : +EmptyLayout::EmptyLayout(Color color, bool visible, KDText::FontSize size, bool margins) : StaticLayoutHierarchy(), m_isVisible(visible), - m_color(color) + m_color(color), + m_size(size), + m_margins(margins) { } ExpressionLayout * EmptyLayout::clone() const { - EmptyLayout * layout = new EmptyLayout(m_color, m_isVisible); + EmptyLayout * layout = new EmptyLayout(m_color, m_isVisible, m_size, m_margins); return layout; } @@ -56,18 +58,18 @@ int EmptyLayout::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSi void EmptyLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { if (m_isVisible) { KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); - ctx->fillRect(KDRect(p.x()+k_marginWidth, p.y()+k_marginHeight, k_width, k_height), fillColor); + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); } } KDSize EmptyLayout::computeSize() { - KDCoordinate width = m_isVisible ? k_width + 2*k_marginWidth : 0; - return KDSize(width, k_height + 2*k_marginHeight); + KDCoordinate sizeWidth = m_isVisible ? width() + 2*(m_margins ? k_marginWidth : 0) : 0; + return KDSize(sizeWidth, height() + 2*(m_margins ? k_marginHeight : 0)); } void EmptyLayout::computeBaseline() { - m_baseline = k_marginHeight + k_height/2; + m_baseline = (m_margins ? k_marginHeight : 0) + height()/2; m_baselined = true; } diff --git a/poincare/src/layout/empty_layout.h b/poincare/src/layout/empty_layout.h index 16d98a9fc..77ce71b3a 100644 --- a/poincare/src/layout/empty_layout.h +++ b/poincare/src/layout/empty_layout.h @@ -2,6 +2,7 @@ #define POINCARE_empty_layout_H #include +#include #include namespace Poincare { @@ -12,7 +13,7 @@ public: Yellow, Grey }; - EmptyLayout(Color color = Color::Yellow, bool visible = true); + EmptyLayout(Color color = Color::Yellow, bool visible = true, KDText::FontSize size = KDText::FontSize::Large, bool margins = true); ExpressionLayout * clone() const override; // EmptyLayout @@ -44,14 +45,16 @@ protected: } void privateAddSibling(ExpressionLayoutCursor * cursor, ExpressionLayout * sibling, bool moveCursor) override; private: - constexpr static KDCoordinate k_width = 7; - constexpr static KDCoordinate k_height = 12; constexpr static KDCoordinate k_marginWidth = 1; constexpr static KDCoordinate k_marginHeight = 3; constexpr static KDCoordinate k_lineThickness = 1; ExpressionLayoutCursor cursorVerticalOf(VerticalDirection direction, ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; + KDCoordinate height() const { return KDText::charSize(m_size).height() - 2*k_marginHeight; } + KDCoordinate width() const { return KDText::charSize(m_size).width() - 2*k_marginWidth; } bool m_isVisible; Color m_color; + KDText::FontSize m_size; + bool m_margins; }; } From 4e6b12114f25a7f85a81d1adb7911550141eaabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 13:52:52 +0200 Subject: [PATCH 456/459] [poincare] Remove DEBUG comment Change-Id: Ia9d35816bb71ad81f6b3d03e3e3184b1697b1c67 --- poincare/src/layout_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 65fc1ef3d..df39f8145 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -104,7 +104,7 @@ int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expre buffer[bufferSize-1] = 0; int numberOfChar = 0; int numberOfOperands = (expression != nullptr) ? expression->numberOfOperands() : expressionLayout->numberOfChildren(); - assert(numberOfOperands > 0); //TODO MERGE SAISIEJOLIE 1 dans HEAD + assert(numberOfOperands > 0); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } From a84686d2626d94eee09f82451eb018f56a4d3fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 14:32:26 +0200 Subject: [PATCH 457/459] [poincare] Finer addition of parenthesis when serializing fraction Change-Id: I48f4fdad8185ab97916dcfc9b6f56e786854fe2a --- poincare/include/poincare/expression_layout.h | 2 + poincare/include/poincare/layout_engine.h | 7 +-- poincare/src/layout/fraction_layout.h | 1 + poincare/src/layout/horizontal_layout.cpp | 13 +++++ poincare/src/layout/horizontal_layout.h | 1 + .../src/layout/vertical_offset_layout.cpp | 7 ++- poincare/src/layout/vertical_offset_layout.h | 1 + poincare/src/layout_engine.cpp | 49 +++++++++++-------- 8 files changed, 53 insertions(+), 28 deletions(-) diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index c4af5a2c2..ba59e8a71 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -102,6 +102,8 @@ public: bool addGreySquaresToAllMatrixAncestors(); bool removeGreySquaresFromAllMatrixAncestors(); bool hasText() const; + virtual bool needsParenthesesWithParent() const { return false; } + virtual bool childMightNeedParentheses() const { return false; } virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } /* isCollapsable is used when adding a sibling fraction: should the layout be * inserted in the numerator (or denominator)? For instance, 1+2|3-4 should diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 818f38e82..b70df9671 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -32,7 +32,6 @@ public: const char * operatorName); /* ExpressionLayout to Text */ - typedef bool (*ChildNeedsParenthesis)(const char * operatorName); static int writeInfixExpressionLayoutTextInBuffer( const ExpressionLayout * expressionLayout, char * buffer, @@ -40,9 +39,7 @@ public: int numberOfDigits, const char * operatorName, int firstChildIndex = 0, - int lastChildIndex = -1, - ChildNeedsParenthesis childNeedsParenthesis = [](const char * operatorName) { - return (operatorName[1] == 0 && (operatorName[0] == divideChar)); }); + int lastChildIndex = -1); static int writePrefixExpressionLayoutTextInBuffer( const ExpressionLayout * expressionLayout, char * buffer, @@ -57,7 +54,7 @@ public: private: static constexpr char divideChar = '/'; // These two functions return the index of the null-terminating char. - static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis); + static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex); static int writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, bool writeFirstChild = true); }; diff --git a/poincare/src/layout/fraction_layout.h b/poincare/src/layout/fraction_layout.h index 31562945f..6ababe90e 100644 --- a/poincare/src/layout/fraction_layout.h +++ b/poincare/src/layout/fraction_layout.h @@ -34,6 +34,7 @@ public: * an omitted multiplication layout factor. We have the same problem with * 2^3 1/2 being serialized as 2^3**1/2, so must override the Right version * and not canBeOmittedMultiplicationLeftFactor. */ + bool childMightNeedParentheses() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 139c664f5..a9ea44039 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -337,6 +337,19 @@ ExpressionLayoutCursor HorizontalLayout::equivalentCursor(ExpressionLayoutCursor return result; } +bool HorizontalLayout::needsParenthesesWithParent() const { + if (!parent()->childMightNeedParentheses()) { + return false; + } + int numberOfOpenParenthesis = 0; + for (int i = 0; i < numberOfChildren(); i++) { + if (!child(i)->isCollapsable(&numberOfOpenParenthesis, true)) { + return true; + } + } + return false; +} + KDSize HorizontalLayout::computeSize() { KDCoordinate totalWidth = 0; int i = 0; diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index f4f0b03b9..d70a9d826 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -44,6 +44,7 @@ public: // Other bool isHorizontal() const override { return true; } bool isEmpty() const override { return m_numberOfChildren == 1 && child(0)->isEmpty(); } + bool needsParenthesesWithParent() const override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return m_numberOfChildren != 0; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} diff --git a/poincare/src/layout/vertical_offset_layout.cpp b/poincare/src/layout/vertical_offset_layout.cpp index 39c2466a4..ef34b5350 100644 --- a/poincare/src/layout/vertical_offset_layout.cpp +++ b/poincare/src/layout/vertical_offset_layout.cpp @@ -185,8 +185,11 @@ int VerticalOffsetLayout::writeTextInBuffer(char * buffer, int bufferSize, int n return numberOfChar; } assert(m_type == Type::Superscript); - // If the layout is a superscript, write "^(indice)" - int numberOfChar = LayoutEngine::writePrefixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "^"); + // If the layout is a superscript, write "^indice", with parentheses if needed + int numberOfChar = LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '^'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits, "^"); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Add a multiplication if omitted. int indexInParent = -1; diff --git a/poincare/src/layout/vertical_offset_layout.h b/poincare/src/layout/vertical_offset_layout.h index 02bb3f935..8741c49ce 100644 --- a/poincare/src/layout/vertical_offset_layout.h +++ b/poincare/src/layout/vertical_offset_layout.h @@ -32,6 +32,7 @@ public: // Other bool mustHaveLeftSibling() const override { return true; } bool isVerticalOffset() const override { return true; } + bool childMightNeedParentheses() const override { return m_type == Type::Superscript; } protected: ExpressionLayout * indiceLayout() { return editableChild(0);} ExpressionLayout * baseLayout(); diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index df39f8145..51faab43b 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -81,22 +81,22 @@ ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, Ex } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName) { - return writeInfixExpressionOrExpressionLayoutTextInBuffer(expression, nullptr, buffer, bufferSize, numberOfDigits, operatorName, 0, -1, [](const char * operatorName) { return true; }); + return writeInfixExpressionOrExpressionLayoutTextInBuffer(expression, nullptr, buffer, bufferSize, numberOfDigits, operatorName, 0, -1); } int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName) { return writePrefixExpressionOrExpressionLayoutTextInBuffer(expression, nullptr, buffer, bufferSize, numberOfDigits, operatorName); } -int LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis) { - return writeInfixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, numberOfDigits, operatorName, firstChildIndex, lastChildIndex, childNeedsParenthesis); +int LayoutEngine::writeInfixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex) { + return writeInfixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, numberOfDigits, operatorName, firstChildIndex, lastChildIndex); } int LayoutEngine::writePrefixExpressionLayoutTextInBuffer(const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, bool writeFirstChild) { return writePrefixExpressionOrExpressionLayoutTextInBuffer(nullptr, expressionLayout, buffer, bufferSize, numberOfDigits, operatorName, writeFirstChild); } -int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis) { +int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex) { assert(expression != nullptr || expressionLayout != nullptr); if (bufferSize == 0) { return -1; @@ -109,37 +109,44 @@ int LayoutEngine::writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expre return bufferSize-1; } - if ((expression != nullptr && expression->operand(firstChildIndex)->needParenthesisWithParent(expression)) - || (expression == nullptr && childNeedsParenthesis(operatorName))) - { - buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { - return bufferSize-1; - } - } + bool currentChildNeedsParentheses = + (expression != nullptr + && expression->operand(firstChildIndex)->needParenthesisWithParent(expression)) + || (expression == nullptr + && expressionLayout->child(firstChildIndex)->needsParenthesesWithParent()); + // Write first operand + if (currentChildNeedsParentheses){ + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } numberOfChar += (expression != nullptr) ? expression->operand(firstChildIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfDigits) : expressionLayout->child(firstChildIndex)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfDigits); - if ((expression != nullptr && expression->operand(firstChildIndex)->needParenthesisWithParent(expression)) - || (expression == nullptr && childNeedsParenthesis(operatorName))) - { + if (currentChildNeedsParentheses){ buffer[numberOfChar++] = ')'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } + int lastIndex = lastChildIndex < 0 ? numberOfOperands - 1 : lastChildIndex; for (int i = firstChildIndex + 1; i < lastIndex+1; i++) { if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write operator numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - if ((expression != nullptr && expression->operand(i)->needParenthesisWithParent(expression)) - || (expression == nullptr && childNeedsParenthesis(operatorName))) - { + + // Write next operand + currentChildNeedsParentheses = + (expression != nullptr + && expression->operand(i)->needParenthesisWithParent(expression)) + || (expression == nullptr + && expressionLayout->child(i)->needsParenthesesWithParent()); + + if (currentChildNeedsParentheses) { buffer[numberOfChar++] = '('; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } numberOfChar += (expression != nullptr) ? expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfDigits) : expressionLayout->child(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfDigits); - if ((expression != nullptr && expression->operand(i)->needParenthesisWithParent(expression)) - || (expression == nullptr && childNeedsParenthesis(operatorName))) - { + if (currentChildNeedsParentheses) { buffer[numberOfChar++] = ')'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } From 16de5291bbb89546567c394fe6579f780db20ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 16:29:35 +0200 Subject: [PATCH 458/459] [apps/sequence] Fix "Un" size in sequence table Change-Id: I8f46a2f6f49da08a58d8c24252cf9fa8d09d2a0e --- apps/sequence/sequence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index e6775f127..d42e29a87 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -224,7 +224,7 @@ int Sequence::numberOfElements() { Poincare::ExpressionLayout * Sequence::nameLayout() { if (m_nameLayout == nullptr) { m_nameLayout = new HorizontalLayout( - new CharLayout(name()[0], KDText::FontSize::Large), + new CharLayout(name()[0], KDText::FontSize::Small), new VerticalOffsetLayout(new CharLayout('n', KDText::FontSize::Small), VerticalOffsetLayout::Type::Subscript, false), false); } From 379dcdba1a5951396c69653b8205b7198a091b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 15 May 2018 18:05:32 +0200 Subject: [PATCH 459/459] [poincarE] Add unary tests on Layouts. Change-Id: I21f33e84eb4a60ecbabbba99a966abed6a23039c --- poincare/Makefile | 4 ++ poincare/test/binomial_coefficient_layout.cpp | 10 +++ poincare/test/fraction_layout.cpp | 68 +++++++++++++++++++ poincare/test/helper.cpp | 29 ++++++++ poincare/test/helper.h | 6 ++ poincare/test/nth_root_layout.cpp | 10 +++ poincare/test/parentheses_layout.cpp | 32 +++++++++ poincare/test/vertical_offset_layout.cpp | 23 +++++++ 8 files changed, 182 insertions(+) create mode 100644 poincare/test/binomial_coefficient_layout.cpp create mode 100644 poincare/test/fraction_layout.cpp create mode 100644 poincare/test/nth_root_layout.cpp create mode 100644 poincare/test/parentheses_layout.cpp create mode 100644 poincare/test/vertical_offset_layout.cpp diff --git a/poincare/Makefile b/poincare/Makefile index ab2450b03..4ef675962 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -121,16 +121,19 @@ objs += $(addprefix poincare/src/layout/,\ tests += $(addprefix poincare/test/,\ addition.cpp\ arithmetic.cpp\ + binomial_coefficient_layout.cpp\ complex.cpp\ convert_expression_to_text.cpp\ division.cpp\ factorial.cpp\ + fraction_layout.cpp\ function.cpp\ helper.cpp\ integer.cpp\ logarithm.cpp\ matrix.cpp\ multiplication.cpp\ + nth_root_layout.cpp\ parser.cpp\ power.cpp\ properties.cpp\ @@ -140,6 +143,7 @@ tests += $(addprefix poincare/test/,\ symbol.cpp\ store.cpp\ trigo.cpp\ + vertical_offset_layout.cpp\ ) # simplify_utils.cpp\ diff --git a/poincare/test/binomial_coefficient_layout.cpp b/poincare/test/binomial_coefficient_layout.cpp new file mode 100644 index 000000000..c7960c551 --- /dev/null +++ b/poincare/test/binomial_coefficient_layout.cpp @@ -0,0 +1,10 @@ +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_binomial_coefficient_layout_serialize) { + assert_parsed_expression_layout_serialize_to_self("binomial(7,6)"); +} diff --git a/poincare/test/fraction_layout.cpp b/poincare/test/fraction_layout.cpp new file mode 100644 index 000000000..a2e060917 --- /dev/null +++ b/poincare/test/fraction_layout.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_fraction_layout_create) { + + /* 12 + * 12|34+5 -> "Divide" -> --- + 5 + * |34 + * */ + HorizontalLayout * layout = static_cast(LayoutEngine::createStringLayout("1234+5", 6)); + ExpressionLayoutCursor cursor(layout->editableChild(2), ExpressionLayoutCursor::Position::Left); + cursor.addFractionLayoutAndCollapseSiblings(); + assert_expression_layout_serialize_to(layout, "12/34+5"); + assert(cursor.isEquivalentTo(ExpressionLayoutCursor(layout->editableChild(0)->editableChild(1), ExpressionLayoutCursor::Position::Left))); + delete layout; +} + +QUIZ_CASE(poincare_fraction_layout_delete) { + + /* 12 + * --- -> "BackSpace" -> 12|34 + * |34 + * */ + HorizontalLayout * layout1 = new HorizontalLayout( + new FractionLayout( + LayoutEngine::createStringLayout("12", 2), + LayoutEngine::createStringLayout("34", 2), + false), + false); + ExpressionLayoutCursor cursor1(layout1->editableChild(0)->editableChild(1), ExpressionLayoutCursor::Position::Left); + cursor1.performBackspace(); + assert_expression_layout_serialize_to(layout1, "1234"); + assert(cursor1.isEquivalentTo(ExpressionLayoutCursor(layout1->editableChild(1), ExpressionLayoutCursor::Position::Right))); + delete layout1; + + /* • + * 1 + --- -> "BackSpace" -> 1+|3 + * |3 + * */ + HorizontalLayout * layout2 = new HorizontalLayout( + new CharLayout('1'), + new CharLayout('+'), + new FractionLayout( + new EmptyLayout(), + new CharLayout('3'), + false), + false); + ExpressionLayoutCursor cursor2(layout2->editableChild(2)->editableChild(1), ExpressionLayoutCursor::Position::Left); + cursor2.performBackspace(); + assert_expression_layout_serialize_to(layout2, "1+3"); + assert(cursor2.isEquivalentTo(ExpressionLayoutCursor(layout2->editableChild(1), ExpressionLayoutCursor::Position::Right))); + delete layout2; +} + +QUIZ_CASE(poincare_fraction_layout_serialize) { + FractionLayout * layout = new FractionLayout( + new CharLayout('1'), + LayoutEngine::createStringLayout("2+3", 3), + false); + assert_expression_layout_serialize_to(layout, "1/(2+3)"); + delete layout; +} diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 801ecd684..c1e658f7c 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -106,5 +106,34 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * delete e; } +void assert_parsed_expression_layout_serialize_to_self(const char * expressionLayout) { + Expression * e = parse_expression(expressionLayout); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- Serialize: " << expressionLayout << "----" << endl; +#endif + ExpressionLayout * el = e->createLayout(); + int bufferSize = 255; + char buffer[bufferSize]; + el->writeTextInBuffer(buffer, bufferSize); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- serialized to: " << buffer << " ----\n" << endl; +#endif + assert(strcmp(expressionLayout, buffer) == 0); + delete e; + delete el; +} + +void assert_expression_layout_serialize_to(Poincare::ExpressionLayout * layout, const char * serialization) { + int bufferSize = 255; + char buffer[bufferSize]; + layout->writeTextInBuffer(buffer, bufferSize); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- Serialize: " << serialization << "----" << endl; + cout << "---- serialized to: " << buffer << " ----" << endl; + cout << "----- compared to: " << serialization << " ----\n" << endl; +#endif + assert(strcmp(serialization, buffer) == 0); +} + template void assert_parsed_expression_evaluates_to(char const*, Poincare::Complex*, int, int, Poincare::Expression::AngleUnit); template void assert_parsed_expression_evaluates_to(char const*, Poincare::Complex*, int, int, Poincare::Expression::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 460e7bd03..f182418dd 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -1,5 +1,7 @@ #include +// Expressions + constexpr Poincare::Expression::AngleUnit Degree = Poincare::Expression::AngleUnit::Degree; constexpr Poincare::Expression::AngleUnit Radian = Poincare::Expression::AngleUnit::Radian; @@ -15,3 +17,7 @@ void assert_parsed_expression_evaluates_to(const char * expression, Poincare::Co assert_parsed_expression_evaluates_to(expression, results, 0, 0, angleUnit); } void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Poincare::Expression::AngleUnit angleUnit = Poincare::Expression::AngleUnit::Radian); + +// Layouts +void assert_parsed_expression_layout_serialize_to_self(const char * expressionLayout); +void assert_expression_layout_serialize_to(Poincare::ExpressionLayout * layout, const char * serialization); diff --git a/poincare/test/nth_root_layout.cpp b/poincare/test/nth_root_layout.cpp new file mode 100644 index 000000000..ea0debc7e --- /dev/null +++ b/poincare/test/nth_root_layout.cpp @@ -0,0 +1,10 @@ +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_nth_root_layout_serialize) { + assert_parsed_expression_layout_serialize_to_self("root(7,3)"); +} diff --git a/poincare/test/parentheses_layout.cpp b/poincare/test/parentheses_layout.cpp new file mode 100644 index 000000000..0b175a54d --- /dev/null +++ b/poincare/test/parentheses_layout.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_parenthesis_layout_size) { + /* 3 + * (2+(---)6)1 + * 4 + * Assert that the first and last parentheses have the same size. + */ + HorizontalLayout * layout = new HorizontalLayout(); + LeftParenthesisLayout leftPar = new LeftParenthesisLayout(); + RightParenthesisLayout rightPar = new RightParenthesisLayout(); + layout->addChildAtIndex(leftPar, 0); + layout->addChildAtIndex(new CharLayout('2'), 1); + layout->addChildAtIndex(new CharLayout('+'), 2); + layout->addChildAtIndex(new LeftParenthesisLayout(), 3); + layout->addChildAtIndex(new FractionLayout( + new CharLayout('3'), + new CharLayout('4')), + 4); + layout->addChildAtIndex(new RightParenthesisLayout(), 3); + layout->addChildAtIndex(new CharLayout('6'), 5); + layout->addChildAtIndex(rightPar, 7); + layout->addChildAtIndex(new CharLayout('1'), 8); + assert(leftPar->size().height() == rightPar->size().height()); + delete layout; +} diff --git a/poincare/test/vertical_offset_layout.cpp b/poincare/test/vertical_offset_layout.cpp new file mode 100644 index 000000000..bea971293 --- /dev/null +++ b/poincare/test/vertical_offset_layout.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include "helper.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_vertical_offset_layout_serialize) { + assert_parsed_expression_layout_serialize_to_self("2^3"); + + HorizontalLayout * layout = new HorizontalLayout( + new CharLayout('2'), + new VerticalOffsetLayout( + LayoutEngine::createStringLayout("4+5", 3), + VerticalOffsetLayout::Type::Superscript, + false), + false); + assert_expression_layout_serialize_to(layout, "2^(4+5)"); + delete layout; + +}