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] [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;