From 279e04bdd93ea3675c5589ccb2491c7603b2af5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 14:56:01 +0200 Subject: [PATCH] [poincare] LayoutNode::equivalentCursor --- .../poincare/allocation_failed_layout_node.h | 5 +++ .../include/poincare/horizontal_layout_node.h | 3 ++ poincare/include/poincare/layout_cursor.h | 5 +++ poincare/include/poincare/layout_node.h | 8 ++-- poincare/src/horizontal_layout_node.cpp | 37 +++++++++++++++++++ poincare/src/layout_node.cpp | 4 +- 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 195184796..7b39e6f7b 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -3,6 +3,7 @@ #include "layout_node.h" #include "layout_reference.h" +#include "layout_cursor.h" namespace Poincare { @@ -13,6 +14,10 @@ public: assert(false); return 0; } + LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); } + void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override { } + void deleteBeforeCursor(LayoutCursor * cursor) override { } + // TreeNode size_t size() const override { return sizeof(AllocationFailedLayoutNode); } const char * description() const override { return "Allocation Failed"; } diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 9169daa21..527313246 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -17,6 +17,9 @@ public: m_numberOfChildren(0) {} + // Tree navigation + LayoutCursor equivalentCursor(LayoutCursor * cursor) override; + // Tree modification void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren); void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren); diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 41afc22b0..ae2cd0d9e 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -7,9 +7,12 @@ namespace Poincare { +class HorizontalLayoutNode; + class LayoutCursor { template friend class LayoutReference; + friend class HorizontalLayoutNode; public: constexpr static KDCoordinate k_cursorWidth = 1; @@ -52,6 +55,8 @@ public: /* Getters and setters */ LayoutRef layoutReference() { return m_layoutRef; } + LayoutNode * layoutNode() { return m_layoutRef.typedNode(); } // TODO Make private + friend classes ? + int layoutIdentifier() { return m_layoutRef.identifier(); } void setLayoutReference(LayoutRef r) { if (r != m_layoutRef) { diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 88e055c34..cde6a11ee 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -23,9 +23,9 @@ public: } bool hasText() const { - /* 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. */ - if (isEmpty()){ + /* A layout has text if it is not empty or an allocation failure and it is + * not an horizontal layout with no child or with one child with no text. */ + if (isEmpty() || isAllocationFailure()){ return false; } int numChildren = numberOfChildren(); @@ -66,7 +66,7 @@ public: virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} virtual void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} virtual void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} - virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); //TODO + virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); // Tree modification void addSibling(LayoutCursor * cursor, LayoutNode * sibling); diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 5069327ce..8743e54a8 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -5,6 +5,39 @@ namespace Poincare { static inline KDCoordinate maxCoordinate(KDCoordinate c1, KDCoordinate c2) { return c1 > c2 ? c1 : c2; } + +// Tree navigation + +LayoutCursor HorizontalLayoutNode::equivalentCursor(LayoutCursor * cursor) { + if (cursor->layoutReference().node() == this) { + // First or last child, if any + int childrenCount = numberOfChildren(); + if (childrenCount == 0) { + return LayoutCursor(); + } + int index = cursor->position() == LayoutCursor::Position::Left ? 0 : childrenCount - 1; + return LayoutCursor(childAtIndex(index), cursor->position()); + } + // Left or right of a child: return right or left of its sibling, or of this + int indexOfPointedLayout = indexOfChild(cursor->layoutNode()); + if (indexOfPointedLayout < 0) { + return LayoutCursor(); + } + if (cursor->position() == LayoutCursor::Position::Left) { + if (indexOfPointedLayout == 0) { + return LayoutCursor(this, LayoutCursor::Position::Left); + } + return LayoutCursor(childAtIndex(indexOfPointedLayout - 1), LayoutCursor::Position::Right); + } + assert(cursor->position() == LayoutCursor::Position::Right); + if (indexOfPointedLayout == numberOfChildren() - 1) { + return LayoutCursor(this, LayoutCursor::Position::Right); + } + return LayoutCursor(childAtIndex(indexOfPointedLayout + 1), LayoutCursor::Position::Left); +} + +// Tree modification + void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren) { if (l->isHorizontal()) { mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren); @@ -79,6 +112,8 @@ void HorizontalLayoutNode::removeChildAndMoveCursor(LayoutNode * l, LayoutCursor LayoutNode::removeChildAndMoveCursor(l, cursor); } +// LayoutNode + int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (numberOfChildren() == 0) { if (bufferSize == 0) { @@ -180,6 +215,8 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR return childAtIndex(childIndex+1)->moveCursorRight(cursor, shouldRecomputeLayout); } +// Protected + void HorizontalLayoutNode::computeSize() { assert(!m_sized); KDCoordinate totalWidth = 0; diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index d355a0cc6..623afba0e 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -69,7 +69,9 @@ TreeNode * LayoutNode::FailedAllocationStaticNode() { // Tree navigation LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { - return LayoutCursor(cursor->layoutReference()); + // Only HorizontalLayout may have no parent, and it overloads this method + assert(parent()); + return (cursor->layoutReference().node() == this) ? parent()->equivalentCursor(cursor) : LayoutCursor(); } // Tree modification