diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index e4e0a1687..7f2aed74a 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -341,6 +341,21 @@ bool LayoutField::handleEvent(Ion::Events::Event event) { didHandleEvent = true; } else if (privateHandleSelectionEvent(event, &shouldRecomputeLayout)) { didHandleEvent = true; + // Handle matrices + if (!m_contentView.selectionIsEmpty()) { + bool removedSquares = false; + Layout * selectStart = m_contentView.selectionStart(); + Layout * selectEnd = m_contentView.selectionEnd(); + if (*selectStart != *selectEnd) { + Layout p = selectStart->parent(); + assert(p == selectEnd->parent()); + assert(p.type() == LayoutNode::Type::HorizontalLayout); + removedSquares = p.removeGreySquaresFromAllMatrixChildren(); + } else { + removedSquares = selectStart->removeGreySquaresFromAllMatrixChildren(); + } + shouldRecomputeLayout = m_contentView.cursor()->layout().removeGreySquaresFromAllMatrixChildren() || removedSquares || shouldRecomputeLayout; + } } else if (privateHandleEvent(event)) { shouldRecomputeLayout = true; didHandleEvent = true; @@ -472,24 +487,22 @@ bool eventIsSelection(Ion::Events::Event event) { } bool LayoutField::privateHandleSelectionEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { - LayoutCursor result; - if (eventIsSelection(event)) { - Layout addedSelection; - LayoutCursor::Direction direction = event == Ion::Events::ShiftLeft ? LayoutCursor::Direction::Left : - (event == Ion::Events::ShiftRight ? LayoutCursor::Direction::Right : - (event == Ion::Events::ShiftUp ? LayoutCursor::Direction::Up : - LayoutCursor::Direction::Down)); - result = m_contentView.cursor()->selectAtDirection(direction, shouldRecomputeLayout, &addedSelection); - if (addedSelection.isUninitialized()) { - return false; - } - m_contentView.addSelection(addedSelection); + if (!eventIsSelection(event)) { + return false; } - if (result.isDefined()) { - m_contentView.setCursor(result); - return true; + Layout addedSelection; + LayoutCursor::Direction direction = event == Ion::Events::ShiftLeft ? LayoutCursor::Direction::Left : + (event == Ion::Events::ShiftRight ? LayoutCursor::Direction::Right : + (event == Ion::Events::ShiftUp ? LayoutCursor::Direction::Up : + LayoutCursor::Direction::Down)); + LayoutCursor result = m_contentView.cursor()->selectAtDirection(direction, shouldRecomputeLayout, &addedSelection); + if (addedSelection.isUninitialized()) { + return false; } - return false; + m_contentView.addSelection(addedSelection); + assert(result.isDefined()); + m_contentView.setCursor(result); + return true; } void LayoutField::scrollRightOfLayout(Layout layoutR) { diff --git a/poincare/include/poincare/layout.h b/poincare/include/poincare/layout.h index f53582fc8..66e423f7d 100644 --- a/poincare/include/poincare/layout.h +++ b/poincare/include/poincare/layout.h @@ -60,6 +60,7 @@ public: // Layout modification void deleteBeforeCursor(LayoutCursor * cursor) { return node()->deleteBeforeCursor(cursor); } bool removeGreySquaresFromAllMatrixAncestors() { return node()->removeGreySquaresFromAllMatrixAncestors(); } + bool removeGreySquaresFromAllMatrixChildren() { return node()->removeGreySquaresFromAllMatrixChildren(); } bool addGreySquaresToAllMatrixAncestors() { return node()->addGreySquaresToAllMatrixAncestors(); } Layout layoutToPointWhenInserting(Expression * correspondingExpression) { // Pointer to correspondingExpr because expression.h includes layout.h diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 9b4f9a5f1..5ec8855c3 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -104,8 +104,9 @@ public: // Other virtual LayoutNode * layoutToPointWhenInserting(Expression * correspondingExpression); - bool removeGreySquaresFromAllMatrixAncestors() { return changeGreySquaresOfAllMatrixAncestors(false); } - bool addGreySquaresToAllMatrixAncestors() { return changeGreySquaresOfAllMatrixAncestors(true); } + bool removeGreySquaresFromAllMatrixAncestors(); + bool removeGreySquaresFromAllMatrixChildren(); + bool addGreySquaresToAllMatrixAncestors(); /* 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. */ virtual bool hasText() const { return true; } @@ -173,7 +174,7 @@ private: int * resultScore, bool forSelection); virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor, Layout * selectionStart = nullptr, Layout * selectionEnd = nullptr, KDColor selectionColor = KDColorRed) = 0; - bool changeGreySquaresOfAllMatrixAncestors(bool add); + void changeGreySquaresOfAllMatrixRelatives(bool add, bool ancestors, bool * changedSquares); }; } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index c1ece351f..2bcc177b7 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -128,6 +128,24 @@ LayoutNode * LayoutNode::layoutToPointWhenInserting(Expression * correspondingEx return numberOfChildren() > 0 ? childAtIndex(0) : this; } +bool LayoutNode::removeGreySquaresFromAllMatrixAncestors() { + bool result = false; + changeGreySquaresOfAllMatrixRelatives(false, true, &result); + return result; +} + +bool LayoutNode::removeGreySquaresFromAllMatrixChildren() { + bool result = false; + changeGreySquaresOfAllMatrixRelatives(false, false, &result); + return result; +} + +bool LayoutNode::addGreySquaresToAllMatrixAncestors() { + bool result = false; + changeGreySquaresOfAllMatrixRelatives(true, true, &result); + return result; +} + bool LayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) { if (!force) { Layout(this).replaceChildWithEmpty(Layout(l), cursor); @@ -253,21 +271,37 @@ void LayoutNode::scoreCursorInDescendantsVertically ( } } -bool LayoutNode::changeGreySquaresOfAllMatrixAncestors(bool add) { - bool changedSquares = false; - Layout currentAncestor = Layout(parent()); - while (!currentAncestor.isUninitialized()) { - if (currentAncestor.type() == Type::MatrixLayout) { - if (add) { - MatrixLayout(static_cast(currentAncestor.node())).addGreySquares(); - } else { - MatrixLayout(static_cast(currentAncestor.node())).removeGreySquares(); - } - changedSquares = true; - } - currentAncestor = currentAncestor.parent(); +bool addRemoveGreySquaresInLayoutIfNeeded(bool add, Layout * l) { + if (l->type() != LayoutNode::Type::MatrixLayout) { + return false; + } + if (add) { + static_cast(l->node())->addGreySquares(); + } else { + static_cast(l->node())->removeGreySquares(); + } + return true; +} + +void LayoutNode::changeGreySquaresOfAllMatrixRelatives(bool add, bool ancestors, bool * changedSquares) { + if (!ancestors) { + // If in children, we also change the squares for this + Layout thisLayout = Layout(this); + if (addRemoveGreySquaresInLayoutIfNeeded(add, &thisLayout)) { + *changedSquares = true; + } + for (Layout l : children()) { + l.node()->changeGreySquaresOfAllMatrixRelatives(add, false, changedSquares); + } + } else { + Layout currentAncestor = Layout(parent()); + while (!currentAncestor.isUninitialized()) { + if (addRemoveGreySquaresInLayoutIfNeeded(add, ¤tAncestor)) { + *changedSquares = true; + } + currentAncestor = currentAncestor.parent(); + } } - return changedSquares; } }