diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 582f9fde4..d7790814c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -108,6 +108,7 @@ public: // TODO: put private virtual bool willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { return true; } virtual bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { return true; } + virtual void willAddSiblingToEmptyChildAtIndex(int childIndex) {} virtual bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force); virtual void didReplaceChildAtIndex(int index, LayoutCursor * cursor, bool force) {} virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force); diff --git a/poincare/include/poincare/matrix_layout_node.h b/poincare/include/poincare/matrix_layout_node.h index 152aff69f..bf6408fff 100644 --- a/poincare/include/poincare/matrix_layout_node.h +++ b/poincare/include/poincare/matrix_layout_node.h @@ -13,13 +13,13 @@ public: using GridLayoutNode::GridLayoutNode; // MatrixLayoutNode - void newRowOrColumnAtIndex(int index); void addGreySquares(); void removeGreySquares(); // LayoutNode void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void willAddSiblingToEmptyChildAtIndex(int childIndex) override; bool isMatrix() const override { return true; } // SerializableNode @@ -37,11 +37,11 @@ protected: // LayoutNode void computeSize() override; KDPoint positionOfChild(LayoutNode * l) override; - void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; + void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; private: // MatrixNode - void childWasReplacedAtIndex(int index); + void newRowOrColumnAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; bool hasGreySquares() const; diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 2f898eb42..8610ab7f6 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -77,10 +77,19 @@ bool EmptyLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling * being filled in, so add a new empty row or column. */ LayoutNode * parentNode = parent(); assert(parentNode != nullptr); - static_cast(parentNode)->newRowOrColumnAtIndex(parentNode->indexOfChild(this)); - // WARNING: Do not use "this" afterwards. + LayoutRef parentRef(parentNode); + parentNode->willAddSiblingToEmptyChildAtIndex(parentRef.indexOfChild(thisRef)); + // WARNING: Do not use previous node pointers afterwards. + bool shouldContinueAddition = !(parentRef.isAllocationFailure()); + if (!shouldContinueAddition) { + if (moveCursor) { + cursor->setLayoutReference(parentRef); + } + return false; + } + } - if (sibling->mustHaveLeftSibling()) { + if (siblingRef.mustHaveLeftSibling()) { thisRef.setColor(Color::Yellow); return true; } else { diff --git a/poincare/src/matrix_layout_node.cpp b/poincare/src/matrix_layout_node.cpp index 314ed5b86..967771298 100644 --- a/poincare/src/matrix_layout_node.cpp +++ b/poincare/src/matrix_layout_node.cpp @@ -8,35 +8,6 @@ namespace Poincare { // MatrixLayoutNode -void MatrixLayoutNode::newRowOrColumnAtIndex(int index) { - assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows); - bool shouldAddNewRow = childIsBottomOfGrid(index); // We need to compute this boolean before modifying the layout - int correspondingRow = rowAtChildIndex(index); - if (childIsRightOfGrid(index)) { - // Color the grey EmptyLayouts of the column in yellow. - int correspondingColumn = m_numberOfColumns - 1; - for (int i = 0; i < m_numberOfRows - 1; i++) { - LayoutNode * lastLayoutOfRow = childAtIndex(i*m_numberOfColumns+correspondingColumn); - if (lastLayoutOfRow->isEmpty()) { - static_cast(lastLayoutOfRow)->setColor(EmptyLayoutNode::Color::Yellow); - } - } - // Add a column of grey EmptyLayouts on the right. - addEmptyColumn(EmptyLayoutNode::Color::Grey); - } - if (shouldAddNewRow) { - // Color the grey EmptyLayouts of the row in yellow. - for (int i = 0; i < m_numberOfColumns - 1; i++) { - LayoutNode * lastLayoutOfColumn = childAtIndex(correspondingRow*m_numberOfColumns+i); - if (lastLayoutOfColumn->isEmpty()) { - static_cast(lastLayoutOfColumn)->setColor(EmptyLayoutNode::Color::Yellow); - } - } - // Add a row of grey EmptyLayouts at the bottom. - addEmptyRow(EmptyLayoutNode::Color::Grey); - } -} - void MatrixLayoutNode::addGreySquares() { if (!hasGreySquares()) { addEmptyRow(EmptyLayoutNode::Color::Grey); @@ -113,6 +84,11 @@ void MatrixLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecom GridLayoutNode::moveCursorRight(cursor, shouldRecomputeLayout); } +void MatrixLayoutNode::willAddSiblingToEmptyChildAtIndex(int childIndex) { + if (childIsRightOfGrid(childIndex) || childIsBottomOfGrid(childIndex)) { + newRowOrColumnAtIndex(childIndex); + } +} // SerializableNode @@ -183,6 +159,35 @@ void MatrixLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutC // Private +void MatrixLayoutNode::newRowOrColumnAtIndex(int index) { + assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows); + bool shouldAddNewRow = childIsBottomOfGrid(index); // We need to compute this boolean before modifying the layout + int correspondingRow = rowAtChildIndex(index); + if (childIsRightOfGrid(index)) { + // Color the grey EmptyLayouts of the column in yellow. + int correspondingColumn = m_numberOfColumns - 1; + for (int i = 0; i < m_numberOfRows - 1; i++) { + LayoutNode * lastLayoutOfRow = childAtIndex(i*m_numberOfColumns+correspondingColumn); + if (lastLayoutOfRow->isEmpty()) { + static_cast(lastLayoutOfRow)->setColor(EmptyLayoutNode::Color::Yellow); + } + } + // Add a column of grey EmptyLayouts on the right. + addEmptyColumn(EmptyLayoutNode::Color::Grey); + } + if (shouldAddNewRow) { + // Color the grey EmptyLayouts of the row in yellow. + for (int i = 0; i < m_numberOfColumns - 1; i++) { + LayoutNode * lastLayoutOfColumn = childAtIndex(correspondingRow*m_numberOfColumns+i); + if (lastLayoutOfColumn->isEmpty()) { + static_cast(lastLayoutOfColumn)->setColor(EmptyLayoutNode::Color::Yellow); + } + } + // Add a row of grey EmptyLayouts at the bottom. + addEmptyRow(EmptyLayoutNode::Color::Grey); + } +} + bool MatrixLayoutNode::isRowEmpty(int index) const { assert(index >= 0 && index < m_numberOfRows); for (int i = index * m_numberOfColumns; i < (index+1) * m_numberOfColumns; i++) {