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;