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); };