From 3cd101561465f99ca0854fb99cd18599178b9167 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 12 Jun 2018 13:56:20 +0200 Subject: [PATCH 001/156] Initial import --- Makefile | 12 +++ addition_node.h | 46 +++++++++++ expression_node.h | 22 +++++ expression_reference.h | 38 +++++++++ float_node.h | 41 ++++++++++ test.cpp | 107 +++++++++++++++++++++++++ tree_node.h | 178 +++++++++++++++++++++++++++++++++++++++++ tree_pool.cpp | 52 ++++++++++++ tree_pool.h | 79 ++++++++++++++++++ tree_reference.cpp | 14 ++++ tree_reference.h | 88 ++++++++++++++++++++ 11 files changed, 677 insertions(+) create mode 100644 Makefile create mode 100644 addition_node.h create mode 100644 expression_node.h create mode 100644 expression_reference.h create mode 100644 float_node.h create mode 100644 test.cpp create mode 100644 tree_node.h create mode 100644 tree_pool.cpp create mode 100644 tree_pool.h create mode 100644 tree_reference.cpp create mode 100644 tree_reference.h diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..992202f4f --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +OBJS = tree_pool.o tree_reference.o test.o +CXXFLAGS = -std=c++11 -g -O0 + +test: $(OBJS) + clang++ $(CXXFLAGS) $^ -o $@ + +clean: + rm -f $(OBJS) + +%.o: %.cpp + clang++ $(CXXFLAGS) -c $< -o $@ + diff --git a/addition_node.h b/addition_node.h new file mode 100644 index 000000000..b7c427f9e --- /dev/null +++ b/addition_node.h @@ -0,0 +1,46 @@ +#ifndef ADDITION_NODE_H +#define ADDITION_NODE_H + +#include "expression_reference.h" +#include "expression_node.h" + +class AdditionNode : public ExpressionNode { +public: + AdditionNode(int identifier) : ExpressionNode(identifier) { + printf("Create Addition\n"); + } +#if TREE_LOGGING + const char * description() const override { + return "Addition"; + } +#endif + float approximate() override { + float result = 0.0f; + for (int i=0; iapproximate(); + } + return result; + } +/* + Expression simplify() override { + // Scan operands, merge constants + Addition a = wrapped(this); + if (operand(0)->type() == Integer && operand(1)->type() == Integer) { + } + } + */ +}; + +class Addition : public ExpressionReference { +public: + Addition(Expression e1, Expression e2) : + ExpressionReference() + { + // Ok, here I want to take e1 and e2 as operands + } +}; + + +//typedef ExpressionReference Addition; + +#endif diff --git a/expression_node.h b/expression_node.h new file mode 100644 index 000000000..eeeb6c439 --- /dev/null +++ b/expression_node.h @@ -0,0 +1,22 @@ +#ifndef EXPRESSION_NODE_H +#define EXPRESSION_NODE_H + +#include "tree_node.h" + +class TreePool; + +class ExpressionNode : public TreeNode { +public: + ExpressionNode(int identifier) : TreeNode(identifier) {} + + static TreePool * Pool() { + static TreePool pool; + return &pool; + } + + virtual float approximate() = 0; + int numberOfOperands() { return numberOfChildren(); } + ExpressionNode * operand(int i) { return static_cast(childAtIndex(i)); } +}; + +#endif diff --git a/expression_reference.h b/expression_reference.h new file mode 100644 index 000000000..b851a67d4 --- /dev/null +++ b/expression_reference.h @@ -0,0 +1,38 @@ +#ifndef EXPRESSION_REFERENCE_H +#define EXPRESSION_REFERENCE_H + +#include "tree_reference.h" +#include "expression_node.h" + +#include + +template +class ExpressionReference : public TreeReference { +public: + ExpressionReference() : TreeReference(ExpressionNode::Pool()) { } + + /*ExpressionReference(const ExpressionReference & er) { + }*/ + + // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression + operator ExpressionReference() const { + printf("ExpressionReference cast\n"); + // TODO: make sure this is kosher + // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); + return *(reinterpret_cast *>(this)); + } + + float approximate() const { + return this->node()->approximate(); + } + + /* + ExpressionReference simplify() { + return node()->simplify(); + } + */ +}; + +typedef ExpressionReference Expression; + +#endif diff --git a/float_node.h b/float_node.h new file mode 100644 index 000000000..6aae43a7f --- /dev/null +++ b/float_node.h @@ -0,0 +1,41 @@ +#ifndef FLOAT_NODE_H +#define FLOAT_NODE_H + +#include "expression_reference.h" +#include "expression_node.h" + +class FloatNode : public ExpressionNode { +public: + FloatNode(int identifier) : ExpressionNode(identifier) { + printf("Create float\n"); + } + size_t size() const override { + return sizeof(FloatNode); + } + float approximate() override { + return m_value; + } +#if TREE_LOGGING + const char * description() const override { + if (m_value > 1) { + return "BigFloat"; + } else { + return "SmallFloat"; + } + } +#endif + void setFloat(float f) { m_value = f; } +private: + float m_value; +}; + +class Float : public ExpressionReference { +public: + Float(float f) : ExpressionReference() { + this->node()->setFloat(f); + } +}; + +//typedef ExpressionReference Float; + +#endif diff --git a/test.cpp b/test.cpp new file mode 100644 index 000000000..23ebf14f3 --- /dev/null +++ b/test.cpp @@ -0,0 +1,107 @@ +#include "float_node.h" +#include "addition_node.h" +#include + + +int main() { + printf("Hello\n"); + + ExpressionNode::Pool()->log(); + + Float e(0.2f); + + ExpressionNode::Pool()->log(); + + if (true) { + Expression j = e; + + ExpressionNode::Pool()->log(); + + Float m(3.4f); + + ExpressionNode::Pool()->log(); + } + + ExpressionNode::Pool()->log(); + + Addition a(e, e); + + ExpressionNode::Pool()->log(); + + /* + Expression e = Parse("1+1"); + Expression j = e; + Expression f = Addition(e, Parse("5")); + f.removeChildAtIndex(0); + */ +#if 0 + TreeNodePool pool; + TreeNodePool * p = &pool; + + pool.log(); + + TreeNode * t1 = new (pool) AdditionNode(); + + TreeNode * t1 = TreeNode::Create(p, 11); + TreeNode * t2 = TreeNode::Create(p, 12); + TreeNode * t3 = TreeNode::Create(p, 13); + + TreeNode * t4 = AddNode::Create(t1, t3); + //TreeNode * t4 = new(p) IntNode(4); + // + t4->createChild(Addition() + + pool.log(); + + pool.move(t1, t3); + + pool.log(); +#endif + + return 0; +} + + +#if 0 + +static inline swap(uint32_t * a, uint32_t * b) { + uint32_t tmp = *a; + *a = *b; + *b = tmp; +} + +void insert(char * source, char * destination, size_t length) { + assert(length % 4 == 0); + assert(source % 4 == 0); + assert(destination % 4 == 0); + uint32_t * src = reinterpret_cast(source); + uint32_t * dst = reinterpret_cast(destination); + size_t len = length/4; + + if (dst < src) { + if (src - dst <= len) { + uint32_t * srcPointer = src; + uint32_t * dstPointer = dst; + while (dstPointer != src) { + swap(srcPointer, dstPointer); + srcPointer++; + dstPointer++; + if (srcPointer == src + len) { + srcPointer = src; + } + } + } + } +} + +void TreeNodePool::move(TreeNode * source, TreeNode * destination) { + if (source == destination) { + return; + } + insert(source, destination, source->deepSize()); +} + +bool TreeNode::hasVariableNumberOfChildren() const { + return false; +} +#endif diff --git a/tree_node.h b/tree_node.h new file mode 100644 index 000000000..7f9e50ef6 --- /dev/null +++ b/tree_node.h @@ -0,0 +1,178 @@ +#ifndef TREE_NODE_H +#define TREE_NODE_H + +#include +#include +#include + +#define TREE_LOGGING 1 + +#include + +class TreeNode { + //friend class TreeReference; + // friend class TreePool; +public: + virtual ~TreeNode() { + } + + + // Iterators + + class Iterator { + public: + Iterator(TreeNode * node) : m_node(node) {} + TreeNode * operator*() { return m_node; } + bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } + protected: + TreeNode * m_node; + }; + + class DepthFirst { + public: + DepthFirst(TreeNode * node) : m_node(node) {} + class Iterator : public TreeNode::Iterator { + public: + using TreeNode::Iterator::Iterator; + Iterator & operator++() { + printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); + m_node = m_node->next(); + return *this; + } + }; + Iterator begin() const { return Iterator(m_node); } + Iterator end() const { return Iterator(m_node->nextSibling()); } + private: + TreeNode * m_node; + }; + + DepthFirst depthFirstChildren() { return DepthFirst(this); } + + + int identifier() const { return m_identifier; } + +#if TREE_LOGGING + virtual const char * description() const { + return "UNKNOWN"; + } +#endif + + virtual size_t size() const { + return sizeof(TreeNode); + } + + void retain() { + m_referenceCounter++; + } + void release() { + m_referenceCounter--; + } + + int retainCount() { + return m_referenceCounter; + } + + virtual bool hasVariableNumberOfChildren() const { + return false; + } + + int numberOfChildren() const { + if (hasVariableNumberOfChildren()) { + int numberOfChildren = 0; + TreeNode * child = next(); + while (!child->isEndMarker()) { + child = child->nextSibling(); + numberOfChildren++; + } + return numberOfChildren; + } else { + // TODO: Make this function virtual + return 0; + } + } + + TreeNode * childAtIndex(int i) const { + assert(i >= 0); + assert(i < numberOfChildren()); + TreeNode * child = next(); + while (i>0) { + child = child->nextSibling(); + assert(child != nullptr); + assert(!child->isEndMarker()); + i--; + } + return child; + } + + /* + void addChild(TreeNode * node) { + // This will move node in the pool so that it becomes + // a children of this + pool->move(node, this + size()); + } + */ + +//private: + + // FIXME: Make this private + TreeNode(int identifier) : + m_identifier(identifier), + m_referenceCounter(1) + { + } + + constexpr static int EmptyIdentifier = 0; + constexpr static int EndMarkerIdentifier = 1; + + bool isEndMarker() const { + return (m_identifier == EndMarkerIdentifier); + } + + bool isEmpty() const { + return (m_identifier == EmptyIdentifier); + } + + void markAsEmpty() { + m_identifier = EmptyIdentifier; + } + + TreeNode * next() const { + // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. + // Unfortunately, we want TreeNode to have a VARIABLE size + return reinterpret_cast(reinterpret_cast(const_cast(this)) + size()); + } + + TreeNode * nextSibling() const { + TreeNode * n = const_cast(this); + int depth = 0; + do { + if (n->hasVariableNumberOfChildren()) { + depth++; + } + /* + if (n->isEndMarker()) { + depth--; + } + */ + n = n->next(); + // TODO: Return nullptr if n overflows the pool! + assert(depth >= 0); + } while(depth != 0); + return n; + } + + size_t deepSize() const { + // TODO: Error handling + return + reinterpret_cast(nextSibling()) + - + reinterpret_cast(this); + ; + } + +//private: + int m_identifier; + int m_referenceCounter; +}; + +#endif diff --git a/tree_pool.cpp b/tree_pool.cpp new file mode 100644 index 000000000..af69c5494 --- /dev/null +++ b/tree_pool.cpp @@ -0,0 +1,52 @@ +#include "tree_pool.h" +#include +#include "tree_node.h" + +void * TreePool::alloc(size_t size) { + void * result = m_cursor; + m_cursor += size; + return result; +} + +void TreePool::dealloc(void * ptr, size_t size) { + // Step 1 - Compact the pool + memmove( + ptr, + static_cast(ptr) - size, + m_cursor - static_cast(ptr) + ); + m_cursor -= size; +} + +TreeNode * TreePool::node(int identifier) const { + for (TreeNode * node : *this) { + if (node->identifier() == identifier) { + return node; + } + } + /* + TreeNode * node = const_cast(reinterpret_cast(m_buffer)); + TreeNode * endOfPool = reinterpret_cast(m_cursor); + while (node < endOfPool) { + if (node->identifier() == identifier) { + return node; + } + node = node->next(); + } + */ + return nullptr; +} + +#if TREE_LOGGING +#include + +void TreePool::log() { + printf("POOL:"); + for (TreeNode * node : *this) { + printf("|%d", node->m_identifier); + //printf("|(%03d|%s|%03d)", node->m_identifier, node->description(), node->retainCount()); + } + printf("|\n"); +} +#endif + diff --git a/tree_pool.h b/tree_pool.h new file mode 100644 index 000000000..196b861bf --- /dev/null +++ b/tree_pool.h @@ -0,0 +1,79 @@ +#ifndef TREE_POOL_H +#define TREE_POOL_H + +#include + +#include "tree_node.h" + +class TreePool { +public: + TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} + + int generateIdentifier() { + assert(node(m_lastIdentifier) == nullptr); + return m_lastIdentifier++; + } + void reclaimIdentifier(int identifier) { + } + + void * alloc(size_t size); + void dealloc(void * ptr, size_t size); + + TreeNode * node(int identifier) const; +#if TREE_LOGGING + void log(); +#endif + +private: + + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_buffer))); } + TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_cursor))); } + + int m_lastIdentifier; + char * m_cursor; + char m_buffer[256]; +}; + +#if 0 +class TreePool { +public: + TreePool() : + m_identifier(0), + m_cursor(m_data) + { + } + + class Slot { + public: + Slot(int identifier, void * area) : + m_identifier(identifier), m_area(area) {} + int identifier() const { return m_identifier; } + void * area() const { return m_area; } + private: + int m_identifier; + void * m_area; + int m_size; + }; + + Slot alloc(size_t size); + void dealloc(Slot s, size_t size); + + //TreeNode * node(int identifier) const; + TreeNode * alloc(size_t size) { + + } + void dealloc(TreeNode * node); + + void move(TreeNode * source, TreeNode * destination); +//#define TREE_LOGGING 1 +#if TREE_LOGGING + void log(); +#endif + private: + int m_identifier; + char * m_cursor; + char m_data[200]; +}; +#endif + +#endif diff --git a/tree_reference.cpp b/tree_reference.cpp new file mode 100644 index 000000000..e42312dad --- /dev/null +++ b/tree_reference.cpp @@ -0,0 +1,14 @@ +#include "tree_reference.h" + +#if 0 +void TreeReference::addOperand(TreeReference t) { + // At this point, e has been copied. + // We can therefore pilfer its node! + Node * n = node(); + pool->move( + t->node(), + t->next() + ); + node->stealAsOperand(t->node()); +} +#endif diff --git a/tree_reference.h b/tree_reference.h new file mode 100644 index 000000000..a2c13f0c5 --- /dev/null +++ b/tree_reference.h @@ -0,0 +1,88 @@ +#ifndef TREE_REFERENCE_H +#define TREE_REFERENCE_H + +#include "tree_pool.h" +#include + +#include + +template +class TreeReference { +public: + TreeReference(const TreeReference & tr) : + m_pool(tr.m_pool), + m_identifier(tr.m_identifier) + { + printf("TreeReference copy\n"); + node()->retain(); + } + + ~TreeReference() { + TreeNode * node = this->node(); + node->release(); + if (node->retainCount() == 0) { + printf("Discarding node %d(%p)\n", node->identifier(), node); + // Here the static_cast should fail if T is not a subclass of TreeNode + size_t deepNodeSize = node->deepSize(); +#if 0 + // Here, if needed, call reclaimIdentifier + for (TreeNode * child : node->depthFirstChildren()) { + m_pool->reclaimIdentifier(child->identifier()); + } + m_pool->reclaimIdentifier(node->identifier()); +#endif + static_cast(node)->~T(); + m_pool->dealloc(node, deepNodeSize); + } + } + + int numberOfChildren() const { + return node()->numberOfChildren(); + } + + TreeReference childAtIndex(int i) const { + return TreeReference(node()->childAtIndex(i)); + } + + void addOperand(TreeReference t) { + assert(t.m_pool == m_pool); + /* + m_pool->move( + t->node(), + t->next() + ); + */ + } + +protected: + TreeReference(TreePool * pool) : + m_pool(pool) + { + int identifier = pool->generateIdentifier(); + void * area = pool->alloc(sizeof(T)); + TreeNode * n = new (area) T(identifier); + m_identifier = n->identifier(); + assert(m_identifier == identifier); + //m_cachedNode = n; + } + + T * node() const { + // TODO: Here, assert that the node type is indeed T + return static_cast(m_pool->node(m_identifier)); + } +private: + TreeReference(TreePool * pool, TreeNode * node) : + m_pool(pool), + m_identifier(node->identifier()) + //m_cachedNode(node) + { + node->retain(); + } + + + TreePool * m_pool; + int m_identifier; + //TreeNode * m_cachedNode; +}; + +#endif From 68f663d47ebaa48522fc5e7a3f2598a0b05d0a8f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 12 Jun 2018 16:50:49 +0200 Subject: [PATCH 002/156] Use operator new/delete directly on ExpressionNode --- Makefile | 2 +- addition_node.h | 9 +++- end_node.h | 25 +++++++++ expression_node.h | 23 ++++++-- expression_reference.h | 4 ++ float_node.h | 2 +- test.cpp | 119 +++++++++++------------------------------ tree_node.cpp | 16 ++++++ tree_node.h | 29 ++++++++-- tree_pool.cpp | 48 +++++++++++++++-- tree_pool.h | 68 ++++++++--------------- tree_reference.h | 53 ++++++++++++------ 12 files changed, 234 insertions(+), 164 deletions(-) create mode 100644 end_node.h create mode 100644 tree_node.cpp diff --git a/Makefile b/Makefile index 992202f4f..e2ef28479 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -OBJS = tree_pool.o tree_reference.o test.o +OBJS = tree_pool.o tree_node.o tree_reference.o test.o CXXFLAGS = -std=c++11 -g -O0 test: $(OBJS) diff --git a/addition_node.h b/addition_node.h index b7c427f9e..e559e7a34 100644 --- a/addition_node.h +++ b/addition_node.h @@ -6,7 +6,7 @@ class AdditionNode : public ExpressionNode { public: - AdditionNode(int identifier) : ExpressionNode(identifier) { + AdditionNode() : ExpressionNode() { printf("Create Addition\n"); } #if TREE_LOGGING @@ -31,12 +31,17 @@ public: */ }; +#include "end_node.h" + class Addition : public ExpressionReference { public: Addition(Expression e1, Expression e2) : ExpressionReference() { - // Ok, here I want to take e1 and e2 as operands + ExpressionReference end; + ExpressionNode::Pool()->log(); + addOperand(end); + ExpressionNode::Pool()->log(); } }; diff --git a/end_node.h b/end_node.h new file mode 100644 index 000000000..e454765c1 --- /dev/null +++ b/end_node.h @@ -0,0 +1,25 @@ +#ifndef END_NODE_H +#define END_NODE_H + +#include "expression_reference.h" +#include "expression_node.h" + +class EndNode : public ExpressionNode { +public: + EndNode() : ExpressionNode() { + printf("Create end node\n"); + } + float approximate() override { + assert(false); + return 0.0f; + } +#if TREE_LOGGING + const char * description() const override { + return "End"; + } +#endif +}; + +//typedef ExpressionReference End; + +#endif diff --git a/expression_node.h b/expression_node.h index eeeb6c439..03d05ad71 100644 --- a/expression_node.h +++ b/expression_node.h @@ -2,12 +2,23 @@ #define EXPRESSION_NODE_H #include "tree_node.h" - -class TreePool; +#include "tree_pool.h" class ExpressionNode : public TreeNode { public: - ExpressionNode(int identifier) : TreeNode(identifier) {} + ExpressionNode() : TreeNode(Pool()->generateIdentifier()) {} + + // TODO: operator new and delte + // this behavior is the same for every TreeNode + // Find a way to define it on the TreeNode + + void * operator new(size_t count) { + return Pool()->alloc(count); + } + + void operator delete(void * ptr) { + Pool()->dealloc(ptr); + } static TreePool * Pool() { static TreePool pool; @@ -20,3 +31,9 @@ public: }; #endif + +/* Code I want to write: + * + * ExpressionNode * n = new AdditionNode(); + * delete n; + */ diff --git a/expression_reference.h b/expression_reference.h index b851a67d4..9b6e93e24 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -22,6 +22,10 @@ public: return *(reinterpret_cast *>(this)); } + void addOperand(ExpressionReference e) { + TreeReference::addChild(e); + } + float approximate() const { return this->node()->approximate(); } diff --git a/float_node.h b/float_node.h index 6aae43a7f..843de0ee0 100644 --- a/float_node.h +++ b/float_node.h @@ -6,7 +6,7 @@ class FloatNode : public ExpressionNode { public: - FloatNode(int identifier) : ExpressionNode(identifier) { + FloatNode() : ExpressionNode() { printf("Create float\n"); } size_t size() const override { diff --git a/test.cpp b/test.cpp index 23ebf14f3..7a643d9bd 100644 --- a/test.cpp +++ b/test.cpp @@ -2,31 +2,43 @@ #include "addition_node.h" #include +void poolTest() { + ExpressionNode::Pool()->log(); + + FloatNode * f = new FloatNode(); + f->setFloat(0.1f); + + FloatNode * g = new FloatNode(); + g->setFloat(1.1f); + + AdditionNode * h = new AdditionNode(); + + EndNode * i = new EndNode(); + + ExpressionNode::Pool()->log(); + + delete g; + + ExpressionNode::Pool()->log(); +} + +Expression buildAddition() { + Float smallFloat(0.2f); + Float bigFloat(3.4f); + + ExpressionNode::Pool()->log(); + + Addition a(smallFloat, bigFloat); + + ExpressionNode::Pool()->log(); + return a; +} int main() { printf("Hello\n"); + buildAddition(); - ExpressionNode::Pool()->log(); - Float e(0.2f); - - ExpressionNode::Pool()->log(); - - if (true) { - Expression j = e; - - ExpressionNode::Pool()->log(); - - Float m(3.4f); - - ExpressionNode::Pool()->log(); - } - - ExpressionNode::Pool()->log(); - - Addition a(e, e); - - ExpressionNode::Pool()->log(); /* Expression e = Parse("1+1"); @@ -34,74 +46,7 @@ int main() { Expression f = Addition(e, Parse("5")); f.removeChildAtIndex(0); */ -#if 0 - TreeNodePool pool; - TreeNodePool * p = &pool; - pool.log(); - - TreeNode * t1 = new (pool) AdditionNode(); - - TreeNode * t1 = TreeNode::Create(p, 11); - TreeNode * t2 = TreeNode::Create(p, 12); - TreeNode * t3 = TreeNode::Create(p, 13); - - TreeNode * t4 = AddNode::Create(t1, t3); - //TreeNode * t4 = new(p) IntNode(4); - // - t4->createChild(Addition() - - pool.log(); - - pool.move(t1, t3); - - pool.log(); -#endif return 0; } - - -#if 0 - -static inline swap(uint32_t * a, uint32_t * b) { - uint32_t tmp = *a; - *a = *b; - *b = tmp; -} - -void insert(char * source, char * destination, size_t length) { - assert(length % 4 == 0); - assert(source % 4 == 0); - assert(destination % 4 == 0); - uint32_t * src = reinterpret_cast(source); - uint32_t * dst = reinterpret_cast(destination); - size_t len = length/4; - - if (dst < src) { - if (src - dst <= len) { - uint32_t * srcPointer = src; - uint32_t * dstPointer = dst; - while (dstPointer != src) { - swap(srcPointer, dstPointer); - srcPointer++; - dstPointer++; - if (srcPointer == src + len) { - srcPointer = src; - } - } - } - } -} - -void TreeNodePool::move(TreeNode * source, TreeNode * destination) { - if (source == destination) { - return; - } - insert(source, destination, source->deepSize()); -} - -bool TreeNode::hasVariableNumberOfChildren() const { - return false; -} -#endif diff --git a/tree_node.cpp b/tree_node.cpp new file mode 100644 index 000000000..f5e69032f --- /dev/null +++ b/tree_node.cpp @@ -0,0 +1,16 @@ +#include "tree_node.h" +#include "expression_node.h" + +void TreeNode::release() { + m_referenceCounter--; + for (TreeNode * child : directChildren()) { + child->release(); + } + if (m_referenceCounter == 0) { + printf("DELETE %d(%p)\n", m_identifier, this); + delete this; + //dealloc(); + printf("Will log\n"); + ExpressionNode::Pool()->log(); + } +} diff --git a/tree_node.h b/tree_node.h index 7f9e50ef6..8034c120e 100644 --- a/tree_node.h +++ b/tree_node.h @@ -16,7 +16,6 @@ public: virtual ~TreeNode() { } - // Iterators class Iterator { @@ -28,6 +27,25 @@ public: TreeNode * m_node; }; + class Direct { + public: + Direct(TreeNode * node) : m_node(node) {} + class Iterator : public TreeNode::Iterator { + public: + using TreeNode::Iterator::Iterator; + Iterator & operator++() { + m_node = m_node->nextSibling(); + return *this; + } + }; + Iterator begin() const { return Iterator(m_node->next()); } + Iterator end() const { return Iterator(m_node->nextSibling()); } + private: + TreeNode * m_node; + }; + + Direct directChildren() { return Direct(this); } + class DepthFirst { public: DepthFirst(TreeNode * node) : m_node(node) {} @@ -35,7 +53,7 @@ public: public: using TreeNode::Iterator::Iterator; Iterator & operator++() { - printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); + // printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); m_node = m_node->next(); return *this; } @@ -64,8 +82,11 @@ public: void retain() { m_referenceCounter++; } - void release() { - m_referenceCounter--; + void release(); + + void rename(int identifier) { + m_identifier = identifier; + m_referenceCounter = 1; } int retainCount() { diff --git a/tree_pool.cpp b/tree_pool.cpp index af69c5494..c6c7479ec 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -8,11 +8,15 @@ void * TreePool::alloc(size_t size) { return result; } -void TreePool::dealloc(void * ptr, size_t size) { +void TreePool::dealloc(void * ptr) { + assert(ptr >= m_buffer && ptr < m_cursor); + TreeNode * node = reinterpret_cast(ptr); + size_t size = node->size(); + printf("Dealloc %d(%p) of size %d\n", node->m_identifier, node, size); // Step 1 - Compact the pool memmove( ptr, - static_cast(ptr) - size, + static_cast(ptr) + size, m_cursor - static_cast(ptr) ); m_cursor -= size; @@ -37,14 +41,50 @@ TreeNode * TreePool::node(int identifier) const { return nullptr; } +static inline void swap(uint32_t * a, uint32_t * b) { + uint32_t tmp = *a; + *a = *b; + *b = tmp; +} + +static inline void insert(char * source, char * destination, size_t length) { + assert(length % 4 == 0); + assert((long)source % 4 == 0); + assert((long)destination % 4 == 0); + uint32_t * src = reinterpret_cast(source); + uint32_t * dst = reinterpret_cast(destination); + size_t len = length/4; + + if (dst < src) { + if (src - dst <= len) { + uint32_t * srcPointer = src; + uint32_t * dstPointer = dst; + while (dstPointer != src) { + swap(srcPointer, dstPointer); + srcPointer++; + dstPointer++; + if (srcPointer == src + len) { + srcPointer = src; + } + } + } + } +} + +void TreePool::move(TreeNode * source, TreeNode * destination) { + if (source == destination) { + return; + } + insert(reinterpret_cast(source), reinterpret_cast(destination), source->deepSize()); +} + #if TREE_LOGGING #include void TreePool::log() { printf("POOL:"); for (TreeNode * node : *this) { - printf("|%d", node->m_identifier); - //printf("|(%03d|%s|%03d)", node->m_identifier, node->description(), node->retainCount()); + printf("|(%03d|%s|%03d|%p)", node->m_identifier, node->description(), node->retainCount(), node); } printf("|\n"); } diff --git a/tree_pool.h b/tree_pool.h index 196b861bf..63b68fedd 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -10,70 +10,46 @@ public: TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} int generateIdentifier() { - assert(node(m_lastIdentifier) == nullptr); + /* For now we're not bothering with making sure the identifiers are indeed + * unique. We're just assuming we'll never overflow... */ + //assert(node(m_lastIdentifier) == nullptr); return m_lastIdentifier++; } void reclaimIdentifier(int identifier) { } void * alloc(size_t size); - void dealloc(void * ptr, size_t size); + void dealloc(void * ptr); TreeNode * node(int identifier) const; + void move(TreeNode * source, TreeNode * destination); + TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } + TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + + TreeNode * deepCopy(TreeNode * node) { + size_t size = node->deepSize(); + void * ptr = alloc(size); + memcpy(ptr, static_cast(node), size); + TreeNode * copy = reinterpret_cast(ptr); + copy->rename(generateIdentifier()); + for (TreeNode * child : copy->depthFirstChildren()) { + child->rename(generateIdentifier()); + } + return copy; + } + #if TREE_LOGGING void log(); #endif private: - TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_buffer))); } - TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_cursor))); } + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } + TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } int m_lastIdentifier; char * m_cursor; char m_buffer[256]; }; -#if 0 -class TreePool { -public: - TreePool() : - m_identifier(0), - m_cursor(m_data) - { - } - - class Slot { - public: - Slot(int identifier, void * area) : - m_identifier(identifier), m_area(area) {} - int identifier() const { return m_identifier; } - void * area() const { return m_area; } - private: - int m_identifier; - void * m_area; - int m_size; - }; - - Slot alloc(size_t size); - void dealloc(Slot s, size_t size); - - //TreeNode * node(int identifier) const; - TreeNode * alloc(size_t size) { - - } - void dealloc(TreeNode * node); - - void move(TreeNode * source, TreeNode * destination); -//#define TREE_LOGGING 1 -#if TREE_LOGGING - void log(); -#endif - private: - int m_identifier; - char * m_cursor; - char m_data[200]; -}; -#endif - #endif diff --git a/tree_reference.h b/tree_reference.h index a2c13f0c5..3a47f47f5 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -20,8 +20,17 @@ public: ~TreeReference() { TreeNode * node = this->node(); node->release(); +#if 0 if (node->retainCount() == 0) { + + + // Here we deal with removing a node. + // It's not as easy as one may think. + // -> When a node is not needed anymore + + printf("Discarding node %d(%p)\n", node->identifier(), node); + // Here the static_cast should fail if T is not a subclass of TreeNode size_t deepNodeSize = node->deepSize(); #if 0 @@ -34,6 +43,13 @@ public: static_cast(node)->~T(); m_pool->dealloc(node, deepNodeSize); } +#endif + } + + operator TreeReference() const { + // TODO: make sure this is kosher + // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); + return *(reinterpret_cast *>(this)); } int numberOfChildren() const { @@ -44,32 +60,37 @@ public: return TreeReference(node()->childAtIndex(i)); } - void addOperand(TreeReference t) { - assert(t.m_pool == m_pool); - /* + void addChild(TreeReference t) { + //assert(t.m_pool == m_pool); + //t.node()->retain(); + TreeNode * deepCopy = m_pool->deepCopy(t.node()); m_pool->move( - t->node(), - t->next() + deepCopy, + node()->next() ); - */ } -protected: - TreeReference(TreePool * pool) : - m_pool(pool) - { - int identifier = pool->generateIdentifier(); - void * area = pool->alloc(sizeof(T)); - TreeNode * n = new (area) T(identifier); - m_identifier = n->identifier(); - assert(m_identifier == identifier); - //m_cachedNode = n; + void removeChild(TreeReference t) { + m_pool->move( + t.node(), + m_pool->last() + ); + t.node()->release(); } T * node() const { // TODO: Here, assert that the node type is indeed T return static_cast(m_pool->node(m_identifier)); } + +protected: + TreeReference(TreePool * pool) : + m_pool(pool) + { + TreeNode * node = new T(); + m_identifier = node->identifier(); + } + private: TreeReference(TreePool * pool, TreeNode * node) : m_pool(pool), From a301de137839accc72c2c04d5f0a6a6a28cc2bef Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 12 Jun 2018 17:39:10 +0200 Subject: [PATCH 003/156] Addition seems to be working --- Makefile | 2 +- addition_node.h | 15 +++++------ end_node.h | 25 ------------------ test.cpp | 11 ++++---- tree_node.cpp | 11 ++++---- tree_node.h | 67 ++++++++---------------------------------------- tree_pool.h | 1 + tree_reference.h | 35 ++++++------------------- 8 files changed, 37 insertions(+), 130 deletions(-) delete mode 100644 end_node.h diff --git a/Makefile b/Makefile index e2ef28479..55257d260 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ test: $(OBJS) clang++ $(CXXFLAGS) $^ -o $@ clean: - rm -f $(OBJS) + rm -f $(OBJS) test %.o: %.cpp clang++ $(CXXFLAGS) -c $< -o $@ diff --git a/addition_node.h b/addition_node.h index e559e7a34..e3a8ab618 100644 --- a/addition_node.h +++ b/addition_node.h @@ -6,9 +6,6 @@ class AdditionNode : public ExpressionNode { public: - AdditionNode() : ExpressionNode() { - printf("Create Addition\n"); - } #if TREE_LOGGING const char * description() const override { return "Addition"; @@ -21,6 +18,10 @@ public: } return result; } + + int numberOfChildren() const override { + return 2; + } /* Expression simplify() override { // Scan operands, merge constants @@ -31,17 +32,13 @@ public: */ }; -#include "end_node.h" - class Addition : public ExpressionReference { public: Addition(Expression e1, Expression e2) : ExpressionReference() { - ExpressionReference end; - ExpressionNode::Pool()->log(); - addOperand(end); - ExpressionNode::Pool()->log(); + addOperand(e2); + addOperand(e1); } }; diff --git a/end_node.h b/end_node.h deleted file mode 100644 index e454765c1..000000000 --- a/end_node.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef END_NODE_H -#define END_NODE_H - -#include "expression_reference.h" -#include "expression_node.h" - -class EndNode : public ExpressionNode { -public: - EndNode() : ExpressionNode() { - printf("Create end node\n"); - } - float approximate() override { - assert(false); - return 0.0f; - } -#if TREE_LOGGING - const char * description() const override { - return "End"; - } -#endif -}; - -//typedef ExpressionReference End; - -#endif diff --git a/test.cpp b/test.cpp index 7a643d9bd..f58e54047 100644 --- a/test.cpp +++ b/test.cpp @@ -13,8 +13,6 @@ void poolTest() { AdditionNode * h = new AdditionNode(); - EndNode * i = new EndNode(); - ExpressionNode::Pool()->log(); delete g; @@ -26,17 +24,20 @@ Expression buildAddition() { Float smallFloat(0.2f); Float bigFloat(3.4f); - ExpressionNode::Pool()->log(); - Addition a(smallFloat, bigFloat); ExpressionNode::Pool()->log(); + printf("EXITING\n"); + printf("smallFloat ref = %d\n", smallFloat.identifier()); + printf("bigFloat ref = %d\n", bigFloat.identifier()); return a; } int main() { printf("Hello\n"); - buildAddition(); + Expression a = buildAddition(); + printf("HAS RETURNED\n"); + ExpressionNode::Pool()->log(); diff --git a/tree_node.cpp b/tree_node.cpp index f5e69032f..94f029d6b 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,15 +2,14 @@ #include "expression_node.h" void TreeNode::release() { + printf("release of %d\n", m_identifier); m_referenceCounter--; - for (TreeNode * child : directChildren()) { - child->release(); - } if (m_referenceCounter == 0) { + for (TreeNode * child : directChildren()) { + child->release(); + } + printf("DELETE %d(%p)\n", m_identifier, this); delete this; - //dealloc(); - printf("Will log\n"); - ExpressionNode::Pool()->log(); } } diff --git a/tree_node.h b/tree_node.h index 8034c120e..5d764026f 100644 --- a/tree_node.h +++ b/tree_node.h @@ -58,7 +58,7 @@ public: return *this; } }; - Iterator begin() const { return Iterator(m_node); } + Iterator begin() const { return Iterator(m_node->next()); } Iterator end() const { return Iterator(m_node->nextSibling()); } private: TreeNode * m_node; @@ -93,23 +93,8 @@ public: return m_referenceCounter; } - virtual bool hasVariableNumberOfChildren() const { - return false; - } - - int numberOfChildren() const { - if (hasVariableNumberOfChildren()) { - int numberOfChildren = 0; - TreeNode * child = next(); - while (!child->isEndMarker()) { - child = child->nextSibling(); - numberOfChildren++; - } - return numberOfChildren; - } else { - // TODO: Make this function virtual - return 0; - } + virtual int numberOfChildren() const { + return 0; } TreeNode * childAtIndex(int i) const { @@ -119,20 +104,11 @@ public: while (i>0) { child = child->nextSibling(); assert(child != nullptr); - assert(!child->isEndMarker()); i--; } return child; } - /* - void addChild(TreeNode * node) { - // This will move node in the pool so that it becomes - // a children of this - pool->move(node, this + size()); - } - */ - //private: // FIXME: Make this private @@ -142,21 +118,6 @@ public: { } - constexpr static int EmptyIdentifier = 0; - constexpr static int EndMarkerIdentifier = 1; - - bool isEndMarker() const { - return (m_identifier == EndMarkerIdentifier); - } - - bool isEmpty() const { - return (m_identifier == EmptyIdentifier); - } - - void markAsEmpty() { - m_identifier = EmptyIdentifier; - } - TreeNode * next() const { // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. // Unfortunately, we want TreeNode to have a VARIABLE size @@ -164,22 +125,14 @@ public: } TreeNode * nextSibling() const { - TreeNode * n = const_cast(this); - int depth = 0; + TreeNode * node = const_cast(this); + int remainingNodesToVisit = 0; do { - if (n->hasVariableNumberOfChildren()) { - depth++; - } - /* - if (n->isEndMarker()) { - depth--; - } - */ - n = n->next(); - // TODO: Return nullptr if n overflows the pool! - assert(depth >= 0); - } while(depth != 0); - return n; + remainingNodesToVisit += node->numberOfChildren(); + node = node->next(); + remainingNodesToVisit--; + } while (remainingNodesToVisit > 0); + return node; } size_t deepSize() const { diff --git a/tree_pool.h b/tree_pool.h index 63b68fedd..fbf11f375 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -10,6 +10,7 @@ public: TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} int generateIdentifier() { + printf("Generating identifier %d\n", m_lastIdentifier); /* For now we're not bothering with making sure the identifiers are indeed * unique. We're just assuming we'll never overflow... */ //assert(node(m_lastIdentifier) == nullptr); diff --git a/tree_reference.h b/tree_reference.h index 3a47f47f5..7bedd292a 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -13,37 +13,14 @@ public: m_pool(tr.m_pool), m_identifier(tr.m_identifier) { - printf("TreeReference copy\n"); + printf("TreeReference copy of %d\n", m_identifier); node()->retain(); } ~TreeReference() { - TreeNode * node = this->node(); - node->release(); -#if 0 - if (node->retainCount() == 0) { - - - // Here we deal with removing a node. - // It's not as easy as one may think. - // -> When a node is not needed anymore - - - printf("Discarding node %d(%p)\n", node->identifier(), node); - - // Here the static_cast should fail if T is not a subclass of TreeNode - size_t deepNodeSize = node->deepSize(); -#if 0 - // Here, if needed, call reclaimIdentifier - for (TreeNode * child : node->depthFirstChildren()) { - m_pool->reclaimIdentifier(child->identifier()); - } - m_pool->reclaimIdentifier(node->identifier()); -#endif - static_cast(node)->~T(); - m_pool->dealloc(node, deepNodeSize); - } -#endif + printf("TreeRef destroy of %d\n", m_identifier); + assert(node()->m_identifier == m_identifier); + node()->release(); } operator TreeReference() const { @@ -83,12 +60,15 @@ public: return static_cast(m_pool->node(m_identifier)); } + int identifier() const { return m_identifier; } + protected: TreeReference(TreePool * pool) : m_pool(pool) { TreeNode * node = new T(); m_identifier = node->identifier(); + printf("TreeNode orig build of %d\n", m_identifier); } private: @@ -97,6 +77,7 @@ private: m_identifier(node->identifier()) //m_cachedNode(node) { + printf("TreeNode build of %d\n", m_identifier); node->retain(); } From 3777304adb78f5955cbeb9c12010f7c9884e4f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 14:17:55 +0200 Subject: [PATCH 004/156] Implement some tree methods --- tree_node.cpp | 21 ++++++++++++++++++++- tree_node.h | 23 ++++++++++++++++++++++- tree_pool.cpp | 3 +++ tree_pool.h | 11 +++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index 94f029d6b..caf86e33b 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,12 +2,31 @@ #include "expression_node.h" void TreeNode::release() { - printf("release of %d\n", m_identifier); + printf("releasing of %d(%p)\n", m_identifier, this); m_referenceCounter--; if (m_referenceCounter == 0) { +#if 0 for (TreeNode * child : directChildren()) { + // BUG FIXME + // Here, if we end up delete-ing the node + // then the 'next child' is wrong... child->release(); } +#endif + if (numberOfChildren() != 0) { + int lastIdentifier = lastDescendant()->identifier(); + TreeNode * child = this; + do { + bool childWillBeDeleted = (child->m_referenceCounter == 1); + child->release(); + if (!childWillBeDeleted) { + printf("Incrementing iterator\n"); + child = child->next(); + } else { + printf("Keeping iterator\n"); + } + } while (child->identifier() != lastIdentifier); + } printf("DELETE %d(%p)\n", m_identifier, this); delete this; diff --git a/tree_node.h b/tree_node.h index 5d764026f..573cc3a50 100644 --- a/tree_node.h +++ b/tree_node.h @@ -9,6 +9,12 @@ #include +/* What's in a TreeNode, really? + * - a vtable + * - an identifier + * - a reference counter + */ + class TreeNode { //friend class TreeReference; // friend class TreePool; @@ -75,7 +81,7 @@ public: } #endif - virtual size_t size() const { + virtual size_t size() const { // Consider making this full abstract? return sizeof(TreeNode); } @@ -135,6 +141,21 @@ public: return node; } + TreeNode * lastDescendant() const { + TreeNode * node = const_cast(this); + + int remainingNodesToVisit = 0; + while (true) { + remainingNodesToVisit += node->numberOfChildren(); + if (remainingNodesToVisit == 0) { + return node; + } + node = node->next(); + remainingNodesToVisit--; + } + return node; + } + size_t deepSize() const { // TODO: Error handling return diff --git a/tree_pool.cpp b/tree_pool.cpp index c6c7479ec..f31dc8471 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -68,6 +68,8 @@ static inline void insert(char * source, char * destination, size_t length) { } } } + } else { + assert(false); // TODO: Implement this case } } @@ -76,6 +78,7 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { return; } insert(reinterpret_cast(source), reinterpret_cast(destination), source->deepSize()); + // Here, update the nodeForIdentifier array } #if TREE_LOGGING diff --git a/tree_pool.h b/tree_pool.h index fbf11f375..98c8939ae 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -9,6 +9,17 @@ class TreePool { public: TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} + template + TreeNode * createTreeNode() { + // Find a new identifier + // Find a memory location for node + } + void discardTreeNode(TreeNode * node) { + // Reclaim node's identifier + // then dealloc node's memory + // Then call the destructor on node + } + int generateIdentifier() { printf("Generating identifier %d\n", m_lastIdentifier); /* For now we're not bothering with making sure the identifiers are indeed From 2f8d8890cbcd5aa25cbe80c5bfb1458b51c72ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 14:16:18 +0200 Subject: [PATCH 005/156] Map node/identifier in an array and implement newIdentifier() --- expression_node.h | 4 +++- tree_pool.cpp | 18 ++---------------- tree_pool.h | 41 ++++++++++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/expression_node.h b/expression_node.h index 03d05ad71..35826ec1b 100644 --- a/expression_node.h +++ b/expression_node.h @@ -6,7 +6,9 @@ class ExpressionNode : public TreeNode { public: - ExpressionNode() : TreeNode(Pool()->generateIdentifier()) {} + ExpressionNode() : TreeNode(Pool()->generateIdentifier()) { + Pool()->registerNode(this); + } // TODO: operator new and delte // this behavior is the same for every TreeNode diff --git a/tree_pool.cpp b/tree_pool.cpp index f31dc8471..979328c0e 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -23,22 +23,8 @@ void TreePool::dealloc(void * ptr) { } TreeNode * TreePool::node(int identifier) const { - for (TreeNode * node : *this) { - if (node->identifier() == identifier) { - return node; - } - } - /* - TreeNode * node = const_cast(reinterpret_cast(m_buffer)); - TreeNode * endOfPool = reinterpret_cast(m_cursor); - while (node < endOfPool) { - if (node->identifier() == identifier) { - return node; - } - node = node->next(); - } - */ - return nullptr; + assert(identifier >= 0 && identifier <= MaxNumberOfNodes); + return m_nodeForIdentifier[identifier]; } static inline void swap(uint32_t * a, uint32_t * b) { diff --git a/tree_pool.h b/tree_pool.h index 98c8939ae..465ca211a 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -7,7 +7,7 @@ class TreePool { public: - TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} + TreePool() : m_cursor(m_buffer) { } template TreeNode * createTreeNode() { @@ -21,13 +21,20 @@ public: } int generateIdentifier() { - printf("Generating identifier %d\n", m_lastIdentifier); - /* For now we're not bothering with making sure the identifiers are indeed - * unique. We're just assuming we'll never overflow... */ - //assert(node(m_lastIdentifier) == nullptr); - return m_lastIdentifier++; + int newIdentifier = -1; + for (int i = 0; i < MaxNumberOfNodes; i++) { + if (m_nodeForIdentifier[i] == nullptr) { + newIdentifier = i; + break; + } + } + printf("Generating identifier %d\n", newIdentifier); + return newIdentifier; } - void reclaimIdentifier(int identifier) { + + void freeIdentifier(int identifier) { + assert(identifier >= 0 && identifier < MaxNumberOfNodes); + m_nodeForIdentifier[identifier] = nullptr; } void * alloc(size_t size); @@ -38,14 +45,23 @@ public: TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + void registerNode(TreeNode * node) { + m_nodeForIdentifier[node->identifier()] = node; + } + + void renameNode(TreeNode * node) { + node->rename(generateIdentifier()); + registerNode(node); + } + TreeNode * deepCopy(TreeNode * node) { size_t size = node->deepSize(); void * ptr = alloc(size); memcpy(ptr, static_cast(node), size); TreeNode * copy = reinterpret_cast(ptr); - copy->rename(generateIdentifier()); + renameNode(copy); for (TreeNode * child : copy->depthFirstChildren()) { - child->rename(generateIdentifier()); + renameNode(child); } return copy; } @@ -59,9 +75,12 @@ private: TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } - int m_lastIdentifier; char * m_cursor; - char m_buffer[256]; + + constexpr static int BufferSize = 256; + char m_buffer[BufferSize]; + constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); + TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; }; #endif From 42c57ae6f2d8ab5cbbabbae13d6bea525237cb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 14:34:22 +0200 Subject: [PATCH 006/156] Fix TreePool::alloc and dealloc --- tree_pool.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tree_pool.cpp b/tree_pool.cpp index 979328c0e..684839bdc 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -3,6 +3,9 @@ #include "tree_node.h" void * TreePool::alloc(size_t size) { + if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { + return nullptr; + } void * result = m_cursor; m_cursor += size; return result; @@ -12,14 +15,22 @@ void TreePool::dealloc(void * ptr) { assert(ptr >= m_buffer && ptr < m_cursor); TreeNode * node = reinterpret_cast(ptr); size_t size = node->size(); - printf("Dealloc %d(%p) of size %d\n", node->m_identifier, node, size); + printf("Dealloc %d(%p) of size %zu\n", node->m_identifier, node, size); + // Step 1 - Compact the pool memmove( ptr, static_cast(ptr) + size, - m_cursor - static_cast(ptr) + m_cursor - (static_cast(ptr) + size) ); m_cursor -= size; + + // Step 2 - Update m_nodeForIdentifier + for (int i = 0; i < MaxNumberOfNodes; i++) { + if (m_nodeForIdentifier[i] > node) { + m_nodeForIdentifier[i] -= size; + } + } } TreeNode * TreePool::node(int identifier) const { From 7af35728f27aa597bb31d00deb3100a9bbc1990d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 15:28:10 +0200 Subject: [PATCH 007/156] Fix TreePool::insert, move and other methods --- tree_pool.cpp | 67 +++++++++++++++++++++++++++++++++++---------------- tree_pool.h | 26 +++++++++++--------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/tree_pool.cpp b/tree_pool.cpp index 684839bdc..f0209d222 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -38,35 +38,41 @@ TreeNode * TreePool::node(int identifier) const { return m_nodeForIdentifier[identifier]; } -static inline void swap(uint32_t * a, uint32_t * b) { - uint32_t tmp = *a; - *a = *b; - *b = tmp; +static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { + if (dst > src) { + src += len; + dst += len; + while (len--) { + *--dst = *--src; + } + } else { + while (len--) { + *dst++ = *src++; + } + } } -static inline void insert(char * source, char * destination, size_t length) { +void TreePool::insert(char * destination, char * source, size_t length) { + if (source == destination || destination < source + length) { + return; + } + assert(length % 4 == 0); assert((long)source % 4 == 0); assert((long)destination % 4 == 0); + uint32_t * src = reinterpret_cast(source); uint32_t * dst = reinterpret_cast(destination); size_t len = length/4; - + char tempBuffer[BufferSize]; + uint32_t * tmp = reinterpret_cast(tempBuffer); + memmove32(reinterpret_cast(tmp), src, len); if (dst < src) { - if (src - dst <= len) { - uint32_t * srcPointer = src; - uint32_t * dstPointer = dst; - while (dstPointer != src) { - swap(srcPointer, dstPointer); - srcPointer++; - dstPointer++; - if (srcPointer == src + len) { - srcPointer = src; - } - } - } + memmove32(dst + len, dst, src - dst); + memmove32(dst, tmp, len); } else { - assert(false); // TODO: Implement this case + memmove32(src, src + len, dst - (src + len)); + memmove32(dst - len, tmp, len); } } @@ -74,8 +80,27 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { if (source == destination) { return; } - insert(reinterpret_cast(source), reinterpret_cast(destination), source->deepSize()); - // Here, update the nodeForIdentifier array + // Move the Node + size_t srcDeepSize = source->deepSize(); + insert(reinterpret_cast(destination), reinterpret_cast(source), srcDeepSize); + + // Update the nodeForIdentifier array + for (int i = 0; i < MaxNumberOfNodes; i++) { + void * nodeAddress = m_nodeForIdentifier[i]; + if (nodeAddress == nullptr) { + continue; + } else if (nodeAddress >= source && nodeAddress < source + srcDeepSize) { + if (destination < source) { + m_nodeForIdentifier[i] -= (source - destination); + } else { + m_nodeForIdentifier[i] += destination - (source + srcDeepSize); + } + } else if (nodeAddress > source && nodeAddress < destination) { + m_nodeForIdentifier[i] -= srcDeepSize; + } else if (nodeAddress < source && nodeAddress > destination) { + m_nodeForIdentifier[i] += srcDeepSize; + } + } } #if TREE_LOGGING diff --git a/tree_pool.h b/tree_pool.h index 465ca211a..2a237c4f1 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -9,17 +9,6 @@ class TreePool { public: TreePool() : m_cursor(m_buffer) { } - template - TreeNode * createTreeNode() { - // Find a new identifier - // Find a memory location for node - } - void discardTreeNode(TreeNode * node) { - // Reclaim node's identifier - // then dealloc node's memory - // Then call the destructor on node - } - int generateIdentifier() { int newIdentifier = -1; for (int i = 0; i < MaxNumberOfNodes; i++) { @@ -40,6 +29,19 @@ public: void * alloc(size_t size); void dealloc(void * ptr); + // Node + template + TreeNode * createTreeNode() { + // TODO + // Find a new identifier + // Find a memory location for node + } + void discardTreeNode(TreeNode * node) { + // TODO + // Reclaim node's identifier + // Then call the destructor on node + // then dealloc node's memory + } TreeNode * node(int identifier) const; void move(TreeNode * source, TreeNode * destination); TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } @@ -71,7 +73,7 @@ public: #endif private: - + static inline void insert(char * destination, char * source, size_t length); TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } From 4c300e66d73892310aace48859d7413529a090fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 15:30:03 +0200 Subject: [PATCH 008/156] Reorganize tree_pool.h --- tree_pool.cpp | 2 +- tree_pool.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tree_pool.cpp b/tree_pool.cpp index f0209d222..d2443e1e9 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -1,6 +1,6 @@ #include "tree_pool.h" -#include #include "tree_node.h" +#include void * TreePool::alloc(size_t size) { if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { diff --git a/tree_pool.h b/tree_pool.h index 2a237c4f1..9aa8edf1e 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -9,6 +9,7 @@ class TreePool { public: TreePool() : m_cursor(m_buffer) { } + // Identifiers int generateIdentifier() { int newIdentifier = -1; for (int i = 0; i < MaxNumberOfNodes; i++) { @@ -26,6 +27,7 @@ public: m_nodeForIdentifier[identifier] = nullptr; } + // Pool memory void * alloc(size_t size); void dealloc(void * ptr); @@ -43,10 +45,11 @@ public: // then dealloc node's memory } TreeNode * node(int identifier) const; - void move(TreeNode * source, TreeNode * destination); TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + void move(TreeNode * source, TreeNode * destination); + void registerNode(TreeNode * node) { m_nodeForIdentifier[node->identifier()] = node; } From c6af4bb16c71a578fcec65bdbec5e33dd8931738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 20 Jun 2018 15:59:35 +0200 Subject: [PATCH 009/156] Clean and correct TreeNode --- tree_node.cpp | 12 ++---------- tree_node.h | 14 +++++--------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index caf86e33b..edbd382b2 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,20 +2,12 @@ #include "expression_node.h" void TreeNode::release() { - printf("releasing of %d(%p)\n", m_identifier, this); + printf("Releasing of %d(%p)\n", m_identifier, this); m_referenceCounter--; if (m_referenceCounter == 0) { -#if 0 - for (TreeNode * child : directChildren()) { - // BUG FIXME - // Here, if we end up delete-ing the node - // then the 'next child' is wrong... - child->release(); - } -#endif if (numberOfChildren() != 0) { int lastIdentifier = lastDescendant()->identifier(); - TreeNode * child = this; + TreeNode * child = next(); do { bool childWillBeDeleted = (child->m_referenceCounter == 1); child->release(); diff --git a/tree_node.h b/tree_node.h index 573cc3a50..de27920e4 100644 --- a/tree_node.h +++ b/tree_node.h @@ -59,7 +59,6 @@ public: public: using TreeNode::Iterator::Iterator; Iterator & operator++() { - // printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); m_node = m_node->next(); return *this; } @@ -88,6 +87,7 @@ public: void retain() { m_referenceCounter++; } + void release(); void rename(int identifier) { @@ -107,7 +107,7 @@ public: assert(i >= 0); assert(i < numberOfChildren()); TreeNode * child = next(); - while (i>0) { + while (i > 0) { child = child->nextSibling(); assert(child != nullptr); i--; @@ -143,15 +143,11 @@ public: TreeNode * lastDescendant() const { TreeNode * node = const_cast(this); - - int remainingNodesToVisit = 0; - while (true) { - remainingNodesToVisit += node->numberOfChildren(); - if (remainingNodesToVisit == 0) { - return node; - } + int remainingNodesToVisit = node->numberOfChildren(); + while (remainingNodesToVisit > 0) { node = node->next(); remainingNodesToVisit--; + remainingNodesToVisit += node->numberOfChildren(); } return node; } From 8ed138fafe1b94a58dc7a237738e10baf2ddb067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 10:11:10 +0200 Subject: [PATCH 010/156] NodeForIdentifier array works properly --- expression_node.h | 5 ----- tree_node.cpp | 9 ++++++++- tree_node.h | 5 +++++ tree_pool.cpp | 48 +++++++++++++++++++++++++++++++++-------------- tree_pool.h | 6 +++++- tree_reference.h | 3 +++ 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/expression_node.h b/expression_node.h index 35826ec1b..61e4d2ea0 100644 --- a/expression_node.h +++ b/expression_node.h @@ -22,11 +22,6 @@ public: Pool()->dealloc(ptr); } - static TreePool * Pool() { - static TreePool pool; - return &pool; - } - virtual float approximate() = 0; int numberOfOperands() { return numberOfChildren(); } ExpressionNode * operand(int i) { return static_cast(childAtIndex(i)); } diff --git a/tree_node.cpp b/tree_node.cpp index edbd382b2..3b1c4018e 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -1,6 +1,12 @@ #include "tree_node.h" +#include "tree_pool.h" #include "expression_node.h" +TreePool * TreeNode::Pool() { + static TreePool pool; + return &pool; +} + void TreeNode::release() { printf("Releasing of %d(%p)\n", m_identifier, this); m_referenceCounter--; @@ -19,8 +25,9 @@ void TreeNode::release() { } } while (child->identifier() != lastIdentifier); } - printf("DELETE %d(%p)\n", m_identifier, this); + int identifier = m_identifier; delete this; + Pool()->freeIdentifier(identifier); } } diff --git a/tree_node.h b/tree_node.h index de27920e4..c41549453 100644 --- a/tree_node.h +++ b/tree_node.h @@ -15,6 +15,8 @@ * - a reference counter */ +class TreePool; + class TreeNode { //friend class TreeReference; // friend class TreePool; @@ -22,6 +24,9 @@ public: virtual ~TreeNode() { } + // Pool + static TreePool * Pool(); + // Iterators class Iterator { diff --git a/tree_pool.cpp b/tree_pool.cpp index d2443e1e9..878c4345b 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -1,5 +1,4 @@ #include "tree_pool.h" -#include "tree_node.h" #include void * TreePool::alloc(size_t size) { @@ -27,8 +26,8 @@ void TreePool::dealloc(void * ptr) { // Step 2 - Update m_nodeForIdentifier for (int i = 0; i < MaxNumberOfNodes; i++) { - if (m_nodeForIdentifier[i] > node) { - m_nodeForIdentifier[i] -= size; + if (m_nodeForIdentifier[i] != nullptr && m_nodeForIdentifier[i] > node) { + m_nodeForIdentifier[i] = reinterpret_cast(reinterpret_cast(m_nodeForIdentifier[i]) - size); } } } @@ -53,7 +52,7 @@ static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { } void TreePool::insert(char * destination, char * source, size_t length) { - if (source == destination || destination < source + length) { + if (source == destination || (destination > source && destination < source + length)) { return; } @@ -76,31 +75,50 @@ void TreePool::insert(char * destination, char * source, size_t length) { } } +void TreePool::logNodeForIdentifierArray() { + printf("\n\n"); + for (int i = 0; i < MaxNumberOfNodes; i++) { + if (m_nodeForIdentifier[i] != nullptr) { + printf("Identifier %d, node %p\n", i, m_nodeForIdentifier[i]); + } + } + printf("\n\n"); +} + void TreePool::move(TreeNode * source, TreeNode * destination) { if (source == destination) { return; } + + log(); + // Move the Node size_t srcDeepSize = source->deepSize(); - insert(reinterpret_cast(destination), reinterpret_cast(source), srcDeepSize); + printf("SourceDeepSize %zu\n", srcDeepSize); + char * destinationAddress = reinterpret_cast(destination); + char * sourceAddress = reinterpret_cast(source); + insert(destinationAddress, sourceAddress, srcDeepSize); // Update the nodeForIdentifier array for (int i = 0; i < MaxNumberOfNodes; i++) { - void * nodeAddress = m_nodeForIdentifier[i]; + char * nodeAddress = reinterpret_cast(m_nodeForIdentifier[i]); if (nodeAddress == nullptr) { continue; - } else if (nodeAddress >= source && nodeAddress < source + srcDeepSize) { - if (destination < source) { - m_nodeForIdentifier[i] -= (source - destination); + } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + srcDeepSize) { + printf("Source %p, dest %p, currentNode identifier %d, pointer %p\n", sourceAddress, destinationAddress, i, m_nodeForIdentifier[i]); + if (destinationAddress < sourceAddress) { + printf("former pointer %p, pointer difference %ld", m_nodeForIdentifier[i], sourceAddress - destinationAddress); + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - (sourceAddress - destinationAddress)); } else { - m_nodeForIdentifier[i] += destination - (source + srcDeepSize); + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + srcDeepSize))); } - } else if (nodeAddress > source && nodeAddress < destination) { - m_nodeForIdentifier[i] -= srcDeepSize; - } else if (nodeAddress < source && nodeAddress > destination) { - m_nodeForIdentifier[i] += srcDeepSize; + } else if (nodeAddress > sourceAddress && nodeAddress <= destinationAddress) { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - srcDeepSize); + } else if (nodeAddress < sourceAddress && nodeAddress >= destinationAddress) { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + srcDeepSize); } } + log(); } #if TREE_LOGGING @@ -112,6 +130,8 @@ void TreePool::log() { printf("|(%03d|%s|%03d|%p)", node->m_identifier, node->description(), node->retainCount(), node); } printf("|\n"); + + logNodeForIdentifierArray(); } #endif diff --git a/tree_pool.h b/tree_pool.h index 9aa8edf1e..9f0b4ffaa 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -2,7 +2,6 @@ #define TREE_POOL_H #include - #include "tree_node.h" class TreePool { @@ -19,11 +18,13 @@ public: } } printf("Generating identifier %d\n", newIdentifier); + assert(newIdentifier != -1); // TODO error handling return newIdentifier; } void freeIdentifier(int identifier) { assert(identifier >= 0 && identifier < MaxNumberOfNodes); + printf("DELETE IDENTIFIER %d\n", identifier); m_nodeForIdentifier[identifier] = nullptr; } @@ -48,9 +49,12 @@ public: TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + void logNodeForIdentifierArray(); + void move(TreeNode * source, TreeNode * destination); void registerNode(TreeNode * node) { + printf("Registering identifier %d with node %p\n", node->identifier(), node); m_nodeForIdentifier[node->identifier()] = node; } diff --git a/tree_reference.h b/tree_reference.h index 7bedd292a..079a60f9c 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -19,6 +19,9 @@ public: ~TreeReference() { printf("TreeRef destroy of %d\n", m_identifier); + assert(node()); + printf("TreeRef's node %p\n", node()); + printf("TreeRef's node identifier %d and node identifier %d\n", node()->m_identifier, m_identifier); assert(node()->m_identifier == m_identifier); node()->release(); } From f39f974b7633611e2064c85b1ea0496a612e35e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 10:27:33 +0200 Subject: [PATCH 011/156] One tree pool instance --- expression_node.h | 9 ++++----- expression_reference.h | 2 +- test.cpp | 10 +++++----- tree_node.cpp | 7 +------ tree_node.h | 5 ----- tree_pool.cpp | 5 +++++ tree_pool.h | 3 ++- tree_reference.h | 22 +++++++--------------- 8 files changed, 25 insertions(+), 38 deletions(-) diff --git a/expression_node.h b/expression_node.h index 61e4d2ea0..65aa43e16 100644 --- a/expression_node.h +++ b/expression_node.h @@ -2,12 +2,11 @@ #define EXPRESSION_NODE_H #include "tree_node.h" -#include "tree_pool.h" class ExpressionNode : public TreeNode { public: - ExpressionNode() : TreeNode(Pool()->generateIdentifier()) { - Pool()->registerNode(this); + ExpressionNode() : TreeNode(TreePool::sharedPool()->generateIdentifier()) { + TreePool::sharedPool()->registerNode(this); } // TODO: operator new and delte @@ -15,11 +14,11 @@ public: // Find a way to define it on the TreeNode void * operator new(size_t count) { - return Pool()->alloc(count); + return TreePool::sharedPool()->alloc(count); } void operator delete(void * ptr) { - Pool()->dealloc(ptr); + TreePool::sharedPool()->dealloc(ptr); } virtual float approximate() = 0; diff --git a/expression_reference.h b/expression_reference.h index 9b6e93e24..76776affd 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -9,7 +9,7 @@ template class ExpressionReference : public TreeReference { public: - ExpressionReference() : TreeReference(ExpressionNode::Pool()) { } + ExpressionReference() : TreeReference() { } /*ExpressionReference(const ExpressionReference & er) { }*/ diff --git a/test.cpp b/test.cpp index f58e54047..4a1015a49 100644 --- a/test.cpp +++ b/test.cpp @@ -3,7 +3,7 @@ #include void poolTest() { - ExpressionNode::Pool()->log(); + TreePool::sharedPool()->log(); FloatNode * f = new FloatNode(); f->setFloat(0.1f); @@ -13,11 +13,11 @@ void poolTest() { AdditionNode * h = new AdditionNode(); - ExpressionNode::Pool()->log(); + TreePool::sharedPool()->log(); delete g; - ExpressionNode::Pool()->log(); + TreePool::sharedPool()->log(); } Expression buildAddition() { @@ -26,7 +26,7 @@ Expression buildAddition() { Addition a(smallFloat, bigFloat); - ExpressionNode::Pool()->log(); + TreePool::sharedPool()->log(); printf("EXITING\n"); printf("smallFloat ref = %d\n", smallFloat.identifier()); printf("bigFloat ref = %d\n", bigFloat.identifier()); @@ -37,7 +37,7 @@ int main() { printf("Hello\n"); Expression a = buildAddition(); printf("HAS RETURNED\n"); - ExpressionNode::Pool()->log(); + TreePool::sharedPool()->log(); diff --git a/tree_node.cpp b/tree_node.cpp index 3b1c4018e..c1b51c59d 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,11 +2,6 @@ #include "tree_pool.h" #include "expression_node.h" -TreePool * TreeNode::Pool() { - static TreePool pool; - return &pool; -} - void TreeNode::release() { printf("Releasing of %d(%p)\n", m_identifier, this); m_referenceCounter--; @@ -28,6 +23,6 @@ void TreeNode::release() { printf("DELETE %d(%p)\n", m_identifier, this); int identifier = m_identifier; delete this; - Pool()->freeIdentifier(identifier); + TreePool::sharedPool()->freeIdentifier(identifier); } } diff --git a/tree_node.h b/tree_node.h index c41549453..de27920e4 100644 --- a/tree_node.h +++ b/tree_node.h @@ -15,8 +15,6 @@ * - a reference counter */ -class TreePool; - class TreeNode { //friend class TreeReference; // friend class TreePool; @@ -24,9 +22,6 @@ public: virtual ~TreeNode() { } - // Pool - static TreePool * Pool(); - // Iterators class Iterator { diff --git a/tree_pool.cpp b/tree_pool.cpp index 878c4345b..815e88518 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -1,6 +1,11 @@ #include "tree_pool.h" #include +TreePool * TreePool::sharedPool() { + static TreePool pool; + return &pool; +} + void * TreePool::alloc(size_t size) { if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { return nullptr; diff --git a/tree_pool.h b/tree_pool.h index 9f0b4ffaa..6ddb0d0f9 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -6,7 +6,7 @@ class TreePool { public: - TreePool() : m_cursor(m_buffer) { } + static TreePool * sharedPool(); // Identifiers int generateIdentifier() { @@ -80,6 +80,7 @@ public: #endif private: + TreePool() : m_cursor(m_buffer) { } static inline void insert(char * destination, char * source, size_t length); TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } diff --git a/tree_reference.h b/tree_reference.h index 079a60f9c..39455b61c 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -10,7 +10,6 @@ template class TreeReference { public: TreeReference(const TreeReference & tr) : - m_pool(tr.m_pool), m_identifier(tr.m_identifier) { printf("TreeReference copy of %d\n", m_identifier); @@ -41,42 +40,37 @@ public: } void addChild(TreeReference t) { - //assert(t.m_pool == m_pool); - //t.node()->retain(); - TreeNode * deepCopy = m_pool->deepCopy(t.node()); - m_pool->move( + TreeNode * deepCopy = TreePool::sharedPool()->deepCopy(t.node()); + TreePool::sharedPool()->move( deepCopy, node()->next() ); } void removeChild(TreeReference t) { - m_pool->move( + TreePool::sharedPool()->move( t.node(), - m_pool->last() + TreePool::sharedPool()->last() ); t.node()->release(); } T * node() const { // TODO: Here, assert that the node type is indeed T - return static_cast(m_pool->node(m_identifier)); + return static_cast(TreePool::sharedPool()->node(m_identifier)); } int identifier() const { return m_identifier; } protected: - TreeReference(TreePool * pool) : - m_pool(pool) - { + TreeReference() { TreeNode * node = new T(); m_identifier = node->identifier(); printf("TreeNode orig build of %d\n", m_identifier); } private: - TreeReference(TreePool * pool, TreeNode * node) : - m_pool(pool), + TreeReference(TreeNode * node) : m_identifier(node->identifier()) //m_cachedNode(node) { @@ -84,8 +78,6 @@ private: node->retain(); } - - TreePool * m_pool; int m_identifier; //TreeNode * m_cachedNode; }; From b81d491644d8518d710da0d5f1bfae3520c51f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 14:37:41 +0200 Subject: [PATCH 012/156] Clean code and debug printing --- expression_reference.h | 1 - float_node.h | 2 +- test.cpp | 15 +++++++++++---- tree_node.cpp | 4 ++-- tree_pool.cpp | 3 --- tree_pool.h | 4 ++-- tree_reference.h | 18 +++++++----------- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/expression_reference.h b/expression_reference.h index 76776affd..75c53f3d7 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -16,7 +16,6 @@ public: // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression operator ExpressionReference() const { - printf("ExpressionReference cast\n"); // TODO: make sure this is kosher // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); return *(reinterpret_cast *>(this)); diff --git a/float_node.h b/float_node.h index 843de0ee0..90e6193ca 100644 --- a/float_node.h +++ b/float_node.h @@ -7,7 +7,7 @@ class FloatNode : public ExpressionNode { public: FloatNode() : ExpressionNode() { - printf("Create float\n"); + printf("Created float\n"); } size_t size() const override { return sizeof(FloatNode); diff --git a/test.cpp b/test.cpp index 4a1015a49..a450bd51d 100644 --- a/test.cpp +++ b/test.cpp @@ -21,20 +21,27 @@ void poolTest() { } Expression buildAddition() { + printf("\n\n-----------------------------\n"); + printf("CODE: Float smallFloat(0.2f);\n\n"); Float smallFloat(0.2f); + + printf("\n\n-----------------------------\n"); + printf("CODE: Float bigFloat(3.4f);\n\n"); Float bigFloat(3.4f); + printf("\n\n-----------------------------\n"); + printf("CODE: Addition a(smallFloat, bigFloat);\n\n"); Addition a(smallFloat, bigFloat); TreePool::sharedPool()->log(); - printf("EXITING\n"); - printf("smallFloat ref = %d\n", smallFloat.identifier()); - printf("bigFloat ref = %d\n", bigFloat.identifier()); + printf("\n\n-----------------------------\n"); + printf("CODE: return a;\n\n"); return a; } int main() { - printf("Hello\n"); + printf("\n\n-----------------------------\n"); + printf("CODE: Expression a = buildAddition();\n\n"); Expression a = buildAddition(); printf("HAS RETURNED\n"); TreePool::sharedPool()->log(); diff --git a/tree_node.cpp b/tree_node.cpp index c1b51c59d..2c131a9fa 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -3,7 +3,7 @@ #include "expression_node.h" void TreeNode::release() { - printf("Releasing of %d(%p)\n", m_identifier, this); + printf("Release %d(%p)\n", m_identifier, this); m_referenceCounter--; if (m_referenceCounter == 0) { if (numberOfChildren() != 0) { @@ -20,7 +20,7 @@ void TreeNode::release() { } } while (child->identifier() != lastIdentifier); } - printf("DELETE %d(%p)\n", m_identifier, this); + printf("Delete %d(%p)\n", m_identifier, this); int identifier = m_identifier; delete this; TreePool::sharedPool()->freeIdentifier(identifier); diff --git a/tree_pool.cpp b/tree_pool.cpp index 815e88518..13a3796d6 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -99,7 +99,6 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { // Move the Node size_t srcDeepSize = source->deepSize(); - printf("SourceDeepSize %zu\n", srcDeepSize); char * destinationAddress = reinterpret_cast(destination); char * sourceAddress = reinterpret_cast(source); insert(destinationAddress, sourceAddress, srcDeepSize); @@ -110,9 +109,7 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { if (nodeAddress == nullptr) { continue; } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + srcDeepSize) { - printf("Source %p, dest %p, currentNode identifier %d, pointer %p\n", sourceAddress, destinationAddress, i, m_nodeForIdentifier[i]); if (destinationAddress < sourceAddress) { - printf("former pointer %p, pointer difference %ld", m_nodeForIdentifier[i], sourceAddress - destinationAddress); m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - (sourceAddress - destinationAddress)); } else { m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + srcDeepSize))); diff --git a/tree_pool.h b/tree_pool.h index 6ddb0d0f9..aeb44f5b2 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -17,14 +17,14 @@ public: break; } } - printf("Generating identifier %d\n", newIdentifier); + //printf("Generating identifier %d\n", newIdentifier); assert(newIdentifier != -1); // TODO error handling return newIdentifier; } void freeIdentifier(int identifier) { assert(identifier >= 0 && identifier < MaxNumberOfNodes); - printf("DELETE IDENTIFIER %d\n", identifier); + printf("Freeing identifier %d\n", identifier); m_nodeForIdentifier[identifier] = nullptr; } diff --git a/tree_reference.h b/tree_reference.h index 39455b61c..2c22518ee 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -9,18 +9,16 @@ template class TreeReference { public: - TreeReference(const TreeReference & tr) : - m_identifier(tr.m_identifier) - { - printf("TreeReference copy of %d\n", m_identifier); - node()->retain(); + TreeReference(const TreeReference & tr) { + int trNodeIdentifier = tr.m_identifier; + printf("TreeReference copy of %d\n", trNodeIdentifier); + TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(TreePool::sharedPool()->node(trNodeIdentifier)); + m_identifier = nodeCopy->identifier(); } ~TreeReference() { printf("TreeRef destroy of %d\n", m_identifier); assert(node()); - printf("TreeRef's node %p\n", node()); - printf("TreeRef's node identifier %d and node identifier %d\n", node()->m_identifier, m_identifier); assert(node()->m_identifier == m_identifier); node()->release(); } @@ -66,20 +64,18 @@ protected: TreeReference() { TreeNode * node = new T(); m_identifier = node->identifier(); - printf("TreeNode orig build of %d\n", m_identifier); + printf("Creating TreeRef of new node %d\n", m_identifier); } private: TreeReference(TreeNode * node) : m_identifier(node->identifier()) - //m_cachedNode(node) { - printf("TreeNode build of %d\n", m_identifier); + printf("Creating TreeRef of existing node %d\n", m_identifier); node->retain(); } int m_identifier; - //TreeNode * m_cachedNode; }; #endif From b201e82cddce1d9eaf5ea9eb29e8b31db71b1623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 14:39:48 +0200 Subject: [PATCH 013/156] Fix some methods --- tree_node.cpp | 17 ++++++++--------- tree_node.h | 21 ++++++++++++++++----- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index 2c131a9fa..edc4beee7 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -7,18 +7,17 @@ void TreeNode::release() { m_referenceCounter--; if (m_referenceCounter == 0) { if (numberOfChildren() != 0) { - int lastIdentifier = lastDescendant()->identifier(); + int lastIdentifier = lastChild()->identifier(); TreeNode * child = next(); - do { - bool childWillBeDeleted = (child->m_referenceCounter == 1); + bool lastChildReleased = false; + while (!lastChildReleased) { + lastChildReleased = child->identifier() == lastIdentifier; + int nextSiblingIdentifier = lastChildReleased ? -1 : child->nextSibling()->identifier(); child->release(); - if (!childWillBeDeleted) { - printf("Incrementing iterator\n"); - child = child->next(); - } else { - printf("Keeping iterator\n"); + if (nextSiblingIdentifier != -1) { + child = TreePool::sharedPool()->node(nextSiblingIdentifier); } - } while (child->identifier() != lastIdentifier); + } } printf("Delete %d(%p)\n", m_identifier, this); int identifier = m_identifier; diff --git a/tree_node.h b/tree_node.h index de27920e4..059d19891 100644 --- a/tree_node.h +++ b/tree_node.h @@ -131,17 +131,17 @@ public: } TreeNode * nextSibling() const { - TreeNode * node = const_cast(this); - int remainingNodesToVisit = 0; - do { + int remainingNodesToVisit = numberOfChildren(); + TreeNode * node = const_cast(this)->next(); + while (remainingNodesToVisit > 0) { remainingNodesToVisit += node->numberOfChildren(); node = node->next(); remainingNodesToVisit--; - } while (remainingNodesToVisit > 0); + } return node; } - TreeNode * lastDescendant() const { + /*TreeNode * lastDescendant() const { TreeNode * node = const_cast(this); int remainingNodesToVisit = node->numberOfChildren(); while (remainingNodesToVisit > 0) { @@ -150,6 +150,17 @@ public: remainingNodesToVisit += node->numberOfChildren(); } return node; + }*/ + + TreeNode * lastChild() const { + if (numberOfChildren() == 0) { + return const_cast(this); + } + TreeNode * node = next(); + for (int i = 0; i < numberOfChildren() - 1; i++) { + node = node->nextSibling(); + } + return node; } size_t deepSize() const { From a63d7e35fea5647f7b6d4cc16c3d31ec585c70a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 14:53:13 +0200 Subject: [PATCH 014/156] Protected/private tree node methods --- tree_node.h | 24 ++++++++++++------------ tree_reference.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tree_node.h b/tree_node.h index 059d19891..d3a7b5e06 100644 --- a/tree_node.h +++ b/tree_node.h @@ -16,12 +16,14 @@ */ class TreeNode { - //friend class TreeReference; - // friend class TreePool; +// friend class TreeReference; + friend class TreePool; public: virtual ~TreeNode() { } + int indentifier() const { return m_identifier; } + // Iterators class Iterator { @@ -115,21 +117,19 @@ public: return child; } -//private: - - // FIXME: Make this private - TreeNode(int identifier) : - m_identifier(identifier), - m_referenceCounter(1) - { - } - TreeNode * next() const { // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. // Unfortunately, we want TreeNode to have a VARIABLE size return reinterpret_cast(reinterpret_cast(const_cast(this)) + size()); } +protected: + TreeNode(int identifier) : + m_identifier(identifier), + m_referenceCounter(1) + { + } + TreeNode * nextSibling() const { int remainingNodesToVisit = numberOfChildren(); TreeNode * node = const_cast(this)->next(); @@ -172,7 +172,7 @@ public: ; } -//private: +private: int m_identifier; int m_referenceCounter; }; diff --git a/tree_reference.h b/tree_reference.h index 2c22518ee..0a5a277b4 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -19,7 +19,7 @@ public: ~TreeReference() { printf("TreeRef destroy of %d\n", m_identifier); assert(node()); - assert(node()->m_identifier == m_identifier); + assert(node()->identifier() == m_identifier); node()->release(); } From 4440f183c49672376f40e143cd844491c5a6059a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 15:00:18 +0200 Subject: [PATCH 015/156] TreeNode::size is pure virtual --- addition_node.h | 4 ++++ tree_node.h | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addition_node.h b/addition_node.h index e3a8ab618..e60f2143b 100644 --- a/addition_node.h +++ b/addition_node.h @@ -11,6 +11,10 @@ public: return "Addition"; } #endif + + size_t size() const override { + return sizeof(AdditionNode); + } float approximate() override { float result = 0.0f; for (int i=0; i Date: Thu, 21 Jun 2018 16:13:35 +0200 Subject: [PATCH 016/156] Replace new/delete TreeNode with TreePool::create/discardTreeNode --- expression_node.h | 12 ------------ tree_node.cpp | 4 +--- tree_pool.h | 28 +++++++++++++++++++--------- tree_reference.h | 2 +- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/expression_node.h b/expression_node.h index 65aa43e16..12aaea11a 100644 --- a/expression_node.h +++ b/expression_node.h @@ -9,18 +9,6 @@ public: TreePool::sharedPool()->registerNode(this); } - // TODO: operator new and delte - // this behavior is the same for every TreeNode - // Find a way to define it on the TreeNode - - void * operator new(size_t count) { - return TreePool::sharedPool()->alloc(count); - } - - void operator delete(void * ptr) { - TreePool::sharedPool()->dealloc(ptr); - } - virtual float approximate() = 0; int numberOfOperands() { return numberOfChildren(); } ExpressionNode * operand(int i) { return static_cast(childAtIndex(i)); } diff --git a/tree_node.cpp b/tree_node.cpp index edc4beee7..d2ae1e070 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -20,8 +20,6 @@ void TreeNode::release() { } } printf("Delete %d(%p)\n", m_identifier, this); - int identifier = m_identifier; - delete this; - TreePool::sharedPool()->freeIdentifier(identifier); + TreePool::sharedPool()->discardTreeNode(this); } } diff --git a/tree_pool.h b/tree_pool.h index aeb44f5b2..4f70c8ac6 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -3,6 +3,7 @@ #include #include "tree_node.h" +#include class TreePool { public: @@ -33,18 +34,27 @@ public: void dealloc(void * ptr); // Node - template - TreeNode * createTreeNode() { - // TODO - // Find a new identifier - // Find a memory location for node + template + T * createTreeNode() { + int nodeIdentifier = generateIdentifier(); + if (nodeIdentifier == -1) { + return nullptr; // TODO return static node "failedAllocation" + } + void * ptr = alloc(sizeof(T)); + // TODO handle allocation problem! + TreeNode * node = new(ptr) T(); + node->rename(nodeIdentifier); + registerNode(node); + return reinterpret_cast(node); } + void discardTreeNode(TreeNode * node) { - // TODO - // Reclaim node's identifier - // Then call the destructor on node - // then dealloc node's memory + int nodeIdentifier = node->identifier(); + node->~TreeNode(); + dealloc(static_cast(node)); + freeIdentifier(nodeIdentifier); } + TreeNode * node(int identifier) const; TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } diff --git a/tree_reference.h b/tree_reference.h index 0a5a277b4..fa794fc2d 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -62,7 +62,7 @@ public: protected: TreeReference() { - TreeNode * node = new T(); + TreeNode * node = TreePool::sharedPool()->createTreeNode(); m_identifier = node->identifier(); printf("Creating TreeRef of new node %d\n", m_identifier); } From 9a2c458f49c156fe87d981672df34203b52ac881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 16:15:03 +0200 Subject: [PATCH 017/156] Clean code --- expression_node.h | 6 ------ test.cpp | 28 ---------------------------- tree_pool.h | 1 - tree_reference.h | 1 - 4 files changed, 36 deletions(-) diff --git a/expression_node.h b/expression_node.h index 12aaea11a..7cd7bdffd 100644 --- a/expression_node.h +++ b/expression_node.h @@ -15,9 +15,3 @@ public: }; #endif - -/* Code I want to write: - * - * ExpressionNode * n = new AdditionNode(); - * delete n; - */ diff --git a/test.cpp b/test.cpp index a450bd51d..cdbfc143d 100644 --- a/test.cpp +++ b/test.cpp @@ -2,24 +2,6 @@ #include "addition_node.h" #include -void poolTest() { - TreePool::sharedPool()->log(); - - FloatNode * f = new FloatNode(); - f->setFloat(0.1f); - - FloatNode * g = new FloatNode(); - g->setFloat(1.1f); - - AdditionNode * h = new AdditionNode(); - - TreePool::sharedPool()->log(); - - delete g; - - TreePool::sharedPool()->log(); -} - Expression buildAddition() { printf("\n\n-----------------------------\n"); printf("CODE: Float smallFloat(0.2f);\n\n"); @@ -46,15 +28,5 @@ int main() { printf("HAS RETURNED\n"); TreePool::sharedPool()->log(); - - - /* - Expression e = Parse("1+1"); - Expression j = e; - Expression f = Addition(e, Parse("5")); - f.removeChildAtIndex(0); - */ - - return 0; } diff --git a/tree_pool.h b/tree_pool.h index 4f70c8ac6..cb509aec5 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -18,7 +18,6 @@ public: break; } } - //printf("Generating identifier %d\n", newIdentifier); assert(newIdentifier != -1); // TODO error handling return newIdentifier; } diff --git a/tree_reference.h b/tree_reference.h index fa794fc2d..97f85a3e8 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -2,7 +2,6 @@ #define TREE_REFERENCE_H #include "tree_pool.h" -#include #include From 267ae5843b950b661a12d8a3d1ca399c1123d24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 16:15:16 +0200 Subject: [PATCH 018/156] Add const qualifier --- tree_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tree_node.h b/tree_node.h index 4373ffdcc..21ed5a240 100644 --- a/tree_node.h +++ b/tree_node.h @@ -95,7 +95,7 @@ public: m_referenceCounter = 1; } - int retainCount() { + int retainCount() const { return m_referenceCounter; } From 1adff31abd59303ea6e4af9ac15c2289d2c94a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 21 Jun 2018 16:37:07 +0200 Subject: [PATCH 019/156] Remove TreeNode constructor arguments --- tree_node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tree_node.h b/tree_node.h index 21ed5a240..45b84b6d3 100644 --- a/tree_node.h +++ b/tree_node.h @@ -122,8 +122,8 @@ public: } protected: - TreeNode(int identifier) : - m_identifier(identifier), + TreeNode() : + m_identifier(-1), m_referenceCounter(1) { } From 287c9ca990e5f53acd7e74732370fc7b9847389b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 10:23:40 +0200 Subject: [PATCH 020/156] TreeNode::parent algorithm --- tree_node.cpp | 29 +++++++++++++++++++++++++++++ tree_node.h | 9 +++------ tree_pool.h | 33 +++++++++++++++++++++++++++------ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index d2ae1e070..678205491 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,6 +2,35 @@ #include "tree_pool.h" #include "expression_node.h" +TreeNode * TreeNode::parent() const { + int cursor = -1; + TreeNode * parentsHistory[TreePool::MaxNumberOfNodes]; + int numberOfChildrenHistory[TreePool::MaxNumberOfNodes]; + int childrenVisitedCountHistory[TreePool::MaxNumberOfNodes]; + for (TreeNode * node : TreePool::sharedPool()->allNodes()) { + if (node->identifier() == m_identifier) { + printf("Parent of %d is %d\n", m_identifier, cursor >= 0 ? parentsHistory[cursor]->identifier() : -1); + return cursor >= 0 ? parentsHistory[cursor] : nullptr; + } + if (cursor >= 0) { + childrenVisitedCountHistory[cursor] = childrenVisitedCountHistory[cursor]+1; + } + int nodeChildrenCount = node->numberOfChildren(); + if (nodeChildrenCount > 0) { + cursor++; + parentsHistory[cursor] = node; + numberOfChildrenHistory[cursor] = nodeChildrenCount; + childrenVisitedCountHistory[cursor] = 0; + } else { + if (cursor >= 0 && (numberOfChildrenHistory[cursor] == childrenVisitedCountHistory[cursor])) { + cursor--; + } + } + } + assert(false); + return nullptr; +} + void TreeNode::release() { printf("Release %d(%p)\n", m_identifier, this); m_referenceCounter--; diff --git a/tree_node.h b/tree_node.h index 45b84b6d3..0a0cdfc9d 100644 --- a/tree_node.h +++ b/tree_node.h @@ -19,15 +19,13 @@ class TreeNode { // friend class TreeReference; friend class TreePool; public: - virtual ~TreeNode() { - } - + virtual ~TreeNode() {} int indentifier() const { return m_identifier; } - // Iterators + TreeNode * parent() const; class Iterator { - public: + public: Iterator(TreeNode * node) : m_node(node) {} TreeNode * operator*() { return m_node; } bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } @@ -73,7 +71,6 @@ public: DepthFirst depthFirstChildren() { return DepthFirst(this); } - int identifier() const { return m_identifier; } #if TREE_LOGGING diff --git a/tree_pool.h b/tree_pool.h index cb509aec5..b8b981a27 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -6,6 +6,7 @@ #include class TreePool { + friend class TreeNode; public: static TreePool * sharedPool(); @@ -88,17 +89,37 @@ public: void log(); #endif -private: - TreePool() : m_cursor(m_buffer) { } - static inline void insert(char * destination, char * source, size_t length); +protected: + constexpr static int BufferSize = 256; + constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); + + class AllPool { + public: + AllPool(TreeNode * node) : m_node(node) {} + class Iterator : public TreeNode::Iterator { + public: + using TreeNode::Iterator::Iterator; + Iterator & operator++() { + m_node = m_node->next(); + return *this; + } + }; + Iterator begin() const { return Iterator(m_node); } + Iterator end() const { return Iterator(TreePool::sharedPool()->last()); } + private: + TreeNode * m_node; + }; + AllPool allNodes() { return AllPool(*(begin())); } + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } - char * m_cursor; +private: + TreePool() : m_cursor(m_buffer) { } + static inline void insert(char * destination, char * source, size_t length); - constexpr static int BufferSize = 256; + char * m_cursor; char m_buffer[BufferSize]; - constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; }; From edce759ae58a5d36ecae4cd49896c43344811827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 10:24:14 +0200 Subject: [PATCH 021/156] Rename operand to child --- addition_node.h | 4 ++-- expression_node.h | 7 +------ tree_node.h | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/addition_node.h b/addition_node.h index e60f2143b..b03278a70 100644 --- a/addition_node.h +++ b/addition_node.h @@ -17,8 +17,8 @@ public: } float approximate() override { float result = 0.0f; - for (int i=0; iapproximate(); + for (int i=0; iapproximate(); } return result; } diff --git a/expression_node.h b/expression_node.h index 7cd7bdffd..433bb5ce7 100644 --- a/expression_node.h +++ b/expression_node.h @@ -5,13 +5,8 @@ class ExpressionNode : public TreeNode { public: - ExpressionNode() : TreeNode(TreePool::sharedPool()->generateIdentifier()) { - TreePool::sharedPool()->registerNode(this); - } - virtual float approximate() = 0; - int numberOfOperands() { return numberOfChildren(); } - ExpressionNode * operand(int i) { return static_cast(childAtIndex(i)); } + ExpressionNode * child(int i) { return static_cast(treeChildAtIndex(i)); } }; #endif diff --git a/tree_node.h b/tree_node.h index 0a0cdfc9d..f94978c70 100644 --- a/tree_node.h +++ b/tree_node.h @@ -100,7 +100,7 @@ public: return 0; } - TreeNode * childAtIndex(int i) const { + TreeNode * treeChildAtIndex(int i) const { assert(i >= 0); assert(i < numberOfChildren()); TreeNode * child = next(); From ac182b04d1772944ba1473a129a35198aa486afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 10:39:40 +0200 Subject: [PATCH 022/156] Clean TreeNode --- tree_node.cpp | 15 +++++++++++- tree_node.h | 68 +++++++++++++++++---------------------------------- 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index 678205491..e05cc7bc7 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,7 +2,7 @@ #include "tree_pool.h" #include "expression_node.h" -TreeNode * TreeNode::parent() const { +TreeNode * TreeNode::treeParent() const { int cursor = -1; TreeNode * parentsHistory[TreePool::MaxNumberOfNodes]; int numberOfChildrenHistory[TreePool::MaxNumberOfNodes]; @@ -31,6 +31,19 @@ TreeNode * TreeNode::parent() const { return nullptr; } +TreeNode * TreeNode::treeChildAtIndex(int i) const { + assert(i >= 0); + assert(i < numberOfChildren()); + TreeNode * child = next(); + while (i > 0) { + child = child->nextSibling(); + assert(child != nullptr); + i--; + } + return child; +} + + void TreeNode::release() { printf("Release %d(%p)\n", m_identifier, this); m_referenceCounter--; diff --git a/tree_node.h b/tree_node.h index f94978c70..d892f6829 100644 --- a/tree_node.h +++ b/tree_node.h @@ -20,9 +20,29 @@ class TreeNode { friend class TreePool; public: virtual ~TreeNode() {} - int indentifier() const { return m_identifier; } - TreeNode * parent() const; + // Attributes + virtual size_t size() const = 0; + int identifier() const { return m_identifier; } + int retainCount() const { return m_referenceCounter; } +#if TREE_LOGGING + virtual const char * description() const { + return "UNKNOWN"; + } +#endif + + // Node operations + void retain() { m_referenceCounter++; } + void release(); + void rename(int identifier) { + m_identifier = identifier; + m_referenceCounter = 1; + } + + // Hierarchy + TreeNode * treeParent() const; + virtual int numberOfChildren() const { return 0; } + TreeNode * treeChildAtIndex(int i) const; class Iterator { public: @@ -50,8 +70,6 @@ public: TreeNode * m_node; }; - Direct directChildren() { return Direct(this); } - class DepthFirst { public: DepthFirst(TreeNode * node) : m_node(node) {} @@ -69,49 +87,9 @@ public: TreeNode * m_node; }; + Direct directChildren() { return Direct(this); } DepthFirst depthFirstChildren() { return DepthFirst(this); } - int identifier() const { return m_identifier; } - -#if TREE_LOGGING - virtual const char * description() const { - return "UNKNOWN"; - } -#endif - - virtual size_t size() const = 0; - - void retain() { - m_referenceCounter++; - } - - void release(); - - void rename(int identifier) { - m_identifier = identifier; - m_referenceCounter = 1; - } - - int retainCount() const { - return m_referenceCounter; - } - - virtual int numberOfChildren() const { - return 0; - } - - TreeNode * treeChildAtIndex(int i) const { - assert(i >= 0); - assert(i < numberOfChildren()); - TreeNode * child = next(); - while (i > 0) { - child = child->nextSibling(); - assert(child != nullptr); - i--; - } - return child; - } - TreeNode * next() const { // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. // Unfortunately, we want TreeNode to have a VARIABLE size From 2908c20defbfabcce9686e10eb6360ed1dee1390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 11:07:04 +0200 Subject: [PATCH 023/156] Add methods to tree node and new parent() algorithm --- tree_node.cpp | 23 +++++++++++++++++++++++ tree_node.h | 12 +++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index e05cc7bc7..2499511e1 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -3,6 +3,9 @@ #include "expression_node.h" TreeNode * TreeNode::treeParent() const { +// Choose between those two algorithms: the first has complexity O(numberNodes) but uses 0(3maxNumberNodes) space +// The second is much clearer for the reader and uses no space, but has complexity 0 +#if 0 int cursor = -1; TreeNode * parentsHistory[TreePool::MaxNumberOfNodes]; int numberOfChildrenHistory[TreePool::MaxNumberOfNodes]; @@ -29,6 +32,26 @@ TreeNode * TreeNode::treeParent() const { } assert(false); return nullptr; +#else + for (TreeNode * node : TreePool::sharedPool()->allNodes()) { + if (node == this) { + return nullptr; + } + if (node->hasChild(this)) { + return node; + } + } + assert(false); + return nullptr; +#endif +} + +int TreeNode::numberOfDescendants(bool includeSelf) const { + int result = includeSelf ? 1 : 0; + for (TreeNode * child : depthFirstChildren()) { + result++; + } + return result; } TreeNode * TreeNode::treeChildAtIndex(int i) const { diff --git a/tree_node.h b/tree_node.h index d892f6829..74b413618 100644 --- a/tree_node.h +++ b/tree_node.h @@ -42,11 +42,13 @@ public: // Hierarchy TreeNode * treeParent() const; virtual int numberOfChildren() const { return 0; } + int numberOfDescendants(bool includeSelf) const; TreeNode * treeChildAtIndex(int i) const; + bool hasChild(const TreeNode * child) const; class Iterator { public: - Iterator(TreeNode * node) : m_node(node) {} + Iterator(const TreeNode * node) : m_node(const_cast(node)) {} TreeNode * operator*() { return m_node; } bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } protected: @@ -55,7 +57,7 @@ public: class Direct { public: - Direct(TreeNode * node) : m_node(node) {} + Direct(const TreeNode * node) : m_node(const_cast(node)) {} class Iterator : public TreeNode::Iterator { public: using TreeNode::Iterator::Iterator; @@ -72,7 +74,7 @@ public: class DepthFirst { public: - DepthFirst(TreeNode * node) : m_node(node) {} + DepthFirst(const TreeNode * node) : m_node(const_cast(node)) {} class Iterator : public TreeNode::Iterator { public: using TreeNode::Iterator::Iterator; @@ -87,8 +89,8 @@ public: TreeNode * m_node; }; - Direct directChildren() { return Direct(this); } - DepthFirst depthFirstChildren() { return DepthFirst(this); } + Direct directChildren() const { return Direct(this); } + DepthFirst depthFirstChildren() const { return DepthFirst(this); } TreeNode * next() const { // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. From 0fb04ea45a384c1d487b6abf4f852ea7f8d4d81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 11:49:24 +0200 Subject: [PATCH 024/156] New TreeNode methods --- expression_node.h | 2 +- tree_node.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++-- tree_node.h | 8 ++++-- tree_pool.h | 18 +++++++++++++ 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/expression_node.h b/expression_node.h index 433bb5ce7..6512d864c 100644 --- a/expression_node.h +++ b/expression_node.h @@ -6,7 +6,7 @@ class ExpressionNode : public TreeNode { public: virtual float approximate() = 0; - ExpressionNode * child(int i) { return static_cast(treeChildAtIndex(i)); } + ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } }; #endif diff --git a/tree_node.cpp b/tree_node.cpp index 2499511e1..034ef3aac 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,7 +2,7 @@ #include "tree_pool.h" #include "expression_node.h" -TreeNode * TreeNode::treeParent() const { +TreeNode * TreeNode::parentTree() const { // Choose between those two algorithms: the first has complexity O(numberNodes) but uses 0(3maxNumberNodes) space // The second is much clearer for the reader and uses no space, but has complexity 0 #if 0 @@ -46,6 +46,16 @@ TreeNode * TreeNode::treeParent() const { #endif } +TreeNode * TreeNode::editableRootTree() { + for (TreeNode * root : TreePool::sharedPool()->roots()) { + if (hasAncestor(root, true)) { + return root; + } + } + assert(false); + return nullptr; +} + int TreeNode::numberOfDescendants(bool includeSelf) const { int result = includeSelf ? 1 : 0; for (TreeNode * child : depthFirstChildren()) { @@ -54,7 +64,7 @@ int TreeNode::numberOfDescendants(bool includeSelf) const { return result; } -TreeNode * TreeNode::treeChildAtIndex(int i) const { +TreeNode * TreeNode::childTreeAtIndex(int i) const { assert(i >= 0); assert(i < numberOfChildren()); TreeNode * child = next(); @@ -66,6 +76,60 @@ TreeNode * TreeNode::treeChildAtIndex(int i) const { return child; } +int TreeNode::indexOfChild(const TreeNode * child) const { + if (child == nullptr) { + return -1; + } + int childrenCount = numberOfChildren(); + TreeNode * childAtIndexi = next(); + for (int i = 0; i < childrenCount; i++) { + if (childAtIndexi == child) { + return i; + } + childAtIndexi = childAtIndexi->nextSibling(); + } + return -1; +} + +bool TreeNode::hasChild(const TreeNode * child) const { + if (child == nullptr) { + return false; + } + for (TreeNode * c : directChildren()) { + if (child == c) { + return true; + } + } + return false; +} + +bool TreeNode::hasAncestor(const TreeNode * node, bool includeSelf) const { + if (includeSelf && node == this) { + return true; + } + for (TreeNode * t : node->depthFirstChildren()) { + if (this == t) { + return true; + } + } + return false; +} + +bool TreeNode::hasSibling(const TreeNode * e) const { + if (e == nullptr) { + return false; + } + TreeNode * parent = parentTree(); + if (parent == nullptr) { + return false; + } + for (TreeNode * childNode : parent->directChildren()) { + if (childNode == e) { + return true; + } + } + return false; +} void TreeNode::release() { printf("Release %d(%p)\n", m_identifier, this); diff --git a/tree_node.h b/tree_node.h index 74b413618..f8f6f815e 100644 --- a/tree_node.h +++ b/tree_node.h @@ -40,11 +40,15 @@ public: } // Hierarchy - TreeNode * treeParent() const; + TreeNode * parentTree() const; + TreeNode * editableRootTree(); virtual int numberOfChildren() const { return 0; } int numberOfDescendants(bool includeSelf) const; - TreeNode * treeChildAtIndex(int i) const; + TreeNode * childTreeAtIndex(int i) const; + int indexOfChild(const TreeNode * child) const; bool hasChild(const TreeNode * child) const; + bool hasAncestor(const TreeNode * node, bool includeSelf) const; + bool hasSibling(const TreeNode * e) const; class Iterator { public: diff --git a/tree_pool.h b/tree_pool.h index b8b981a27..5a744fc73 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -111,6 +111,24 @@ protected: }; AllPool allNodes() { return AllPool(*(begin())); } + class Roots { + public: + Roots(TreeNode * node) : m_node(node) {} + class Iterator : public TreeNode::Iterator { + public: + using TreeNode::Iterator::Iterator; + Iterator & operator++() { + m_node = m_node->nextSibling(); + return *this; + } + }; + Iterator begin() const { return Iterator(m_node); } + Iterator end() const { return Iterator(TreePool::sharedPool()->last()); } + private: + TreeNode * m_node; + }; + Roots roots() { return Roots(*(begin())); } + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } From 6f598acc10b0ead5cb4736c03415f9e9cfcf2d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 14:05:23 +0200 Subject: [PATCH 025/156] ReplaceWith and ReplaceChild methods on References --- expression_reference.h | 8 ++++++ test.cpp | 11 ++++++-- tree_node.cpp | 48 +++++++++++++++++--------------- tree_reference.cpp | 14 ---------- tree_reference.h | 63 +++++++++++++++++++++++++----------------- 5 files changed, 81 insertions(+), 63 deletions(-) delete mode 100644 tree_reference.cpp diff --git a/expression_reference.h b/expression_reference.h index 75c53f3d7..072699f71 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -25,6 +25,14 @@ public: TreeReference::addChild(e); } + ExpressionReference childAtIndex(int i) { + return TreeReference::childAtIndex(i); + } + + void replaceChildAtIndex(int oldChildIndex, ExpressionReference newChild) { + TreeReference::replaceChildAtIndex(oldChildIndex, newChild); + } + float approximate() const { return this->node()->approximate(); } diff --git a/test.cpp b/test.cpp index cdbfc143d..2e1d9b637 100644 --- a/test.cpp +++ b/test.cpp @@ -2,7 +2,7 @@ #include "addition_node.h" #include -Expression buildAddition() { +Addition buildAddition() { printf("\n\n-----------------------------\n"); printf("CODE: Float smallFloat(0.2f);\n\n"); Float smallFloat(0.2f); @@ -24,7 +24,14 @@ Expression buildAddition() { int main() { printf("\n\n-----------------------------\n"); printf("CODE: Expression a = buildAddition();\n\n"); - Expression a = buildAddition(); + Addition a = buildAddition(); + float result = a.approximate(); + printf("a = %f \n", result); + Float smallFloat(1.3f); + a.replaceChildAtIndex(0, smallFloat); + float result2 = a.approximate(); + printf("a = %f \n", result2); + printf("HAS RETURNED\n"); TreePool::sharedPool()->log(); diff --git a/tree_node.cpp b/tree_node.cpp index 034ef3aac..f227ca2ef 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -2,6 +2,32 @@ #include "tree_pool.h" #include "expression_node.h" +// Node operations + +void TreeNode::release() { + printf("Release %d(%p)\n", m_identifier, this); + m_referenceCounter--; + if (m_referenceCounter == 0) { + if (numberOfChildren() != 0) { + int lastIdentifier = lastChild()->identifier(); + TreeNode * child = next(); + bool lastChildReleased = false; + while (!lastChildReleased) { + lastChildReleased = child->identifier() == lastIdentifier; + int nextSiblingIdentifier = lastChildReleased ? -1 : child->nextSibling()->identifier(); + child->release(); + if (nextSiblingIdentifier != -1) { + child = TreePool::sharedPool()->node(nextSiblingIdentifier); + } + } + } + printf("Delete %d(%p)\n", m_identifier, this); + TreePool::sharedPool()->discardTreeNode(this); + } +} + +// Hierarchy + TreeNode * TreeNode::parentTree() const { // Choose between those two algorithms: the first has complexity O(numberNodes) but uses 0(3maxNumberNodes) space // The second is much clearer for the reader and uses no space, but has complexity 0 @@ -130,25 +156,3 @@ bool TreeNode::hasSibling(const TreeNode * e) const { } return false; } - -void TreeNode::release() { - printf("Release %d(%p)\n", m_identifier, this); - m_referenceCounter--; - if (m_referenceCounter == 0) { - if (numberOfChildren() != 0) { - int lastIdentifier = lastChild()->identifier(); - TreeNode * child = next(); - bool lastChildReleased = false; - while (!lastChildReleased) { - lastChildReleased = child->identifier() == lastIdentifier; - int nextSiblingIdentifier = lastChildReleased ? -1 : child->nextSibling()->identifier(); - child->release(); - if (nextSiblingIdentifier != -1) { - child = TreePool::sharedPool()->node(nextSiblingIdentifier); - } - } - } - printf("Delete %d(%p)\n", m_identifier, this); - TreePool::sharedPool()->discardTreeNode(this); - } -} diff --git a/tree_reference.cpp b/tree_reference.cpp deleted file mode 100644 index e42312dad..000000000 --- a/tree_reference.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "tree_reference.h" - -#if 0 -void TreeReference::addOperand(TreeReference t) { - // At this point, e has been copied. - // We can therefore pilfer its node! - Node * n = node(); - pool->move( - t->node(), - t->next() - ); - node->stealAsOperand(t->node()); -} -#endif diff --git a/tree_reference.h b/tree_reference.h index 97f85a3e8..74a80b119 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -9,7 +9,7 @@ template class TreeReference { public: TreeReference(const TreeReference & tr) { - int trNodeIdentifier = tr.m_identifier; + int trNodeIdentifier = tr.identifier(); printf("TreeReference copy of %d\n", trNodeIdentifier); TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(TreePool::sharedPool()->node(trNodeIdentifier)); m_identifier = nodeCopy->identifier(); @@ -28,30 +28,6 @@ public: return *(reinterpret_cast *>(this)); } - int numberOfChildren() const { - return node()->numberOfChildren(); - } - - TreeReference childAtIndex(int i) const { - return TreeReference(node()->childAtIndex(i)); - } - - void addChild(TreeReference t) { - TreeNode * deepCopy = TreePool::sharedPool()->deepCopy(t.node()); - TreePool::sharedPool()->move( - deepCopy, - node()->next() - ); - } - - void removeChild(TreeReference t) { - TreePool::sharedPool()->move( - t.node(), - TreePool::sharedPool()->last() - ); - t.node()->release(); - } - T * node() const { // TODO: Here, assert that the node type is indeed T return static_cast(TreePool::sharedPool()->node(m_identifier)); @@ -59,6 +35,43 @@ public: int identifier() const { return m_identifier; } + // Hierarchy + int numberOfChildren() const { + return node()->numberOfChildren(); + } + + TreeReference parent() const { + return TreeReference(node()->parentTree()); + } + + TreeReference childAtIndex(int i) const { + return TreeReference(node()->child(i)); + } + + // Hierarchy operations + + void addChild(TreeReference t) { + TreeNode * deepCopy = TreePool::sharedPool()->deepCopy(t.node()); + TreePool::sharedPool()->move(deepCopy, node()->next()); + } + + void removeChild(TreeReference t) { + TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); + t.node()->release(); + } + + void replaceWith(TreeReference t) { + parent().replaceChild(node()->indexOfChild(t.node()), t); + } + + void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { + assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); + TreeReference oldChild = childAtIndex(oldChildIndex); + TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); + newChild.node()->retain(); + TreePool::sharedPool()->move(oldChild.node(), TreePool::sharedPool()->last()); + oldChild.node()->release(); + } protected: TreeReference() { TreeNode * node = TreePool::sharedPool()->createTreeNode(); From d7ea9f3bf736dc6d4a15a102827a5cf18e25b31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 15:16:48 +0200 Subject: [PATCH 026/156] Remove debug printing --- float_node.h | 4 +--- test.cpp | 18 ------------------ tree_node.cpp | 3 --- tree_pool.cpp | 3 +-- tree_pool.h | 2 -- tree_reference.h | 4 ---- 6 files changed, 2 insertions(+), 32 deletions(-) diff --git a/float_node.h b/float_node.h index 90e6193ca..ff53b186d 100644 --- a/float_node.h +++ b/float_node.h @@ -6,9 +6,7 @@ class FloatNode : public ExpressionNode { public: - FloatNode() : ExpressionNode() { - printf("Created float\n"); - } + FloatNode() : ExpressionNode() {} size_t size() const override { return sizeof(FloatNode); } diff --git a/test.cpp b/test.cpp index 2e1d9b637..1e9a4fda6 100644 --- a/test.cpp +++ b/test.cpp @@ -3,37 +3,19 @@ #include Addition buildAddition() { - printf("\n\n-----------------------------\n"); - printf("CODE: Float smallFloat(0.2f);\n\n"); Float smallFloat(0.2f); - - printf("\n\n-----------------------------\n"); - printf("CODE: Float bigFloat(3.4f);\n\n"); Float bigFloat(3.4f); - - printf("\n\n-----------------------------\n"); - printf("CODE: Addition a(smallFloat, bigFloat);\n\n"); Addition a(smallFloat, bigFloat); - TreePool::sharedPool()->log(); - printf("\n\n-----------------------------\n"); - printf("CODE: return a;\n\n"); return a; } int main() { - printf("\n\n-----------------------------\n"); - printf("CODE: Expression a = buildAddition();\n\n"); Addition a = buildAddition(); float result = a.approximate(); - printf("a = %f \n", result); Float smallFloat(1.3f); a.replaceChildAtIndex(0, smallFloat); float result2 = a.approximate(); - printf("a = %f \n", result2); - - printf("HAS RETURNED\n"); TreePool::sharedPool()->log(); - return 0; } diff --git a/tree_node.cpp b/tree_node.cpp index f227ca2ef..13c116acb 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -5,7 +5,6 @@ // Node operations void TreeNode::release() { - printf("Release %d(%p)\n", m_identifier, this); m_referenceCounter--; if (m_referenceCounter == 0) { if (numberOfChildren() != 0) { @@ -21,7 +20,6 @@ void TreeNode::release() { } } } - printf("Delete %d(%p)\n", m_identifier, this); TreePool::sharedPool()->discardTreeNode(this); } } @@ -38,7 +36,6 @@ TreeNode * TreeNode::parentTree() const { int childrenVisitedCountHistory[TreePool::MaxNumberOfNodes]; for (TreeNode * node : TreePool::sharedPool()->allNodes()) { if (node->identifier() == m_identifier) { - printf("Parent of %d is %d\n", m_identifier, cursor >= 0 ? parentsHistory[cursor]->identifier() : -1); return cursor >= 0 ? parentsHistory[cursor] : nullptr; } if (cursor >= 0) { diff --git a/tree_pool.cpp b/tree_pool.cpp index 13a3796d6..7363f0a15 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -19,7 +19,6 @@ void TreePool::dealloc(void * ptr) { assert(ptr >= m_buffer && ptr < m_cursor); TreeNode * node = reinterpret_cast(ptr); size_t size = node->size(); - printf("Dealloc %d(%p) of size %zu\n", node->m_identifier, node, size); // Step 1 - Compact the pool memmove( @@ -133,7 +132,7 @@ void TreePool::log() { } printf("|\n"); - logNodeForIdentifierArray(); + //logNodeForIdentifierArray(); } #endif diff --git a/tree_pool.h b/tree_pool.h index 5a744fc73..8de940434 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -25,7 +25,6 @@ public: void freeIdentifier(int identifier) { assert(identifier >= 0 && identifier < MaxNumberOfNodes); - printf("Freeing identifier %d\n", identifier); m_nodeForIdentifier[identifier] = nullptr; } @@ -64,7 +63,6 @@ public: void move(TreeNode * source, TreeNode * destination); void registerNode(TreeNode * node) { - printf("Registering identifier %d with node %p\n", node->identifier(), node); m_nodeForIdentifier[node->identifier()] = node; } diff --git a/tree_reference.h b/tree_reference.h index 74a80b119..19c2ba9a6 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -10,13 +10,11 @@ class TreeReference { public: TreeReference(const TreeReference & tr) { int trNodeIdentifier = tr.identifier(); - printf("TreeReference copy of %d\n", trNodeIdentifier); TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(TreePool::sharedPool()->node(trNodeIdentifier)); m_identifier = nodeCopy->identifier(); } ~TreeReference() { - printf("TreeRef destroy of %d\n", m_identifier); assert(node()); assert(node()->identifier() == m_identifier); node()->release(); @@ -76,14 +74,12 @@ protected: TreeReference() { TreeNode * node = TreePool::sharedPool()->createTreeNode(); m_identifier = node->identifier(); - printf("Creating TreeRef of new node %d\n", m_identifier); } private: TreeReference(TreeNode * node) : m_identifier(node->identifier()) { - printf("Creating TreeRef of existing node %d\n", m_identifier); node->retain(); } From fbaaa96ab1e3fb028130f60c010a7ac8672374af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 15:37:07 +0200 Subject: [PATCH 027/156] Fix TreePool::move --- tree_pool.cpp | 40 +++++++++++++++++++--------------------- tree_pool.h | 2 +- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/tree_pool.cpp b/tree_pool.cpp index 7363f0a15..4f663e23b 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -55,9 +55,9 @@ static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { } } -void TreePool::insert(char * destination, char * source, size_t length) { +bool TreePool::insert(char * destination, char * source, size_t length) { if (source == destination || (destination > source && destination < source + length)) { - return; + return false; } assert(length % 4 == 0); @@ -77,6 +77,7 @@ void TreePool::insert(char * destination, char * source, size_t length) { memmove32(src, src + len, dst - (src + len)); memmove32(dst - len, tmp, len); } + return true; } void TreePool::logNodeForIdentifierArray() { @@ -94,32 +95,29 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { return; } - log(); - // Move the Node size_t srcDeepSize = source->deepSize(); char * destinationAddress = reinterpret_cast(destination); char * sourceAddress = reinterpret_cast(source); - insert(destinationAddress, sourceAddress, srcDeepSize); - - // Update the nodeForIdentifier array - for (int i = 0; i < MaxNumberOfNodes; i++) { - char * nodeAddress = reinterpret_cast(m_nodeForIdentifier[i]); - if (nodeAddress == nullptr) { - continue; - } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + srcDeepSize) { - if (destinationAddress < sourceAddress) { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - (sourceAddress - destinationAddress)); - } else { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + srcDeepSize))); + if (insert(destinationAddress, sourceAddress, srcDeepSize)) { + // Update the nodeForIdentifier array + for (int i = 0; i < MaxNumberOfNodes; i++) { + char * nodeAddress = reinterpret_cast(m_nodeForIdentifier[i]); + if (nodeAddress == nullptr) { + continue; + } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + srcDeepSize) { + if (destinationAddress < sourceAddress) { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - (sourceAddress - destinationAddress)); + } else { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + srcDeepSize))); + } + } else if (nodeAddress > sourceAddress && nodeAddress < destinationAddress) { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - srcDeepSize); + } else if (nodeAddress < sourceAddress && nodeAddress >= destinationAddress) { + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + srcDeepSize); } - } else if (nodeAddress > sourceAddress && nodeAddress <= destinationAddress) { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - srcDeepSize); - } else if (nodeAddress < sourceAddress && nodeAddress >= destinationAddress) { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + srcDeepSize); } } - log(); } #if TREE_LOGGING diff --git a/tree_pool.h b/tree_pool.h index 8de940434..292d7ab4b 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -132,7 +132,7 @@ protected: private: TreePool() : m_cursor(m_buffer) { } - static inline void insert(char * destination, char * source, size_t length); + static inline bool insert(char * destination, char * source, size_t length); char * m_cursor; char m_buffer[BufferSize]; From 517b2892bb59a4ad701ef113cc67a219a8b0f5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Jun 2018 15:42:28 +0200 Subject: [PATCH 028/156] TreeNode::swap --- test.cpp | 1 + tree_reference.h | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/test.cpp b/test.cpp index 1e9a4fda6..9779f720c 100644 --- a/test.cpp +++ b/test.cpp @@ -16,6 +16,7 @@ int main() { Float smallFloat(1.3f); a.replaceChildAtIndex(0, smallFloat); float result2 = a.approximate(); + a.swapChildren(1,0); TreePool::sharedPool()->log(); return 0; } diff --git a/tree_reference.h b/tree_reference.h index 19c2ba9a6..d5f44ba20 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -2,9 +2,11 @@ #define TREE_REFERENCE_H #include "tree_pool.h" - #include +static inline int min(int i, int j) { return i < j ? i : j; } +static inline int max(int i, int j) { return i > j ? i : j; } + template class TreeReference { public: @@ -70,6 +72,22 @@ public: TreePool::sharedPool()->move(oldChild.node(), TreePool::sharedPool()->last()); oldChild.node()->release(); } + + void swapChildren(int i, int j) { + assert(i >= 0 && i < numberOfChildren()); + assert(j >= 0 && j < numberOfChildren()); + if (i == j) { + return; + } + int firstChildIndex = min(i, j); + int secondChildIndex = max(i, j); + TreeReference firstChild = childAtIndex(firstChildIndex); + TreeReference secondChild = childAtIndex(secondChildIndex); + TreeNode * firstChildNode = firstChild.node(); + TreePool::sharedPool()->move(firstChildNode, secondChild.node()->next()); + TreePool::sharedPool()->move(secondChild.node(), firstChildNode); + } + protected: TreeReference() { TreeNode * node = TreePool::sharedPool()->createTreeNode(); From 0af06b5f3aec98ac27bd1e84b095fa7c4c861115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 25 Jun 2018 13:37:28 +0200 Subject: [PATCH 029/156] Add Layouts --- char_layout_node.h | 33 ++++++++++++++++++++++ layout_cursor.cpp | 38 +++++++++++++++++++++++++ layout_cursor.h | 58 +++++++++++++++++++++++++++++++++++++++ layout_cursor_reference.h | 35 +++++++++++++++++++++++ layout_node.cpp | 32 +++++++++++++++++++++ layout_node.h | 49 +++++++++++++++++++++++++++++++++ layout_reference.h | 50 +++++++++++++++++++++++++++++++++ test.cpp | 14 +++++++++- tree_reference.h | 7 +++-- 9 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 char_layout_node.h create mode 100644 layout_cursor.cpp create mode 100644 layout_cursor.h create mode 100644 layout_cursor_reference.h create mode 100644 layout_node.cpp create mode 100644 layout_node.h create mode 100644 layout_reference.h diff --git a/char_layout_node.h b/char_layout_node.h new file mode 100644 index 000000000..763b89ecd --- /dev/null +++ b/char_layout_node.h @@ -0,0 +1,33 @@ +#ifndef CHAR_LAYOUT_H +#define CHAR_LAYOUT_H + +#include "layout_reference.h" +#include "layout_node.h" + +//#define TREE_LOGGING 1 + +class CharLayoutNode : public LayoutNode { +public: + CharLayoutNode() : LayoutNode() {} + size_t size() const override { + return sizeof(CharLayoutNode); + } +#if TREE_LOGGING + const char * description() const override { + static char Description[] = {'C', 'h', 'a', 'r', ' ', m_char, 0}; + return Description; + } +#endif + void setChar(char c) { m_char = c; } +private: + char m_char; +}; + +class CharLayout : public LayoutReference { +public: + CharLayout(char c) : LayoutReference() { + this->node()->setChar(c); + } +}; + +#endif diff --git a/layout_cursor.cpp b/layout_cursor.cpp new file mode 100644 index 000000000..c092a649d --- /dev/null +++ b/layout_cursor.cpp @@ -0,0 +1,38 @@ +#include "layout_cursor.h" +#include "layout_reference.h" +#include + +/* Comparison */ + +bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { + assert(isDefined()); + assert(cursor.isDefined()); + return middleLeftPoint() == cursor.middleLeftPoint(); +} + +/* Position */ + +int LayoutCursor::middleLeftPoint() { + int layoutOrigin = m_layoutPointer.absoluteOrigin(); + return layoutOrigin; +} + +/* Move */ + +void LayoutCursor::moveLeft(bool * shouldRecomputeLayout) { + m_layoutPointer.moveCursorLeft(this, shouldRecomputeLayout); +} + +void LayoutCursor::moveRight(bool * shouldRecomputeLayout) { + m_layoutPointer.moveCursorRight(this, shouldRecomputeLayout); +} + +void LayoutCursor::moveAbove(bool * shouldRecomputeLayout) { + m_layoutPointer.moveCursorUp(this, shouldRecomputeLayout); +} + +void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { + m_layoutPointer.moveCursorDown(this, shouldRecomputeLayout); +} + + diff --git a/layout_cursor.h b/layout_cursor.h new file mode 100644 index 000000000..a3711e2ae --- /dev/null +++ b/layout_cursor.h @@ -0,0 +1,58 @@ +#ifndef LAYOUT_CURSOR_H +#define LAYOUT_CURSOR_H + +#include "tree_pool.h" +#include "layout_cursor_reference.h" +#include "layout_node.h" +#include + +class LayoutCursor { +public: + enum class Position { + Left, + Right + }; + LayoutCursor(Layout * layoutPointer, Position position = Position::Right) : + m_layoutPointer(layoutPointer), + m_position(position) + { + } + + bool isDefined() const { return m_layoutPointer.isDefined(); } + + /* Debug */ + void log() { + printf("Pointed Layout id %d, cursor position ", m_layoutPointer.identifier()); + if (m_position == Position::Left) { + printf("Left"); + } else { + printf("Right"); + } + printf("\n"); + } + + /* Getters and setters */ + //int pointedLayoutIdentifier() const { return m_layoutIdentifier; } + //void setPointedLayoutIdentifier(int layoutID) { m_layoutIdentifier = layoutID; } + Position position() const { return m_position; } + void setPosition(Position position) { m_position = position; } + int cursorHeight() { return 1; } //TODO + int baseline() { return 1; } //TODO + + /* Comparison */ + bool isEquivalentTo(LayoutCursor cursor); + + /* Position */ + int middleLeftPoint(); + + /* Move */ + void moveLeft(bool * shouldRecomputeLayout); + void moveRight(bool * shouldRecomputeLayout); + void moveAbove(bool * shouldRecomputeLayout); + void moveUnder(bool * shouldRecomputeLayout); +private: + LayoutPointer m_layoutPointer; + Position m_position; +}; + +#endif diff --git a/layout_cursor_reference.h b/layout_cursor_reference.h new file mode 100644 index 000000000..8bc23eed1 --- /dev/null +++ b/layout_cursor_reference.h @@ -0,0 +1,35 @@ +#ifndef LAYOUT_CURSOR_REFERENCE_H +#define LAYOUT_CURSOR_REFERENCE_H + +#include "layout_node.h" +#include "layout_reference.h" + +class LayoutCursor; + +template +class LayoutCursorReference : public LayoutReference { +public: + //using LayoutReference::LayoutReference; + LayoutCursorReference(LayoutReference * r) : + LayoutReference(r->node()) + { + } + + LayoutCursorReference(const LayoutCursorReference & r) : + LayoutReference(r.node()) + { + } + + // Tree navigation + + /* We cannot have LayoutCursor cursorLeftOf(LayoutCursor cursor) because of + * circular header dependency */ + virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} + 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) {} +}; + +typedef LayoutCursorReference LayoutPointer; + +#endif diff --git a/layout_node.cpp b/layout_node.cpp new file mode 100644 index 000000000..17a11e301 --- /dev/null +++ b/layout_node.cpp @@ -0,0 +1,32 @@ +#include "layout_node.h" + +void LayoutNode::draw() { + for (LayoutNode * child : children()) { + child->draw(); + } + render(); +} + +int LayoutNode::origin() { + LayoutNode * parentLayout = parent(); + if (parentLayout == nullptr) { + return absoluteOrigin(); + } else { + return 1; //KDPoint(absoluteOrigin().x() - parentLayout->absoluteOrigin().x(), absoluteOrigin().y() - parentLayout->absoluteOrigin().y()); + } + return 0; +} + +int LayoutNode::absoluteOrigin() { + /*if (!m_positioned) { + LayoutNode * parentLayout = parent(); + if (parentLayout != nullptr) { + m_frame.setOrigin(parentLayout->absoluteOrigin().translatedBy(parentLayout->positionOfChild(this))); + } else { + m_frame.setOrigin(KDPointZero); + } + m_positioned = true; + } + return m_frame.origin();*/ + return 1; +} diff --git a/layout_node.h b/layout_node.h new file mode 100644 index 000000000..e3137ce77 --- /dev/null +++ b/layout_node.h @@ -0,0 +1,49 @@ +#ifndef LAYOUT_NODE_H +#define LAYOUT_NODE_H + +#include "tree_node.h" + +class LayoutNode : public TreeNode { +public: + /* Hierarchy */ + LayoutNode * parent() const { return static_cast(parentTree()); } + + /* Rendering */ + void draw(); + int origin(); + int absoluteOrigin(); + + LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } + +protected: + class Iterator { + public: + Iterator(LayoutNode * node) : m_node(node) {} + LayoutNode * operator*() { return m_node; } + bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } + protected: + LayoutNode * m_node; + }; + class DirectChildren { + public: + DirectChildren(LayoutNode * node) : m_node(node) {} + class Iterator : public LayoutNode::Iterator { + public: + using LayoutNode::Iterator::Iterator; + Iterator & operator++() { + m_node = static_cast(m_node->nextSibling()); + return *this; + } + }; + Iterator begin() const { return Iterator(static_cast(m_node->next())); } + Iterator end() const { return Iterator(static_cast(m_node->nextSibling())); } + private: + LayoutNode * m_node; + }; + DirectChildren children() { return DirectChildren(this); } + +private: + virtual void render() {}; +}; + +#endif diff --git a/layout_reference.h b/layout_reference.h new file mode 100644 index 000000000..dd27ba71b --- /dev/null +++ b/layout_reference.h @@ -0,0 +1,50 @@ +#ifndef LAYOUT_REFERENCE_H +#define LAYOUT_REFERENCE_H + +#include "tree_reference.h" +//#include "layout_cursor.h" +#include "layout_node.h" + +template +class LayoutReference : public TreeReference { + friend class LayoutCursor; +public: + using TreeReference::TreeReference; + + /* Allow every LayoutReference to be transformed into a + * LayoutReference, i.e. Layout */ + operator LayoutReference() const { + // TODO: make sure this is kosher + return *(reinterpret_cast *>(this)); + } + + LayoutReference * pointer() { + return (reinterpret_cast *>(this)); + } + + // LayoutReference cursorReference() const; + + void addChild(LayoutReference l) { + TreeReference::addChild(l); + } + + LayoutReference childAtIndex(int i) { + return TreeReference::childAtIndex(i); + } + + void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { + TreeReference::replaceChildAtIndex(oldChildIndex, newChild); + } + + int layoutOrigin() { + return this->node()->layoutOrigin(); + } + + int absoluteOrigin() { + return this->node()->absoluteOrigin(); + } +}; + +typedef LayoutReference Layout; + +#endif diff --git a/test.cpp b/test.cpp index 9779f720c..255883f76 100644 --- a/test.cpp +++ b/test.cpp @@ -1,5 +1,7 @@ #include "float_node.h" +#include "char_layout_node.h" #include "addition_node.h" +#include "layout_cursor.h" #include Addition buildAddition() { @@ -11,12 +13,22 @@ Addition buildAddition() { } int main() { - Addition a = buildAddition(); + /*Addition a = buildAddition(); float result = a.approximate(); Float smallFloat(1.3f); a.replaceChildAtIndex(0, smallFloat); float result2 = a.approximate(); a.swapChildren(1,0); + TreePool::sharedPool()->log();*/ + + printf("\nCHAR LAYOUT\n"); + CharLayout aChar('a'); TreePool::sharedPool()->log(); + LayoutCursor cursor(aChar.pointer()); + TreePool::sharedPool()->log(); + cursor.log(); + bool recompute = false; + cursor.moveLeft(&recompute); + cursor.log(); return 0; } diff --git a/tree_reference.h b/tree_reference.h index d5f44ba20..59efeab89 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -7,7 +7,7 @@ static inline int min(int i, int j) { return i < j ? i : j; } static inline int max(int i, int j) { return i > j ? i : j; } -template +template class TreeReference { public: TreeReference(const TreeReference & tr) { @@ -18,10 +18,13 @@ public: ~TreeReference() { assert(node()); + printf("Delete TreeReference of m_id %d, nodeId %d\n", m_identifier, node()->identifier()); assert(node()->identifier() == m_identifier); node()->release(); } + bool isDefined() const { return m_identifier >= 0 && TreePool::sharedPool()->node(m_identifier) != nullptr; } + operator TreeReference() const { // TODO: make sure this is kosher // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); @@ -94,13 +97,11 @@ protected: m_identifier = node->identifier(); } -private: TreeReference(TreeNode * node) : m_identifier(node->identifier()) { node->retain(); } - int m_identifier; }; From 7587b05c8bfea75365afc868c8253f5b3421753a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 25 Jun 2018 13:50:38 +0200 Subject: [PATCH 030/156] Some layout navigation --- char_layout_node.h | 24 ++++++++++++++++++++++++ layout_cursor_reference.h | 5 ++--- layout_node.h | 9 +++++++++ test.cpp | 2 ++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/char_layout_node.h b/char_layout_node.h index 763b89ecd..4149ec696 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -3,6 +3,7 @@ #include "layout_reference.h" #include "layout_node.h" +#include "layout_cursor.h" //#define TREE_LOGGING 1 @@ -12,6 +13,29 @@ public: size_t size() const override { return sizeof(CharLayoutNode); } + + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { + if (cursor->position() == LayoutCursor::Position::Right) { + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } + } + + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { + if (cursor->position() == LayoutCursor::Position::Left) { + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } + } + #if TREE_LOGGING const char * description() const override { static char Description[] = {'C', 'h', 'a', 'r', ' ', m_char, 0}; diff --git a/layout_cursor_reference.h b/layout_cursor_reference.h index 8bc23eed1..42b4dec5e 100644 --- a/layout_cursor_reference.h +++ b/layout_cursor_reference.h @@ -9,7 +9,6 @@ class LayoutCursor; template class LayoutCursorReference : public LayoutReference { public: - //using LayoutReference::LayoutReference; LayoutCursorReference(LayoutReference * r) : LayoutReference(r->node()) { @@ -24,8 +23,8 @@ public: /* We cannot have LayoutCursor cursorLeftOf(LayoutCursor cursor) because of * circular header dependency */ - virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} - virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} + virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { return this->node()->moveCursorLeft(cursor, shouldRecomputeLayout); } + virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { return this->node()->moveCursorRight(cursor, shouldRecomputeLayout); } virtual void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} virtual void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} }; diff --git a/layout_node.h b/layout_node.h index e3137ce77..4fbafe641 100644 --- a/layout_node.h +++ b/layout_node.h @@ -3,6 +3,8 @@ #include "tree_node.h" +class LayoutCursor; + class LayoutNode : public TreeNode { public: /* Hierarchy */ @@ -13,6 +15,13 @@ public: int origin(); int absoluteOrigin(); + /* Tree navigation */ + virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} + 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) {} + + LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } protected: diff --git a/test.cpp b/test.cpp index 255883f76..6586020bd 100644 --- a/test.cpp +++ b/test.cpp @@ -30,5 +30,7 @@ int main() { bool recompute = false; cursor.moveLeft(&recompute); cursor.log(); + cursor.moveRight(&recompute); + cursor.log(); return 0; } From c60bc61d32a550fb54fbd8cfa23e595fc6d48b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 14:30:04 +0200 Subject: [PATCH 031/156] Add class cursor on for all TreeReferences --- cursor.h | 16 ++++++++++++++++ test.cpp | 8 ++++---- tree_reference.h | 5 +++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 cursor.h diff --git a/cursor.h b/cursor.h new file mode 100644 index 000000000..a66aeafa0 --- /dev/null +++ b/cursor.h @@ -0,0 +1,16 @@ +#ifndef CURSOR_H +#define CURSOR_H + +#include "char_layout_node.h" +#include "tree_node.h" +#include "tree_reference.h" + +class Cursor { + template + friend class TreeReference; +private: + Cursor(TreeNode * node) : m_treeReference(node) {} + TreeReference m_treeReference; +}; + +#endif diff --git a/test.cpp b/test.cpp index 6586020bd..96a79bb7a 100644 --- a/test.cpp +++ b/test.cpp @@ -1,7 +1,7 @@ #include "float_node.h" #include "char_layout_node.h" #include "addition_node.h" -#include "layout_cursor.h" +#include "cursor.h" #include Addition buildAddition() { @@ -24,13 +24,13 @@ int main() { printf("\nCHAR LAYOUT\n"); CharLayout aChar('a'); TreePool::sharedPool()->log(); - LayoutCursor cursor(aChar.pointer()); - TreePool::sharedPool()->log(); + Cursor cursor = aChar.cursor(); +/* TreePool::sharedPool()->log(); cursor.log(); bool recompute = false; cursor.moveLeft(&recompute); cursor.log(); cursor.moveRight(&recompute); - cursor.log(); + cursor.log();*/ return 0; } diff --git a/tree_reference.h b/tree_reference.h index 59efeab89..7ef1bb5b0 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -7,8 +7,11 @@ static inline int min(int i, int j) { return i < j ? i : j; } static inline int max(int i, int j) { return i > j ? i : j; } +class Cursor; + template class TreeReference { + friend class Cursor; public: TreeReference(const TreeReference & tr) { int trNodeIdentifier = tr.identifier(); @@ -38,6 +41,8 @@ public: int identifier() const { return m_identifier; } + Cursor cursor(); + // Hierarchy int numberOfChildren() const { return node()->numberOfChildren(); From f8d08f8599496b2e35a3a3acbe705b7a6524a8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 14:30:42 +0200 Subject: [PATCH 032/156] Make numberOfChildren virtual pure --- char_layout_node.h | 2 ++ float_node.h | 1 + tree_node.h | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/char_layout_node.h b/char_layout_node.h index 4149ec696..fe3ff5bb8 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -14,6 +14,8 @@ public: return sizeof(CharLayoutNode); } + int numberOfChildren() const override { return 0; } + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { if (cursor->position() == LayoutCursor::Position::Right) { cursor->setPosition(LayoutCursor::Position::Left); diff --git a/float_node.h b/float_node.h index ff53b186d..3385544f2 100644 --- a/float_node.h +++ b/float_node.h @@ -10,6 +10,7 @@ public: size_t size() const override { return sizeof(FloatNode); } + int numberOfChildren() const override { return 0; } float approximate() override { return m_value; } diff --git a/tree_node.h b/tree_node.h index f8f6f815e..f241952d4 100644 --- a/tree_node.h +++ b/tree_node.h @@ -42,7 +42,7 @@ public: // Hierarchy TreeNode * parentTree() const; TreeNode * editableRootTree(); - virtual int numberOfChildren() const { return 0; } + virtual int numberOfChildren() const = 0; int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; int indexOfChild(const TreeNode * child) const; From b58ab0a8ca3bdca03da90b9185bf07ab4c1b14ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 15:11:04 +0200 Subject: [PATCH 033/156] LayoutCursor --- char_layout_node.h | 5 +---- cursor.h | 5 +++-- layout_cursor.cpp | 10 +++++----- layout_cursor.h | 26 ++++++++++++++------------ layout_reference.cpp | 10 ++++++++++ layout_reference.h | 7 ++++--- tree_reference.cpp | 11 +++++++++++ tree_reference.h | 2 +- 8 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 layout_reference.cpp create mode 100644 tree_reference.cpp diff --git a/char_layout_node.h b/char_layout_node.h index fe3ff5bb8..d4ff030d2 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -5,8 +5,6 @@ #include "layout_node.h" #include "layout_cursor.h" -//#define TREE_LOGGING 1 - class CharLayoutNode : public LayoutNode { public: CharLayoutNode() : LayoutNode() {} @@ -38,12 +36,11 @@ public: } } -#if TREE_LOGGING const char * description() const override { static char Description[] = {'C', 'h', 'a', 'r', ' ', m_char, 0}; return Description; } -#endif + void setChar(char c) { m_char = c; } private: char m_char; diff --git a/cursor.h b/cursor.h index a66aeafa0..e5dab3537 100644 --- a/cursor.h +++ b/cursor.h @@ -1,14 +1,15 @@ #ifndef CURSOR_H #define CURSOR_H -#include "char_layout_node.h" #include "tree_node.h" #include "tree_reference.h" class Cursor { template friend class TreeReference; -private: +public: + bool isDefined() const { return m_treeReference.isDefined(); } +protected: Cursor(TreeNode * node) : m_treeReference(node) {} TreeReference m_treeReference; }; diff --git a/layout_cursor.cpp b/layout_cursor.cpp index c092a649d..73445d4b7 100644 --- a/layout_cursor.cpp +++ b/layout_cursor.cpp @@ -13,26 +13,26 @@ bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { /* Position */ int LayoutCursor::middleLeftPoint() { - int layoutOrigin = m_layoutPointer.absoluteOrigin(); + int layoutOrigin = layoutReference().absoluteOrigin(); return layoutOrigin; } /* Move */ void LayoutCursor::moveLeft(bool * shouldRecomputeLayout) { - m_layoutPointer.moveCursorLeft(this, shouldRecomputeLayout); + layoutReference().node()->moveCursorLeft(this, shouldRecomputeLayout); } void LayoutCursor::moveRight(bool * shouldRecomputeLayout) { - m_layoutPointer.moveCursorRight(this, shouldRecomputeLayout); + layoutReference().node()->moveCursorRight(this, shouldRecomputeLayout); } void LayoutCursor::moveAbove(bool * shouldRecomputeLayout) { - m_layoutPointer.moveCursorUp(this, shouldRecomputeLayout); + layoutReference().node()->moveCursorUp(this, shouldRecomputeLayout); } void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { - m_layoutPointer.moveCursorDown(this, shouldRecomputeLayout); + layoutReference().node()->moveCursorDown(this, shouldRecomputeLayout); } diff --git a/layout_cursor.h b/layout_cursor.h index a3711e2ae..549f5e63e 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -1,28 +1,23 @@ #ifndef LAYOUT_CURSOR_H #define LAYOUT_CURSOR_H -#include "tree_pool.h" -#include "layout_cursor_reference.h" +#include "cursor.h" +#include "layout_reference.h" #include "layout_node.h" #include -class LayoutCursor { +class LayoutCursor : public Cursor { + template + friend class LayoutReference; public: enum class Position { Left, Right }; - LayoutCursor(Layout * layoutPointer, Position position = Position::Right) : - m_layoutPointer(layoutPointer), - m_position(position) - { - } - - bool isDefined() const { return m_layoutPointer.isDefined(); } /* Debug */ void log() { - printf("Pointed Layout id %d, cursor position ", m_layoutPointer.identifier()); + printf("Pointed Layout id %d, cursor position ", m_treeReference.identifier()); if (m_position == Position::Left) { printf("Left"); } else { @@ -32,6 +27,9 @@ public: } /* Getters and setters */ + LayoutReference layoutReference() { + return LayoutReference(m_treeReference.node()); + } //int pointedLayoutIdentifier() const { return m_layoutIdentifier; } //void setPointedLayoutIdentifier(int layoutID) { m_layoutIdentifier = layoutID; } Position position() const { return m_position; } @@ -51,7 +49,11 @@ public: void moveAbove(bool * shouldRecomputeLayout); void moveUnder(bool * shouldRecomputeLayout); private: - LayoutPointer m_layoutPointer; + LayoutCursor(TreeNode * node, Position position = Position::Right) : + Cursor(node), + m_position(position) + { + } Position m_position; }; diff --git a/layout_reference.cpp b/layout_reference.cpp new file mode 100644 index 000000000..abfb824d5 --- /dev/null +++ b/layout_reference.cpp @@ -0,0 +1,10 @@ +#include "layout_reference.h" +#include "layout_cursor.h" +#include "char_layout_node.h" + +template +LayoutCursor LayoutReference::cursor() const { + return LayoutCursor(this->node()); +} + +template LayoutCursor LayoutReference::cursor() const; diff --git a/layout_reference.h b/layout_reference.h index dd27ba71b..c98dda91f 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -2,9 +2,10 @@ #define LAYOUT_REFERENCE_H #include "tree_reference.h" -//#include "layout_cursor.h" #include "layout_node.h" +class LayoutCursor; + template class LayoutReference : public TreeReference { friend class LayoutCursor; @@ -22,9 +23,9 @@ public: return (reinterpret_cast *>(this)); } - // LayoutReference cursorReference() const; + LayoutCursor cursor() const; - void addChild(LayoutReference l) { + virtual void addChild(LayoutReference l) { TreeReference::addChild(l); } diff --git a/tree_reference.cpp b/tree_reference.cpp new file mode 100644 index 000000000..d497a941d --- /dev/null +++ b/tree_reference.cpp @@ -0,0 +1,11 @@ +#include "tree_reference.h" +#include "char_layout_node.h" +#include "cursor.h" + +template +Cursor TreeReference::treeCursor() { + return Cursor(node()); +} + +template Cursor TreeReference::treeCursor(); +template Cursor TreeReference::treeCursor(); diff --git a/tree_reference.h b/tree_reference.h index 7ef1bb5b0..6301c00bd 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -41,7 +41,7 @@ public: int identifier() const { return m_identifier; } - Cursor cursor(); + Cursor treeCursor(); // Hierarchy int numberOfChildren() const { From 0ef7077bd3c51f73c091d50a2792ce61b494e83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 15:24:01 +0200 Subject: [PATCH 034/156] Fix CharLayoutNode::Description --- char_layout_node.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/char_layout_node.h b/char_layout_node.h index d4ff030d2..f7f072a2a 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -37,7 +37,8 @@ public: } const char * description() const override { - static char Description[] = {'C', 'h', 'a', 'r', ' ', m_char, 0}; + static char Description[] = "Char a"; + Description[5] = m_char; return Description; } From 9a7441d0451660be716d4b4dd2ad9ac4dc46c9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 15:56:03 +0200 Subject: [PATCH 035/156] Define a cursor on layout children --- horizontal_layout_node.h | 95 ++++++++++++++++++++++++++++++++++++++++ layout_reference.cpp | 2 + layout_reference.h | 3 +- test.cpp | 13 ++++-- tree_reference.h | 14 +++--- 5 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 horizontal_layout_node.h diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h new file mode 100644 index 000000000..d1643cf44 --- /dev/null +++ b/horizontal_layout_node.h @@ -0,0 +1,95 @@ +#ifndef HORIZONTAL_LAYOUT_H +#define HORIZONTAL_LAYOUT_H + +#include "layout_reference.h" +#include "layout_node.h" +#include "layout_cursor.h" + +class HorizontalLayoutNode : public LayoutNode { +public: + HorizontalLayoutNode() : + LayoutNode(), + m_numberOfChildren(0) + {} + + size_t size() const override { + return sizeof(HorizontalLayoutNode); + } + + int numberOfChildren() const override { return m_numberOfChildren; } + void incrementNumberOfChildren() { m_numberOfChildren++; } + + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { + if (this == cursor->layoutReference().node()) { + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + /* Case: Right. Go to the last child if there is one, and move Left. Else + * go Left and ask the parent. */ + int childrenCount = numberOfChildren(); + if (childrenCount >= 1) { + cursor->setLayoutNode(static_cast(childTreeAtIndex(childrenCount-1))); + } else { + cursor->setPosition(LayoutCursor::Position::Left); + } + return cursor->moveLeft(shouldRecomputeLayout); + } + + // Case: The cursor is Left of a child. + assert(cursor->position() == LayoutCursor::Position::Left); + int childIndex = indexOfChildByIdentifier(cursor->layoutIdentifier()); + assert(childIndex >= 0); + if (childIndex == 0) { + // Case: the child is the leftmost. Ask the parent. + if (parent()) { + cursor->setLayoutNode(this); + return cursor->moveLeft(shouldRecomputeLayout); + } + return; + } + // Case: the child is not the leftmost. Go to its left sibling and move Left. + cursor->setLayoutNode(static_cast(childTreeAtIndex(childIndex-1))); + cursor->setPosition(LayoutCursor::Position::Right); + cursor->moveLeft(shouldRecomputeLayout); + } + + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { + //TODO + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } + } + + const char * description() const override { + return "Horizontal Layout"; + } +private: + int m_numberOfChildren; +}; + +class HorizontalLayoutRef : public LayoutReference { +public: + HorizontalLayoutRef() : LayoutReference() {} + HorizontalLayoutRef(LayoutRef l) : LayoutReference() { + addChild(l); + } + + HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference() { + addChild(l2); + addChild(l1); + } + + virtual void addChild(LayoutRef l) override { + LayoutReference::addChild(l); + node()->incrementNumberOfChildren(); + } +}; + +#endif diff --git a/layout_reference.cpp b/layout_reference.cpp index abfb824d5..52ffecc96 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -1,5 +1,6 @@ #include "layout_reference.h" #include "layout_cursor.h" +#include "layout_node.h" #include "char_layout_node.h" template @@ -7,4 +8,5 @@ LayoutCursor LayoutReference::cursor() const { return LayoutCursor(this->node()); } +template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; diff --git a/layout_reference.h b/layout_reference.h index c98dda91f..b9659ab8f 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -30,7 +30,8 @@ public: } LayoutReference childAtIndex(int i) { - return TreeReference::childAtIndex(i); + TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); + return LayoutReference(treeRefChild.node()); } void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { diff --git a/test.cpp b/test.cpp index 96a79bb7a..00da8a0ef 100644 --- a/test.cpp +++ b/test.cpp @@ -1,5 +1,6 @@ #include "float_node.h" #include "char_layout_node.h" +#include "horizontal_layout_node.h" #include "addition_node.h" #include "cursor.h" #include @@ -22,11 +23,17 @@ int main() { TreePool::sharedPool()->log();*/ printf("\nCHAR LAYOUT\n"); - CharLayout aChar('a'); + CharLayout aChar('c'); + CharLayout bChar('b'); TreePool::sharedPool()->log(); - Cursor cursor = aChar.cursor(); -/* TreePool::sharedPool()->log(); + + HorizontalLayout h(aChar, bChar); + TreePool::sharedPool()->log(); + + LayoutCursor cursor = h.childAtIndex(1).cursor(); cursor.log(); + + /*cursor.log(); bool recompute = false; cursor.moveLeft(&recompute); cursor.log(); diff --git a/tree_reference.h b/tree_reference.h index 6301c00bd..d99894089 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -12,6 +12,10 @@ class Cursor; template class TreeReference { friend class Cursor; + template + friend class ExpressionReference; + template + friend class LayoutReference; public: TreeReference(const TreeReference & tr) { int trNodeIdentifier = tr.identifier(); @@ -52,8 +56,8 @@ public: return TreeReference(node()->parentTree()); } - TreeReference childAtIndex(int i) const { - return TreeReference(node()->child(i)); + TreeReference treeChildAtIndex(int i) const { + return TreeReference(node()->childTreeAtIndex(i)); } // Hierarchy operations @@ -74,7 +78,7 @@ public: void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); - TreeReference oldChild = childAtIndex(oldChildIndex); + TreeReference oldChild = treeChildAtIndex(oldChildIndex); TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); newChild.node()->retain(); TreePool::sharedPool()->move(oldChild.node(), TreePool::sharedPool()->last()); @@ -89,8 +93,8 @@ public: } int firstChildIndex = min(i, j); int secondChildIndex = max(i, j); - TreeReference firstChild = childAtIndex(firstChildIndex); - TreeReference secondChild = childAtIndex(secondChildIndex); + TreeReference firstChild = treeChildAtIndex(firstChildIndex); + TreeReference secondChild = treeChildAtIndex(secondChildIndex); TreeNode * firstChildNode = firstChild.node(); TreePool::sharedPool()->move(firstChildNode, secondChild.node()->next()); TreePool::sharedPool()->move(secondChild.node(), firstChildNode); From 2906d72aeef1000b2530533bb0fdedfd7e131294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 17:32:22 +0200 Subject: [PATCH 036/156] MoveLeft is working --- cursor.h | 4 ++++ test.cpp | 6 ++++++ tree_node.cpp | 14 +++++++++----- tree_node.h | 1 + 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cursor.h b/cursor.h index e5dab3537..6085509d7 100644 --- a/cursor.h +++ b/cursor.h @@ -8,6 +8,10 @@ class Cursor { template friend class TreeReference; public: + TreeReference treeReference() { return m_treeReference; } + int treeReferenceIdentifier() { return m_treeReference.identifier(); } + void setTreeReference(TreeReference t) { m_treeReference = t; } + void setTreeNode(TreeNode * t) { m_treeReference = TreeReference(t); } bool isDefined() const { return m_treeReference.isDefined(); } protected: Cursor(TreeNode * node) : m_treeReference(node) {} diff --git a/test.cpp b/test.cpp index 00da8a0ef..9207edbf4 100644 --- a/test.cpp +++ b/test.cpp @@ -31,6 +31,12 @@ int main() { TreePool::sharedPool()->log(); LayoutCursor cursor = h.childAtIndex(1).cursor(); + LayoutCursor cursor2 = aChar.cursor(); + cursor.log(); + bool recompute = false; + cursor.moveLeft(&recompute); + cursor.log(); + cursor.moveLeft(&recompute); cursor.log(); /*cursor.log(); diff --git a/tree_node.cpp b/tree_node.cpp index 13c116acb..605cc43a2 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -99,14 +99,11 @@ TreeNode * TreeNode::childTreeAtIndex(int i) const { return child; } -int TreeNode::indexOfChild(const TreeNode * child) const { - if (child == nullptr) { - return -1; - } +int TreeNode::indexOfChildByIdentifier(int childID) const { int childrenCount = numberOfChildren(); TreeNode * childAtIndexi = next(); for (int i = 0; i < childrenCount; i++) { - if (childAtIndexi == child) { + if (childAtIndexi->identifier() == childID) { return i; } childAtIndexi = childAtIndexi->nextSibling(); @@ -114,6 +111,13 @@ int TreeNode::indexOfChild(const TreeNode * child) const { return -1; } +int TreeNode::indexOfChild(const TreeNode * child) const { + if (child == nullptr) { + return -1; + } + return indexOfChildByIdentifier(child->identifier()); +} + bool TreeNode::hasChild(const TreeNode * child) const { if (child == nullptr) { return false; diff --git a/tree_node.h b/tree_node.h index f241952d4..4e16b0a0c 100644 --- a/tree_node.h +++ b/tree_node.h @@ -45,6 +45,7 @@ public: virtual int numberOfChildren() const = 0; int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; + int indexOfChildByIdentifier(int childID) const; int indexOfChild(const TreeNode * child) const; bool hasChild(const TreeNode * child) const; bool hasAncestor(const TreeNode * node, bool includeSelf) const; From f67eb9c0a88f181f07fd372f0e0d31b76e7ecd23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 17:59:30 +0200 Subject: [PATCH 037/156] TreeReferences do not deepcopy unless asked --- addition_node.h | 7 ++----- char_layout_node.h | 4 ++-- cursor.h | 8 ++++++-- expression_reference.h | 2 +- float_node.h | 6 ++---- layout_reference.h | 2 +- test.cpp | 21 +++++++++++---------- tree_node.cpp | 1 + tree_reference.h | 23 ++++++++++++++++++----- 9 files changed, 44 insertions(+), 30 deletions(-) diff --git a/addition_node.h b/addition_node.h index b03278a70..4476a7374 100644 --- a/addition_node.h +++ b/addition_node.h @@ -36,9 +36,9 @@ public: */ }; -class Addition : public ExpressionReference { +class AdditionRef : public ExpressionReference { public: - Addition(Expression e1, Expression e2) : + AdditionRef(ExpressionRef e1, ExpressionRef e2) : ExpressionReference() { addOperand(e2); @@ -46,7 +46,4 @@ public: } }; - -//typedef ExpressionReference Addition; - #endif diff --git a/char_layout_node.h b/char_layout_node.h index f7f072a2a..3ea2f04ed 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -47,9 +47,9 @@ private: char m_char; }; -class CharLayout : public LayoutReference { +class CharLayoutRef : public LayoutReference { public: - CharLayout(char c) : LayoutReference() { + CharLayoutRef(char c) : LayoutReference() { this->node()->setChar(c); } }; diff --git a/cursor.h b/cursor.h index 6085509d7..d6ab875d5 100644 --- a/cursor.h +++ b/cursor.h @@ -10,8 +10,12 @@ class Cursor { public: TreeReference treeReference() { return m_treeReference; } int treeReferenceIdentifier() { return m_treeReference.identifier(); } - void setTreeReference(TreeReference t) { m_treeReference = t; } - void setTreeNode(TreeNode * t) { m_treeReference = TreeReference(t); } + void setTreeReference(TreeReference t) { + m_treeReference = t; + } + void setTreeNode(TreeNode * t) { + m_treeReference = TreeReference(t); + } bool isDefined() const { return m_treeReference.isDefined(); } protected: Cursor(TreeNode * node) : m_treeReference(node) {} diff --git a/expression_reference.h b/expression_reference.h index 072699f71..0ba47873c 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -44,6 +44,6 @@ public: */ }; -typedef ExpressionReference Expression; +typedef ExpressionReference ExpressionRef; #endif diff --git a/float_node.h b/float_node.h index 3385544f2..2074c19e7 100644 --- a/float_node.h +++ b/float_node.h @@ -28,13 +28,11 @@ private: float m_value; }; -class Float : public ExpressionReference { +class FloatRef : public ExpressionReference { public: - Float(float f) : ExpressionReference() { + FloatRef(float f) : ExpressionReference() { this->node()->setFloat(f); } }; -//typedef ExpressionReference Float; - #endif diff --git a/layout_reference.h b/layout_reference.h index b9659ab8f..a6178a95a 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -47,6 +47,6 @@ public: } }; -typedef LayoutReference Layout; +typedef LayoutReference LayoutRef; #endif diff --git a/test.cpp b/test.cpp index 9207edbf4..d2d9d31f8 100644 --- a/test.cpp +++ b/test.cpp @@ -5,10 +5,10 @@ #include "cursor.h" #include -Addition buildAddition() { - Float smallFloat(0.2f); - Float bigFloat(3.4f); - Addition a(smallFloat, bigFloat); +AdditionRef buildAddition() { + FloatRef smallFloat(0.2f); + FloatRef bigFloat(3.4f); + AdditionRef a(smallFloat, bigFloat); TreePool::sharedPool()->log(); return a; } @@ -23,21 +23,22 @@ int main() { TreePool::sharedPool()->log();*/ printf("\nCHAR LAYOUT\n"); - CharLayout aChar('c'); - CharLayout bChar('b'); + CharLayoutRef aChar('c'); + CharLayoutRef bChar('b'); TreePool::sharedPool()->log(); - HorizontalLayout h(aChar, bChar); + HorizontalLayoutRef h(aChar, bChar); TreePool::sharedPool()->log(); LayoutCursor cursor = h.childAtIndex(1).cursor(); - LayoutCursor cursor2 = aChar.cursor(); - cursor.log(); + // LayoutCursor cursor2 = aChar.cursor(); + /*cursor.log(); bool recompute = false; cursor.moveLeft(&recompute); cursor.log(); cursor.moveLeft(&recompute); - cursor.log(); + cursor.log();*/ + TreePool::sharedPool()->log(); /*cursor.log(); bool recompute = false; diff --git a/tree_node.cpp b/tree_node.cpp index 605cc43a2..d4ae12a57 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -1,6 +1,7 @@ #include "tree_node.h" #include "tree_pool.h" #include "expression_node.h" +#include // Node operations diff --git a/tree_reference.h b/tree_reference.h index d99894089..e3d035f70 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -18,9 +18,22 @@ class TreeReference { friend class LayoutReference; public: TreeReference(const TreeReference & tr) { - int trNodeIdentifier = tr.identifier(); - TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(TreePool::sharedPool()->node(trNodeIdentifier)); - m_identifier = nodeCopy->identifier(); + setTo(tr); + } + + TreeReference& operator=(const TreeReference& tr) { + setTo(tr); + return *this; + } + + void setTo(const TreeReference & tr) { + m_identifier = tr.identifier(); + TreePool::sharedPool()->node(m_identifier)->retain(); + } + + TreeReference clone() const { + TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(node()); + return TreeReference(nodeCopy); } ~TreeReference() { @@ -63,8 +76,8 @@ public: // Hierarchy operations void addChild(TreeReference t) { - TreeNode * deepCopy = TreePool::sharedPool()->deepCopy(t.node()); - TreePool::sharedPool()->move(deepCopy, node()->next()); + t.node()->retain(); + TreePool::sharedPool()->move(t.node(), node()->next()); } void removeChild(TreeReference t) { From 8c536abd803f91dc494cb42564a8df677dd94134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 26 Jun 2018 18:12:30 +0200 Subject: [PATCH 038/156] Remove Cursor class --- cursor.h | 25 ------------------------- layout_cursor.h | 22 ++++++++++++---------- layout_cursor_reference.h | 34 ---------------------------------- test.cpp | 2 +- tree_reference.cpp | 11 ----------- tree_reference.h | 2 -- 6 files changed, 13 insertions(+), 83 deletions(-) delete mode 100644 cursor.h delete mode 100644 layout_cursor_reference.h delete mode 100644 tree_reference.cpp diff --git a/cursor.h b/cursor.h deleted file mode 100644 index d6ab875d5..000000000 --- a/cursor.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CURSOR_H -#define CURSOR_H - -#include "tree_node.h" -#include "tree_reference.h" - -class Cursor { - template - friend class TreeReference; -public: - TreeReference treeReference() { return m_treeReference; } - int treeReferenceIdentifier() { return m_treeReference.identifier(); } - void setTreeReference(TreeReference t) { - m_treeReference = t; - } - void setTreeNode(TreeNode * t) { - m_treeReference = TreeReference(t); - } - bool isDefined() const { return m_treeReference.isDefined(); } -protected: - Cursor(TreeNode * node) : m_treeReference(node) {} - TreeReference m_treeReference; -}; - -#endif diff --git a/layout_cursor.h b/layout_cursor.h index 549f5e63e..e654bd9b9 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -1,12 +1,11 @@ #ifndef LAYOUT_CURSOR_H #define LAYOUT_CURSOR_H -#include "cursor.h" #include "layout_reference.h" #include "layout_node.h" #include -class LayoutCursor : public Cursor { +class LayoutCursor { template friend class LayoutReference; public: @@ -17,7 +16,7 @@ public: /* Debug */ void log() { - printf("Pointed Layout id %d, cursor position ", m_treeReference.identifier()); + printf("Pointed Layout id %d, cursor position ", m_layoutRef.identifier()); if (m_position == Position::Left) { printf("Left"); } else { @@ -26,12 +25,14 @@ public: printf("\n"); } + bool isDefined() const { return m_layoutRef.isDefined(); } + + /* Getters and setters */ - LayoutReference layoutReference() { - return LayoutReference(m_treeReference.node()); - } - //int pointedLayoutIdentifier() const { return m_layoutIdentifier; } - //void setPointedLayoutIdentifier(int layoutID) { m_layoutIdentifier = layoutID; } + LayoutRef layoutReference() { return m_layoutRef; } + int layoutReferenceIdentifier() { return m_layoutRef.identifier(); } + void setLayoutReference(LayoutRef r) { m_layoutRef = r; } + void setLayoutNode(LayoutNode * n) { m_layoutRef = LayoutRef(n); } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } int cursorHeight() { return 1; } //TODO @@ -49,11 +50,12 @@ public: void moveAbove(bool * shouldRecomputeLayout); void moveUnder(bool * shouldRecomputeLayout); private: - LayoutCursor(TreeNode * node, Position position = Position::Right) : - Cursor(node), + LayoutCursor(LayoutNode * node, Position position = Position::Right) : + m_layoutRef(node), m_position(position) { } + LayoutRef m_layoutRef; Position m_position; }; diff --git a/layout_cursor_reference.h b/layout_cursor_reference.h deleted file mode 100644 index 42b4dec5e..000000000 --- a/layout_cursor_reference.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef LAYOUT_CURSOR_REFERENCE_H -#define LAYOUT_CURSOR_REFERENCE_H - -#include "layout_node.h" -#include "layout_reference.h" - -class LayoutCursor; - -template -class LayoutCursorReference : public LayoutReference { -public: - LayoutCursorReference(LayoutReference * r) : - LayoutReference(r->node()) - { - } - - LayoutCursorReference(const LayoutCursorReference & r) : - LayoutReference(r.node()) - { - } - - // Tree navigation - - /* We cannot have LayoutCursor cursorLeftOf(LayoutCursor cursor) because of - * circular header dependency */ - virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { return this->node()->moveCursorLeft(cursor, shouldRecomputeLayout); } - virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { return this->node()->moveCursorRight(cursor, shouldRecomputeLayout); } - virtual void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} - virtual void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} -}; - -typedef LayoutCursorReference LayoutPointer; - -#endif diff --git a/test.cpp b/test.cpp index d2d9d31f8..1eef0d97c 100644 --- a/test.cpp +++ b/test.cpp @@ -2,7 +2,7 @@ #include "char_layout_node.h" #include "horizontal_layout_node.h" #include "addition_node.h" -#include "cursor.h" +#include "layout_cursor.h" #include AdditionRef buildAddition() { diff --git a/tree_reference.cpp b/tree_reference.cpp deleted file mode 100644 index d497a941d..000000000 --- a/tree_reference.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "tree_reference.h" -#include "char_layout_node.h" -#include "cursor.h" - -template -Cursor TreeReference::treeCursor() { - return Cursor(node()); -} - -template Cursor TreeReference::treeCursor(); -template Cursor TreeReference::treeCursor(); diff --git a/tree_reference.h b/tree_reference.h index e3d035f70..ebfaa7df7 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -58,8 +58,6 @@ public: int identifier() const { return m_identifier; } - Cursor treeCursor(); - // Hierarchy int numberOfChildren() const { return node()->numberOfChildren(); From 2bc5290ff1a0e96a34b37977ec10b9d7649318ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 10:42:41 +0200 Subject: [PATCH 039/156] Clean unary tests --- expression_reference.h | 7 +-- layout_cursor.h | 2 +- test.cpp | 99 ++++++++++++++++++++++++++++++++---------- tree_pool.h | 10 +++++ tree_reference.h | 6 ++- 5 files changed, 95 insertions(+), 29 deletions(-) diff --git a/expression_reference.h b/expression_reference.h index 0ba47873c..3c1898e6b 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -9,10 +9,7 @@ template class ExpressionReference : public TreeReference { public: - ExpressionReference() : TreeReference() { } - - /*ExpressionReference(const ExpressionReference & er) { - }*/ + using TreeReference::TreeReference; // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression operator ExpressionReference() const { @@ -26,7 +23,7 @@ public: } ExpressionReference childAtIndex(int i) { - return TreeReference::childAtIndex(i); + return ExpressionReference(TreeReference::treeChildAtIndex(i).node()); } void replaceChildAtIndex(int oldChildIndex, ExpressionReference newChild) { diff --git a/layout_cursor.h b/layout_cursor.h index e654bd9b9..823812962 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -30,7 +30,7 @@ public: /* Getters and setters */ LayoutRef layoutReference() { return m_layoutRef; } - int layoutReferenceIdentifier() { return m_layoutRef.identifier(); } + int layoutIdentifier() { return m_layoutRef.identifier(); } void setLayoutReference(LayoutRef r) { m_layoutRef = r; } void setLayoutNode(LayoutNode * n) { m_layoutRef = LayoutRef(n); } Position position() const { return m_position; } diff --git a/test.cpp b/test.cpp index 1eef0d97c..e8de3d777 100644 --- a/test.cpp +++ b/test.cpp @@ -9,42 +9,97 @@ AdditionRef buildAddition() { FloatRef smallFloat(0.2f); FloatRef bigFloat(3.4f); AdditionRef a(smallFloat, bigFloat); - TreePool::sharedPool()->log(); + assert(TreePool::sharedPool()->numberOfNodes() == 3); return a; } -int main() { - /*Addition a = buildAddition(); +void testAddition() { + printf("Addition test\n"); + assert(TreePool::sharedPool()->numberOfNodes() == 0); + AdditionRef a = buildAddition(); + assert(TreePool::sharedPool()->numberOfNodes() == 3); + float result = a.approximate(); - Float smallFloat(1.3f); + assert(result = 3.6f); + + FloatRef smallFloat(1.3f); a.replaceChildAtIndex(0, smallFloat); float result2 = a.approximate(); - a.swapChildren(1,0); - TreePool::sharedPool()->log();*/ + assert(result2 == 4.7f); - printf("\nCHAR LAYOUT\n"); - CharLayoutRef aChar('c'); + a.swapChildren(1,0); + assert(a.childAtIndex(0).identifier() == 1); + assert(a.childAtIndex(1).identifier() == 3); +} + +void createNodes() { + FloatRef smallFloat(0.2f); + FloatRef bigFloat(3.4f); + AdditionRef a(smallFloat, bigFloat); +} + +void testPoolEmpties() { + printf("Pool empties test\n"); + assert(TreePool::sharedPool()->numberOfNodes() == 0); + createNodes(); + assert(TreePool::sharedPool()->numberOfNodes() == 0); +} + +void testCursorCreateAndRetain() { + printf("Cursor create and retain test\n"); + CharLayoutRef aChar('a'); CharLayoutRef bChar('b'); - TreePool::sharedPool()->log(); + assert(aChar.identifier() == 0); + assert(bChar.identifier() == 1); + assert(aChar.nodeRetainCount() == 1); + assert(bChar.nodeRetainCount() == 1); + assert(strcmp(aChar.node()->description(), "Char a") == 0); + assert(strcmp(bChar.node()->description(), "Char b") == 0); + assert(TreePool::sharedPool()->numberOfNodes() == 2); HorizontalLayoutRef h(aChar, bChar); - TreePool::sharedPool()->log(); + assert(aChar.identifier() == 0); + assert(bChar.identifier() == 1); + assert(h.identifier() == 2); + assert(aChar.nodeRetainCount() == 2); + assert(bChar.nodeRetainCount() == 2); + assert(h.nodeRetainCount() == 1); + assert(aChar == h.childAtIndex(0)); + assert(bChar == h.childAtIndex(1)); + + LayoutCursor cursorA = aChar.cursor(); + assert(cursorA.layoutIdentifier() == aChar.identifier()); + assert(aChar.nodeRetainCount() == 3); +} + +void testCursorMoveLeft() { + printf("Cursor move left test\n"); + CharLayoutRef aChar('a'); + CharLayoutRef bChar('b'); + HorizontalLayoutRef h(aChar, bChar); LayoutCursor cursor = h.childAtIndex(1).cursor(); - // LayoutCursor cursor2 = aChar.cursor(); - /*cursor.log(); - bool recompute = false; - cursor.moveLeft(&recompute); - cursor.log(); - cursor.moveLeft(&recompute); - cursor.log();*/ - TreePool::sharedPool()->log(); + assert(bChar.nodeRetainCount() == 3); + assert(cursor.layoutIdentifier() == h.childAtIndex(1).identifier()); - /*cursor.log(); bool recompute = false; + assert(cursor.layoutIdentifier() == bChar.identifier()); + assert(cursor.position() == LayoutCursor::Position::Right); cursor.moveLeft(&recompute); - cursor.log(); - cursor.moveRight(&recompute); - cursor.log();*/ + assert(cursor.layoutIdentifier() == bChar.identifier()); + assert(cursor.position() == LayoutCursor::Position::Left); + assert(bChar.nodeRetainCount() == 3); + assert(aChar.nodeRetainCount() == 2); + cursor.moveLeft(&recompute); + assert(cursor.layoutIdentifier() == aChar.identifier()); + assert(cursor.position() == LayoutCursor::Position::Left); + assert(aChar.nodeRetainCount() == 3); +} + +int main() { + testAddition(); + testPoolEmpties(); + testCursorCreateAndRetain(); + testCursorMoveLeft(); return 0; } diff --git a/tree_pool.h b/tree_pool.h index 292d7ab4b..6c3acf556 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -87,6 +87,16 @@ public: void log(); #endif + // Debug + int numberOfNodes() const { + int count = 0; + AllPool nodes = const_cast(this)->allNodes(); + for (TreeNode * t : nodes) { + count++; + } + return count; + } + protected: constexpr static int BufferSize = 256; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); diff --git a/tree_reference.h b/tree_reference.h index ebfaa7df7..0c17cb87b 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -26,6 +26,8 @@ public: return *this; } + inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } + void setTo(const TreeReference & tr) { m_identifier = tr.identifier(); TreePool::sharedPool()->node(m_identifier)->retain(); @@ -38,13 +40,15 @@ public: ~TreeReference() { assert(node()); - printf("Delete TreeReference of m_id %d, nodeId %d\n", m_identifier, node()->identifier()); + //printf("Delete TreeReference of m_id %d, nodeId %d\n", m_identifier, node()->identifier()); assert(node()->identifier() == m_identifier); node()->release(); } bool isDefined() const { return m_identifier >= 0 && TreePool::sharedPool()->node(m_identifier) != nullptr; } + int nodeRetainCount() const { return node()->retainCount(); } + operator TreeReference() const { // TODO: make sure this is kosher // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); From 920d815b672f3f6b8978c910e1a008894c5dbe7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 11:40:12 +0200 Subject: [PATCH 040/156] Remove dangerous casts --- expression_reference.h | 4 +--- layout_reference.h | 7 +------ tree_pool.h | 4 ++-- tree_reference.h | 6 +++--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/expression_reference.h b/expression_reference.h index 3c1898e6b..efd6291ba 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -13,9 +13,7 @@ public: // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression operator ExpressionReference() const { - // TODO: make sure this is kosher - // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); - return *(reinterpret_cast *>(this)); + return ExpressionReference(this->node()); } void addOperand(ExpressionReference e) { diff --git a/layout_reference.h b/layout_reference.h index a6178a95a..29c5d7f2d 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -15,12 +15,7 @@ public: /* Allow every LayoutReference to be transformed into a * LayoutReference, i.e. Layout */ operator LayoutReference() const { - // TODO: make sure this is kosher - return *(reinterpret_cast *>(this)); - } - - LayoutReference * pointer() { - return (reinterpret_cast *>(this)); + return LayoutReference(this->node()); } LayoutCursor cursor() const; diff --git a/tree_pool.h b/tree_pool.h index 6c3acf556..2de14fb8a 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -41,10 +41,10 @@ public: } void * ptr = alloc(sizeof(T)); // TODO handle allocation problem! - TreeNode * node = new(ptr) T(); + T * node = new(ptr) T(); node->rename(nodeIdentifier); registerNode(node); - return reinterpret_cast(node); + return node; } void discardTreeNode(TreeNode * node) { diff --git a/tree_reference.h b/tree_reference.h index 0c17cb87b..4ae378391 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -13,6 +13,8 @@ template class TreeReference { friend class Cursor; template + friend class TreeReference; + template friend class ExpressionReference; template friend class LayoutReference; @@ -50,9 +52,7 @@ public: int nodeRetainCount() const { return node()->retainCount(); } operator TreeReference() const { - // TODO: make sure this is kosher - // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); - return *(reinterpret_cast *>(this)); + return TreeReference(this->node()); } T * node() const { From 6f418165007b87e5298a36af646597596ab9c1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 12:25:58 +0200 Subject: [PATCH 041/156] Clean TreePool --- tree_pool.cpp | 109 +++++++++++++++++++++++++------------------------- tree_pool.h | 94 ++++++++++++++++++++++--------------------- 2 files changed, 102 insertions(+), 101 deletions(-) diff --git a/tree_pool.cpp b/tree_pool.cpp index 4f663e23b..1d963cb01 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -6,36 +6,6 @@ TreePool * TreePool::sharedPool() { return &pool; } -void * TreePool::alloc(size_t size) { - if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { - return nullptr; - } - void * result = m_cursor; - m_cursor += size; - return result; -} - -void TreePool::dealloc(void * ptr) { - assert(ptr >= m_buffer && ptr < m_cursor); - TreeNode * node = reinterpret_cast(ptr); - size_t size = node->size(); - - // Step 1 - Compact the pool - memmove( - ptr, - static_cast(ptr) + size, - m_cursor - (static_cast(ptr) + size) - ); - m_cursor -= size; - - // Step 2 - Update m_nodeForIdentifier - for (int i = 0; i < MaxNumberOfNodes; i++) { - if (m_nodeForIdentifier[i] != nullptr && m_nodeForIdentifier[i] > node) { - m_nodeForIdentifier[i] = reinterpret_cast(reinterpret_cast(m_nodeForIdentifier[i]) - size); - } - } -} - TreeNode * TreePool::node(int identifier) const { assert(identifier >= 0 && identifier <= MaxNumberOfNodes); return m_nodeForIdentifier[identifier]; @@ -55,31 +25,6 @@ static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { } } -bool TreePool::insert(char * destination, char * source, size_t length) { - if (source == destination || (destination > source && destination < source + length)) { - return false; - } - - assert(length % 4 == 0); - assert((long)source % 4 == 0); - assert((long)destination % 4 == 0); - - uint32_t * src = reinterpret_cast(source); - uint32_t * dst = reinterpret_cast(destination); - size_t len = length/4; - char tempBuffer[BufferSize]; - uint32_t * tmp = reinterpret_cast(tempBuffer); - memmove32(reinterpret_cast(tmp), src, len); - if (dst < src) { - memmove32(dst + len, dst, src - dst); - memmove32(dst, tmp, len); - } else { - memmove32(src, src + len, dst - (src + len)); - memmove32(dst - len, tmp, len); - } - return true; -} - void TreePool::logNodeForIdentifierArray() { printf("\n\n"); for (int i = 0; i < MaxNumberOfNodes; i++) { @@ -134,3 +79,57 @@ void TreePool::log() { } #endif +void * TreePool::alloc(size_t size) { + if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { + return nullptr; + } + void * result = m_cursor; + m_cursor += size; + return result; +} + +void TreePool::dealloc(TreeNode * node) { + char * ptr = reinterpret_cast(node); + assert(ptr >= m_buffer && ptr < m_cursor); + size_t size = node->size(); + + // Step 1 - Compact the pool + memmove( + ptr, + ptr + size, + m_cursor - (ptr + size) + ); + m_cursor -= size; + + // Step 2 - Update m_nodeForIdentifier + for (int i = 0; i < MaxNumberOfNodes; i++) { + if (m_nodeForIdentifier[i] != nullptr && m_nodeForIdentifier[i] > node) { + m_nodeForIdentifier[i] = reinterpret_cast(reinterpret_cast(m_nodeForIdentifier[i]) - size); + } + } +} + +bool TreePool::insert(char * destination, char * source, size_t length) { + if (source == destination || (destination > source && destination < source + length)) { + return false; + } + + assert(length % 4 == 0); + assert((long)source % 4 == 0); + assert((long)destination % 4 == 0); + + uint32_t * src = reinterpret_cast(source); + uint32_t * dst = reinterpret_cast(destination); + size_t len = length/4; + char tempBuffer[BufferSize]; + uint32_t * tmp = reinterpret_cast(tempBuffer); + memmove32(reinterpret_cast(tmp), src, len); + if (dst < src) { + memmove32(dst + len, dst, src - dst); + memmove32(dst, tmp, len); + } else { + memmove32(src, src + len, dst - (src + len)); + memmove32(dst - len, tmp, len); + } + return true; +} diff --git a/tree_pool.h b/tree_pool.h index 2de14fb8a..e14401d13 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -10,29 +10,10 @@ class TreePool { public: static TreePool * sharedPool(); - // Identifiers - int generateIdentifier() { - int newIdentifier = -1; - for (int i = 0; i < MaxNumberOfNodes; i++) { - if (m_nodeForIdentifier[i] == nullptr) { - newIdentifier = i; - break; - } - } - assert(newIdentifier != -1); // TODO error handling - return newIdentifier; - } - - void freeIdentifier(int identifier) { - assert(identifier >= 0 && identifier < MaxNumberOfNodes); - m_nodeForIdentifier[identifier] = nullptr; - } - - // Pool memory - void * alloc(size_t size); - void dealloc(void * ptr); - // Node + TreeNode * node(int identifier) const; + TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + template T * createTreeNode() { int nodeIdentifier = generateIdentifier(); @@ -47,30 +28,8 @@ public: return node; } - void discardTreeNode(TreeNode * node) { - int nodeIdentifier = node->identifier(); - node->~TreeNode(); - dealloc(static_cast(node)); - freeIdentifier(nodeIdentifier); - } - - TreeNode * node(int identifier) const; - TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } - TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } - - void logNodeForIdentifierArray(); - void move(TreeNode * source, TreeNode * destination); - void registerNode(TreeNode * node) { - m_nodeForIdentifier[node->identifier()] = node; - } - - void renameNode(TreeNode * node) { - node->rename(generateIdentifier()); - registerNode(node); - } - TreeNode * deepCopy(TreeNode * node) { size_t size = node->deepSize(); void * ptr = alloc(size); @@ -97,10 +56,29 @@ public: return count; } -protected: +private: constexpr static int BufferSize = 256; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); + // TreeNode + void discardTreeNode(TreeNode * node) { + int nodeIdentifier = node->identifier(); + node->~TreeNode(); + dealloc(node); + freeIdentifier(nodeIdentifier); + } + void registerNode(TreeNode * node) { + m_nodeForIdentifier[node->identifier()] = node; + } + void renameNode(TreeNode * node) { + node->rename(generateIdentifier()); + registerNode(node); + } + + // Iterators + + TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } + class AllPool { public: AllPool(TreeNode * node) : m_node(node) {} @@ -140,10 +118,34 @@ protected: TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } -private: TreePool() : m_cursor(m_buffer) { } + + // Pool memory + void * alloc(size_t size); + void dealloc(TreeNode * ptr); static inline bool insert(char * destination, char * source, size_t length); + // Identifiers + int generateIdentifier() { + int newIdentifier = -1; + for (int i = 0; i < MaxNumberOfNodes; i++) { + if (m_nodeForIdentifier[i] == nullptr) { + newIdentifier = i; + break; + } + } + assert(newIdentifier != -1); // TODO error handling + return newIdentifier; + } + + void freeIdentifier(int identifier) { + assert(identifier >= 0 && identifier < MaxNumberOfNodes); + m_nodeForIdentifier[identifier] = nullptr; + } + + // Debug + void logNodeForIdentifierArray(); + char * m_cursor; char m_buffer[BufferSize]; TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; From 1e4f65e414d812b1a135f0e4ec59a5d5eb60a40e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 13:24:11 +0200 Subject: [PATCH 042/156] Cleaning --- tree_node.h | 1 - tree_pool.h | 2 +- tree_reference.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tree_node.h b/tree_node.h index 4e16b0a0c..a83cb515c 100644 --- a/tree_node.h +++ b/tree_node.h @@ -16,7 +16,6 @@ */ class TreeNode { -// friend class TreeReference; friend class TreePool; public: virtual ~TreeNode() {} diff --git a/tree_pool.h b/tree_pool.h index e14401d13..549a066e2 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -134,7 +134,7 @@ private: break; } } - assert(newIdentifier != -1); // TODO error handling + assert(newIdentifier != -1); return newIdentifier; } diff --git a/tree_reference.h b/tree_reference.h index 4ae378391..b23d6700f 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -42,7 +42,6 @@ public: ~TreeReference() { assert(node()); - //printf("Delete TreeReference of m_id %d, nodeId %d\n", m_identifier, node()->identifier()); assert(node()->identifier() == m_identifier); node()->release(); } From adc422235b03d6fd9192ba55bbb93590fe484b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 15:33:06 +0200 Subject: [PATCH 043/156] Rule of 5 for TreeReference --- tree_reference.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tree_reference.h b/tree_reference.h index b23d6700f..cc5ae1571 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -19,14 +19,16 @@ class TreeReference { template friend class LayoutReference; public: - TreeReference(const TreeReference & tr) { - setTo(tr); - } - + TreeReference(const TreeReference & tr) { setTo(tr); } + TreeReference(TreeReference&& tr) { setTo(tr); } TreeReference& operator=(const TreeReference& tr) { setTo(tr); return *this; } + TreeReference& operator=(TreeReference&& tr) { + setTo(tr); + return *this; + } inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } From d3db6827ae0ff704f74e546b63f606a2ed41974d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 15:34:33 +0200 Subject: [PATCH 044/156] Modify tests --- test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test.cpp b/test.cpp index e8de3d777..bb82355af 100644 --- a/test.cpp +++ b/test.cpp @@ -36,6 +36,8 @@ void createNodes() { FloatRef smallFloat(0.2f); FloatRef bigFloat(3.4f); AdditionRef a(smallFloat, bigFloat); + ExpressionRef e = a; + ExpressionRef f = e; } void testPoolEmpties() { From 3d5e8dc4c44db017568e4ec94255f172c454951c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 15:58:16 +0200 Subject: [PATCH 045/156] Fix retain count when changing cursor pointed node --- layout_cursor.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/layout_cursor.h b/layout_cursor.h index 823812962..9d7eaa6f8 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -32,7 +32,10 @@ public: LayoutRef layoutReference() { return m_layoutRef; } int layoutIdentifier() { return m_layoutRef.identifier(); } void setLayoutReference(LayoutRef r) { m_layoutRef = r; } - void setLayoutNode(LayoutNode * n) { m_layoutRef = LayoutRef(n); } + void setLayoutNode(LayoutNode * n) { + m_layoutRef.node()->release(); + m_layoutRef = LayoutRef(n); + } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } int cursorHeight() { return 1; } //TODO From 08f16bca23e02fa502aaabc141341094c92ee153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 15:58:59 +0200 Subject: [PATCH 046/156] Add assertions on pool emptiness --- test.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test.cpp b/test.cpp index bb82355af..22c08bb6f 100644 --- a/test.cpp +++ b/test.cpp @@ -98,10 +98,17 @@ void testCursorMoveLeft() { assert(aChar.nodeRetainCount() == 3); } +typedef void (test)(); +void runTest(test t) { + assert(TreePool::sharedPool()->numberOfNodes() == 0); + t(); + assert(TreePool::sharedPool()->numberOfNodes() == 0); +} + int main() { - testAddition(); - testPoolEmpties(); - testCursorCreateAndRetain(); - testCursorMoveLeft(); + runTest(testAddition); + runTest(testPoolEmpties); + runTest(testCursorCreateAndRetain); + runTest(testCursorMoveLeft); return 0; } From 2248a257c82fab6905dc85a87ed8d4c1475fb14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 16:14:13 +0200 Subject: [PATCH 047/156] Cleaning --- float_node.h | 16 +++------------- tree_node.h | 4 ---- tree_pool.cpp | 2 -- tree_pool.h | 2 -- 4 files changed, 3 insertions(+), 21 deletions(-) diff --git a/float_node.h b/float_node.h index 2074c19e7..0942c4f3b 100644 --- a/float_node.h +++ b/float_node.h @@ -7,22 +7,12 @@ class FloatNode : public ExpressionNode { public: FloatNode() : ExpressionNode() {} - size_t size() const override { - return sizeof(FloatNode); - } + size_t size() const override { return sizeof(FloatNode); } int numberOfChildren() const override { return 0; } - float approximate() override { - return m_value; - } -#if TREE_LOGGING + float approximate() override { return m_value; } const char * description() const override { - if (m_value > 1) { - return "BigFloat"; - } else { - return "SmallFloat"; - } + return m_value > 1 ? "BigFloat" : "SmallFloat"; } -#endif void setFloat(float f) { m_value = f; } private: float m_value; diff --git a/tree_node.h b/tree_node.h index a83cb515c..dbd06fed5 100644 --- a/tree_node.h +++ b/tree_node.h @@ -5,8 +5,6 @@ #include #include -#define TREE_LOGGING 1 - #include /* What's in a TreeNode, really? @@ -24,11 +22,9 @@ public: virtual size_t size() const = 0; int identifier() const { return m_identifier; } int retainCount() const { return m_referenceCounter; } -#if TREE_LOGGING virtual const char * description() const { return "UNKNOWN"; } -#endif // Node operations void retain() { m_referenceCounter++; } diff --git a/tree_pool.cpp b/tree_pool.cpp index 1d963cb01..90b32cad3 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -65,7 +65,6 @@ void TreePool::move(TreeNode * source, TreeNode * destination) { } } -#if TREE_LOGGING #include void TreePool::log() { @@ -77,7 +76,6 @@ void TreePool::log() { //logNodeForIdentifierArray(); } -#endif void * TreePool::alloc(size_t size) { if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) { diff --git a/tree_pool.h b/tree_pool.h index 549a066e2..0f5cbafe3 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -42,9 +42,7 @@ public: return copy; } -#if TREE_LOGGING void log(); -#endif // Debug int numberOfNodes() const { From 170ce950416b69508daceea1ab026a9983c0dfd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 16:14:52 +0200 Subject: [PATCH 048/156] AllocationFail --- allocation_failed_expression_node.h | 22 ++++++++++++++++++++++ refs.h | 8 ++++++++ test.cpp | 23 ++++++++++++++++++----- tree_pool.h | 4 +++- 4 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 allocation_failed_expression_node.h create mode 100644 refs.h diff --git a/allocation_failed_expression_node.h b/allocation_failed_expression_node.h new file mode 100644 index 000000000..4e33c71d1 --- /dev/null +++ b/allocation_failed_expression_node.h @@ -0,0 +1,22 @@ +#ifndef ALLOCATION_FAILED_EXPRESSION_NODE_H +#define ALLOCATION_FAILED_EXPRESSION_NODE_H + +#include "expression_node.h" + +class AllocationFailedExpressionNode : public ExpressionNode { +public: + // ExpressionNode + float approximate() override { return -1; } // Should return nan + + // TreeNode + size_t size() const override { return sizeof(AllocationFailedExpressionNode); } + const char * description() const override { return "Allocation Failed"; } + int numberOfChildren() const override { return 0; } +}; + +class AllocationFailedExpressionRef : public ExpressionReference { +public: + AllocationFailedExpressionRef() : ExpressionReference() {} +}; + +#endif diff --git a/refs.h b/refs.h new file mode 100644 index 000000000..7135baceb --- /dev/null +++ b/refs.h @@ -0,0 +1,8 @@ +#include "addition_node.h" +#include "allocation_failed_expression_node.h" +#include "float_node.h" + +#include "char_layout_node.h" +#include "horizontal_layout_node.h" + +#include "layout_cursor.h" diff --git a/test.cpp b/test.cpp index 22c08bb6f..0d472e05a 100644 --- a/test.cpp +++ b/test.cpp @@ -1,8 +1,4 @@ -#include "float_node.h" -#include "char_layout_node.h" -#include "horizontal_layout_node.h" -#include "addition_node.h" -#include "layout_cursor.h" +#include "refs.h" #include AdditionRef buildAddition() { @@ -98,6 +94,20 @@ void testCursorMoveLeft() { assert(aChar.nodeRetainCount() == 3); } +void testPoolAllocationFail() { + printf("Pool allocation fail test\n"); + + // Fill the pool for size 256 + + // Allocation fail + assert(TreePool::sharedPool()->numberOfNodes() == 0); + AllocationFailedExpressionRef a; + assert(TreePool::sharedPool()->numberOfNodes() == 1); + + /*Expression e = ; + e.simplify*/ +} + typedef void (test)(); void runTest(test t) { assert(TreePool::sharedPool()->numberOfNodes() == 0); @@ -106,9 +116,12 @@ void runTest(test t) { } int main() { + printf("\n*******************\nStart running tests\n*******************\n\n"); runTest(testAddition); runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); runTest(testCursorMoveLeft); + runTest(testPoolAllocationFail); + printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_pool.h b/tree_pool.h index 0f5cbafe3..41b9770d8 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -21,7 +21,9 @@ public: return nullptr; // TODO return static node "failedAllocation" } void * ptr = alloc(sizeof(T)); - // TODO handle allocation problem! + if (ptr == nullptr) { + return nullptr; + } T * node = new(ptr) T(); node->rename(nodeIdentifier); registerNode(node); From c208da2f90fca6173fccc4453834b8b2589b1e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 27 Jun 2018 17:22:14 +0200 Subject: [PATCH 049/156] Increment node numberOfChildren when adding child --- horizontal_layout_node.h | 7 +------ layout_reference.h | 4 ---- tree_node.h | 1 + tree_reference.h | 1 + 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h index d1643cf44..eeafa600c 100644 --- a/horizontal_layout_node.h +++ b/horizontal_layout_node.h @@ -17,7 +17,7 @@ public: } int numberOfChildren() const override { return m_numberOfChildren; } - void incrementNumberOfChildren() { m_numberOfChildren++; } + void incrementNumberOfChildren() override { m_numberOfChildren++; } void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { if (this == cursor->layoutReference().node()) { @@ -85,11 +85,6 @@ public: addChild(l2); addChild(l1); } - - virtual void addChild(LayoutRef l) override { - LayoutReference::addChild(l); - node()->incrementNumberOfChildren(); - } }; #endif diff --git a/layout_reference.h b/layout_reference.h index 29c5d7f2d..31760fcfb 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -20,10 +20,6 @@ public: LayoutCursor cursor() const; - virtual void addChild(LayoutReference l) { - TreeReference::addChild(l); - } - LayoutReference childAtIndex(int i) { TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); return LayoutReference(treeRefChild.node()); diff --git a/tree_node.h b/tree_node.h index dbd06fed5..5cddb5fa4 100644 --- a/tree_node.h +++ b/tree_node.h @@ -38,6 +38,7 @@ public: TreeNode * parentTree() const; TreeNode * editableRootTree(); virtual int numberOfChildren() const = 0; + virtual void incrementNumberOfChildren() {} //TODO Put an assert false int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; int indexOfChildByIdentifier(int childID) const; diff --git a/tree_reference.h b/tree_reference.h index cc5ae1571..cbe4631d4 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -81,6 +81,7 @@ public: void addChild(TreeReference t) { t.node()->retain(); TreePool::sharedPool()->move(t.node(), node()->next()); + node()->incrementNumberOfChildren(); } void removeChild(TreeReference t) { From 46d56ade21e5e4acbca58ec514cc8a3ea066e076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 28 Jun 2018 14:50:45 +0200 Subject: [PATCH 050/156] Allocation failure fix and test --- addition_node.h | 15 ++++--- allocation_failed_expression_node.h | 3 ++ allocation_failed_layout_node.h | 21 ++++++++++ expression_node.cpp | 8 ++++ expression_node.h | 1 + expression_reference.cpp | 8 ++++ expression_reference.h | 8 +++- float_node.h | 3 +- horizontal_layout_node.h | 10 +++-- layout_node.cpp | 5 +++ layout_node.h | 2 + layout_reference.cpp | 7 ++++ layout_reference.h | 2 + test.cpp | 63 ++++++++++++++++++++++++----- tree_node.h | 3 ++ tree_pool.h | 8 ++-- tree_reference.h | 12 +++++- 17 files changed, 151 insertions(+), 28 deletions(-) create mode 100644 allocation_failed_layout_node.h create mode 100644 expression_node.cpp create mode 100644 expression_reference.cpp diff --git a/addition_node.h b/addition_node.h index 4476a7374..d6fe1efed 100644 --- a/addition_node.h +++ b/addition_node.h @@ -6,11 +6,9 @@ class AdditionNode : public ExpressionNode { public: -#if TREE_LOGGING const char * description() const override { return "Addition"; } -#endif size_t size() const override { return sizeof(AdditionNode); @@ -23,8 +21,11 @@ public: return result; } - int numberOfChildren() const override { - return 2; + int numberOfChildren() const override { return m_numberOfChildren; } + void incrementNumberOfChildren() override { m_numberOfChildren++; } + void decrementNumberOfChildren() override { + assert(m_numberOfChildren > 0); + m_numberOfChildren--; } /* Expression simplify() override { @@ -34,6 +35,8 @@ public: } } */ +private: + int m_numberOfChildren; }; class AdditionRef : public ExpressionReference { @@ -41,8 +44,8 @@ public: AdditionRef(ExpressionRef e1, ExpressionRef e2) : ExpressionReference() { - addOperand(e2); - addOperand(e1); + addChild(e2); + addChild(e1); } }; diff --git a/allocation_failed_expression_node.h b/allocation_failed_expression_node.h index 4e33c71d1..fae6873a0 100644 --- a/allocation_failed_expression_node.h +++ b/allocation_failed_expression_node.h @@ -2,6 +2,8 @@ #define ALLOCATION_FAILED_EXPRESSION_NODE_H #include "expression_node.h" +#include "expression_reference.h" +#include class AllocationFailedExpressionNode : public ExpressionNode { public: @@ -12,6 +14,7 @@ public: size_t size() const override { return sizeof(AllocationFailedExpressionNode); } const char * description() const override { return "Allocation Failed"; } int numberOfChildren() const override { return 0; } + bool isAllocationFailure() const override { return true; } }; class AllocationFailedExpressionRef : public ExpressionReference { diff --git a/allocation_failed_layout_node.h b/allocation_failed_layout_node.h new file mode 100644 index 000000000..d41c329ed --- /dev/null +++ b/allocation_failed_layout_node.h @@ -0,0 +1,21 @@ +#ifndef ALLOCATION_FAILED_LAYOUT_NODE_H +#define ALLOCATION_FAILED_LAYOUT_NODE_H + +#include "layout_node.h" +#include "layout_reference.h" + +class AllocationFailedLayoutNode : public LayoutNode { +public: + // TreeNode + size_t size() const override { return sizeof(AllocationFailedLayoutNode); } + const char * description() const override { return "Allocation Failed"; } + int numberOfChildren() const override { return 0; } + bool isAllocationFailure() const override { return true; } +}; + +class AllocationFailedLayoutRef : public LayoutReference { +public: + AllocationFailedLayoutRef() : LayoutReference() {} +}; + +#endif diff --git a/expression_node.cpp b/expression_node.cpp new file mode 100644 index 000000000..a112c302b --- /dev/null +++ b/expression_node.cpp @@ -0,0 +1,8 @@ +#include "expression_node.h" +#include "expression_reference.h" + +TreeNode * ExpressionNode::failedAllocationNode() { + return ExpressionRef::failedAllocationNode(); +} + + diff --git a/expression_node.h b/expression_node.h index 6512d864c..9c1fd6c25 100644 --- a/expression_node.h +++ b/expression_node.h @@ -5,6 +5,7 @@ class ExpressionNode : public TreeNode { public: + static TreeNode * failedAllocationNode(); virtual float approximate() = 0; ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } }; diff --git a/expression_reference.cpp b/expression_reference.cpp new file mode 100644 index 000000000..b1ef3e524 --- /dev/null +++ b/expression_reference.cpp @@ -0,0 +1,8 @@ +#include "expression_reference.h" +#include "allocation_failed_expression_node.h" + +template<> +TreeNode * ExpressionRef::failedAllocationNode() { + static AllocationFailedExpressionRef FailureRef; + return FailureRef.node(); +} diff --git a/expression_reference.h b/expression_reference.h index efd6291ba..78e3f1338 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -16,8 +16,12 @@ public: return ExpressionReference(this->node()); } - void addOperand(ExpressionReference e) { - TreeReference::addChild(e); + static TreeNode * failedAllocationNode(); + + void addChild(ExpressionReference e) { + if (!this->node()->isAllocationFailure()) { + TreeReference::addTreeChild(e); + } } ExpressionReference childAtIndex(int i) { diff --git a/float_node.h b/float_node.h index 0942c4f3b..555e714a9 100644 --- a/float_node.h +++ b/float_node.h @@ -14,6 +14,7 @@ public: return m_value > 1 ? "BigFloat" : "SmallFloat"; } void setFloat(float f) { m_value = f; } + void init(float f) override { m_value = f; } private: float m_value; }; @@ -21,7 +22,7 @@ private: class FloatRef : public ExpressionReference { public: FloatRef(float f) : ExpressionReference() { - this->node()->setFloat(f); + this->uncastedNode()->init(f); } }; diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h index eeafa600c..6fff30feb 100644 --- a/horizontal_layout_node.h +++ b/horizontal_layout_node.h @@ -18,6 +18,10 @@ public: int numberOfChildren() const override { return m_numberOfChildren; } void incrementNumberOfChildren() override { m_numberOfChildren++; } + void decrementNumberOfChildren() override { + assert(m_numberOfChildren > 0); + m_numberOfChildren--; + } void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { if (this == cursor->layoutReference().node()) { @@ -78,12 +82,12 @@ class HorizontalLayoutRef : public LayoutReference { public: HorizontalLayoutRef() : LayoutReference() {} HorizontalLayoutRef(LayoutRef l) : LayoutReference() { - addChild(l); + addTreeChild(l); } HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference() { - addChild(l2); - addChild(l1); + addTreeChild(l2); + addTreeChild(l1); } }; diff --git a/layout_node.cpp b/layout_node.cpp index 17a11e301..fcc02d983 100644 --- a/layout_node.cpp +++ b/layout_node.cpp @@ -1,4 +1,9 @@ #include "layout_node.h" +#include "layout_reference.h" + +TreeNode * LayoutNode::failedAllocationNode() { + return LayoutRef::failedAllocationNode(); +} void LayoutNode::draw() { for (LayoutNode * child : children()) { diff --git a/layout_node.h b/layout_node.h index 4fbafe641..5f4ab2881 100644 --- a/layout_node.h +++ b/layout_node.h @@ -7,6 +7,8 @@ class LayoutCursor; class LayoutNode : public TreeNode { public: + static TreeNode * failedAllocationNode(); + /* Hierarchy */ LayoutNode * parent() const { return static_cast(parentTree()); } diff --git a/layout_reference.cpp b/layout_reference.cpp index 52ffecc96..35de1075f 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -1,8 +1,15 @@ #include "layout_reference.h" #include "layout_cursor.h" +#include "allocation_failed_layout_node.h" #include "layout_node.h" #include "char_layout_node.h" +template<> +TreeNode * LayoutRef::failedAllocationNode() { + static AllocationFailedLayoutRef FailureRef; + return FailureRef.node(); +} + template LayoutCursor LayoutReference::cursor() const { return LayoutCursor(this->node()); diff --git a/layout_reference.h b/layout_reference.h index 31760fcfb..0e347cfa0 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -18,6 +18,8 @@ public: return LayoutReference(this->node()); } + static TreeNode * failedAllocationNode(); + LayoutCursor cursor() const; LayoutReference childAtIndex(int i) { diff --git a/test.cpp b/test.cpp index 0d472e05a..16a05fd63 100644 --- a/test.cpp +++ b/test.cpp @@ -94,25 +94,66 @@ void testCursorMoveLeft() { assert(aChar.nodeRetainCount() == 3); } -void testPoolAllocationFail() { - printf("Pool allocation fail test\n"); +void testPoolExpressionAllocationFail() { + printf("Pool expression allocation fail test\n"); - // Fill the pool for size 256 - - // Allocation fail - assert(TreePool::sharedPool()->numberOfNodes() == 0); - AllocationFailedExpressionRef a; + ExpressionRef::failedAllocationNode(); assert(TreePool::sharedPool()->numberOfNodes() == 1); + // Fill the pool for size 256 + FloatRef f1(0.0f); + FloatRef f2(1.0f); + AdditionRef a1(f1, f2); + float result1 = a1.approximate(); + assert(result1 == 1); + + FloatRef f3(2.0f); + FloatRef f4(3.0f); + FloatRef f5(4.0f); + FloatRef f6(5.0f); + FloatRef f7(6.0f); + FloatRef f8(7.0f); + FloatRef f9(8.0f); + + // Allocation fail + FloatRef f11(10.0f); + AdditionRef a(f11, f3); + float result = a.approximate(); + assert(result == -1); + assert(ExpressionRef::failedAllocationNode()->retainCount() == 3); + + f1.replaceWith(f11); + float result2 = a1.approximate(); + assert(result2 == 0); + TreePool::sharedPool()->log(); +} + +void testPoolLayoutAllocationFail() { + printf("Pool layout allocation fail test\n"); + + // Fill the pool for size 256 + CharLayoutRef char1('a'); + LayoutRef::failedAllocationNode(); + CharLayoutRef char2('b'); + CharLayoutRef char3('a'); + CharLayoutRef char4('b'); + CharLayoutRef char5('a'); + CharLayoutRef char6('b'); + CharLayoutRef char7('a'); + CharLayoutRef char8('b'); + CharLayoutRef char9('a'); + CharLayoutRef char10('b'); + + // Allocation fail + CharLayoutRef char11('a'); /*Expression e = ; - e.simplify*/ + e.simplify*/ } typedef void (test)(); void runTest(test t) { - assert(TreePool::sharedPool()->numberOfNodes() == 0); + // TODO add aserts on the pool size once we decide to create allocationFailureNodesFromTheStart t(); - assert(TreePool::sharedPool()->numberOfNodes() == 0); } int main() { @@ -121,7 +162,7 @@ int main() { runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); runTest(testCursorMoveLeft); - runTest(testPoolAllocationFail); + runTest(testPoolExpressionAllocationFail); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_node.h b/tree_node.h index 5cddb5fa4..a56e63f06 100644 --- a/tree_node.h +++ b/tree_node.h @@ -25,8 +25,10 @@ public: virtual const char * description() const { return "UNKNOWN"; } + virtual bool isAllocationFailure() const { return false; } // Node operations + virtual void init(float f) {} void retain() { m_referenceCounter++; } void release(); void rename(int identifier) { @@ -39,6 +41,7 @@ public: TreeNode * editableRootTree(); virtual int numberOfChildren() const = 0; virtual void incrementNumberOfChildren() {} //TODO Put an assert false + virtual void decrementNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; int indexOfChildByIdentifier(int childID) const; diff --git a/tree_pool.h b/tree_pool.h index 41b9770d8..002eecbc3 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -15,14 +15,16 @@ public: TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } template - T * createTreeNode() { + TreeNode * createTreeNode() { int nodeIdentifier = generateIdentifier(); if (nodeIdentifier == -1) { - return nullptr; // TODO return static node "failedAllocation" + T::failedAllocationNode()->retain(); + return T::failedAllocationNode(); // TODO return static node "failedAllocation" } void * ptr = alloc(sizeof(T)); if (ptr == nullptr) { - return nullptr; + T::failedAllocationNode()->retain(); + return T::failedAllocationNode(); } T * node = new(ptr) T(); node->rename(nodeIdentifier); diff --git a/tree_reference.h b/tree_reference.h index cbe4631d4..4afe8e386 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -58,9 +58,15 @@ public: T * node() const { // TODO: Here, assert that the node type is indeed T + // ?? Might be allocation failure, not T return static_cast(TreePool::sharedPool()->node(m_identifier)); } + TreeNode * uncastedNode() const { + return TreePool::sharedPool()->node(m_identifier); + } + + int identifier() const { return m_identifier; } // Hierarchy @@ -78,7 +84,7 @@ public: // Hierarchy operations - void addChild(TreeReference t) { + void addTreeChild(TreeReference t) { t.node()->retain(); TreePool::sharedPool()->move(t.node(), node()->next()); node()->incrementNumberOfChildren(); @@ -90,10 +96,12 @@ public: } void replaceWith(TreeReference t) { - parent().replaceChild(node()->indexOfChild(t.node()), t); + TreeReference p = parent(); + p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { + // TODO decrement the children count of the new child parent assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = treeChildAtIndex(oldChildIndex); TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); From c8acf7dbda21bb1a0af160f7d69953562218f5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 28 Jun 2018 15:56:02 +0200 Subject: [PATCH 051/156] Add second test case for allcoation fail --- test.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++- tree_reference.h | 29 ++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/test.cpp b/test.cpp index 16a05fd63..69f7fa06c 100644 --- a/test.cpp +++ b/test.cpp @@ -125,7 +125,54 @@ void testPoolExpressionAllocationFail() { f1.replaceWith(f11); float result2 = a1.approximate(); assert(result2 == 0); +} + +void testPoolExpressionAllocationFail2() { + printf("Pool expression allocation fail second test\n"); + + ExpressionRef::failedAllocationNode(); + assert(TreePool::sharedPool()->numberOfNodes() == 1); + + // Fill the pool for size 256 + FloatRef f1(0.0f); + FloatRef f2(1.0f); + AdditionRef a1(f1, f2); + float result1 = a1.approximate(); + assert(result1 == 1); + + FloatRef f3(2.0f); + FloatRef f4(3.0f); + AdditionRef a2(f3, f4); + float result2 = a2.approximate(); + assert(result2 == 5); + + FloatRef f5(4.0f); + FloatRef f6(5.0f); + FloatRef f7(6.0f); + FloatRef f8(7.0f); + // Allocation fail + FloatRef f9(8.0f); + FloatRef f10(8.0f); + + printf("\n"); TreePool::sharedPool()->log(); + printf("\n"); + f1.replaceWith(f9); + result1 = a1.approximate(); + assert(result1 == -1); + + TreePool::sharedPool()->log(); + printf("\n"); + f3.replaceWith(f10); + result2 = a2.approximate(); + assert(result2 == -1); + + printf("\n"); + TreePool::sharedPool()->log(); + result1 = a1.approximate(); + printf("a1 number children %d\n", a1.numberOfChildren()); + printf("a1 %f\n", result1); + assert(result1 == -1); } void testPoolLayoutAllocationFail() { @@ -162,7 +209,8 @@ int main() { runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); runTest(testCursorMoveLeft); - runTest(testPoolExpressionAllocationFail); + //runTest(testPoolExpressionAllocationFail); + runTest(testPoolExpressionAllocationFail2); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_reference.h b/tree_reference.h index 4afe8e386..6c02fe7d5 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -43,14 +43,18 @@ public: } ~TreeReference() { - assert(node()); - assert(node()->identifier() == m_identifier); - node()->release(); + if (m_identifier >= 0) { + assert(node()); + assert(node()->identifier() == m_identifier); + node()->release(); + } } bool isDefined() const { return m_identifier >= 0 && TreePool::sharedPool()->node(m_identifier) != nullptr; } int nodeRetainCount() const { return node()->retainCount(); } + void incrementNumberOfChildren() { return node()->incrementNumberOfChildren(); } + void decrementNumberOfChildren() { return node()->decrementNumberOfChildren(); } operator TreeReference() const { return TreeReference(this->node()); @@ -96,12 +100,16 @@ public: } void replaceWith(TreeReference t) { - TreeReference p = parent(); + TreeReference p = parent(); p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { // TODO decrement the children count of the new child parent + TreeReference p = newChild.parent(); + if (p.isDefined()) { + p.decrementNumberOfChildren(); + } assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = treeChildAtIndex(oldChildIndex); TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); @@ -131,12 +139,17 @@ protected: m_identifier = node->identifier(); } - TreeReference(TreeNode * node) : - m_identifier(node->identifier()) - { - node->retain(); + TreeReference(TreeNode * node) { + if (node == nullptr) { + m_identifier = -1; + } else { + m_identifier = node->identifier(); + node->retain(); + } } int m_identifier; }; +typedef TreeReference TreeRef; + #endif From 069ed145a3e78f9847ec588d9d5ce10e3f235bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 28 Jun 2018 17:07:24 +0200 Subject: [PATCH 052/156] Replace node() with castedNode() --- char_layout_node.h | 2 +- expression_reference.h | 2 +- float_node.h | 2 +- layout_cursor.cpp | 8 ++++---- layout_reference.cpp | 2 +- layout_reference.h | 4 ++-- tree_reference.h | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/char_layout_node.h b/char_layout_node.h index 3ea2f04ed..71efb07b1 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -50,7 +50,7 @@ private: class CharLayoutRef : public LayoutReference { public: CharLayoutRef(char c) : LayoutReference() { - this->node()->setChar(c); + this->castedNode()->setChar(c); //TODO use init } }; diff --git a/expression_reference.h b/expression_reference.h index 78e3f1338..9b02d944d 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -33,7 +33,7 @@ public: } float approximate() const { - return this->node()->approximate(); + return this->castedNode()->approximate(); } /* diff --git a/float_node.h b/float_node.h index 555e714a9..36ccfc317 100644 --- a/float_node.h +++ b/float_node.h @@ -22,7 +22,7 @@ private: class FloatRef : public ExpressionReference { public: FloatRef(float f) : ExpressionReference() { - this->uncastedNode()->init(f); + this->node()->init(f); } }; diff --git a/layout_cursor.cpp b/layout_cursor.cpp index 73445d4b7..aff142e85 100644 --- a/layout_cursor.cpp +++ b/layout_cursor.cpp @@ -20,19 +20,19 @@ int LayoutCursor::middleLeftPoint() { /* Move */ void LayoutCursor::moveLeft(bool * shouldRecomputeLayout) { - layoutReference().node()->moveCursorLeft(this, shouldRecomputeLayout); + layoutReference().castedNode()->moveCursorLeft(this, shouldRecomputeLayout); } void LayoutCursor::moveRight(bool * shouldRecomputeLayout) { - layoutReference().node()->moveCursorRight(this, shouldRecomputeLayout); + layoutReference().castedNode()->moveCursorRight(this, shouldRecomputeLayout); } void LayoutCursor::moveAbove(bool * shouldRecomputeLayout) { - layoutReference().node()->moveCursorUp(this, shouldRecomputeLayout); + layoutReference().castedNode()->moveCursorUp(this, shouldRecomputeLayout); } void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { - layoutReference().node()->moveCursorDown(this, shouldRecomputeLayout); + layoutReference().castedNode()->moveCursorDown(this, shouldRecomputeLayout); } diff --git a/layout_reference.cpp b/layout_reference.cpp index 35de1075f..ca87dc84b 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -12,7 +12,7 @@ TreeNode * LayoutRef::failedAllocationNode() { template LayoutCursor LayoutReference::cursor() const { - return LayoutCursor(this->node()); + return LayoutCursor(this->castedNode()); } template LayoutCursor LayoutReference::cursor() const; diff --git a/layout_reference.h b/layout_reference.h index 0e347cfa0..c93316ce7 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -32,11 +32,11 @@ public: } int layoutOrigin() { - return this->node()->layoutOrigin(); + return this->castedNode()->layoutOrigin(); } int absoluteOrigin() { - return this->node()->absoluteOrigin(); + return this->castedNode()->absoluteOrigin(); } }; diff --git a/tree_reference.h b/tree_reference.h index 6c02fe7d5..3f7626b99 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -60,13 +60,13 @@ public: return TreeReference(this->node()); } - T * node() const { + T * castedNode() const { // TODO: Here, assert that the node type is indeed T // ?? Might be allocation failure, not T return static_cast(TreePool::sharedPool()->node(m_identifier)); } - TreeNode * uncastedNode() const { + TreeNode * node() const { return TreePool::sharedPool()->node(m_identifier); } From bd61298374701cd4d25f6bbf5529997b3e26bd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 28 Jun 2018 17:34:47 +0200 Subject: [PATCH 053/156] Make tests more independent --- test.cpp | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/test.cpp b/test.cpp index 69f7fa06c..b66e3440b 100644 --- a/test.cpp +++ b/test.cpp @@ -2,18 +2,19 @@ #include AdditionRef buildAddition() { + int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); FloatRef smallFloat(0.2f); FloatRef bigFloat(3.4f); AdditionRef a(smallFloat, bigFloat); - assert(TreePool::sharedPool()->numberOfNodes() == 3); + assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes + 3); return a; } void testAddition() { printf("Addition test\n"); - assert(TreePool::sharedPool()->numberOfNodes() == 0); + int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); AdditionRef a = buildAddition(); - assert(TreePool::sharedPool()->numberOfNodes() == 3); + assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes + 3); float result = a.approximate(); assert(result = 3.6f); @@ -23,9 +24,11 @@ void testAddition() { float result2 = a.approximate(); assert(result2 == 4.7f); + int firstChildIdentifier = a.childAtIndex(0).identifier(); + int secondChildIdentifier = a.childAtIndex(1).identifier(); a.swapChildren(1,0); - assert(a.childAtIndex(0).identifier() == 1); - assert(a.childAtIndex(1).identifier() == 3); + assert(a.childAtIndex(0).identifier() == secondChildIdentifier); + assert(a.childAtIndex(1).identifier() == firstChildIdentifier); } void createNodes() { @@ -38,27 +41,29 @@ void createNodes() { void testPoolEmpties() { printf("Pool empties test\n"); - assert(TreePool::sharedPool()->numberOfNodes() == 0); + int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); createNodes(); - assert(TreePool::sharedPool()->numberOfNodes() == 0); + assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes); } void testCursorCreateAndRetain() { printf("Cursor create and retain test\n"); + int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); CharLayoutRef aChar('a'); CharLayoutRef bChar('b'); - assert(aChar.identifier() == 0); - assert(bChar.identifier() == 1); + int aCharID = aChar.identifier(); + int bCharID = bChar.identifier(); + assert(bCharID = aCharID + 1); assert(aChar.nodeRetainCount() == 1); assert(bChar.nodeRetainCount() == 1); assert(strcmp(aChar.node()->description(), "Char a") == 0); assert(strcmp(bChar.node()->description(), "Char b") == 0); - assert(TreePool::sharedPool()->numberOfNodes() == 2); + assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes + 2); HorizontalLayoutRef h(aChar, bChar); - assert(aChar.identifier() == 0); - assert(bChar.identifier() == 1); - assert(h.identifier() == 2); + assert(aChar.identifier() == aCharID); + assert(bChar.identifier() == bCharID); + assert(h.identifier() == bCharID + 1); assert(aChar.nodeRetainCount() == 2); assert(bChar.nodeRetainCount() == 2); assert(h.nodeRetainCount() == 1); @@ -97,9 +102,6 @@ void testCursorMoveLeft() { void testPoolExpressionAllocationFail() { printf("Pool expression allocation fail test\n"); - ExpressionRef::failedAllocationNode(); - assert(TreePool::sharedPool()->numberOfNodes() == 1); - // Fill the pool for size 256 FloatRef f1(0.0f); FloatRef f2(1.0f); @@ -130,9 +132,6 @@ void testPoolExpressionAllocationFail() { void testPoolExpressionAllocationFail2() { printf("Pool expression allocation fail second test\n"); - ExpressionRef::failedAllocationNode(); - assert(TreePool::sharedPool()->numberOfNodes() == 1); - // Fill the pool for size 256 FloatRef f1(0.0f); FloatRef f2(1.0f); @@ -199,12 +198,15 @@ void testPoolLayoutAllocationFail() { typedef void (test)(); void runTest(test t) { - // TODO add aserts on the pool size once we decide to create allocationFailureNodesFromTheStart + int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); t(); + assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes); } int main() { printf("\n*******************\nStart running tests\n*******************\n\n"); + ExpressionRef::failedAllocationNode(); + assert(TreePool::sharedPool()->numberOfNodes() == 1); runTest(testAddition); runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); From cb77fbe2ff316e8cd308ea3b6b79d67aaf6e88de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 28 Jun 2018 17:59:06 +0200 Subject: [PATCH 054/156] Fix AllocationFailure when multiple instances --- expression_reference.cpp | 5 +++ expression_reference.h | 5 +-- layout_cursor.h | 2 +- layout_reference.cpp | 6 ++-- layout_reference.h | 4 +-- test.cpp | 4 +-- tree_node.cpp | 32 ++++++++++------- tree_node.h | 5 +++ tree_pool.h | 32 +++++++++++++++-- tree_reference.h | 77 ++++++++++++++++++++++++++++++++-------- 10 files changed, 133 insertions(+), 39 deletions(-) diff --git a/expression_reference.cpp b/expression_reference.cpp index b1ef3e524..9c7c29d64 100644 --- a/expression_reference.cpp +++ b/expression_reference.cpp @@ -6,3 +6,8 @@ TreeNode * ExpressionRef::failedAllocationNode() { static AllocationFailedExpressionRef FailureRef; return FailureRef.node(); } + +template<> +ExpressionReference ExpressionRef::failedAllocationRef() { + return ExpressionReference(failedAllocationNode()); +} diff --git a/expression_reference.h b/expression_reference.h index 9b02d944d..390ab704a 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -12,10 +12,11 @@ public: using TreeReference::TreeReference; // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression - operator ExpressionReference() const { + operator ExpressionReference() { return ExpressionReference(this->node()); } + static ExpressionReference failedAllocationRef(); static TreeNode * failedAllocationNode(); void addChild(ExpressionReference e) { @@ -32,7 +33,7 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - float approximate() const { + float approximate() { return this->castedNode()->approximate(); } diff --git a/layout_cursor.h b/layout_cursor.h index 9d7eaa6f8..1281b1479 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -25,7 +25,7 @@ public: printf("\n"); } - bool isDefined() const { return m_layoutRef.isDefined(); } + bool isDefined() { return m_layoutRef.isDefined(); } /* Getters and setters */ diff --git a/layout_reference.cpp b/layout_reference.cpp index ca87dc84b..505ae3f57 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -11,9 +11,9 @@ TreeNode * LayoutRef::failedAllocationNode() { } template -LayoutCursor LayoutReference::cursor() const { +LayoutCursor LayoutReference::cursor() { return LayoutCursor(this->castedNode()); } -template LayoutCursor LayoutReference::cursor() const; -template LayoutCursor LayoutReference::cursor() const; +template LayoutCursor LayoutReference::cursor(); +template LayoutCursor LayoutReference::cursor(); diff --git a/layout_reference.h b/layout_reference.h index c93316ce7..606e8f037 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -14,13 +14,13 @@ public: /* Allow every LayoutReference to be transformed into a * LayoutReference, i.e. Layout */ - operator LayoutReference() const { + operator LayoutReference() { return LayoutReference(this->node()); } static TreeNode * failedAllocationNode(); - LayoutCursor cursor() const; + LayoutCursor cursor(); LayoutReference childAtIndex(int i) { TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); diff --git a/test.cpp b/test.cpp index b66e3440b..80f6df654 100644 --- a/test.cpp +++ b/test.cpp @@ -126,7 +126,7 @@ void testPoolExpressionAllocationFail() { f1.replaceWith(f11); float result2 = a1.approximate(); - assert(result2 == 0); + assert(result2 == -1); } void testPoolExpressionAllocationFail2() { @@ -211,7 +211,7 @@ int main() { runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); runTest(testCursorMoveLeft); - //runTest(testPoolExpressionAllocationFail); + runTest(testPoolExpressionAllocationFail); runTest(testPoolExpressionAllocationFail2); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; diff --git a/tree_node.cpp b/tree_node.cpp index d4ae12a57..6a2d4e612 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -8,23 +8,31 @@ void TreeNode::release() { m_referenceCounter--; if (m_referenceCounter == 0) { - if (numberOfChildren() != 0) { - int lastIdentifier = lastChild()->identifier(); - TreeNode * child = next(); - bool lastChildReleased = false; - while (!lastChildReleased) { - lastChildReleased = child->identifier() == lastIdentifier; - int nextSiblingIdentifier = lastChildReleased ? -1 : child->nextSibling()->identifier(); - child->release(); - if (nextSiblingIdentifier != -1) { - child = TreePool::sharedPool()->node(nextSiblingIdentifier); - } + releaseChildrenAndDestroy(); + } +} + +void TreeNode::releaseChildren() { + if (numberOfChildren() != 0) { + int lastIdentifier = lastChild()->identifier(); + TreeNode * child = next(); + bool lastChildReleased = false; + while (!lastChildReleased) { + lastChildReleased = child->identifier() == lastIdentifier; + int nextSiblingIdentifier = lastChildReleased ? -1 : child->nextSibling()->identifier(); + child->release(); + if (nextSiblingIdentifier != -1) { + child = TreePool::sharedPool()->node(nextSiblingIdentifier); } } - TreePool::sharedPool()->discardTreeNode(this); } } +void TreeNode::releaseChildrenAndDestroy() { + releaseChildren(); + TreePool::sharedPool()->discardTreeNode(this); +} + // Hierarchy TreeNode * TreeNode::parentTree() const { diff --git a/tree_node.h b/tree_node.h index a56e63f06..b662d3f5c 100644 --- a/tree_node.h +++ b/tree_node.h @@ -31,6 +31,8 @@ public: virtual void init(float f) {} void retain() { m_referenceCounter++; } void release(); + void releaseChildren(); + void releaseChildrenAndDestroy(); void rename(int identifier) { m_identifier = identifier; m_referenceCounter = 1; @@ -102,6 +104,9 @@ public: return reinterpret_cast(reinterpret_cast(const_cast(this)) + size()); } + // Hierarchy operations + void moveAndReleaseAllChildren(); + protected: TreeNode() : m_identifier(-1), diff --git a/tree_pool.h b/tree_pool.h index 002eecbc3..96a6edd1e 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -8,6 +8,7 @@ class TreePool { friend class TreeNode; public: + static constexpr int AllocationFailureIdentifier = 0; static TreePool * sharedPool(); // Node @@ -19,7 +20,7 @@ public: int nodeIdentifier = generateIdentifier(); if (nodeIdentifier == -1) { T::failedAllocationNode()->retain(); - return T::failedAllocationNode(); // TODO return static node "failedAllocation" + return T::failedAllocationNode(); } void * ptr = alloc(sizeof(T)); if (ptr == nullptr) { @@ -46,9 +47,34 @@ public: return copy; } - void log(); + // Allocation failure handling + + bool nodeWasReplacedWithAllocationFailure(int id) { + return m_allocationFailureRetainCount[id] > 0; + } + + void releaseAllocationFailure(int id) { + int currrentRetainCount = m_allocationFailureRetainCount[id]; + assert(currrentRetainCount > 0); + m_allocationFailureRetainCount[id] = currrentRetainCount - 1; + if (m_allocationFailureRetainCount[id] == 0) { + freeIdentifier(id); + } + } + + void registerIdentiferAsAllocationFailure(int id, int retainCount) { + if (retainCount == 0) { + freeIdentifier(id); + } else { + assert(id >= 0 && id < MaxNumberOfNodes); + m_nodeForIdentifier[id] = first(); // TODO for now the first node in the pool is the allocation failure node (WARNING when implementing for Layouts... HAVE 2 POOLS?) + m_allocationFailureRetainCount[id] = retainCount; + } + } // Debug + void log(); + int numberOfNodes() const { int count = 0; AllPool nodes = const_cast(this)->allNodes(); @@ -72,6 +98,7 @@ private: void registerNode(TreeNode * node) { m_nodeForIdentifier[node->identifier()] = node; } + void renameNode(TreeNode * node) { node->rename(generateIdentifier()); registerNode(node); @@ -151,6 +178,7 @@ private: char * m_cursor; char m_buffer[BufferSize]; TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; + int m_allocationFailureRetainCount[MaxNumberOfNodes]; }; #endif diff --git a/tree_reference.h b/tree_reference.h index 3f7626b99..9c456cbce 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -33,12 +33,15 @@ public: inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } void setTo(const TreeReference & tr) { - m_identifier = tr.identifier(); - TreePool::sharedPool()->node(m_identifier)->retain(); + setIdentifierAndRetain(tr.identifier()); } - TreeReference clone() const { - TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(node()); + TreeReference clone() { + TreeNode * myNode = node(); + if (myNode->isAllocationFailure()) { + return TreeReference(TreePool::sharedPool()->node(TreePool::AllocationFailureIdentifier)); + } + TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(myNode); return TreeReference(nodeCopy); } @@ -50,39 +53,50 @@ public: } } - bool isDefined() const { return m_identifier >= 0 && TreePool::sharedPool()->node(m_identifier) != nullptr; } + bool isDefined() { return m_identifier >= 0 && node() != nullptr; } + bool isAllocationFailure() { return node()->isAllocationFailure(); } - int nodeRetainCount() const { return node()->retainCount(); } + int nodeRetainCount() { return node()->retainCount(); } void incrementNumberOfChildren() { return node()->incrementNumberOfChildren(); } void decrementNumberOfChildren() { return node()->decrementNumberOfChildren(); } - operator TreeReference() const { + operator TreeReference() { return TreeReference(this->node()); } - T * castedNode() const { + T * castedNode() { // TODO: Here, assert that the node type is indeed T // ?? Might be allocation failure, not T + updateIdentifier(); return static_cast(TreePool::sharedPool()->node(m_identifier)); } - TreeNode * node() const { + TreeNode * node() { + updateIdentifier(); return TreePool::sharedPool()->node(m_identifier); } + void updateIdentifier() { + /* If the node was replaced with an allocation failure, change the + * identifier */ + if (TreePool::sharedPool()->nodeWasReplacedWithAllocationFailure(m_identifier)) { + TreePool::sharedPool()->releaseAllocationFailure(m_identifier); + setIdentifierAndRetain(TreePool::AllocationFailureIdentifier); + } + } int identifier() const { return m_identifier; } // Hierarchy - int numberOfChildren() const { + int numberOfChildren() { return node()->numberOfChildren(); } - TreeReference parent() const { + TreeReference parent() { return TreeReference(node()->parentTree()); } - TreeReference treeChildAtIndex(int i) const { + TreeReference treeChildAtIndex(int i) { return TreeReference(node()->childTreeAtIndex(i)); } @@ -105,7 +119,10 @@ public: } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { - // TODO decrement the children count of the new child parent + if (newChild.isAllocationFailure()) { + replaceWithAllocationFailure(); + return; + } TreeReference p = newChild.parent(); if (p.isDefined()) { p.decrementNumberOfChildren(); @@ -118,6 +135,32 @@ public: oldChild.node()->release(); } + void replaceWithAllocationFailure() { + TreeReference p = parent(); + int currentRetainCount = node()->retainCount(); + + // Move the node to the end of the pool and decrease children count of parent + TreePool::sharedPool()->move(node(), TreePool::sharedPool()->last()); + if (p.isDefined()) { + p.decrementNumberOfChildren(); + } + + // Release all children and delete the node in the pool + node()->releaseChildrenAndDestroy(); + + /* In case another ref is pointing to the node, register the identifier as + * AllocationFailure. If the retainCount is 1 (this reference is the only + * one pointing to the node), the pool will register the identifier as + * free. */ + TreePool::sharedPool()->registerIdentiferAsAllocationFailure(m_identifier, currentRetainCount - 1); + setIdentifierAndRetain(TreePool::AllocationFailureIdentifier); + + // Replace parent with AllocationFailure + if (p.isDefined()) { + p.replaceWithAllocationFailure(); + } + } + void swapChildren(int i, int j) { assert(i >= 0 && i < numberOfChildren()); assert(j >= 0 && j < numberOfChildren()); @@ -143,10 +186,14 @@ protected: if (node == nullptr) { m_identifier = -1; } else { - m_identifier = node->identifier(); - node->retain(); + setIdentifierAndRetain(node->identifier()); } } + void setIdentifierAndRetain(int newId) { + m_identifier = newId; + node()->retain(); + } +private: int m_identifier; }; From 2684b2f09fe84705dee3c90c03848e7f5ee79f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 14:21:10 +0200 Subject: [PATCH 055/156] Replace nodes with AllocationFailures inside the tree when needed --- addition_node.h | 6 +++- expression_node.cpp | 7 ++-- expression_node.h | 3 +- expression_reference.cpp | 6 ++-- expression_reference.h | 14 +++++--- layout_cursor.h | 2 +- layout_node.cpp | 5 +-- layout_node.h | 3 +- layout_reference.cpp | 8 ++--- layout_reference.h | 6 ++-- test.cpp | 48 +++++++++++++++++++-------- tree_node.cpp | 8 +++++ tree_node.h | 26 +++++++++------ tree_pool.h | 8 ++--- tree_reference.h | 72 ++++++++++++++++++++++------------------ 15 files changed, 139 insertions(+), 83 deletions(-) diff --git a/addition_node.h b/addition_node.h index d6fe1efed..f68cce382 100644 --- a/addition_node.h +++ b/addition_node.h @@ -16,7 +16,11 @@ public: float approximate() override { float result = 0.0f; for (int i=0; iapproximate(); + float approximateI = child(i)->approximate(); + if (approximateI == -1) { + return -1; + } + result += approximateI; } return result; } diff --git a/expression_node.cpp b/expression_node.cpp index a112c302b..f759167c6 100644 --- a/expression_node.cpp +++ b/expression_node.cpp @@ -1,8 +1,7 @@ #include "expression_node.h" +#include "allocation_failed_expression_node.h" #include "expression_reference.h" -TreeNode * ExpressionNode::failedAllocationNode() { - return ExpressionRef::failedAllocationNode(); +TreeNode * ExpressionNode::staticFailedAllocationStaticNode() { + return ExpressionRef::staticFailedAllocationStaticNode(); } - - diff --git a/expression_node.h b/expression_node.h index 9c1fd6c25..3e2ef389c 100644 --- a/expression_node.h +++ b/expression_node.h @@ -5,7 +5,8 @@ class ExpressionNode : public TreeNode { public: - static TreeNode * failedAllocationNode(); + static TreeNode * staticFailedAllocationStaticNode(); + TreeNode * failedAllocationStaticNode() override { return staticFailedAllocationStaticNode(); } virtual float approximate() = 0; ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } }; diff --git a/expression_reference.cpp b/expression_reference.cpp index 9c7c29d64..d404f3155 100644 --- a/expression_reference.cpp +++ b/expression_reference.cpp @@ -2,12 +2,12 @@ #include "allocation_failed_expression_node.h" template<> -TreeNode * ExpressionRef::failedAllocationNode() { +TreeNode * ExpressionRef::staticFailedAllocationStaticNode() { static AllocationFailedExpressionRef FailureRef; return FailureRef.node(); } template<> -ExpressionReference ExpressionRef::failedAllocationRef() { - return ExpressionReference(failedAllocationNode()); +ExpressionReference ExpressionRef::staticFailedAllocationStaticRef() { + return ExpressionReference(staticFailedAllocationStaticNode()); } diff --git a/expression_reference.h b/expression_reference.h index 390ab704a..9143432fe 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -12,12 +12,12 @@ public: using TreeReference::TreeReference; // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression - operator ExpressionReference() { + operator ExpressionReference() const { return ExpressionReference(this->node()); } - static ExpressionReference failedAllocationRef(); - static TreeNode * failedAllocationNode(); + static ExpressionReference staticFailedAllocationStaticRef(); + static TreeNode * staticFailedAllocationStaticNode(); void addChild(ExpressionReference e) { if (!this->node()->isAllocationFailure()) { @@ -25,6 +25,12 @@ public: } } + void addChildAtIndex(ExpressionReference e, int index) { + if (!this->node()->isAllocationFailure()) { + TreeReference::addTreeChildAtIndex(e, index); + } + } + ExpressionReference childAtIndex(int i) { return ExpressionReference(TreeReference::treeChildAtIndex(i).node()); } @@ -33,7 +39,7 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - float approximate() { + float approximate() const { return this->castedNode()->approximate(); } diff --git a/layout_cursor.h b/layout_cursor.h index 1281b1479..9d7eaa6f8 100644 --- a/layout_cursor.h +++ b/layout_cursor.h @@ -25,7 +25,7 @@ public: printf("\n"); } - bool isDefined() { return m_layoutRef.isDefined(); } + bool isDefined() const { return m_layoutRef.isDefined(); } /* Getters and setters */ diff --git a/layout_node.cpp b/layout_node.cpp index fcc02d983..092d3ea2a 100644 --- a/layout_node.cpp +++ b/layout_node.cpp @@ -1,8 +1,9 @@ #include "layout_node.h" +#include "allocation_failed_layout_node.h" #include "layout_reference.h" -TreeNode * LayoutNode::failedAllocationNode() { - return LayoutRef::failedAllocationNode(); +TreeNode * LayoutNode::staticFailedAllocationStaticNode() { + return LayoutRef::staticFailedAllocationStaticNode(); } void LayoutNode::draw() { diff --git a/layout_node.h b/layout_node.h index 5f4ab2881..f81211f57 100644 --- a/layout_node.h +++ b/layout_node.h @@ -7,7 +7,8 @@ class LayoutCursor; class LayoutNode : public TreeNode { public: - static TreeNode * failedAllocationNode(); + static TreeNode * staticFailedAllocationStaticNode(); + TreeNode * failedAllocationStaticNode() override { return staticFailedAllocationStaticNode(); } /* Hierarchy */ LayoutNode * parent() const { return static_cast(parentTree()); } diff --git a/layout_reference.cpp b/layout_reference.cpp index 505ae3f57..2c4c93726 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -5,15 +5,15 @@ #include "char_layout_node.h" template<> -TreeNode * LayoutRef::failedAllocationNode() { +TreeNode * LayoutRef::staticFailedAllocationStaticNode() { static AllocationFailedLayoutRef FailureRef; return FailureRef.node(); } template -LayoutCursor LayoutReference::cursor() { +LayoutCursor LayoutReference::cursor() const { return LayoutCursor(this->castedNode()); } -template LayoutCursor LayoutReference::cursor(); -template LayoutCursor LayoutReference::cursor(); +template LayoutCursor LayoutReference::cursor() const; +template LayoutCursor LayoutReference::cursor() const; diff --git a/layout_reference.h b/layout_reference.h index 606e8f037..495c33801 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -14,13 +14,13 @@ public: /* Allow every LayoutReference to be transformed into a * LayoutReference, i.e. Layout */ - operator LayoutReference() { + operator LayoutReference() const { return LayoutReference(this->node()); } - static TreeNode * failedAllocationNode(); + static TreeNode * staticFailedAllocationStaticNode(); - LayoutCursor cursor(); + LayoutCursor cursor() const; LayoutReference childAtIndex(int i) { TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); diff --git a/test.cpp b/test.cpp index 80f6df654..866ed9ebc 100644 --- a/test.cpp +++ b/test.cpp @@ -122,7 +122,7 @@ void testPoolExpressionAllocationFail() { AdditionRef a(f11, f3); float result = a.approximate(); assert(result == -1); - assert(ExpressionRef::failedAllocationNode()->retainCount() == 3); + assert(ExpressionRef::staticFailedAllocationStaticNode()->retainCount() == 3); f1.replaceWith(f11); float result2 = a1.approximate(); @@ -130,7 +130,7 @@ void testPoolExpressionAllocationFail() { } void testPoolExpressionAllocationFail2() { - printf("Pool expression allocation fail second test\n"); + printf("Pool expression allocation multiple fail test\n"); // Fill the pool for size 256 FloatRef f1(0.0f); @@ -153,33 +153,54 @@ void testPoolExpressionAllocationFail2() { FloatRef f9(8.0f); FloatRef f10(8.0f); - printf("\n"); - TreePool::sharedPool()->log(); - printf("\n"); f1.replaceWith(f9); result1 = a1.approximate(); assert(result1 == -1); - TreePool::sharedPool()->log(); - printf("\n"); f3.replaceWith(f10); result2 = a2.approximate(); assert(result2 == -1); - printf("\n"); - TreePool::sharedPool()->log(); result1 = a1.approximate(); - printf("a1 number children %d\n", a1.numberOfChildren()); - printf("a1 %f\n", result1); assert(result1 == -1); } +void testPoolExpressionAllocationFailOnImbricatedAdditions() { + printf("Pool expression allocation fail second test\n"); + + // Fill the pool for size 256 + FloatRef f1(0.0f); + FloatRef f2(1.0f); + AdditionRef a1(f1, f2); + float result1 = a1.approximate(); + assert(result1 == 1); + + FloatRef f3(2.0f); + AdditionRef a2(a1, f3); + float result2 = a2.approximate(); + assert(result2 == 3); + + FloatRef f4(3.0f); + FloatRef f5(4.0f); + FloatRef f6(5.0f); + FloatRef f7(6.0f); + FloatRef f8(7.0f); + // Allocation fail + FloatRef f9(7.0f); + f1.replaceWith(f9); + result2 = a2.approximate(); + assert(result2 == -1); + a2.removeChild(a1); + result2 = a2.approximate(); + assert(result2 == 2); +} + void testPoolLayoutAllocationFail() { printf("Pool layout allocation fail test\n"); // Fill the pool for size 256 CharLayoutRef char1('a'); - LayoutRef::failedAllocationNode(); + LayoutRef::staticFailedAllocationStaticNode(); CharLayoutRef char2('b'); CharLayoutRef char3('a'); CharLayoutRef char4('b'); @@ -205,7 +226,7 @@ void runTest(test t) { int main() { printf("\n*******************\nStart running tests\n*******************\n\n"); - ExpressionRef::failedAllocationNode(); + ExpressionRef::staticFailedAllocationStaticNode(); assert(TreePool::sharedPool()->numberOfNodes() == 1); runTest(testAddition); runTest(testPoolEmpties); @@ -213,6 +234,7 @@ int main() { runTest(testCursorMoveLeft); runTest(testPoolExpressionAllocationFail); runTest(testPoolExpressionAllocationFail2); + runTest(testPoolExpressionAllocationFailOnImbricatedAdditions); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_node.cpp b/tree_node.cpp index 6a2d4e612..a26d57b96 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -127,6 +127,14 @@ int TreeNode::indexOfChild(const TreeNode * child) const { return indexOfChildByIdentifier(child->identifier()); } +int TreeNode::indexInParent() const { + TreeNode * p = parentTree(); + if (p == nullptr) { + return -1; + } + return p->indexOfChildByIdentifier(m_identifier); +} + bool TreeNode::hasChild(const TreeNode * child) const { if (child == nullptr) { return false; diff --git a/tree_node.h b/tree_node.h index b662d3f5c..7abdc8251 100644 --- a/tree_node.h +++ b/tree_node.h @@ -22,10 +22,15 @@ public: virtual size_t size() const = 0; int identifier() const { return m_identifier; } int retainCount() const { return m_referenceCounter; } + void setReferenceCounter(int refCount) { m_referenceCounter = refCount; } //TODO make this method privte with only friends that can access it virtual const char * description() const { return "UNKNOWN"; } virtual bool isAllocationFailure() const { return false; } + virtual TreeNode * failedAllocationStaticNode() { + assert(false); + return nullptr; + } // Node operations virtual void init(float f) {} @@ -48,6 +53,7 @@ public: TreeNode * childTreeAtIndex(int i) const; int indexOfChildByIdentifier(int childID) const; int indexOfChild(const TreeNode * child) const; + int indexInParent() const; bool hasChild(const TreeNode * child) const; bool hasAncestor(const TreeNode * node, bool includeSelf) const; bool hasSibling(const TreeNode * e) const; @@ -104,16 +110,6 @@ public: return reinterpret_cast(reinterpret_cast(const_cast(this)) + size()); } - // Hierarchy operations - void moveAndReleaseAllChildren(); - -protected: - TreeNode() : - m_identifier(-1), - m_referenceCounter(1) - { - } - TreeNode * nextSibling() const { int remainingNodesToVisit = numberOfChildren(); TreeNode * node = const_cast(this)->next(); @@ -125,6 +121,16 @@ protected: return node; } + // Hierarchy operations + void moveAndReleaseAllChildren(); + +protected: + TreeNode() : + m_identifier(-1), + m_referenceCounter(1) + { + } + /*TreeNode * lastDescendant() const { TreeNode * node = const_cast(this); int remainingNodesToVisit = node->numberOfChildren(); diff --git a/tree_pool.h b/tree_pool.h index 96a6edd1e..bfe382b65 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -19,13 +19,13 @@ public: TreeNode * createTreeNode() { int nodeIdentifier = generateIdentifier(); if (nodeIdentifier == -1) { - T::failedAllocationNode()->retain(); - return T::failedAllocationNode(); + T::staticFailedAllocationStaticNode()->retain(); + return T::staticFailedAllocationStaticNode(); } void * ptr = alloc(sizeof(T)); if (ptr == nullptr) { - T::failedAllocationNode()->retain(); - return T::failedAllocationNode(); + T::staticFailedAllocationStaticNode()->retain(); + return T::staticFailedAllocationStaticNode(); } T * node = new(ptr) T(); node->rename(nodeIdentifier); diff --git a/tree_reference.h b/tree_reference.h index 9c456cbce..a99cf2c1f 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -36,7 +36,7 @@ public: setIdentifierAndRetain(tr.identifier()); } - TreeReference clone() { + TreeReference clone() const { TreeNode * myNode = node(); if (myNode->isAllocationFailure()) { return TreeReference(TreePool::sharedPool()->node(TreePool::AllocationFailureIdentifier)); @@ -53,69 +53,70 @@ public: } } - bool isDefined() { return m_identifier >= 0 && node() != nullptr; } - bool isAllocationFailure() { return node()->isAllocationFailure(); } + bool isDefined() const { return m_identifier >= 0 && node() != nullptr; } + bool isAllocationFailure() const { return node()->isAllocationFailure(); } - int nodeRetainCount() { return node()->retainCount(); } + int nodeRetainCount() const { return node()->retainCount(); } void incrementNumberOfChildren() { return node()->incrementNumberOfChildren(); } void decrementNumberOfChildren() { return node()->decrementNumberOfChildren(); } - operator TreeReference() { + operator TreeReference() const { return TreeReference(this->node()); } - T * castedNode() { + T * castedNode() const { // TODO: Here, assert that the node type is indeed T // ?? Might be allocation failure, not T - updateIdentifier(); return static_cast(TreePool::sharedPool()->node(m_identifier)); } - TreeNode * node() { - updateIdentifier(); + TreeNode * node() const { return TreePool::sharedPool()->node(m_identifier); } - void updateIdentifier() { - /* If the node was replaced with an allocation failure, change the - * identifier */ - if (TreePool::sharedPool()->nodeWasReplacedWithAllocationFailure(m_identifier)) { - TreePool::sharedPool()->releaseAllocationFailure(m_identifier); - setIdentifierAndRetain(TreePool::AllocationFailureIdentifier); - } - } - int identifier() const { return m_identifier; } // Hierarchy - int numberOfChildren() { + int numberOfChildren() const { return node()->numberOfChildren(); } - TreeReference parent() { + TreeReference parent() const { return TreeReference(node()->parentTree()); } - TreeReference treeChildAtIndex(int i) { + TreeReference treeChildAtIndex(int i) const { return TreeReference(node()->childTreeAtIndex(i)); } // Hierarchy operations void addTreeChild(TreeReference t) { + return addTreeChildAtIndex(t, 0); + } + + void addTreeChildAtIndex(TreeReference t, int index) { + assert(index >= 0 && index <= numberOfChildren()); t.node()->retain(); - TreePool::sharedPool()->move(t.node(), node()->next()); + TreeNode * newChildPosition = node()->next(); + for (int i = 0; i < index; i++) { + newChildPosition = newChildPosition->nextSibling(); + } + TreePool::sharedPool()->move(t.node(), newChildPosition); node()->incrementNumberOfChildren(); } void removeChild(TreeReference t) { TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); t.node()->release(); + node()->decrementNumberOfChildren(); } void replaceWith(TreeReference t) { TreeReference p = parent(); - p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); + if (p.isDefined()) { + p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); + } } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { @@ -137,7 +138,9 @@ public: void replaceWithAllocationFailure() { TreeReference p = parent(); + int indexInParentNode = node()->indexInParent(); int currentRetainCount = node()->retainCount(); + TreeNode * staticAllocFailNode = castedNode()->failedAllocationStaticNode(); // Move the node to the end of the pool and decrease children count of parent TreePool::sharedPool()->move(node(), TreePool::sharedPool()->last()); @@ -148,16 +151,21 @@ public: // Release all children and delete the node in the pool node()->releaseChildrenAndDestroy(); - /* In case another ref is pointing to the node, register the identifier as - * AllocationFailure. If the retainCount is 1 (this reference is the only - * one pointing to the node), the pool will register the identifier as - * free. */ - TreePool::sharedPool()->registerIdentiferAsAllocationFailure(m_identifier, currentRetainCount - 1); - setIdentifierAndRetain(TreePool::AllocationFailureIdentifier); - - // Replace parent with AllocationFailure + /* Create an allocation failure node with the previous node id. We know + * there is room in the pool as we deleted the previous node and an + * AllocationFailure nodes size is smaller or equal to any other node size.*/ + //TODO static assert that the size is smaller + TreeNode * newAllocationFailureNode = TreePool::sharedPool()->deepCopy(staticAllocFailNode); + newAllocationFailureNode->rename(m_identifier); if (p.isDefined()) { - p.replaceWithAllocationFailure(); + assert(indexInParentNode >= 0); + /* Set the refCount to previousRefCount-1 because the previous parent is + * no longer retaining the node. When we add this node to the parent, it + * will retain it and increment the retain count. */ + newAllocationFailureNode->setReferenceCounter(currentRetainCount - 1); + p.addTreeChildAtIndex(newAllocationFailureNode, indexInParentNode); + } else { + newAllocationFailureNode->setReferenceCounter(currentRetainCount); } } From fb9244df98fd4bd9bba0dba755b8606a1e8e86a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 14:22:46 +0200 Subject: [PATCH 056/156] Clean old Allocation failure code --- tree_pool.h | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/tree_pool.h b/tree_pool.h index bfe382b65..9d17f17bd 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -47,31 +47,6 @@ public: return copy; } - // Allocation failure handling - - bool nodeWasReplacedWithAllocationFailure(int id) { - return m_allocationFailureRetainCount[id] > 0; - } - - void releaseAllocationFailure(int id) { - int currrentRetainCount = m_allocationFailureRetainCount[id]; - assert(currrentRetainCount > 0); - m_allocationFailureRetainCount[id] = currrentRetainCount - 1; - if (m_allocationFailureRetainCount[id] == 0) { - freeIdentifier(id); - } - } - - void registerIdentiferAsAllocationFailure(int id, int retainCount) { - if (retainCount == 0) { - freeIdentifier(id); - } else { - assert(id >= 0 && id < MaxNumberOfNodes); - m_nodeForIdentifier[id] = first(); // TODO for now the first node in the pool is the allocation failure node (WARNING when implementing for Layouts... HAVE 2 POOLS?) - m_allocationFailureRetainCount[id] = retainCount; - } - } - // Debug void log(); @@ -178,7 +153,6 @@ private: char * m_cursor; char m_buffer[BufferSize]; TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; - int m_allocationFailureRetainCount[MaxNumberOfNodes]; }; #endif From 3e0552da91498681e245023a15df81579497c9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 14:27:07 +0200 Subject: [PATCH 057/156] Clearer comment --- tree_node.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tree_node.cpp b/tree_node.cpp index a26d57b96..a9b6452ce 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -36,8 +36,9 @@ void TreeNode::releaseChildrenAndDestroy() { // Hierarchy TreeNode * TreeNode::parentTree() const { -// Choose between those two algorithms: the first has complexity O(numberNodes) but uses 0(3maxNumberNodes) space -// The second is much clearer for the reader and uses no space, but has complexity 0 + /* Choose between these algorithms: the first has complexity O(numberNodes) + * but uses O(3maxNumberNodes) space. The second is much clearer for the + * reader and uses no space, but has complexity O(numberNodes^2) */ #if 0 int cursor = -1; TreeNode * parentsHistory[TreePool::MaxNumberOfNodes]; From 8117e735612e310d0fee46b0bab9b858832a675c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 14:33:25 +0200 Subject: [PATCH 058/156] Remove unnecessary method renaming --- expression_reference.h | 12 ------------ horizontal_layout_node.h | 6 +++--- tree_reference.h | 12 ++++++++---- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/expression_reference.h b/expression_reference.h index 9143432fe..af349de29 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -19,18 +19,6 @@ public: static ExpressionReference staticFailedAllocationStaticRef(); static TreeNode * staticFailedAllocationStaticNode(); - void addChild(ExpressionReference e) { - if (!this->node()->isAllocationFailure()) { - TreeReference::addTreeChild(e); - } - } - - void addChildAtIndex(ExpressionReference e, int index) { - if (!this->node()->isAllocationFailure()) { - TreeReference::addTreeChildAtIndex(e, index); - } - } - ExpressionReference childAtIndex(int i) { return ExpressionReference(TreeReference::treeChildAtIndex(i).node()); } diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h index 6fff30feb..5e024e964 100644 --- a/horizontal_layout_node.h +++ b/horizontal_layout_node.h @@ -82,12 +82,12 @@ class HorizontalLayoutRef : public LayoutReference { public: HorizontalLayoutRef() : LayoutReference() {} HorizontalLayoutRef(LayoutRef l) : LayoutReference() { - addTreeChild(l); + addChild(l); } HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference() { - addTreeChild(l2); - addTreeChild(l1); + addChild(l2); + addChild(l1); } }; diff --git a/tree_reference.h b/tree_reference.h index a99cf2c1f..d538d1733 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -91,11 +91,15 @@ public: // Hierarchy operations - void addTreeChild(TreeReference t) { - return addTreeChildAtIndex(t, 0); + void addChild(TreeReference t) { + return addChildAtIndex(t, 0); } - void addTreeChildAtIndex(TreeReference t, int index) { + void addChildAtIndex(TreeReference t, int index) { + if (node()->isAllocationFailure()) { + return; + } + // TODO detach t assert(index >= 0 && index <= numberOfChildren()); t.node()->retain(); TreeNode * newChildPosition = node()->next(); @@ -163,7 +167,7 @@ public: * no longer retaining the node. When we add this node to the parent, it * will retain it and increment the retain count. */ newAllocationFailureNode->setReferenceCounter(currentRetainCount - 1); - p.addTreeChildAtIndex(newAllocationFailureNode, indexInParentNode); + p.addChildAtIndex(newAllocationFailureNode, indexInParentNode); } else { newAllocationFailureNode->setReferenceCounter(currentRetainCount); } From a4471e1570069a83e62aca974f69b8e0fbbdbf84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 15:30:40 +0200 Subject: [PATCH 059/156] StaticAllocationFailureNodes are not stored in the pool --- expression_node.cpp | 4 ++-- expression_node.h | 11 +++++++++-- expression_reference.cpp | 15 +++++++-------- expression_reference.h | 3 +-- layout_node.cpp | 4 ++-- layout_node.h | 10 ++++++++-- layout_reference.cpp | 10 +++++++--- layout_reference.h | 2 +- test.cpp | 5 +---- tree_node.h | 4 ++++ tree_pool.cpp | 5 +++++ tree_pool.h | 24 +++++++++++++++++++----- tree_reference.h | 3 ++- 13 files changed, 68 insertions(+), 32 deletions(-) diff --git a/expression_node.cpp b/expression_node.cpp index f759167c6..ff3194342 100644 --- a/expression_node.cpp +++ b/expression_node.cpp @@ -2,6 +2,6 @@ #include "allocation_failed_expression_node.h" #include "expression_reference.h" -TreeNode * ExpressionNode::staticFailedAllocationStaticNode() { - return ExpressionRef::staticFailedAllocationStaticNode(); +TreeNode * ExpressionNode::FailedAllocationStaticNode() { + return ExpressionRef::FailedAllocationStaticNode(); } diff --git a/expression_node.h b/expression_node.h index 3e2ef389c..b8ccd7a88 100644 --- a/expression_node.h +++ b/expression_node.h @@ -5,8 +5,15 @@ class ExpressionNode : public TreeNode { public: - static TreeNode * staticFailedAllocationStaticNode(); - TreeNode * failedAllocationStaticNode() override { return staticFailedAllocationStaticNode(); } + static TreeNode * FailedAllocationStaticNode(); + static int AllocationFailureNodeIdentifier() { + return FailedAllocationStaticNode()->identifier(); + } + int allocationFailureNodeIdentifier() override { + return AllocationFailureNodeIdentifier(); + } + + TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } virtual float approximate() = 0; ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } }; diff --git a/expression_reference.cpp b/expression_reference.cpp index d404f3155..e1fbefb11 100644 --- a/expression_reference.cpp +++ b/expression_reference.cpp @@ -2,12 +2,11 @@ #include "allocation_failed_expression_node.h" template<> -TreeNode * ExpressionRef::staticFailedAllocationStaticNode() { - static AllocationFailedExpressionRef FailureRef; - return FailureRef.node(); -} - -template<> -ExpressionReference ExpressionRef::staticFailedAllocationStaticRef() { - return ExpressionReference(staticFailedAllocationStaticNode()); +TreeNode * ExpressionRef::FailedAllocationStaticNode() { + static AllocationFailedExpressionNode FailureNode; + if (FailureNode.identifier() >= -1) { + int newIdentifier = TreePool::sharedPool()->registerStaticNode(&FailureNode); + FailureNode.rename(newIdentifier); + } + return &FailureNode; } diff --git a/expression_reference.h b/expression_reference.h index af349de29..eaaf93370 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -16,8 +16,7 @@ public: return ExpressionReference(this->node()); } - static ExpressionReference staticFailedAllocationStaticRef(); - static TreeNode * staticFailedAllocationStaticNode(); + static TreeNode * FailedAllocationStaticNode(); ExpressionReference childAtIndex(int i) { return ExpressionReference(TreeReference::treeChildAtIndex(i).node()); diff --git a/layout_node.cpp b/layout_node.cpp index 092d3ea2a..064a2ca9a 100644 --- a/layout_node.cpp +++ b/layout_node.cpp @@ -2,8 +2,8 @@ #include "allocation_failed_layout_node.h" #include "layout_reference.h" -TreeNode * LayoutNode::staticFailedAllocationStaticNode() { - return LayoutRef::staticFailedAllocationStaticNode(); +TreeNode * LayoutNode::FailedAllocationStaticNode() { + return LayoutRef::FailedAllocationStaticNode(); } void LayoutNode::draw() { diff --git a/layout_node.h b/layout_node.h index f81211f57..7aa421a7e 100644 --- a/layout_node.h +++ b/layout_node.h @@ -7,8 +7,14 @@ class LayoutCursor; class LayoutNode : public TreeNode { public: - static TreeNode * staticFailedAllocationStaticNode(); - TreeNode * failedAllocationStaticNode() override { return staticFailedAllocationStaticNode(); } + static TreeNode * FailedAllocationStaticNode(); + TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } + static int AllocationFailureNodeIdentifier() { + return FailedAllocationStaticNode()->identifier(); + } + int allocationFailureNodeIdentifier() override { + return AllocationFailureNodeIdentifier(); + } /* Hierarchy */ LayoutNode * parent() const { return static_cast(parentTree()); } diff --git a/layout_reference.cpp b/layout_reference.cpp index 2c4c93726..42c6455d8 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -5,9 +5,13 @@ #include "char_layout_node.h" template<> -TreeNode * LayoutRef::staticFailedAllocationStaticNode() { - static AllocationFailedLayoutRef FailureRef; - return FailureRef.node(); +TreeNode * LayoutRef::FailedAllocationStaticNode() { + static AllocationFailedLayoutNode FailureNode; + if (FailureNode.identifier() >= -1) { + int newIdentifier = TreePool::sharedPool()->registerStaticNode(&FailureNode); + FailureNode.rename(newIdentifier); + } + return &FailureNode; } template diff --git a/layout_reference.h b/layout_reference.h index 495c33801..521a41997 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -18,7 +18,7 @@ public: return LayoutReference(this->node()); } - static TreeNode * staticFailedAllocationStaticNode(); + static TreeNode * FailedAllocationStaticNode(); LayoutCursor cursor() const; diff --git a/test.cpp b/test.cpp index 866ed9ebc..a6cb1ea3f 100644 --- a/test.cpp +++ b/test.cpp @@ -122,7 +122,6 @@ void testPoolExpressionAllocationFail() { AdditionRef a(f11, f3); float result = a.approximate(); assert(result == -1); - assert(ExpressionRef::staticFailedAllocationStaticNode()->retainCount() == 3); f1.replaceWith(f11); float result2 = a1.approximate(); @@ -200,7 +199,6 @@ void testPoolLayoutAllocationFail() { // Fill the pool for size 256 CharLayoutRef char1('a'); - LayoutRef::staticFailedAllocationStaticNode(); CharLayoutRef char2('b'); CharLayoutRef char3('a'); CharLayoutRef char4('b'); @@ -226,8 +224,7 @@ void runTest(test t) { int main() { printf("\n*******************\nStart running tests\n*******************\n\n"); - ExpressionRef::staticFailedAllocationStaticNode(); - assert(TreePool::sharedPool()->numberOfNodes() == 1); + assert(TreePool::sharedPool()->numberOfNodes() == 0); runTest(testAddition); runTest(testPoolEmpties); runTest(testCursorCreateAndRetain); diff --git a/tree_node.h b/tree_node.h index 7abdc8251..556b25121 100644 --- a/tree_node.h +++ b/tree_node.h @@ -31,6 +31,10 @@ public: assert(false); return nullptr; } + virtual int allocationFailureNodeIdentifier() { + assert(false); + return -1; + } // Node operations virtual void init(float f) {} diff --git a/tree_pool.cpp b/tree_pool.cpp index 90b32cad3..88ff0270a 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -7,6 +7,11 @@ TreePool * TreePool::sharedPool() { } TreeNode * TreePool::node(int identifier) const { + if (identifier < 0) { + int index = indexOfStaticNode(identifier); + assert(index >= 0 && index < MaxNumberOfStaticNodes); + return m_staticNodes[index]; + } assert(identifier >= 0 && identifier <= MaxNumberOfNodes); return m_nodeForIdentifier[identifier]; } diff --git a/tree_pool.h b/tree_pool.h index 9d17f17bd..65526c14e 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -8,7 +8,6 @@ class TreePool { friend class TreeNode; public: - static constexpr int AllocationFailureIdentifier = 0; static TreePool * sharedPool(); // Node @@ -19,13 +18,13 @@ public: TreeNode * createTreeNode() { int nodeIdentifier = generateIdentifier(); if (nodeIdentifier == -1) { - T::staticFailedAllocationStaticNode()->retain(); - return T::staticFailedAllocationStaticNode(); + T::FailedAllocationStaticNode()->retain(); + return T::FailedAllocationStaticNode(); } void * ptr = alloc(sizeof(T)); if (ptr == nullptr) { - T::staticFailedAllocationStaticNode()->retain(); - return T::staticFailedAllocationStaticNode(); + T::FailedAllocationStaticNode()->retain(); + return T::FailedAllocationStaticNode(); } T * node = new(ptr) T(); node->rename(nodeIdentifier); @@ -47,6 +46,16 @@ public: return copy; } + int registerStaticNode(TreeNode * node) { + int nodeID = 0; + while (m_staticNodes[nodeID] != nullptr && nodeID < MaxNumberOfStaticNodes) { + nodeID++; + } + assert(nodeID < MaxNumberOfStaticNodes); + m_staticNodes[nodeID] = node; + return identifierOfStaticNodeAtIndex(nodeID); + } + // Debug void log(); @@ -62,6 +71,7 @@ public: private: constexpr static int BufferSize = 256; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); + constexpr static int MaxNumberOfStaticNodes = 2; // TreeNode void discardTreeNode(TreeNode * node) { @@ -79,6 +89,9 @@ private: registerNode(node); } + int identifierOfStaticNodeAtIndex(int index) const { return - (index+2);} // We do not want positive indexes that are reserved for pool nodes, and -1 is reserved for node initialisation. + int indexOfStaticNode(int id) const { return -id-2;} + // Iterators TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } @@ -153,6 +166,7 @@ private: char * m_cursor; char m_buffer[BufferSize]; TreeNode * m_nodeForIdentifier[MaxNumberOfNodes]; + TreeNode * m_staticNodes[MaxNumberOfStaticNodes]; }; #endif diff --git a/tree_reference.h b/tree_reference.h index d538d1733..4627a5de8 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -39,7 +39,8 @@ public: TreeReference clone() const { TreeNode * myNode = node(); if (myNode->isAllocationFailure()) { - return TreeReference(TreePool::sharedPool()->node(TreePool::AllocationFailureIdentifier)); + int allocationFailureNodeId = myNode->allocationFailureNodeIdentifier(); + return TreeReference(TreePool::sharedPool()->node(allocationFailureNodeId)); } TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(myNode); return TreeReference(nodeCopy); From 6721c25f427078d9a1afd9c261844f68a6347ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 15:53:12 +0200 Subject: [PATCH 060/156] Detach node before adding it --- tree_reference.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tree_reference.h b/tree_reference.h index 4627a5de8..5a2c38065 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -92,6 +92,13 @@ public: // Hierarchy operations + void detach(TreeReference t) { + assert(node()->hasChild(t.node())); + TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); + t.node()->release(); + node()->decrementNumberOfChildren(); + } + void addChild(TreeReference t) { return addChildAtIndex(t, 0); } @@ -100,9 +107,18 @@ public: if (node()->isAllocationFailure()) { return; } - // TODO detach t assert(index >= 0 && index <= numberOfChildren()); + + // Retain t before detaching it, else it might get destroyed t.node()->retain(); + + // Detach t from its parent + TreeReference tParent = t.parent(); + if (tParent.isDefined()) { + tParent.detach(t); + } + + // Move t TreeNode * newChildPosition = node()->next(); for (int i = 0; i < index; i++) { newChildPosition = newChildPosition->nextSibling(); From 8822617f3c211299d600901378b6f443a753b97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 16:05:42 +0200 Subject: [PATCH 061/156] Steal operand test --- test.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test.cpp b/test.cpp index a6cb1ea3f..e84282b2d 100644 --- a/test.cpp +++ b/test.cpp @@ -194,6 +194,28 @@ void testPoolExpressionAllocationFailOnImbricatedAdditions() { assert(result2 == 2); } +void testStealOperand() { + printf("Steal operand test\n"); + + FloatRef f1(0.0f); + FloatRef f2(1.0f); + AdditionRef a1(f1, f2); + int result1 = a1.approximate(); + assert(result1 == 1); + + FloatRef f3(2.0f); + FloatRef f4(3.0f); + AdditionRef a2(f4, f3); + int result2 = a2.approximate(); + assert(result2 == 5); + + a1.addChild(f4); + int result3 = a1.approximate(); + assert(result3 == 4); + int result4 = a2.approximate(); + assert(result4 == 2); +} + void testPoolLayoutAllocationFail() { printf("Pool layout allocation fail test\n"); @@ -232,6 +254,7 @@ int main() { runTest(testPoolExpressionAllocationFail); runTest(testPoolExpressionAllocationFail2); runTest(testPoolExpressionAllocationFailOnImbricatedAdditions); + runTest(testStealOperand); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } From fbce93b1fc06583e504077961938417185486933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 16:16:11 +0200 Subject: [PATCH 062/156] Clean tests --- test.cpp | 78 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/test.cpp b/test.cpp index e84282b2d..6cf988ede 100644 --- a/test.cpp +++ b/test.cpp @@ -1,6 +1,15 @@ #include "refs.h" #include +void assert_expression_approximates_to(ExpressionRef e, float result) { + float b = e.approximate(); + if (b > result) { + assert(b - result < 0.000001f); + } else { + assert(result - b < 0.000001f); + } +} + AdditionRef buildAddition() { int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); FloatRef smallFloat(0.2f); @@ -16,13 +25,12 @@ void testAddition() { AdditionRef a = buildAddition(); assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes + 3); - float result = a.approximate(); - assert(result = 3.6f); + assert_expression_approximates_to(a, 3.6f); FloatRef smallFloat(1.3f); a.replaceChildAtIndex(0, smallFloat); - float result2 = a.approximate(); - assert(result2 == 4.7f); + + assert_expression_approximates_to(a, 4.7f); int firstChildIdentifier = a.childAtIndex(0).identifier(); int secondChildIdentifier = a.childAtIndex(1).identifier(); @@ -106,8 +114,8 @@ void testPoolExpressionAllocationFail() { FloatRef f1(0.0f); FloatRef f2(1.0f); AdditionRef a1(f1, f2); - float result1 = a1.approximate(); - assert(result1 == 1); + + assert_expression_approximates_to(a1, 1); FloatRef f3(2.0f); FloatRef f4(3.0f); @@ -120,12 +128,12 @@ void testPoolExpressionAllocationFail() { // Allocation fail FloatRef f11(10.0f); AdditionRef a(f11, f3); - float result = a.approximate(); - assert(result == -1); + + assert_expression_approximates_to(a, -1); f1.replaceWith(f11); - float result2 = a1.approximate(); - assert(result2 == -1); + + assert_expression_approximates_to(a1, -1); } void testPoolExpressionAllocationFail2() { @@ -135,14 +143,14 @@ void testPoolExpressionAllocationFail2() { FloatRef f1(0.0f); FloatRef f2(1.0f); AdditionRef a1(f1, f2); - float result1 = a1.approximate(); - assert(result1 == 1); + + assert_expression_approximates_to(a1, 1); FloatRef f3(2.0f); FloatRef f4(3.0f); AdditionRef a2(f3, f4); - float result2 = a2.approximate(); - assert(result2 == 5); + + assert_expression_approximates_to(a2, 5); FloatRef f5(4.0f); FloatRef f6(5.0f); @@ -153,15 +161,13 @@ void testPoolExpressionAllocationFail2() { FloatRef f10(8.0f); f1.replaceWith(f9); - result1 = a1.approximate(); - assert(result1 == -1); + + assert_expression_approximates_to(a1, -1); f3.replaceWith(f10); - result2 = a2.approximate(); - assert(result2 == -1); - result1 = a1.approximate(); - assert(result1 == -1); + assert_expression_approximates_to(a2, -1); + assert_expression_approximates_to(a1, -1); } void testPoolExpressionAllocationFailOnImbricatedAdditions() { @@ -171,13 +177,13 @@ void testPoolExpressionAllocationFailOnImbricatedAdditions() { FloatRef f1(0.0f); FloatRef f2(1.0f); AdditionRef a1(f1, f2); - float result1 = a1.approximate(); - assert(result1 == 1); + + assert_expression_approximates_to(a1, 1); FloatRef f3(2.0f); AdditionRef a2(a1, f3); - float result2 = a2.approximate(); - assert(result2 == 3); + + assert_expression_approximates_to(a2, 3); FloatRef f4(3.0f); FloatRef f5(4.0f); @@ -187,11 +193,12 @@ void testPoolExpressionAllocationFailOnImbricatedAdditions() { // Allocation fail FloatRef f9(7.0f); f1.replaceWith(f9); - result2 = a2.approximate(); - assert(result2 == -1); + + assert_expression_approximates_to(a2, -1); + a2.removeChild(a1); - result2 = a2.approximate(); - assert(result2 == 2); + + assert_expression_approximates_to(a2, 2); } void testStealOperand() { @@ -200,20 +207,19 @@ void testStealOperand() { FloatRef f1(0.0f); FloatRef f2(1.0f); AdditionRef a1(f1, f2); - int result1 = a1.approximate(); - assert(result1 == 1); + + assert_expression_approximates_to(a1, 1); FloatRef f3(2.0f); FloatRef f4(3.0f); AdditionRef a2(f4, f3); - int result2 = a2.approximate(); - assert(result2 == 5); + + assert_expression_approximates_to(a2, 5); a1.addChild(f4); - int result3 = a1.approximate(); - assert(result3 == 4); - int result4 = a2.approximate(); - assert(result4 == 2); + + assert_expression_approximates_to(a1, 4); + assert_expression_approximates_to(a2, 2); } void testPoolLayoutAllocationFail() { From 38139a6fe757e1161687b57d1da2b39f9dec7122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 16:49:00 +0200 Subject: [PATCH 063/156] Remove unneeded method --- tree_node.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/tree_node.h b/tree_node.h index 556b25121..c4080143f 100644 --- a/tree_node.h +++ b/tree_node.h @@ -125,9 +125,6 @@ public: return node; } - // Hierarchy operations - void moveAndReleaseAllChildren(); - protected: TreeNode() : m_identifier(-1), From 53bacec72f64f106bef6ee936641c4ebe84c3c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 17:21:03 +0200 Subject: [PATCH 064/156] Remove duplicate method --- tree_reference.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tree_reference.h b/tree_reference.h index 5a2c38065..1efa3cb62 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -92,13 +92,6 @@ public: // Hierarchy operations - void detach(TreeReference t) { - assert(node()->hasChild(t.node())); - TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); - t.node()->release(); - node()->decrementNumberOfChildren(); - } - void addChild(TreeReference t) { return addChildAtIndex(t, 0); } @@ -115,7 +108,7 @@ public: // Detach t from its parent TreeReference tParent = t.parent(); if (tParent.isDefined()) { - tParent.detach(t); + tParent.removeChild(t); } // Move t From f0e2bd0e5cae856a13db87ce9ab6fab9b2305223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 17:54:54 +0200 Subject: [PATCH 065/156] Start expression simplification --- addition_node.h | 33 +++++++++++++++++++++++------ allocation_failed_expression_node.h | 1 + expression_node.h | 33 +++++++++++++++++++++++++++-- expression_reference.h | 13 +++++++----- float_node.h | 1 + horizontal_layout_node.h | 3 +++ test.cpp | 19 ++++++++++++++++- tree_node.cpp | 8 ++++++- tree_node.h | 22 +++++++++++-------- tree_pool.cpp | 26 ++++++++++++++++------- tree_pool.h | 2 ++ tree_reference.h | 18 ++++++++++++++++ 12 files changed, 147 insertions(+), 32 deletions(-) diff --git a/addition_node.h b/addition_node.h index f68cce382..3639c7098 100644 --- a/addition_node.h +++ b/addition_node.h @@ -6,13 +6,10 @@ class AdditionNode : public ExpressionNode { public: - const char * description() const override { - return "Addition"; - } + const char * description() const override { return "Addition"; } + size_t size() const override { return sizeof(AdditionNode); } + Type type() const override { return Type::Addition; } - size_t size() const override { - return sizeof(AdditionNode); - } float approximate() override { float result = 0.0f; for (int i=0; itype() == Type::Addition) { + TreeRef(this).mergeChildren(TreeRef(currentChild)); + // Is it ok to modify memory while executing ? + continue; + } + i++; + } + + return false; + } + int numberOfChildren() const override { return m_numberOfChildren; } void incrementNumberOfChildren() override { m_numberOfChildren++; } void decrementNumberOfChildren() override { assert(m_numberOfChildren > 0); m_numberOfChildren--; } + void eraseNumberOfChildren() override { + m_numberOfChildren = 0; + } /* Expression simplify() override { // Scan operands, merge constants diff --git a/allocation_failed_expression_node.h b/allocation_failed_expression_node.h index fae6873a0..097269bf7 100644 --- a/allocation_failed_expression_node.h +++ b/allocation_failed_expression_node.h @@ -13,6 +13,7 @@ public: // TreeNode size_t size() const override { return sizeof(AllocationFailedExpressionNode); } const char * description() const override { return "Allocation Failed"; } + Type type() const override { return Type::AllocationFailure; } int numberOfChildren() const override { return 0; } bool isAllocationFailure() const override { return true; } }; diff --git a/expression_node.h b/expression_node.h index b8ccd7a88..444fc17ba 100644 --- a/expression_node.h +++ b/expression_node.h @@ -5,6 +5,35 @@ class ExpressionNode : public TreeNode { public: + enum class Type : uint8_t { + AllocationFailure = 0, + Float = 1, + Addition + }; + + // Expression + virtual Type type() const = 0; + virtual float approximate() = 0; + + void deepReduce() { + assert(parentTree() != nullptr); + for (int i = 0; i < numberOfChildren(); i++) { + child(i)->deepReduce(); + } + shallowReduce(); + } + + virtual bool shallowReduce() { + for (int i = 0; i < numberOfChildren(); i++) { + if (child(i)->isAllocationFailure()) { + replaceWithAllocationFailure(); + return true; + } + } + return false; + } + + // Allocation failure static TreeNode * FailedAllocationStaticNode(); static int AllocationFailureNodeIdentifier() { return FailedAllocationStaticNode()->identifier(); @@ -12,9 +41,9 @@ public: int allocationFailureNodeIdentifier() override { return AllocationFailureNodeIdentifier(); } - TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } - virtual float approximate() = 0; + + // Hierarchy ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } }; diff --git a/expression_reference.h b/expression_reference.h index eaaf93370..3b2c460b1 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -11,7 +11,8 @@ class ExpressionReference : public TreeReference { public: using TreeReference::TreeReference; - // Allow every ExpressionReference to be transformed into an ExpressionReference, i.e. Expression + /* Allow every ExpressionReference to be transformed into an + * ExpressionReference, i.e. ExpressionRef */ operator ExpressionReference() const { return ExpressionReference(this->node()); } @@ -30,11 +31,13 @@ public: return this->castedNode()->approximate(); } - /* - ExpressionReference simplify() { - return node()->simplify(); + void deepReduce() { + return this->castedNode()->deepReduce(); + } + + void shallowReduce() { + return this->castedNode()->shallowReduce(); } - */ }; typedef ExpressionReference ExpressionRef; diff --git a/float_node.h b/float_node.h index 36ccfc317..927aaeec4 100644 --- a/float_node.h +++ b/float_node.h @@ -8,6 +8,7 @@ class FloatNode : public ExpressionNode { public: FloatNode() : ExpressionNode() {} size_t size() const override { return sizeof(FloatNode); } + Type type() const override { return Type::Float; } int numberOfChildren() const override { return 0; } float approximate() override { return m_value; } const char * description() const override { diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h index 5e024e964..f412b20d8 100644 --- a/horizontal_layout_node.h +++ b/horizontal_layout_node.h @@ -22,6 +22,9 @@ public: assert(m_numberOfChildren > 0); m_numberOfChildren--; } + void eraseNumberOfChildren() override { + m_numberOfChildren = 0; + } void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { if (this == cursor->layoutReference().node()) { diff --git a/test.cpp b/test.cpp index 6cf988ede..98fdaeaa2 100644 --- a/test.cpp +++ b/test.cpp @@ -222,6 +222,23 @@ void testStealOperand() { assert_expression_approximates_to(a2, 2); } +void testSimplify() { + printf("Symplify test\n"); + + AdditionRef a( + AdditionRef( + FloatRef(0.0f), + FloatRef(1.0f)), + FloatRef(2.0f)); + + assert_expression_approximates_to(a, 3); + + a.deepReduce(); + + assert_expression_approximates_to(a, 3); + assert(a.numberOfChildren() == 3); +} + void testPoolLayoutAllocationFail() { printf("Pool layout allocation fail test\n"); @@ -260,7 +277,7 @@ int main() { runTest(testPoolExpressionAllocationFail); runTest(testPoolExpressionAllocationFail2); runTest(testPoolExpressionAllocationFailOnImbricatedAdditions); - runTest(testStealOperand); + //runTest(testStealOperand); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_node.cpp b/tree_node.cpp index a9b6452ce..94ed1441f 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -1,6 +1,6 @@ #include "tree_node.h" #include "tree_pool.h" -#include "expression_node.h" +#include "tree_reference.h" #include // Node operations @@ -175,3 +175,9 @@ bool TreeNode::hasSibling(const TreeNode * e) const { } return false; } + +void TreeNode::replaceWithAllocationFailure() { + TreeRef t(this); + t.replaceWithAllocationFailure(); + // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? +} diff --git a/tree_node.h b/tree_node.h index c4080143f..1bf1de357 100644 --- a/tree_node.h +++ b/tree_node.h @@ -53,6 +53,7 @@ public: virtual int numberOfChildren() const = 0; virtual void incrementNumberOfChildren() {} //TODO Put an assert false virtual void decrementNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? + virtual void eraseNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; int indexOfChildByIdentifier(int childID) const; @@ -125,14 +126,7 @@ public: return node; } -protected: - TreeNode() : - m_identifier(-1), - m_referenceCounter(1) - { - } - - /*TreeNode * lastDescendant() const { + TreeNode * lastDescendant() const { TreeNode * node = const_cast(this); int remainingNodesToVisit = node->numberOfChildren(); while (remainingNodesToVisit > 0) { @@ -141,7 +135,17 @@ protected: remainingNodesToVisit += node->numberOfChildren(); } return node; - }*/ + } + + // Hierarchy operations + void replaceWithAllocationFailure(); + +protected: + TreeNode() : + m_identifier(-1), + m_referenceCounter(1) + { + } TreeNode * lastChild() const { if (numberOfChildren() == 0) { diff --git a/tree_pool.cpp b/tree_pool.cpp index 88ff0270a..bd4b4b669 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -41,35 +41,45 @@ void TreePool::logNodeForIdentifierArray() { } void TreePool::move(TreeNode * source, TreeNode * destination) { - if (source == destination) { + size_t moveSize = source->deepSize(); + moveNodes(source, destination, moveSize); +} + +void TreePool::moveChildren(TreeNode * sourceParent, TreeNode * destination) { + size_t moveSize = sourceParent->deepSize() - sourceParent->size(); + moveNodes(sourceParent->next(), destination, moveSize); +} + +void TreePool::moveNodes(TreeNode * source, TreeNode * destination, size_t moveSize) { + if (source == destination || moveSize == 0) { return; } - // Move the Node - size_t srcDeepSize = source->deepSize(); char * destinationAddress = reinterpret_cast(destination); char * sourceAddress = reinterpret_cast(source); - if (insert(destinationAddress, sourceAddress, srcDeepSize)) { + if (insert(destinationAddress, sourceAddress, moveSize)) { // Update the nodeForIdentifier array for (int i = 0; i < MaxNumberOfNodes; i++) { char * nodeAddress = reinterpret_cast(m_nodeForIdentifier[i]); if (nodeAddress == nullptr) { continue; - } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + srcDeepSize) { + } else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + moveSize) { if (destinationAddress < sourceAddress) { m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - (sourceAddress - destinationAddress)); } else { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + srcDeepSize))); + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + (destinationAddress - (sourceAddress + moveSize))); } } else if (nodeAddress > sourceAddress && nodeAddress < destinationAddress) { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - srcDeepSize); + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress - moveSize); } else if (nodeAddress < sourceAddress && nodeAddress >= destinationAddress) { - m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + srcDeepSize); + m_nodeForIdentifier[i] = reinterpret_cast(nodeAddress + moveSize); } } } } + + #include void TreePool::log() { diff --git a/tree_pool.h b/tree_pool.h index 65526c14e..0ae8bf3c1 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -33,6 +33,7 @@ public: } void move(TreeNode * source, TreeNode * destination); + void moveChildren(TreeNode * sourceParent, TreeNode * destination); TreeNode * deepCopy(TreeNode * node) { size_t size = node->deepSize(); @@ -141,6 +142,7 @@ private: void * alloc(size_t size); void dealloc(TreeNode * ptr); static inline bool insert(char * destination, char * source, size_t length); + void moveNodes(TreeNode * source, TreeNode * destination, size_t moveLength); // Identifiers int generateIdentifier() { diff --git a/tree_reference.h b/tree_reference.h index 1efa3cb62..55223f73c 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -11,6 +11,9 @@ class Cursor; template class TreeReference { + friend class TreeNode; + friend class AdditionNode; + friend class Cursor; template friend class TreeReference; @@ -126,6 +129,12 @@ public: node()->decrementNumberOfChildren(); } + void removeChildren() { + node()->releaseChildren(); + TreePool::sharedPool()->moveChildren(node(), TreePool::sharedPool()->last()); + node()->eraseNumberOfChildren(); + } + void replaceWith(TreeReference t) { TreeReference p = parent(); if (p.isDefined()) { @@ -198,6 +207,15 @@ public: TreePool::sharedPool()->move(secondChild.node(), firstChildNode); } + void mergeChildren(TreeReference t) { + // Steal operands + TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()); + // If t is a child, remove it + if (node()->hasChild(t.node())) { + removeChild(t); + } + } + protected: TreeReference() { TreeNode * node = TreePool::sharedPool()->createTreeNode(); From a971b0a6baa85b45c548cad90c69b367d326f07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 19:00:33 +0200 Subject: [PATCH 066/156] Fix AllocationFailedExpressionRef constructor --- allocation_failed_expression_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/allocation_failed_expression_node.h b/allocation_failed_expression_node.h index 097269bf7..03283957e 100644 --- a/allocation_failed_expression_node.h +++ b/allocation_failed_expression_node.h @@ -20,7 +20,7 @@ public: class AllocationFailedExpressionRef : public ExpressionReference { public: - AllocationFailedExpressionRef() : ExpressionReference() {} + using ExpressionReference::ExpressionReference; }; #endif From 370a10710c32f8513e4b21b7f81b3031af410aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 11:49:21 +0200 Subject: [PATCH 067/156] SimplificationRootNode --- simplification_root_node.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 simplification_root_node.h diff --git a/simplification_root_node.h b/simplification_root_node.h new file mode 100644 index 000000000..3d641052e --- /dev/null +++ b/simplification_root_node.h @@ -0,0 +1,27 @@ +#ifndef SIMPLIFICATION_ROOT_NODE_H +#define SIMPLIFICATION_ROOT_NODE_H + +#include "expression_reference.h" +#include "expression_node.h" + +class SimplificationRootNode : public ExpressionNode { +public: + SimplificationRootNode() : ExpressionNode() {} + size_t size() const override { return sizeof(SimplificationRootNode); } + Type type() const override { return Type::SimplificationRoot; } + int numberOfChildren() const override { return 1; } + float approximate() override { assert(false); return -1; } + const char * description() const override { return "Simplification root"; } +}; + +class SimplificationRootRef : public ExpressionReference { +public: + using ExpressionReference::ExpressionReference; + SimplificationRootRef(ExpressionRef c) : + SimplificationRootRef() + { + addChild(c); + } +}; + +#endif From 3135fff759217cfce1caf113fc75fa8b63e34432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 20:07:27 +0200 Subject: [PATCH 068/156] Expression simplification --- addition_node.h | 6 +++--- expression_node.h | 3 ++- horizontal_layout_node.h | 6 +++--- refs.h | 1 + test.cpp | 5 +++-- tree_node.h | 4 ++-- tree_pool.h | 2 +- tree_reference.h | 9 ++++++--- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/addition_node.h b/addition_node.h index 3639c7098..7c7d1cecc 100644 --- a/addition_node.h +++ b/addition_node.h @@ -44,10 +44,10 @@ public: } int numberOfChildren() const override { return m_numberOfChildren; } - void incrementNumberOfChildren() override { m_numberOfChildren++; } - void decrementNumberOfChildren() override { + void incrementNumberOfChildren(int increment = 1) override { m_numberOfChildren+= increment; } + void decrementNumberOfChildren(int decrement = 1) override { assert(m_numberOfChildren > 0); - m_numberOfChildren--; + m_numberOfChildren-= decrement; } void eraseNumberOfChildren() override { m_numberOfChildren = 0; diff --git a/expression_node.h b/expression_node.h index 444fc17ba..d0e45c238 100644 --- a/expression_node.h +++ b/expression_node.h @@ -8,7 +8,8 @@ public: enum class Type : uint8_t { AllocationFailure = 0, Float = 1, - Addition + Addition, + SimplificationRoot }; // Expression diff --git a/horizontal_layout_node.h b/horizontal_layout_node.h index f412b20d8..53d332976 100644 --- a/horizontal_layout_node.h +++ b/horizontal_layout_node.h @@ -17,10 +17,10 @@ public: } int numberOfChildren() const override { return m_numberOfChildren; } - void incrementNumberOfChildren() override { m_numberOfChildren++; } - void decrementNumberOfChildren() override { + void incrementNumberOfChildren(int increment = 1) override { m_numberOfChildren+= increment; } + void decrementNumberOfChildren(int decrement = 1) override { assert(m_numberOfChildren > 0); - m_numberOfChildren--; + m_numberOfChildren-= decrement; } void eraseNumberOfChildren() override { m_numberOfChildren = 0; diff --git a/refs.h b/refs.h index 7135baceb..b5892885b 100644 --- a/refs.h +++ b/refs.h @@ -1,6 +1,7 @@ #include "addition_node.h" #include "allocation_failed_expression_node.h" #include "float_node.h" +#include "simplification_root_node.h" #include "char_layout_node.h" #include "horizontal_layout_node.h" diff --git a/test.cpp b/test.cpp index 98fdaeaa2..cd43a074b 100644 --- a/test.cpp +++ b/test.cpp @@ -232,7 +232,7 @@ void testSimplify() { FloatRef(2.0f)); assert_expression_approximates_to(a, 3); - + SimplificationRootRef b(a); a.deepReduce(); assert_expression_approximates_to(a, 3); @@ -277,7 +277,8 @@ int main() { runTest(testPoolExpressionAllocationFail); runTest(testPoolExpressionAllocationFail2); runTest(testPoolExpressionAllocationFailOnImbricatedAdditions); - //runTest(testStealOperand); + runTest(testStealOperand); + runTest(testSimplify); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_node.h b/tree_node.h index 1bf1de357..0d73a11bd 100644 --- a/tree_node.h +++ b/tree_node.h @@ -51,8 +51,8 @@ public: TreeNode * parentTree() const; TreeNode * editableRootTree(); virtual int numberOfChildren() const = 0; - virtual void incrementNumberOfChildren() {} //TODO Put an assert false - virtual void decrementNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? + virtual void incrementNumberOfChildren(int increment = 1) {} //TODO Put an assert false + virtual void decrementNumberOfChildren(int decrement = 1) {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? virtual void eraseNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? int numberOfDescendants(bool includeSelf) const; TreeNode * childTreeAtIndex(int i) const; diff --git a/tree_pool.h b/tree_pool.h index 0ae8bf3c1..11d8c71de 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -141,7 +141,7 @@ private: // Pool memory void * alloc(size_t size); void dealloc(TreeNode * ptr); - static inline bool insert(char * destination, char * source, size_t length); + bool insert(char * destination, char * source, size_t length); void moveNodes(TreeNode * source, TreeNode * destination, size_t moveLength); // Identifiers diff --git a/tree_reference.h b/tree_reference.h index 55223f73c..a9c25bde2 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -61,8 +61,8 @@ public: bool isAllocationFailure() const { return node()->isAllocationFailure(); } int nodeRetainCount() const { return node()->retainCount(); } - void incrementNumberOfChildren() { return node()->incrementNumberOfChildren(); } - void decrementNumberOfChildren() { return node()->decrementNumberOfChildren(); } + void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } + void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } operator TreeReference() const { return TreeReference(this->node()); @@ -209,11 +209,14 @@ public: void mergeChildren(TreeReference t) { // Steal operands - TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()); + int numberOfNewChildren = t.numberOfChildren(); + TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()->next()); + t.node()->eraseNumberOfChildren(); // If t is a child, remove it if (node()->hasChild(t.node())) { removeChild(t); } + node()->incrementNumberOfChildren(numberOfNewChildren); } protected: From 958baee216fc4ba30e587f667d2dbd2aeb8f742b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 29 Jun 2018 20:40:05 +0200 Subject: [PATCH 069/156] Continuing simplification --- addition_node.h | 3 +++ expression_node.cpp | 4 ++++ expression_node.h | 2 ++ expression_reference.h | 17 +++++++++++++++++ test.cpp | 23 +++++++++++++++++++++++ tree_reference.h | 2 +- 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/addition_node.h b/addition_node.h index 7c7d1cecc..814f65ea3 100644 --- a/addition_node.h +++ b/addition_node.h @@ -40,6 +40,9 @@ public: i++; } + // Step 2: Sort the operands + sortChildren(); + return false; } diff --git a/expression_node.cpp b/expression_node.cpp index ff3194342..e392a95a6 100644 --- a/expression_node.cpp +++ b/expression_node.cpp @@ -5,3 +5,7 @@ TreeNode * ExpressionNode::FailedAllocationStaticNode() { return ExpressionRef::FailedAllocationStaticNode(); } + +void ExpressionNode::sortChildren() { + ExpressionRef(this).sortChildren(); +} diff --git a/expression_node.h b/expression_node.h index d0e45c238..68f3bef32 100644 --- a/expression_node.h +++ b/expression_node.h @@ -46,6 +46,8 @@ public: // Hierarchy ExpressionNode * child(int i) { return static_cast(childTreeAtIndex(i)); } +protected: + void sortChildren(); }; #endif diff --git a/expression_reference.h b/expression_reference.h index 3b2c460b1..0702d4790 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -38,6 +38,23 @@ public: void shallowReduce() { return this->castedNode()->shallowReduce(); } + + void sortChildren() { + for (int i = this->numberOfChildren()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < this->numberOfChildren()-1; j++) { + if (this->childAtIndex(j).castedNode()->type() > this->childAtIndex(j+1).castedNode()->type()) { + this->swapChildren(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } + } + } + + }; typedef ExpressionReference ExpressionRef; diff --git a/test.cpp b/test.cpp index cd43a074b..7da9b9b95 100644 --- a/test.cpp +++ b/test.cpp @@ -239,6 +239,28 @@ void testSimplify() { assert(a.numberOfChildren() == 3); } +void testChildSort() { + printf("Child sort test\n"); + + AdditionRef a( + AdditionRef( + FloatRef(1.0f), + FloatRef(2.0f)), + FloatRef(3.0f)); + a.addChild(FloatRef(0.0f)); + + assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(1).castedNode()->type() == ExpressionNode::Type::Addition); + assert(a.childAtIndex(2).castedNode()->type() == ExpressionNode::Type::Float); + + a.sortChildren(); + + assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(1).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(2).castedNode()->type() == ExpressionNode::Type::Addition); +} + + void testPoolLayoutAllocationFail() { printf("Pool layout allocation fail test\n"); @@ -279,6 +301,7 @@ int main() { runTest(testPoolExpressionAllocationFailOnImbricatedAdditions); runTest(testStealOperand); runTest(testSimplify); + runTest(testChildSort); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } diff --git a/tree_reference.h b/tree_reference.h index a9c25bde2..c28123e8a 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -13,7 +13,7 @@ template class TreeReference { friend class TreeNode; friend class AdditionNode; - + friend class ExpressionNode; friend class Cursor; template friend class TreeReference; From 25901330401373fb24eda6cda0585d024f61b401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 11:13:13 +0200 Subject: [PATCH 070/156] Layout allocation fail test --- test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.cpp b/test.cpp index 7da9b9b95..e606fcb3a 100644 --- a/test.cpp +++ b/test.cpp @@ -278,8 +278,7 @@ void testPoolLayoutAllocationFail() { // Allocation fail CharLayoutRef char11('a'); - /*Expression e = ; - e.simplify*/ + assert(strcmp(char11.node()->description(), "Allocation Failed") == 0); } typedef void (test)(); @@ -302,6 +301,7 @@ int main() { runTest(testStealOperand); runTest(testSimplify); runTest(testChildSort); + runTest(testPoolLayoutAllocationFail); printf("\n*******************\nEnd of tests\n*******************\n\n"); return 0; } From 9fc488f22f53ea9297b1433242da7d9aca263463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 11:49:01 +0200 Subject: [PATCH 071/156] Continue addition simplification --- addition_node.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++++ addition_node.h | 25 +----------------------- float_node.h | 5 ++++- test.cpp | 4 +++- tree_node.cpp | 10 ++++++++++ tree_node.h | 2 ++ 6 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 addition_node.cpp diff --git a/addition_node.cpp b/addition_node.cpp new file mode 100644 index 000000000..78bf1c70f --- /dev/null +++ b/addition_node.cpp @@ -0,0 +1,48 @@ +#include "addition_node.h" +#include "float_node.h" + +bool AdditionNode::shallowReduce() { + if (ExpressionNode::shallowReduce()) { + return true; + } + /* Step 1: Addition is associative, so let's start by merging children which + * also are additions themselves. */ + int i = 0; + int initialNumberOfChildren = numberOfChildren(); + while (i < initialNumberOfChildren) { + ExpressionNode * currentChild = child(i); + if (currentChild->type() == Type::Addition) { + TreeRef(this).mergeChildren(TreeRef(currentChild)); + // Is it ok to modify memory while executing ? + continue; + } + i++; + } + + // Step 2: Sort the operands + sortChildren(); + + /* Step 3: Factorize like terms. Thanks to the simplification order, those are + * next to each other at this point. */ + i = 0; + while (i < numberOfChildren()-1) { + ExpressionNode * e1 = child(i); + ExpressionNode * e2 = child(i+1); + if (e1->type() == Type::Float && e2->type() == Type::Float) { + float sum = e1->approximate() + e2->approximate(); + // Remove first e2 then e1, else the pointers change + removeChild(e2); + removeChild(e1); + FloatRef f(sum); + addChildAtIndex(f.node(), i); + continue; + } + /*if (TermsHaveIdenticalNonRationalFactors(e1, e2)) { //TODO + factorizeOperands(e1, e2); //TODO + continue; + }*/ + i++; + } + + return false; +} diff --git a/addition_node.h b/addition_node.h index 814f65ea3..a833195cd 100644 --- a/addition_node.h +++ b/addition_node.h @@ -22,30 +22,7 @@ public: return result; } - bool shallowReduce() override { - if (ExpressionNode::shallowReduce()) { - return true; - } - /* Step 1: Addition is associative, so let's start by merging children which - * also are additions themselves. */ - int i = 0; - int initialNumberOfChildren = numberOfChildren(); - while (i < initialNumberOfChildren) { - ExpressionNode * currentChild = child(i); - if (currentChild->type() == Type::Addition) { - TreeRef(this).mergeChildren(TreeRef(currentChild)); - // Is it ok to modify memory while executing ? - continue; - } - i++; - } - - // Step 2: Sort the operands - sortChildren(); - - return false; - } - + bool shallowReduce() override; int numberOfChildren() const override { return m_numberOfChildren; } void incrementNumberOfChildren(int increment = 1) override { m_numberOfChildren+= increment; } void decrementNumberOfChildren(int decrement = 1) override { diff --git a/float_node.h b/float_node.h index 927aaeec4..87f648ffc 100644 --- a/float_node.h +++ b/float_node.h @@ -6,7 +6,10 @@ class FloatNode : public ExpressionNode { public: - FloatNode() : ExpressionNode() {} + FloatNode(float value = 0) : + ExpressionNode(), + m_value(value) + {} size_t size() const override { return sizeof(FloatNode); } Type type() const override { return Type::Float; } int numberOfChildren() const override { return 0; } diff --git a/test.cpp b/test.cpp index e606fcb3a..0be075366 100644 --- a/test.cpp +++ b/test.cpp @@ -236,7 +236,9 @@ void testSimplify() { a.deepReduce(); assert_expression_approximates_to(a, 3); - assert(a.numberOfChildren() == 3); + assert(a.numberOfChildren() == 1); + assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(0).castedNode()->approximate() == 3.0f); } void testChildSort() { diff --git a/tree_node.cpp b/tree_node.cpp index 94ed1441f..2802aa398 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -181,3 +181,13 @@ void TreeNode::replaceWithAllocationFailure() { t.replaceWithAllocationFailure(); // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? } + +void TreeNode::addChildAtIndex(TreeNode * t, int index) { + TreeRef tr(this); + tr.addChildAtIndex(TreeRef(t), index); +} + +void TreeNode::removeChild(TreeNode * t) { + TreeRef tr(this); + tr.removeChild(TreeRef(t)); +} diff --git a/tree_node.h b/tree_node.h index 0d73a11bd..cdcf854fd 100644 --- a/tree_node.h +++ b/tree_node.h @@ -139,6 +139,8 @@ public: // Hierarchy operations void replaceWithAllocationFailure(); + void addChildAtIndex(TreeNode * t, int index); + void removeChild(TreeNode * t); protected: TreeNode() : From 38cd5332f8cf2b6e8cb6851f176791890a7e89b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 11:56:53 +0200 Subject: [PATCH 072/156] Remove old code --- addition_node.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/addition_node.h b/addition_node.h index a833195cd..00edffee3 100644 --- a/addition_node.h +++ b/addition_node.h @@ -32,14 +32,7 @@ public: void eraseNumberOfChildren() override { m_numberOfChildren = 0; } -/* - Expression simplify() override { - // Scan operands, merge constants - Addition a = wrapped(this); - if (operand(0)->type() == Integer && operand(1)->type() == Integer) { - } - } - */ + private: int m_numberOfChildren; }; From 882e81e4dbbcf894b0367f7d0c2807149b25110a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 13:12:04 +0200 Subject: [PATCH 073/156] Remove Nodes' init method: assert node is not allocationFailure instead --- char_layout_node.h | 4 +++- float_node.h | 5 +++-- tree_node.h | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/char_layout_node.h b/char_layout_node.h index 71efb07b1..44b8c1e62 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -50,7 +50,9 @@ private: class CharLayoutRef : public LayoutReference { public: CharLayoutRef(char c) : LayoutReference() { - this->castedNode()->setChar(c); //TODO use init + if (!(this->node()->isAllocationFailure())) { + this->castedNode()->setChar(c); + } } }; diff --git a/float_node.h b/float_node.h index 87f648ffc..da9cf2851 100644 --- a/float_node.h +++ b/float_node.h @@ -18,7 +18,6 @@ public: return m_value > 1 ? "BigFloat" : "SmallFloat"; } void setFloat(float f) { m_value = f; } - void init(float f) override { m_value = f; } private: float m_value; }; @@ -26,7 +25,9 @@ private: class FloatRef : public ExpressionReference { public: FloatRef(float f) : ExpressionReference() { - this->node()->init(f); + if (!(this->node()->isAllocationFailure())) { + this->castedNode()->setFloat(f); + } } }; diff --git a/tree_node.h b/tree_node.h index cdcf854fd..1cc3b26ba 100644 --- a/tree_node.h +++ b/tree_node.h @@ -37,7 +37,6 @@ public: } // Node operations - virtual void init(float f) {} void retain() { m_referenceCounter++; } void release(); void releaseChildren(); From 253db1ac2c5e75f2708e7bb79d03108e97237970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 14:12:03 +0200 Subject: [PATCH 074/156] castedNode() -> typedNode() --- char_layout_node.h | 2 +- expression_reference.h | 8 ++++---- float_node.h | 2 +- layout_cursor.cpp | 8 ++++---- layout_reference.cpp | 2 +- layout_reference.h | 4 ++-- test.cpp | 16 ++++++++-------- tree_reference.h | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/char_layout_node.h b/char_layout_node.h index 44b8c1e62..329774c7d 100644 --- a/char_layout_node.h +++ b/char_layout_node.h @@ -51,7 +51,7 @@ class CharLayoutRef : public LayoutReference { public: CharLayoutRef(char c) : LayoutReference() { if (!(this->node()->isAllocationFailure())) { - this->castedNode()->setChar(c); + this->typedNode()->setChar(c); } } }; diff --git a/expression_reference.h b/expression_reference.h index 0702d4790..c85781448 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -28,22 +28,22 @@ public: } float approximate() const { - return this->castedNode()->approximate(); + return this->typedNode()->approximate(); } void deepReduce() { - return this->castedNode()->deepReduce(); + return this->typedNode()->deepReduce(); } void shallowReduce() { - return this->castedNode()->shallowReduce(); + return this->typedNode()->shallowReduce(); } void sortChildren() { for (int i = this->numberOfChildren()-1; i > 0; i--) { bool isSorted = true; for (int j = 0; j < this->numberOfChildren()-1; j++) { - if (this->childAtIndex(j).castedNode()->type() > this->childAtIndex(j+1).castedNode()->type()) { + if (this->childAtIndex(j).typedNode()->type() > this->childAtIndex(j+1).typedNode()->type()) { this->swapChildren(j, j+1); isSorted = false; } diff --git a/float_node.h b/float_node.h index da9cf2851..22a9d177c 100644 --- a/float_node.h +++ b/float_node.h @@ -26,7 +26,7 @@ class FloatRef : public ExpressionReference { public: FloatRef(float f) : ExpressionReference() { if (!(this->node()->isAllocationFailure())) { - this->castedNode()->setFloat(f); + this->typedNode()->setFloat(f); } } }; diff --git a/layout_cursor.cpp b/layout_cursor.cpp index aff142e85..2b65f2eaa 100644 --- a/layout_cursor.cpp +++ b/layout_cursor.cpp @@ -20,19 +20,19 @@ int LayoutCursor::middleLeftPoint() { /* Move */ void LayoutCursor::moveLeft(bool * shouldRecomputeLayout) { - layoutReference().castedNode()->moveCursorLeft(this, shouldRecomputeLayout); + layoutReference().typedNode()->moveCursorLeft(this, shouldRecomputeLayout); } void LayoutCursor::moveRight(bool * shouldRecomputeLayout) { - layoutReference().castedNode()->moveCursorRight(this, shouldRecomputeLayout); + layoutReference().typedNode()->moveCursorRight(this, shouldRecomputeLayout); } void LayoutCursor::moveAbove(bool * shouldRecomputeLayout) { - layoutReference().castedNode()->moveCursorUp(this, shouldRecomputeLayout); + layoutReference().typedNode()->moveCursorUp(this, shouldRecomputeLayout); } void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { - layoutReference().castedNode()->moveCursorDown(this, shouldRecomputeLayout); + layoutReference().typedNode()->moveCursorDown(this, shouldRecomputeLayout); } diff --git a/layout_reference.cpp b/layout_reference.cpp index 42c6455d8..587dd6c8f 100644 --- a/layout_reference.cpp +++ b/layout_reference.cpp @@ -16,7 +16,7 @@ TreeNode * LayoutRef::FailedAllocationStaticNode() { template LayoutCursor LayoutReference::cursor() const { - return LayoutCursor(this->castedNode()); + return LayoutCursor(this->typedNode()); } template LayoutCursor LayoutReference::cursor() const; diff --git a/layout_reference.h b/layout_reference.h index 521a41997..547128dc1 100644 --- a/layout_reference.h +++ b/layout_reference.h @@ -32,11 +32,11 @@ public: } int layoutOrigin() { - return this->castedNode()->layoutOrigin(); + return this->typedNode()->layoutOrigin(); } int absoluteOrigin() { - return this->castedNode()->absoluteOrigin(); + return this->typedNode()->absoluteOrigin(); } }; diff --git a/test.cpp b/test.cpp index 0be075366..0ccbb6c98 100644 --- a/test.cpp +++ b/test.cpp @@ -237,8 +237,8 @@ void testSimplify() { assert_expression_approximates_to(a, 3); assert(a.numberOfChildren() == 1); - assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); - assert(a.childAtIndex(0).castedNode()->approximate() == 3.0f); + assert(a.childAtIndex(0).typedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(0).typedNode()->approximate() == 3.0f); } void testChildSort() { @@ -251,15 +251,15 @@ void testChildSort() { FloatRef(3.0f)); a.addChild(FloatRef(0.0f)); - assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); - assert(a.childAtIndex(1).castedNode()->type() == ExpressionNode::Type::Addition); - assert(a.childAtIndex(2).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(0).typedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(1).typedNode()->type() == ExpressionNode::Type::Addition); + assert(a.childAtIndex(2).typedNode()->type() == ExpressionNode::Type::Float); a.sortChildren(); - assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); - assert(a.childAtIndex(1).castedNode()->type() == ExpressionNode::Type::Float); - assert(a.childAtIndex(2).castedNode()->type() == ExpressionNode::Type::Addition); + assert(a.childAtIndex(0).typedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(1).typedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(2).typedNode()->type() == ExpressionNode::Type::Addition); } diff --git a/tree_reference.h b/tree_reference.h index c28123e8a..0143a4bf2 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -68,10 +68,10 @@ public: return TreeReference(this->node()); } - T * castedNode() const { + T * typedNode() const { // TODO: Here, assert that the node type is indeed T // ?? Might be allocation failure, not T - return static_cast(TreePool::sharedPool()->node(m_identifier)); + return static_cast(node()); } TreeNode * node() const { @@ -163,7 +163,7 @@ public: TreeReference p = parent(); int indexInParentNode = node()->indexInParent(); int currentRetainCount = node()->retainCount(); - TreeNode * staticAllocFailNode = castedNode()->failedAllocationStaticNode(); + TreeNode * staticAllocFailNode = typedNode()->failedAllocationStaticNode(); // Move the node to the end of the pool and decrease children count of parent TreePool::sharedPool()->move(node(), TreePool::sharedPool()->last()); From 8bf0923ce6e2acbabedcf4cfa8f14427fc3b60b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 14:47:15 +0200 Subject: [PATCH 075/156] Add pool log test method --- test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test.cpp b/test.cpp index 0ccbb6c98..3c186f9e8 100644 --- a/test.cpp +++ b/test.cpp @@ -1,6 +1,10 @@ #include "refs.h" #include +void logPool() { + TreePool::sharedPool()->log(); +} + void assert_expression_approximates_to(ExpressionRef e, float result) { float b = e.approximate(); if (b > result) { From 77334bc36f0f455c719d970f465e6879410972f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 14:48:02 +0200 Subject: [PATCH 076/156] Remove SimplificationRoot. Simplify now returns a reference to the result. --- expression_node.h | 1 - expression_reference.h | 6 ++++-- refs.h | 1 - simplification_root_node.h | 27 --------------------------- test.cpp | 14 ++++++-------- tree_node.h | 8 ++++++++ tree_reference.h | 4 +++- 7 files changed, 21 insertions(+), 40 deletions(-) delete mode 100644 simplification_root_node.h diff --git a/expression_node.h b/expression_node.h index 68f3bef32..a28355874 100644 --- a/expression_node.h +++ b/expression_node.h @@ -17,7 +17,6 @@ public: virtual float approximate() = 0; void deepReduce() { - assert(parentTree() != nullptr); for (int i = 0; i < numberOfChildren(); i++) { child(i)->deepReduce(); } diff --git a/expression_reference.h b/expression_reference.h index c85781448..e9ce93dd6 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -31,8 +31,10 @@ public: return this->typedNode()->approximate(); } - void deepReduce() { - return this->typedNode()->deepReduce(); + ExpressionReference deepReduce() { + ExpressionReference result = ExpressionReference(this->clone().node()); + result.typedNode()->deepReduce(); + return result; } void shallowReduce() { diff --git a/refs.h b/refs.h index b5892885b..7135baceb 100644 --- a/refs.h +++ b/refs.h @@ -1,7 +1,6 @@ #include "addition_node.h" #include "allocation_failed_expression_node.h" #include "float_node.h" -#include "simplification_root_node.h" #include "char_layout_node.h" #include "horizontal_layout_node.h" diff --git a/simplification_root_node.h b/simplification_root_node.h deleted file mode 100644 index 3d641052e..000000000 --- a/simplification_root_node.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SIMPLIFICATION_ROOT_NODE_H -#define SIMPLIFICATION_ROOT_NODE_H - -#include "expression_reference.h" -#include "expression_node.h" - -class SimplificationRootNode : public ExpressionNode { -public: - SimplificationRootNode() : ExpressionNode() {} - size_t size() const override { return sizeof(SimplificationRootNode); } - Type type() const override { return Type::SimplificationRoot; } - int numberOfChildren() const override { return 1; } - float approximate() override { assert(false); return -1; } - const char * description() const override { return "Simplification root"; } -}; - -class SimplificationRootRef : public ExpressionReference { -public: - using ExpressionReference::ExpressionReference; - SimplificationRootRef(ExpressionRef c) : - SimplificationRootRef() - { - addChild(c); - } -}; - -#endif diff --git a/test.cpp b/test.cpp index 3c186f9e8..e8b39ba1d 100644 --- a/test.cpp +++ b/test.cpp @@ -227,8 +227,7 @@ void testStealOperand() { } void testSimplify() { - printf("Symplify test\n"); - + printf("Simplify test\n"); AdditionRef a( AdditionRef( FloatRef(0.0f), @@ -236,13 +235,12 @@ void testSimplify() { FloatRef(2.0f)); assert_expression_approximates_to(a, 3); - SimplificationRootRef b(a); - a.deepReduce(); - + ExpressionRef b = a.deepReduce(); assert_expression_approximates_to(a, 3); - assert(a.numberOfChildren() == 1); - assert(a.childAtIndex(0).typedNode()->type() == ExpressionNode::Type::Float); - assert(a.childAtIndex(0).typedNode()->approximate() == 3.0f); + assert_expression_approximates_to(b, 3); + assert(b.numberOfChildren() == 1); + assert(b.childAtIndex(0).typedNode()->type() == ExpressionNode::Type::Float); + assert(b.childAtIndex(0).typedNode()->approximate() == 3.0f); } void testChildSort() { diff --git a/tree_node.h b/tree_node.h index 1cc3b26ba..f02f6b6bf 100644 --- a/tree_node.h +++ b/tree_node.h @@ -23,6 +23,14 @@ public: int identifier() const { return m_identifier; } int retainCount() const { return m_referenceCounter; } void setReferenceCounter(int refCount) { m_referenceCounter = refCount; } //TODO make this method privte with only friends that can access it + + void deepResetReferenceCounter() { //TODO make this method private with friends that can access it + setReferenceCounter(0); + for (TreeNode * t : depthFirstChildren()) { + t->setReferenceCounter(1); + } + } + virtual const char * description() const { return "UNKNOWN"; } diff --git a/tree_reference.h b/tree_reference.h index 0143a4bf2..e6a69afd7 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -46,6 +46,7 @@ public: return TreeReference(TreePool::sharedPool()->node(allocationFailureNodeId)); } TreeNode * nodeCopy = TreePool::sharedPool()->deepCopy(myNode); + nodeCopy->deepResetReferenceCounter(); return TreeReference(nodeCopy); } @@ -161,7 +162,8 @@ public: void replaceWithAllocationFailure() { TreeReference p = parent(); - int indexInParentNode = node()->indexInParent(); + bool hasParent = p.isDefined(); + int indexInParentNode = hasParent ? node()->indexInParent() : -1; int currentRetainCount = node()->retainCount(); TreeNode * staticAllocFailNode = typedNode()->failedAllocationStaticNode(); From 02c17907686eac21dc25787aab155bb8349e4a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 15:59:43 +0200 Subject: [PATCH 077/156] [tree] Finish the merge --- apps/Makefile | 1 + apps/main.cpp | 9 +++++++++ apps/tree/Makefile | 11 +++++++++++ apps/tree/expression_node.h | 1 + apps/tree/layout_cursor.h | 2 ++ apps/tree/test.cpp | 30 ++++++++++++++++++++++++++++++ apps/tree/tree_pool.cpp | 5 +++++ apps/tree/tree_pool.h | 3 ++- apps/tree/tree_reference.h | 15 ++++++++------- 9 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 apps/tree/Makefile diff --git a/apps/Makefile b/apps/Makefile index 6249c5f29..ab85bc844 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -3,6 +3,7 @@ include apps/home/Makefile include apps/on_boarding/Makefile include apps/hardware_test/Makefile include apps/usb/Makefile +include apps/tree/Makefile snapshots = # All selected apps are included. Each Makefile below is responsible for setting diff --git a/apps/main.cpp b/apps/main.cpp index 9c2adde8b..17641bbb9 100644 --- a/apps/main.cpp +++ b/apps/main.cpp @@ -1,6 +1,14 @@ #include "apps_container_storage.h" #include "global_preferences.h" +#include "tree/test.cpp" + + +void ion_main(int argc, char * argv[]) { + Test::main(); +} + +#if 0 void ion_main(int argc, char * argv[]) { #if EPSILON_GETOPT for (int i=1; irun(); } +#endif diff --git a/apps/tree/Makefile b/apps/tree/Makefile new file mode 100644 index 000000000..8366d07be --- /dev/null +++ b/apps/tree/Makefile @@ -0,0 +1,11 @@ +app_objs = $(addprefix apps/tree/,\ + addition_node.o\ + expression_node.o\ + expression_reference.o\ + layout_cursor.o\ + layout_node.o\ + layout_reference.o\ + tree_node.o\ + tree_pool.o\ +) + diff --git a/apps/tree/expression_node.h b/apps/tree/expression_node.h index a28355874..536fa8f37 100644 --- a/apps/tree/expression_node.h +++ b/apps/tree/expression_node.h @@ -2,6 +2,7 @@ #define EXPRESSION_NODE_H #include "tree_node.h" +#include class ExpressionNode : public TreeNode { public: diff --git a/apps/tree/layout_cursor.h b/apps/tree/layout_cursor.h index 9d7eaa6f8..0376c24bd 100644 --- a/apps/tree/layout_cursor.h +++ b/apps/tree/layout_cursor.h @@ -16,6 +16,7 @@ public: /* Debug */ void log() { +#if TREE_LOG printf("Pointed Layout id %d, cursor position ", m_layoutRef.identifier()); if (m_position == Position::Left) { printf("Left"); @@ -23,6 +24,7 @@ public: printf("Right"); } printf("\n"); +#endif } bool isDefined() const { return m_layoutRef.isDefined(); } diff --git a/apps/tree/test.cpp b/apps/tree/test.cpp index e8b39ba1d..42d7ca923 100644 --- a/apps/tree/test.cpp +++ b/apps/tree/test.cpp @@ -1,6 +1,8 @@ #include "refs.h" #include +namespace Test { + void logPool() { TreePool::sharedPool()->log(); } @@ -24,7 +26,9 @@ AdditionRef buildAddition() { } void testAddition() { +#if TREE_LOG printf("Addition test\n"); +#endif int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); AdditionRef a = buildAddition(); assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes + 3); @@ -52,14 +56,18 @@ void createNodes() { } void testPoolEmpties() { +#if TREE_LOG printf("Pool empties test\n"); +#endif int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); createNodes(); assert(TreePool::sharedPool()->numberOfNodes() == initialNumberOfNodes); } void testCursorCreateAndRetain() { +#if TREE_LOG printf("Cursor create and retain test\n"); +#endif int initialNumberOfNodes = TreePool::sharedPool()->numberOfNodes(); CharLayoutRef aChar('a'); CharLayoutRef bChar('b'); @@ -88,7 +96,9 @@ void testCursorCreateAndRetain() { } void testCursorMoveLeft() { +#if TREE_LOG printf("Cursor move left test\n"); +#endif CharLayoutRef aChar('a'); CharLayoutRef bChar('b'); HorizontalLayoutRef h(aChar, bChar); @@ -112,7 +122,9 @@ void testCursorMoveLeft() { } void testPoolExpressionAllocationFail() { +#if TREE_LOG printf("Pool expression allocation fail test\n"); +#endif // Fill the pool for size 256 FloatRef f1(0.0f); @@ -141,7 +153,9 @@ void testPoolExpressionAllocationFail() { } void testPoolExpressionAllocationFail2() { +#if TREE_LOG printf("Pool expression allocation multiple fail test\n"); +#endif // Fill the pool for size 256 FloatRef f1(0.0f); @@ -175,7 +189,9 @@ void testPoolExpressionAllocationFail2() { } void testPoolExpressionAllocationFailOnImbricatedAdditions() { +#if TREE_LOG printf("Pool expression allocation fail second test\n"); +#endif // Fill the pool for size 256 FloatRef f1(0.0f); @@ -206,7 +222,9 @@ void testPoolExpressionAllocationFailOnImbricatedAdditions() { } void testStealOperand() { +#if TREE_LOG printf("Steal operand test\n"); +#endif FloatRef f1(0.0f); FloatRef f2(1.0f); @@ -227,7 +245,9 @@ void testStealOperand() { } void testSimplify() { +#if TREE_LOG printf("Simplify test\n"); +#endif AdditionRef a( AdditionRef( FloatRef(0.0f), @@ -244,7 +264,9 @@ void testSimplify() { } void testChildSort() { +#if TREE_LOG printf("Child sort test\n"); +#endif AdditionRef a( AdditionRef( @@ -266,7 +288,9 @@ void testChildSort() { void testPoolLayoutAllocationFail() { +#if TREE_LOG printf("Pool layout allocation fail test\n"); +#endif // Fill the pool for size 256 CharLayoutRef char1('a'); @@ -293,7 +317,9 @@ void runTest(test t) { } int main() { +#if TREE_LOG printf("\n*******************\nStart running tests\n*******************\n\n"); +#endif assert(TreePool::sharedPool()->numberOfNodes() == 0); runTest(testAddition); runTest(testPoolEmpties); @@ -306,6 +332,10 @@ int main() { runTest(testSimplify); runTest(testChildSort); runTest(testPoolLayoutAllocationFail); +#if TREE_LOG printf("\n*******************\nEnd of tests\n*******************\n\n"); +#endif return 0; } + +} diff --git a/apps/tree/tree_pool.cpp b/apps/tree/tree_pool.cpp index bd4b4b669..245d87da1 100644 --- a/apps/tree/tree_pool.cpp +++ b/apps/tree/tree_pool.cpp @@ -1,5 +1,6 @@ #include "tree_pool.h" #include +#include TreePool * TreePool::sharedPool() { static TreePool pool; @@ -31,6 +32,7 @@ static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { } void TreePool::logNodeForIdentifierArray() { +#if TREE_LOG printf("\n\n"); for (int i = 0; i < MaxNumberOfNodes; i++) { if (m_nodeForIdentifier[i] != nullptr) { @@ -38,6 +40,7 @@ void TreePool::logNodeForIdentifierArray() { } } printf("\n\n"); +#endif } void TreePool::move(TreeNode * source, TreeNode * destination) { @@ -83,6 +86,7 @@ void TreePool::moveNodes(TreeNode * source, TreeNode * destination, size_t moveS #include void TreePool::log() { +#if TREE_LOG printf("POOL:"); for (TreeNode * node : *this) { printf("|(%03d|%s|%03d|%p)", node->m_identifier, node->description(), node->retainCount(), node); @@ -90,6 +94,7 @@ void TreePool::log() { printf("|\n"); //logNodeForIdentifierArray(); +#endif } void * TreePool::alloc(size_t size) { diff --git a/apps/tree/tree_pool.h b/apps/tree/tree_pool.h index 11d8c71de..6f6b40c90 100644 --- a/apps/tree/tree_pool.h +++ b/apps/tree/tree_pool.h @@ -1,8 +1,9 @@ #ifndef TREE_POOL_H #define TREE_POOL_H -#include #include "tree_node.h" +#include +#include #include class TreePool { diff --git a/apps/tree/tree_reference.h b/apps/tree/tree_reference.h index e6a69afd7..f8386b470 100644 --- a/apps/tree/tree_reference.h +++ b/apps/tree/tree_reference.h @@ -221,19 +221,20 @@ public: node()->incrementNumberOfChildren(numberOfNewChildren); } -protected: - TreeReference() { - TreeNode * node = TreePool::sharedPool()->createTreeNode(); - m_identifier = node->identifier(); - } - - TreeReference(TreeNode * node) { + TreeReference(TreeNode * node) { // TODO Make this protected if (node == nullptr) { m_identifier = -1; } else { setIdentifierAndRetain(node->identifier()); } } + +protected: + TreeReference() { + TreeNode * node = TreePool::sharedPool()->createTreeNode(); + m_identifier = node->identifier(); + } + void setIdentifierAndRetain(int newId) { m_identifier = newId; node()->retain(); From f3baee9dd0d8d6c777dbd17ce38b2ec5d380eb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 17:03:14 +0200 Subject: [PATCH 078/156] [tree] Move tree files to Poincare --- poincare/include/poincare.h | 9 +++++++++ .../poincare}/allocation_failed_layout_node.h | 8 ++++++-- .../include/poincare}/char_layout_node.h | 14 +++++++++----- .../include/poincare}/horizontal_layout_node.h | 8 ++++++-- .../include/poincare}/layout_cursor.h | 8 ++++++-- .../include/poincare}/layout_node.h | 8 ++++++-- .../include/poincare}/layout_reference.h | 8 ++++++-- .../tree => poincare/include/poincare}/tree_node.h | 8 ++++++-- .../tree => poincare/include/poincare}/tree_pool.h | 8 ++++++-- .../include/poincare}/tree_reference.h | 8 ++++++-- 10 files changed, 66 insertions(+), 21 deletions(-) rename {apps/tree => poincare/include/poincare}/allocation_failed_layout_node.h (82%) rename {apps/tree => poincare/include/poincare}/char_layout_node.h (87%) rename {apps/tree => poincare/include/poincare}/horizontal_layout_node.h (96%) rename {apps/tree => poincare/include/poincare}/layout_cursor.h (94%) rename {apps/tree => poincare/include/poincare}/layout_node.h (96%) rename {apps/tree => poincare/include/poincare}/layout_reference.h (91%) rename {apps/tree => poincare/include/poincare}/tree_node.h (98%) rename {apps/tree => poincare/include/poincare}/tree_pool.h (98%) rename {apps/tree => poincare/include/poincare}/tree_reference.h (98%) diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 279682893..00e756870 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -5,10 +5,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -35,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +46,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -72,6 +78,9 @@ #include #include #include +#include +#include +#include #include #include diff --git a/apps/tree/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h similarity index 82% rename from apps/tree/allocation_failed_layout_node.h rename to poincare/include/poincare/allocation_failed_layout_node.h index d41c329ed..64f78adf0 100644 --- a/apps/tree/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -1,9 +1,11 @@ -#ifndef ALLOCATION_FAILED_LAYOUT_NODE_H -#define ALLOCATION_FAILED_LAYOUT_NODE_H +#ifndef POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H +#define POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H #include "layout_node.h" #include "layout_reference.h" +namespace Poincare { + class AllocationFailedLayoutNode : public LayoutNode { public: // TreeNode @@ -18,4 +20,6 @@ public: AllocationFailedLayoutRef() : LayoutReference() {} }; +} + #endif diff --git a/apps/tree/char_layout_node.h b/poincare/include/poincare/char_layout_node.h similarity index 87% rename from apps/tree/char_layout_node.h rename to poincare/include/poincare/char_layout_node.h index 329774c7d..c2eee9789 100644 --- a/apps/tree/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -1,9 +1,11 @@ -#ifndef CHAR_LAYOUT_H -#define CHAR_LAYOUT_H +#ifndef POINCARE_CHAR_LAYOUT_NODE_H +#define POINCARE_CHAR_LAYOUT_NODE_H -#include "layout_reference.h" -#include "layout_node.h" -#include "layout_cursor.h" +#include +#include +#include + +namespace Poincare { class CharLayoutNode : public LayoutNode { public: @@ -56,4 +58,6 @@ public: } }; +} + #endif diff --git a/apps/tree/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h similarity index 96% rename from apps/tree/horizontal_layout_node.h rename to poincare/include/poincare/horizontal_layout_node.h index 53d332976..4f4647b7c 100644 --- a/apps/tree/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -1,10 +1,12 @@ -#ifndef HORIZONTAL_LAYOUT_H -#define HORIZONTAL_LAYOUT_H +#ifndef POINCARE_HORIZONTAL_LAYOUT_NODE_H +#define POINCARE_HORIZONTAL_LAYOUT_NODE_H #include "layout_reference.h" #include "layout_node.h" #include "layout_cursor.h" +namespace Poincare { + class HorizontalLayoutNode : public LayoutNode { public: HorizontalLayoutNode() : @@ -94,4 +96,6 @@ public: } }; +} + #endif diff --git a/apps/tree/layout_cursor.h b/poincare/include/poincare/layout_cursor.h similarity index 94% rename from apps/tree/layout_cursor.h rename to poincare/include/poincare/layout_cursor.h index 0376c24bd..ac4693af3 100644 --- a/apps/tree/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -1,10 +1,12 @@ -#ifndef LAYOUT_CURSOR_H -#define LAYOUT_CURSOR_H +#ifndef POINCARE_LAYOUT_CURSOR_H +#define POINCARE_LAYOUT_CURSOR_H #include "layout_reference.h" #include "layout_node.h" #include +namespace Poincare { + class LayoutCursor { template friend class LayoutReference; @@ -64,4 +66,6 @@ private: Position m_position; }; +} + #endif diff --git a/apps/tree/layout_node.h b/poincare/include/poincare/layout_node.h similarity index 96% rename from apps/tree/layout_node.h rename to poincare/include/poincare/layout_node.h index 7aa421a7e..49a8ab656 100644 --- a/apps/tree/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -1,8 +1,10 @@ -#ifndef LAYOUT_NODE_H -#define LAYOUT_NODE_H +#ifndef POINCARE_LAYOUT_NODE_H +#define POINCARE_LAYOUT_NODE_H #include "tree_node.h" +namespace Poincare { + class LayoutCursor; class LayoutNode : public TreeNode { @@ -64,4 +66,6 @@ private: virtual void render() {}; }; +} + #endif diff --git a/apps/tree/layout_reference.h b/poincare/include/poincare/layout_reference.h similarity index 91% rename from apps/tree/layout_reference.h rename to poincare/include/poincare/layout_reference.h index 547128dc1..e23a01723 100644 --- a/apps/tree/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -1,9 +1,11 @@ -#ifndef LAYOUT_REFERENCE_H -#define LAYOUT_REFERENCE_H +#ifndef POINCARE_LAYOUT_REFERENCE_H +#define POINCARE_LAYOUT_REFERENCE_H #include "tree_reference.h" #include "layout_node.h" +namespace Poincare { + class LayoutCursor; template @@ -42,4 +44,6 @@ public: typedef LayoutReference LayoutRef; +} + #endif diff --git a/apps/tree/tree_node.h b/poincare/include/poincare/tree_node.h similarity index 98% rename from apps/tree/tree_node.h rename to poincare/include/poincare/tree_node.h index f02f6b6bf..497692629 100644 --- a/apps/tree/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -1,5 +1,5 @@ -#ifndef TREE_NODE_H -#define TREE_NODE_H +#ifndef POINCARE_TREE_NODE_H +#define POINCARE_TREE_NODE_H #include #include @@ -13,6 +13,8 @@ * - a reference counter */ +namespace Poincare { + class TreeNode { friend class TreePool; public: @@ -181,4 +183,6 @@ private: int m_referenceCounter; }; +} + #endif diff --git a/apps/tree/tree_pool.h b/poincare/include/poincare/tree_pool.h similarity index 98% rename from apps/tree/tree_pool.h rename to poincare/include/poincare/tree_pool.h index 6f6b40c90..83d4cd987 100644 --- a/apps/tree/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -1,11 +1,13 @@ -#ifndef TREE_POOL_H -#define TREE_POOL_H +#ifndef POINCARE_TREE_POOL_H +#define POINCARE_TREE_POOL_H #include "tree_node.h" #include #include #include +namespace Poincare { + class TreePool { friend class TreeNode; public: @@ -172,4 +174,6 @@ private: TreeNode * m_staticNodes[MaxNumberOfStaticNodes]; }; +} + #endif diff --git a/apps/tree/tree_reference.h b/poincare/include/poincare/tree_reference.h similarity index 98% rename from apps/tree/tree_reference.h rename to poincare/include/poincare/tree_reference.h index f8386b470..9d7556fa4 100644 --- a/apps/tree/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -1,9 +1,11 @@ -#ifndef TREE_REFERENCE_H -#define TREE_REFERENCE_H +#ifndef POINCARE_TREE_REFERENCE_H +#define POINCARE_TREE_REFERENCE_H #include "tree_pool.h" #include +namespace Poincare { + static inline int min(int i, int j) { return i < j ? i : j; } static inline int max(int i, int j) { return i > j ? i : j; } @@ -245,4 +247,6 @@ private: typedef TreeReference TreeRef; +} + #endif From c955292105364b38ef0b10a577a70ba0d0aa3905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 17:13:02 +0200 Subject: [PATCH 079/156] [poincare] Coninue tree migration --- poincare/Makefile | 5 +++++ {apps/tree => poincare/src}/layout_cursor.cpp | 8 +++++--- {apps/tree => poincare/src}/layout_node.cpp | 10 +++++++--- {apps/tree => poincare/src}/layout_reference.cpp | 14 +++++++++----- {apps/tree => poincare/src}/tree_node.cpp | 10 +++++++--- {apps/tree => poincare/src}/tree_pool.cpp | 6 +++++- 6 files changed, 38 insertions(+), 15 deletions(-) rename {apps/tree => poincare/src}/layout_cursor.cpp (90%) rename {apps/tree => poincare/src}/layout_node.cpp (85%) rename {apps/tree => poincare/src}/layout_reference.cpp (71%) rename {apps/tree => poincare/src}/tree_node.cpp (97%) rename {apps/tree => poincare/src}/tree_pool.cpp (98%) diff --git a/poincare/Makefile b/poincare/Makefile index fa1b389fa..765884a5f 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -47,7 +47,10 @@ objs += $(addprefix poincare/src/,\ imaginary_part.o\ integer.o\ integral.o\ + layout_cursor.o\ layout_engine.o\ + layout_node.o\ + layout_reference.o\ list_data.o\ least_common_multiple.o\ logarithm.o\ @@ -83,6 +86,8 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ + tree_node.o\ + tree_pool.o\ trigonometry.o\ undefined.o\ variable_context.o\ diff --git a/apps/tree/layout_cursor.cpp b/poincare/src/layout_cursor.cpp similarity index 90% rename from apps/tree/layout_cursor.cpp rename to poincare/src/layout_cursor.cpp index 2b65f2eaa..8fb4781b4 100644 --- a/apps/tree/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -1,7 +1,9 @@ -#include "layout_cursor.h" -#include "layout_reference.h" +#include +#include #include +namespace Poincare { + /* Comparison */ bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { @@ -35,4 +37,4 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { layoutReference().typedNode()->moveCursorDown(this, shouldRecomputeLayout); } - +} diff --git a/apps/tree/layout_node.cpp b/poincare/src/layout_node.cpp similarity index 85% rename from apps/tree/layout_node.cpp rename to poincare/src/layout_node.cpp index 064a2ca9a..21241de3e 100644 --- a/apps/tree/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -1,6 +1,8 @@ -#include "layout_node.h" -#include "allocation_failed_layout_node.h" -#include "layout_reference.h" +#include +#include +#include + +namespace Poincare { TreeNode * LayoutNode::FailedAllocationStaticNode() { return LayoutRef::FailedAllocationStaticNode(); @@ -36,3 +38,5 @@ int LayoutNode::absoluteOrigin() { return m_frame.origin();*/ return 1; } + +} diff --git a/apps/tree/layout_reference.cpp b/poincare/src/layout_reference.cpp similarity index 71% rename from apps/tree/layout_reference.cpp rename to poincare/src/layout_reference.cpp index 587dd6c8f..eb04ed627 100644 --- a/apps/tree/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -1,8 +1,10 @@ -#include "layout_reference.h" -#include "layout_cursor.h" -#include "allocation_failed_layout_node.h" -#include "layout_node.h" -#include "char_layout_node.h" +#include +#include +#include +#include +#include + +namespace Poincare { template<> TreeNode * LayoutRef::FailedAllocationStaticNode() { @@ -21,3 +23,5 @@ LayoutCursor LayoutReference::cursor() const { template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; + +} diff --git a/apps/tree/tree_node.cpp b/poincare/src/tree_node.cpp similarity index 97% rename from apps/tree/tree_node.cpp rename to poincare/src/tree_node.cpp index 2802aa398..7e59cdbad 100644 --- a/apps/tree/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -1,8 +1,10 @@ -#include "tree_node.h" -#include "tree_pool.h" -#include "tree_reference.h" +#include +#include +#include #include +namespace Poincare { + // Node operations void TreeNode::release() { @@ -191,3 +193,5 @@ void TreeNode::removeChild(TreeNode * t) { TreeRef tr(this); tr.removeChild(TreeRef(t)); } + +} diff --git a/apps/tree/tree_pool.cpp b/poincare/src/tree_pool.cpp similarity index 98% rename from apps/tree/tree_pool.cpp rename to poincare/src/tree_pool.cpp index 245d87da1..b547b1f00 100644 --- a/apps/tree/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -1,7 +1,9 @@ -#include "tree_pool.h" +#include #include #include +namespace Poincare { + TreePool * TreePool::sharedPool() { static TreePool pool; return &pool; @@ -151,3 +153,5 @@ bool TreePool::insert(char * destination, char * source, size_t length) { } return true; } + +} From 52a49f6bf710c54cc7029bd89d9c539aec4d2a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 17:31:43 +0200 Subject: [PATCH 080/156] [apps] Remove tree tests --- apps/Makefile | 1 - apps/main.cpp | 9 --------- 2 files changed, 10 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index ab85bc844..6249c5f29 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -3,7 +3,6 @@ include apps/home/Makefile include apps/on_boarding/Makefile include apps/hardware_test/Makefile include apps/usb/Makefile -include apps/tree/Makefile snapshots = # All selected apps are included. Each Makefile below is responsible for setting diff --git a/apps/main.cpp b/apps/main.cpp index 17641bbb9..9c2adde8b 100644 --- a/apps/main.cpp +++ b/apps/main.cpp @@ -1,14 +1,6 @@ #include "apps_container_storage.h" #include "global_preferences.h" -#include "tree/test.cpp" - - -void ion_main(int argc, char * argv[]) { - Test::main(); -} - -#if 0 void ion_main(int argc, char * argv[]) { #if EPSILON_GETOPT for (int i=1; irun(); } -#endif From d53abf5bf1a9481e8a395f033fab144df11ec3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 17:34:31 +0200 Subject: [PATCH 081/156] [poincare] Remove warning on unused variable --- poincare/include/poincare/tree_pool.h | 6 ++++-- poincare/src/tree_node.cpp | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 83d4cd987..e88ed52a4 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -65,9 +65,11 @@ public: int numberOfNodes() const { int count = 0; - AllPool nodes = const_cast(this)->allNodes(); - for (TreeNode * t : nodes) { + TreeNode * firstNode = first(); + TreeNode * lastNode = last(); + while (firstNode != lastNode) { count++; + firstNode = firstNode->next(); } return count; } diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 7e59cdbad..56c863bb3 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -93,8 +93,11 @@ TreeNode * TreeNode::editableRootTree() { int TreeNode::numberOfDescendants(bool includeSelf) const { int result = includeSelf ? 1 : 0; - for (TreeNode * child : depthFirstChildren()) { + TreeNode * nextSiblingNode = nextSibling(); + TreeNode * currentNode = next(); + while (currentNode != nextSiblingNode) { result++; + currentNode = currentNode->next(); } return result; } From 049cf772e2b1bd6ae9986e801d7680b5fa5795d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 10:02:29 +0200 Subject: [PATCH 082/156] [poincare] Adapt CharLayoutNode and HorizontalLayoutNode --- poincare/Makefile | 11 +- .../poincare/allocation_failed_layout_node.h | 17 +++ poincare/include/poincare/char_layout_node.h | 67 +++++------ .../include/poincare/horizontal_layout_node.h | 77 ++++--------- poincare/include/poincare/layout_cursor.h | 2 +- poincare/include/poincare/layout_node.h | 53 +++++++-- poincare/include/poincare/layout_reference.h | 4 +- poincare/src/char_layout_node.cpp | 45 ++++++++ poincare/src/horizontal_layout_node.cpp | 104 ++++++++++++++++++ poincare/src/layout_cursor.cpp | 4 +- poincare/src/layout_node.cpp | 64 +++++++---- 11 files changed, 325 insertions(+), 123 deletions(-) create mode 100644 poincare/src/char_layout_node.cpp create mode 100644 poincare/src/horizontal_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 765884a5f..66abfc415 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -3,6 +3,14 @@ SFLAGS += -Ipoincare/include #include poincare/src/simplify/Makefile #include poincare/src/simplification/Makefile +objs += $(addprefix poincare/src/,\ + char_layout_node.o\ + horizontal_layout_node.o\ + layout_cursor.o\ + layout_node.o\ + layout_reference.o\ +) + objs += $(addprefix poincare/src/,\ absolute_value.o\ addition.o\ @@ -47,10 +55,7 @@ objs += $(addprefix poincare/src/,\ imaginary_part.o\ integer.o\ integral.o\ - layout_cursor.o\ layout_engine.o\ - layout_node.o\ - layout_reference.o\ list_data.o\ least_common_multiple.o\ logarithm.o\ diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 64f78adf0..37c4fe2f7 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -8,11 +8,28 @@ namespace Poincare { class AllocationFailedLayoutNode : public LayoutNode { public: + // LayoutNode + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + assert(false); + return 0; + } // TreeNode size_t size() const override { return sizeof(AllocationFailedLayoutNode); } const char * description() const override { return "Allocation Failed"; } int numberOfChildren() const override { return 0; } bool isAllocationFailure() const override { return true; } + +protected: + // LayoutNode + void computeSize() override { m_sized = true; } + void computeBaseline() override { m_baselined = true; } + KDPoint positionOfChild(LayoutNode * child) override { + assert(false); + return KDPointZero; + } + +private: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} }; class AllocationFailedLayoutRef : public LayoutReference { diff --git a/poincare/include/poincare/char_layout_node.h b/poincare/include/poincare/char_layout_node.h index c2eee9789..c45796efb 100644 --- a/poincare/include/poincare/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -1,59 +1,64 @@ #ifndef POINCARE_CHAR_LAYOUT_NODE_H #define POINCARE_CHAR_LAYOUT_NODE_H -#include -#include #include +#include +#include +#include namespace Poincare { class CharLayoutNode : public LayoutNode { public: - CharLayoutNode() : LayoutNode() {} - size_t size() const override { - return sizeof(CharLayoutNode); - } + CharLayoutNode() : + LayoutNode(), + m_char('a'), + m_fontSize(KDText::FontSize::Large) + {} + void setChar(char c) { m_char = c; } + void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } + // LayoutNode + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); + } + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + + // TreeNode + size_t size() const override { return sizeof(CharLayoutNode); } int numberOfChildren() const override { return 0; } - - void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { - if (cursor->position() == LayoutCursor::Position::Right) { - cursor->setPosition(LayoutCursor::Position::Left); - return; - } - LayoutNode * parentNode = parent(); - if (parentNode != nullptr) { - parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); - } - } - - void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { - if (cursor->position() == LayoutCursor::Position::Left) { - cursor->setPosition(LayoutCursor::Position::Right); - return; - } - LayoutNode * parentNode = parent(); - if (parentNode != nullptr) { - parentNode->moveCursorRight(cursor, shouldRecomputeLayout); - } - } - +#if TREE_LOG const char * description() const override { static char Description[] = "Char a"; Description[5] = m_char; return Description; } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override { + assert(false); + return KDPointZero; + } - void setChar(char c) { m_char = c; } private: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; char m_char; + KDText::FontSize m_fontSize; }; class CharLayoutRef : public LayoutReference { public: - CharLayoutRef(char c) : LayoutReference() { + CharLayoutRef(char c, KDText::FontSize fontSize = KDText::FontSize::Large) : + LayoutReference() + { if (!(this->node()->isAllocationFailure())) { this->typedNode()->setChar(c); + this->typedNode()->setFontSize(fontSize); } } }; diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 4f4647b7c..750db81c3 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -7,6 +7,9 @@ namespace Poincare { +/* WARNING: A HorizontalLayout should never have a HorizontalLayout child. For + * instance, use addOrMergeChildAtIndex to add a LayoutNode safely. */ + class HorizontalLayoutNode : public LayoutNode { public: HorizontalLayoutNode() : @@ -14,72 +17,34 @@ public: m_numberOfChildren(0) {} - size_t size() const override { - return sizeof(HorizontalLayoutNode); - } + // LayoutNode + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + // TreeNode + size_t size() const override { return sizeof(HorizontalLayoutNode); } int numberOfChildren() const override { return m_numberOfChildren; } void incrementNumberOfChildren(int increment = 1) override { m_numberOfChildren+= increment; } void decrementNumberOfChildren(int decrement = 1) override { - assert(m_numberOfChildren > 0); + assert(m_numberOfChildren >= decrement); m_numberOfChildren-= decrement; } - void eraseNumberOfChildren() override { - m_numberOfChildren = 0; - } - - void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { - if (this == cursor->layoutReference().node()) { - if (cursor->position() == LayoutCursor::Position::Left) { - // Case: Left. Ask the parent. - LayoutNode * parentNode = parent(); - if (parentNode != nullptr) { - parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); - } - return; - } - assert(cursor->position() == LayoutCursor::Position::Right); - /* Case: Right. Go to the last child if there is one, and move Left. Else - * go Left and ask the parent. */ - int childrenCount = numberOfChildren(); - if (childrenCount >= 1) { - cursor->setLayoutNode(static_cast(childTreeAtIndex(childrenCount-1))); - } else { - cursor->setPosition(LayoutCursor::Position::Left); - } - return cursor->moveLeft(shouldRecomputeLayout); - } - - // Case: The cursor is Left of a child. - assert(cursor->position() == LayoutCursor::Position::Left); - int childIndex = indexOfChildByIdentifier(cursor->layoutIdentifier()); - assert(childIndex >= 0); - if (childIndex == 0) { - // Case: the child is the leftmost. Ask the parent. - if (parent()) { - cursor->setLayoutNode(this); - return cursor->moveLeft(shouldRecomputeLayout); - } - return; - } - // Case: the child is not the leftmost. Go to its left sibling and move Left. - cursor->setLayoutNode(static_cast(childTreeAtIndex(childIndex-1))); - cursor->setPosition(LayoutCursor::Position::Right); - cursor->moveLeft(shouldRecomputeLayout); - } - - void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override { - //TODO - LayoutNode * parentNode = parent(); - if (parentNode != nullptr) { - parentNode->moveCursorRight(cursor, shouldRecomputeLayout); - } - } - + void eraseNumberOfChildren() override { m_numberOfChildren = 0; } +#if TREE_LOG const char * description() const override { return "Horizontal Layout"; } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * l) override; + private: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} int m_numberOfChildren; }; diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index ac4693af3..542f71849 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -49,7 +49,7 @@ public: bool isEquivalentTo(LayoutCursor cursor); /* Position */ - int middleLeftPoint(); + KDPoint middleLeftPoint(); /* Move */ void moveLeft(bool * shouldRecomputeLayout); diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 49a8ab656..990a4c135 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -1,7 +1,9 @@ #ifndef POINCARE_LAYOUT_NODE_H #define POINCARE_LAYOUT_NODE_H -#include "tree_node.h" +#include +#include +#include namespace Poincare { @@ -9,6 +11,30 @@ class LayoutCursor; class LayoutNode : public TreeNode { public: + + // Constructor + LayoutNode() : + TreeNode(), + m_baseline(0), + m_frame(KDRectZero), + m_baselined(false), + m_positioned(false), + m_sized(false) + { + } + + // Rendering + void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); + KDPoint origin(); + KDPoint absoluteOrigin(); + KDSize layoutSize(); + KDCoordinate baseline(); + virtual void invalidAllSizesPositionsAndBaselines(); + + // Serialization + virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; + + // TreeNode static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } static int AllocationFailureNodeIdentifier() { @@ -18,15 +44,10 @@ public: return AllocationFailureNodeIdentifier(); } - /* Hierarchy */ + // Hierarchy LayoutNode * parent() const { return static_cast(parentTree()); } - /* Rendering */ - void draw(); - int origin(); - int absoluteOrigin(); - - /* Tree navigation */ + // Tree navigation virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} virtual void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} @@ -36,6 +57,7 @@ public: LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } protected: + // Iterators class Iterator { public: Iterator(LayoutNode * node) : m_node(node) {} @@ -62,8 +84,21 @@ protected: }; DirectChildren children() { return DirectChildren(this); } + // Sizing and positioning + virtual void computeSize() = 0; + virtual void computeBaseline() = 0; + virtual KDPoint positionOfChild(LayoutNode * child) = 0; + + /* m_baseline is the signed vertical distance from the top of the layout to + * the fraction bar of an hypothetical fraction sibling layout. If the top of + * the layout is under that bar, the baseline is negative. */ + KDCoordinate m_baseline; + KDRect m_frame; + bool m_baselined; + bool m_positioned; + bool m_sized; private: - virtual void render() {}; + virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; }; } diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index e23a01723..a3da269a1 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -33,11 +33,11 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - int layoutOrigin() { + KDPoint layoutOrigin() { return this->typedNode()->layoutOrigin(); } - int absoluteOrigin() { + KDPoint absoluteOrigin() { return this->typedNode()->absoluteOrigin(); } }; diff --git a/poincare/src/char_layout_node.cpp b/poincare/src/char_layout_node.cpp new file mode 100644 index 000000000..5bcaec05d --- /dev/null +++ b/poincare/src/char_layout_node.cpp @@ -0,0 +1,45 @@ +#include + +namespace Poincare { + +void CharLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (cursor->position() == LayoutCursor::Position::Right) { + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void CharLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (cursor->position() == LayoutCursor::Position::Left) { + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +// Sizing and positioning +void CharLayoutNode::computeSize() { + assert(!m_sized); + m_frame.setSize(KDText::charSize(m_fontSize)); + m_sized = true; +} + +void CharLayoutNode::computeBaseline() { + assert(!m_baselined); + m_baseline = (KDText::charSize(m_fontSize).height()+1)/2; //TODO +1 ? + m_baselined = true; +} + +void CharLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + char string[2] = {m_char, 0}; + ctx->drawString(string, p, m_fontSize, expressionColor, backgroundColor); +} + +} diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp new file mode 100644 index 000000000..15d1503fe --- /dev/null +++ b/poincare/src/horizontal_layout_node.cpp @@ -0,0 +1,104 @@ +#include +#include + +namespace Poincare { + +static inline KDCoordinate max(KDCoordinate c1, KDCoordinate c2) { return c1 > c2 ? c1 : c2; } + +int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + if (numberOfChildren() == 0) { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; + } + return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); +} + +void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (this == cursor->layoutReference().node()) { + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + /* Case: Right. Go to the last child if there is one, and move Left. Else + * go Left and ask the parent. */ + int childrenCount = numberOfChildren(); + if (childrenCount >= 1) { + cursor->setLayoutNode(static_cast(childTreeAtIndex(childrenCount-1))); + } else { + cursor->setPosition(LayoutCursor::Position::Left); + } + return cursor->moveLeft(shouldRecomputeLayout); + } + + // Case: The cursor is Left of a child. + assert(cursor->position() == LayoutCursor::Position::Left); + int childIndex = indexOfChildByIdentifier(cursor->layoutIdentifier()); + assert(childIndex >= 0); + if (childIndex == 0) { + // Case: the child is the leftmost. Ask the parent. + if (parent()) { + cursor->setLayoutNode(this); + return cursor->moveLeft(shouldRecomputeLayout); + } + return; + } + // Case: the child is not the leftmost. Go to its left sibling and move Left. + cursor->setLayoutNode(static_cast(childTreeAtIndex(childIndex-1))); + cursor->setPosition(LayoutCursor::Position::Right); + cursor->moveLeft(shouldRecomputeLayout); +} + +void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + //TODO + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +KDSize HorizontalLayoutNode::computeSize() { + assert(!m_sized); + KDCoordinate totalWidth = 0; + KDCoordinate maxUnderBaseline = 0; + KDCoordinate maxAboveBaseline = 0; + for (LayoutNode * l : directChildren()) { + KDSize childSize = l->size(); + totalWidth += childSize.width(); + maxUnderBaseline = max(maxUnderBaseline, childSize.height() - l->baseline()); + maxAboveBaseline = max(maxAboveBaseline, l->baseline()); + } + m_frame.setSize(KDSize(totalWidth, maxUnderBaseline + maxAboveBaseline)); + m_sized = true; +} + +void HorizontalLayoutNode::computeBaseline() { + assert(!m_baselined); + m_baseline = 0; + for (LayoutNode * l : directChildren()) { + m_baseline = max(m_baseline, l->baseline()); + } + m_baselined = true; +} + +KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { + assert(hasChild(l)); + KDCoordinate x = 0; + int index = indexOfChild(l); + assert(index > -1); + if (index > 0) { + LayoutNode * previousChild = child(index-1); + x = previousChild->origin().x() + previousChild->size().width(); + } + KDCoordinate y = baseline() - l->baseline(); + return KDPoint(x, y); +} + +} diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 8fb4781b4..544ca6a09 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -14,8 +14,8 @@ bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { /* Position */ -int LayoutCursor::middleLeftPoint() { - int layoutOrigin = layoutReference().absoluteOrigin(); +KDPoint LayoutCursor::middleLeftPoint() { + KDPoint layoutOrigin = layoutReference().absoluteOrigin(); return layoutOrigin; } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 21241de3e..ff3aace35 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -4,39 +4,65 @@ namespace Poincare { -TreeNode * LayoutNode::FailedAllocationStaticNode() { - return LayoutRef::FailedAllocationStaticNode(); -} +// Rendering -void LayoutNode::draw() { - for (LayoutNode * child : children()) { - child->draw(); +void LayoutNode::draw(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + for (LayoutNode * l : children()) { + l->draw(ctx, p, expressionColor, backgroundColor); } - render(); + render(ctx, absoluteOrigin().translatedBy(p), expressionColor, backgroundColor); } -int LayoutNode::origin() { - LayoutNode * parentLayout = parent(); - if (parentLayout == nullptr) { +KDPoint LayoutNode::origin() { + LayoutNode * p = parent(); + if (p != nullptr) { return absoluteOrigin(); } else { - return 1; //KDPoint(absoluteOrigin().x() - parentLayout->absoluteOrigin().x(), absoluteOrigin().y() - parentLayout->absoluteOrigin().y()); + return KDPoint(absoluteOrigin().x() - p->absoluteOrigin().x(), + absoluteOrigin().y() - p->absoluteOrigin().y()); } - return 0; } -int LayoutNode::absoluteOrigin() { - /*if (!m_positioned) { - LayoutNode * parentLayout = parent(); - if (parentLayout != nullptr) { - m_frame.setOrigin(parentLayout->absoluteOrigin().translatedBy(parentLayout->positionOfChild(this))); +KDPoint LayoutNode::absoluteOrigin() { + LayoutNode * p = parent(); + if (!m_positioned) { + if (p != nullptr) { + m_frame.setOrigin(p->absoluteOrigin().translatedBy(p->positionOfChild(this))); } else { m_frame.setOrigin(KDPointZero); } m_positioned = true; } - return m_frame.origin();*/ - return 1; + return m_frame.origin(); +} + +KDSize LayoutNode::layoutSize() { + if (!m_sized) { + computeSize(); + } + return m_frame.size(); +} + +KDCoordinate LayoutNode::baseline() { + if (!m_baselined) { + computeBaseline(); + } + return m_baseline; +} + +void LayoutNode::invalidAllSizesPositionsAndBaselines() { + m_sized = false; + m_positioned = false; + m_baselined = false; + for (LayoutNode * l : children()) { + l->invalidAllSizesPositionsAndBaselines(); + } +} + +// TreeNode + +TreeNode * LayoutNode::FailedAllocationStaticNode() { + return LayoutRef::FailedAllocationStaticNode(); } } From d0304d4a838b96098834811d60a4897994ee95dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 13:52:33 +0200 Subject: [PATCH 083/156] LayoutField --- escher/Makefile | 2 + escher/include/escher/layout_field.h | 122 ++++++++ escher/include/escher/layout_field_delegate.h | 19 ++ escher/src/layout_field.cpp | 266 ++++++++++++++++++ poincare/include/poincare/layout_cursor.h | 22 ++ poincare/include/poincare/layout_engine.h | 13 + poincare/include/poincare/layout_node.h | 11 +- poincare/include/poincare/layout_reference.h | 14 +- poincare/include/poincare/tree_node.h | 8 + poincare/include/poincare/tree_reference.h | 67 ++--- poincare/src/horizontal_layout_node.cpp | 22 +- poincare/src/layout_engine.cpp | 70 +++++ poincare/src/layout_node.cpp | 6 + poincare/src/layout_reference.cpp | 6 + 14 files changed, 583 insertions(+), 65 deletions(-) create mode 100644 escher/include/escher/layout_field.h create mode 100644 escher/include/escher/layout_field_delegate.h create mode 100644 escher/src/layout_field.cpp diff --git a/escher/Makefile b/escher/Makefile index 237f6ed2f..671ada2d8 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -29,6 +29,8 @@ objs += $(addprefix escher/src/,\ invocation.o\ input_view_controller.o\ key_view.o\ + layout_field.o\ + layout_field_content_view.o\ list_view_data_source.o\ message_table_cell.o\ message_table_cell_with_buffer.o\ diff --git a/escher/include/escher/layout_field.h b/escher/include/escher/layout_field.h new file mode 100644 index 000000000..9c27ae5bf --- /dev/null +++ b/escher/include/escher/layout_field.h @@ -0,0 +1,122 @@ +#ifndef ESCHER_LAYOUT_FIELD_H +#define ESCHER_LAYOUT_FIELD_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class LayoutField : public ScrollableView, public ScrollViewDataSource { +public: + LayoutField(Responder * parentResponder, Poincare::LayoutRef layoutR, LayoutFieldDelegate * delegate = nullptr) : + ScrollableView(parentResponder, &m_contentView, this), + m_contentView(layoutR), + m_delegate(delegate) + {} + void setDelegate(LayoutFieldDelegate * delegate) { m_delegate = delegate; } + bool isEditing() const { return m_contentView.isEditing(); } + void setEditing(bool isEditing) { m_contentView.setEditing(isEditing); } + void clearLayout() { m_contentView.clearLayout(); } + void scrollToCursor() { + scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline()); + } + void reload(); + bool hasText() const { return layoutRef().hasText(); } + int writeTextInBuffer(char * buffer, int bufferLength) { return layoutRef().writeTextInBuffer(buffer, bufferLength); } + Poincare::LayoutRef layoutRef() const { return m_contentView.expressionView()->layoutRef(); } + char XNTChar() { return m_contentView.cursor()->layoutReference().XNTChar(); } + + // ScrollableView + void setBackgroundColor(KDColor c) override { + ScrollableView::setBackgroundColor(c); + m_contentView.setBackgroundColor(c); + } + + /* Responder */ + bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; + bool handleEvent(Ion::Events::Event event) override; + Toolbox * toolbox() override { + return m_delegate != nullptr ? m_delegate->toolboxForLayoutField(this) : nullptr; + } + bool layoutFieldShouldFinishEditing(Ion::Events::Event event) { // TODO REMOVE ? + return m_delegate->layoutFieldShouldFinishEditing(this, event); + } + + /* View */ + KDSize minimalSizeForOptimalDisplay() const override { + KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); + return KDSize(contentViewSize.width(), contentViewSize.height()); + } + +protected: + virtual bool privateHandleEvent(Ion::Events::Event event); + bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); + +private: + constexpr static int k_maxNumberOfLayouts = 152; + static_assert(k_maxNumberOfLayouts == TextField::maxBufferSize(), "Maximal number of layouts in a layout field should be equal to max number of char in text field"); + void scrollRightOfLayout(Poincare::LayoutRef layoutR); + void scrollToBaselinedRect(KDRect rect, KDCoordinate baseline); + void insertLayoutAtCursor(Poincare::LayoutRef layoutR, Poincare::LayoutRef pointedLayoutRef, bool forceCursorRightOfLayout = false); + + class ContentView : public View { + public: + ContentView(Poincare::LayoutRef layoutR) : + m_cursor(layoutR, Poincare::LayoutCursor::Position::Right), + m_expressionView(0.0f, 0.5f, KDColorBlack, KDColorWhite), + m_cursorView(), + m_isEditing(false) + { + m_expressionView.setLayoutRef(layoutR); + } + + bool isEditing() const { return m_isEditing; } + void setEditing(bool isEditing) { + m_isEditing = isEditing; + markRectAsDirty(bounds()); + layoutSubviews(); + } + + void setBackgroundColor(KDColor c) { m_expressionView.setBackgroundColor(c); } + void setCursor(Poincare::LayoutCursor cursor) { m_cursor = cursor; } + void cursorPositionChanged() { layoutCursorSubview(); } + KDRect cursorRect() { return m_cursorView.frame(); } + Poincare::LayoutCursor * cursor() { return &m_cursor; } + const ExpressionView * expressionView() const { return &m_expressionView; } + ExpressionView * editableExpressionView() { return &m_expressionView; } + void clearLayout() { m_cursor.clearLayout(); } + /* View */ + KDSize minimalSizeForOptimalDisplay() const override { + KDSize evSize = m_expressionView.minimalSizeForOptimalDisplay(); + return KDSize(evSize.width() + Poincare::LayoutCursor::k_cursorWidth, evSize.height()); + } + private: + enum class Position { + Top, + Bottom + }; + int numberOfSubviews() const override { return 2; } + View * subviewAtIndex(int index) override { + assert(index >= 0 && index < 2); + View * m_views[] = {&m_expressionView, &m_cursorView}; + return m_views[index]; + } + void layoutSubviews() override { + m_expressionView.setFrame(bounds()); + layoutCursorSubview(); + } + void layoutCursorSubview(); + Poincare::LayoutCursor m_cursor; + ExpressionView m_expressionView; + TextCursorView m_cursorView; + bool m_isEditing; + }; + ContentView m_contentView; + LayoutFieldDelegate * m_delegate; +}; + +#endif diff --git a/escher/include/escher/layout_field_delegate.h b/escher/include/escher/layout_field_delegate.h new file mode 100644 index 000000000..e0ea86b89 --- /dev/null +++ b/escher/include/escher/layout_field_delegate.h @@ -0,0 +1,19 @@ +#ifndef ESCHER_LAYOUT_FIELD_DELEGATE_H +#define ESCHER_LAYOUT_FIELD_DELEGATE_H + +#include +#include + +class LayoutField; + +class LayoutFieldDelegate { +public: + virtual bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) = 0; + virtual bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) = 0; + virtual bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) { return false; } + virtual bool layoutFieldDidAbortEditing(LayoutField * layoutField) { return false; } + virtual void layoutFieldDidChangeSize(LayoutField * layoutField) {} + virtual Toolbox * toolboxForLayoutField(LayoutField * layoutField) = 0; +}; + +#endif diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp new file mode 100644 index 000000000..1b0882e4e --- /dev/null +++ b/escher/src/layout_field.cpp @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +//#include //TODO +#include +#include + +using namespace Poincare; + +void LayoutField::ContentView::layoutCursorSubview() { + if (!m_isEditing) { + m_cursorView.setFrame(KDRectZero); + return; + } + KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); + LayoutRef pointedLayoutR = m_cursor.layoutReference(); + LayoutCursor::Position cursorPosition = m_cursor.position(); + LayoutCursor eqCursor = pointedLayoutR.equivalentCursor(&m_cursor); + if (pointedLayoutR.hasChild(eqCursor.layoutReference())) { + pointedLayoutR = eqCursor.layoutReference(); + cursorPosition = eqCursor.position(); + } + KDPoint cursoredExpressionViewOrigin = pointedLayoutR.absoluteOrigin(); + KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); + if (cursorPosition == LayoutCursor::Position::Right) { + cursorX += pointedLayoutR.layoutSize().width(); + } + KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayoutR.baseline() - m_cursor.baseline()); + m_cursorView.setFrame(KDRect(cursorTopLeftPosition, LayoutCursor::k_cursorWidth, m_cursor.cursorHeight())); +} + +void LayoutField::reload() { + KDSize previousSize = minimalSizeForOptimalDisplay(); + layoutRef().invalidAllSizesPositionsAndBaselines(); + KDSize newSize = minimalSizeForOptimalDisplay(); + if (m_delegate && previousSize.height() != newSize.height()) { + m_delegate->layoutFieldDidChangeSize(this); + } + m_contentView.cursorPositionChanged(); + scrollToCursor(); + markRectAsDirty(bounds()); +} + +bool LayoutField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { + if (text[0] == 0) { + // The text is empty + return true; + } + + int currentNumberOfLayouts = m_contentView.expressionView()->numberOfLayouts(); + if (currentNumberOfLayouts >= k_maxNumberOfLayouts - 6) { + /* We add -6 because in some cases (Ion::Events::Division, + * Ion::Events::Exp...) we let the layout cursor handle the layout insertion + * and these events may add at most 6 layouts (e.g *10^•). */ + return true; + } + + // Handle special cases + if (strcmp(text, Ion::Events::Division.text()) == 0) { + m_contentView.cursor()->addFractionLayoutAndCollapseSiblings(); + } else if (strcmp(text, Ion::Events::Exp.text()) == 0) { + m_contentView.cursor()->addEmptyExponentialLayout(); + } else if (strcmp(text, Ion::Events::Power.text()) == 0) { + m_contentView.cursor()->addEmptyPowerLayout(); + } else if (strcmp(text, Ion::Events::Sqrt.text()) == 0) { + m_contentView.cursor()->addEmptySquareRootLayout(); + } else if (strcmp(text, Ion::Events::Square.text()) == 0) { + m_contentView.cursor()->addEmptySquarePowerLayout(); + } else if (strcmp(text, Ion::Events::EE.text()) == 0) { + m_contentView.cursor()->addEmptyTenPowerLayout(); + } else if ((strcmp(text, "[") == 0) || (strcmp(text, "]") == 0)) { + m_contentView.cursor()->addEmptyMatrixLayout(); + } else { + Expression * resultExpression = Expression::parse(text); + if (resultExpression == nullptr) { + m_contentView.cursor()->insertText(text); + return true; + } + LayoutRef resultLayoutRef = resultExpression->createLayout(); + delete resultExpression; + if (currentNumberOfLayouts + resultLayoutRef.numberOfDescendants(true) >= k_maxNumberOfLayouts) { + return true; + } + // Find the pointed layout. + LayoutRef pointedLayoutRef(nullptr); + if (strcmp(text, I18n::translate(I18n::Message::RandomCommandWithArg)) == 0) { + /* Special case: if the text is "random()", the cursor should not be set + * inside the parentheses. */ + pointedLayoutRef = resultLayoutRef; + } else if (resultLayoutRef.isHorizontal()) { + /* If the layout is horizontal, pick the first open parenthesis. For now, + * all horizontal layouts in MathToolbox have parentheses. */ + for (LayoutRef l : resultLayoutRef.directChildren()) { + if (l.isLeftParenthesis()) { + pointedLayoutRef = l; + break; + } + } + } + /* Insert the layout. If pointedLayout is nullptr, the cursor will be on the + * right of the inserted layout. */ + insertLayoutAtCursor(resultLayoutRef, pointedLayoutRef, forceCursorRightOfText); + } + return true; +} + +bool LayoutField::handleEvent(Ion::Events::Event event) { + bool didHandleEvent = false; + bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded(); + bool moveEventChangedLayout = false; + if (privateHandleMoveEvent(event, &moveEventChangedLayout)) { + if (!isEditing()) { + setEditing(true); + } + shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout; + didHandleEvent = true; + } else if (privateHandleEvent(event)) { + shouldRecomputeLayout = true; + didHandleEvent = true; + } + if (didHandleEvent) { + shouldRecomputeLayout = m_contentView.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; + if (!shouldRecomputeLayout) { + m_contentView.cursorPositionChanged(); + scrollToCursor(); + } else { + reload(); + } + return true; + } + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); + return false; +} + +bool LayoutField::privateHandleEvent(Ion::Events::Event event) { + if (m_delegate && m_delegate->layoutFieldDidReceiveEvent(this, event)) { + return true; + } + if (Responder::handleEvent(event)) { + /* The only event Responder handles is 'Toolbox' displaying. In that case, + * the ExpressionLayoutField is forced into editing mode. */ + if (!isEditing()) { + setEditing(true); + } + return true; + } + if (isEditing() && m_delegate->layoutFieldShouldFinishEditing(this, event)) { //TODO use class method? + setEditing(false); + if (m_delegate->layoutFieldDidFinishEditing(this, layoutRef(), event)) { + clearLayout(); + } + return true; + } + if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { + setEditing(true); + m_contentView.cursor()->setPLayoutReference(layoutRef()); + m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); + return true; + } + if (event == Ion::Events::Back && isEditing()) { + clearLayout(); + setEditing(false); + m_delegate->layoutFieldDidAbortEditing(this); + return true; + } + if (event.hasText() || event == Ion::Events::Paste || event == Ion::Events::Backspace) { + if (!isEditing()) { + setEditing(true); + } + if (event.hasText()) { + handleEventWithText(event.text()); + } else if (event == Ion::Events::Paste) { + handleEventWithText(Clipboard::sharedClipboard()->storedText(), false, true); + } else { + assert(event == Ion::Events::Backspace); + m_contentView.cursor()->performBackspace(); + } + return true; + } + if (event == Ion::Events::Clear && isEditing()) { + clearLayout(); + return true; + } + return false; +} + +bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { + LayoutCursor result; + if (event == Ion::Events::Left) { + result = m_contentView.cursor()->cursorOnLeft(shouldRecomputeLayout); + } else if (event == Ion::Events::Right) { + result = m_contentView.cursor()->cursorOnRight(shouldRecomputeLayout); + } else if (event == Ion::Events::Up) { + result = m_contentView.cursor()->cursorAbove(shouldRecomputeLayout); + } else if (event == Ion::Events::Down) { + result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout); + } else if (event == Ion::Events::ShiftLeft) { + *shouldRecomputeLayout = true; + if (m_contentView.cursor()->layoutReference()->removeGreySquaresFromAllMatrixAncestors()) { + *shouldRecomputeLayout = true; + } + result.setPointedLayoutRef(layoutRef()); + result.setPosition(LayoutCursor::Position::Left); + } else if (event == Ion::Events::ShiftRight) { + if (m_contentView.cursor()->layoutReference()->removeGreySquaresFromAllMatrixAncestors()) { + *shouldRecomputeLayout = true; + } + result.setPointedLayoutRef(layoutRef()); + result.setPosition(LayoutCursor::Position::Right); + } + if (result.isDefined()) { + m_contentView.setCursor(result); + return true; + } + return false; +} + +void LayoutField::scrollRightOfLayout(LayoutRef layoutR) { + KDRect layoutRect(layout.absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layout.size()); + scrollToBaselinedRect(layoutRect, layout.baseline()); +} + +void LayoutField::scrollToBaselinedRect(KDRect rect, KDCoordinate baseline) { + scrollToContentRect(rect, true); + // Show the rect area around its baseline + KDCoordinate underBaseline = rect.height() - baseline; + KDCoordinate minAroundBaseline = min(baseline, underBaseline); + minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); + KDRect balancedRect(rect.x(), rect.y() + baseline - minAroundBaseline, rect.width(), 2 * minAroundBaseline); + scrollToContentRect(balancedRect, true); +} + +void LayoutField::insertLayoutAtCursor(LayoutRef layoutR, LayoutRef pointedLayoutR, bool forceCursorRightOfLayout) { + if (!layoutR.isDefined()) { + return; + } + m_contentView.cursor()->showEmptyLayoutIfNeeded(); + bool layoutWillBeMerged = layoutR->isHorizontal(); + LayoutRef lastMergedLayoutChild = layoutWillBeMerged ? layout.child(layout.numberOfChildren()-1) : nullptr; + m_contentView.cursor()->addLayoutAndMoveCursor(layout); + if (!forceCursorRightOfLayout) { + if (pointedLayoutR.isDefined() && (pointedLayout != layout || !layoutWillBeMerged)) { + m_contentView.cursor()->setPointedLayoutRef(pointedLayoutR); + m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); + } else if (!layoutWillBeMerged) { + m_contentView.cursor()->setPointedLayoutRef(layout.layoutToPointWhenInserting()); + m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); + } + } else if (!layoutWillBeMerged) { + m_contentView.cursor()->setPointedLayoutRef(layout); + m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); + } + m_contentView.cursor()->layoutReference().addGreySquaresToAllMatrixAncestors(); + m_contentView.cursor()->hideEmptyLayoutIfNeeded(); + reload(); + if (!layoutWillBeMerged) { + scrollRightOfLayout(layout); + } else { + assert(lastMergedLayoutChild != nullptr); + scrollRightOfLayout(lastMergedLayoutChild); + } + scrollToCursor(); +} diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 542f71849..87512e658 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -11,11 +11,18 @@ class LayoutCursor { template friend class LayoutReference; public: + constexpr static KDCoordinate k_cursorWidth = 1; + enum class Position { Left, Right }; + LayoutCursor(LayoutRef layoutR, Position position = Position::Right) : + m_layoutRef(layoutR.node()), + m_position(position) + {} + /* Debug */ void log() { #if TREE_LOG @@ -56,6 +63,21 @@ public: void moveRight(bool * shouldRecomputeLayout); void moveAbove(bool * shouldRecomputeLayout); void moveUnder(bool * shouldRecomputeLayout); + + /* Layout modification */ + void clearLayout() {} //TODO + void addFractionLayoutAndCollapseSiblings() {} //TODO + void addEmptyExponentialLayout() {} //TODO + void addEmptyPowerLayout() {} //TODO + void addEmptySquareRootLayout() {} //TODO + void addEmptySquarePowerLayout() {} //TODO + void addEmptyTenPowerLayout() {} //TODO + void addEmptyMatrixLayout() {} //TODO + void insertText(const char * text) {} //TODO + void performBackspace() {} //TODO + bool showEmptyLayoutIfNeeded() { return false; } //TODO + bool hideEmptyLayoutIfNeeded() { return false; } //TODO + private: LayoutCursor(LayoutNode * node, Position position = Position::Right) : m_layoutRef(node), diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index cc6465e66..1256621cc 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -2,6 +2,7 @@ #define POINCARE_LAYOUT_ENGINE_H #include +#include namespace Poincare { @@ -51,6 +52,16 @@ public: const char * operatorName, bool writeFirstChild = true); + /* LayoutReference to Text */ + static int writeInfixTreeRefTextInBuffer( + const TreeRef treeRef, + char * buffer, + int bufferSize, + int numberOfDigits, + const char * operatorName, + int firstChildIndex = 0, + int lastChildIndex = -1); + /* Write one char in buffer */ static int writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite); @@ -59,6 +70,8 @@ private: // These two functions return the index of the null-terminating char. static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis); static int writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, bool writeFirstChild = true); + + static void writeChildTreeInBuffer(TreeRef childRef, TreeRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar); }; } diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 990a4c135..132d5831d 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -1,7 +1,6 @@ #ifndef POINCARE_LAYOUT_NODE_H #define POINCARE_LAYOUT_NODE_H -#include #include #include @@ -23,6 +22,8 @@ public: { } + virtual char XNTChar() const { return 'x'; } + // Rendering void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); KDPoint origin(); @@ -31,9 +32,6 @@ public: KDCoordinate baseline(); virtual void invalidAllSizesPositionsAndBaselines(); - // Serialization - virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; - // TreeNode static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } @@ -46,15 +44,14 @@ public: // Hierarchy LayoutNode * parent() const { return static_cast(parentTree()); } + LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } // Tree navigation virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} 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) {} - - - LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } + virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); //TODO protected: // Iterators diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index a3da269a1..389b4c5d3 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -33,13 +33,15 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - KDPoint layoutOrigin() { - return this->typedNode()->layoutOrigin(); - } + bool hasText() { return this->typedNode()->hasText(); } + char XNTChar() const { return this->typedNode()->XNTChar(); } + KDSize layoutSize() { return this->typedNode()->layoutSize(); } + KDPoint layoutOrigin() { return this->typedNode()->layoutOrigin(); } + KDPoint absoluteOrigin() { return this->typedNode()->absoluteOrigin(); } + KDCoordinate baseline() { return this->typedNode()->baseline(); } + LayoutCursor equivalentCursor(LayoutCursor * cursor); + void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } - KDPoint absoluteOrigin() { - return this->typedNode()->absoluteOrigin(); - } }; typedef LayoutReference LayoutRef; diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 497692629..5ffec60c8 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -1,6 +1,8 @@ #ifndef POINCARE_TREE_NODE_H #define POINCARE_TREE_NODE_H +#include + #include #include #include @@ -36,6 +38,12 @@ public: virtual const char * description() const { return "UNKNOWN"; } + + // Serialization + virtual bool needsParenthesisWithParent(TreeNode * parentNode) { return false; } //TODO virtual pure and override on expresionNode/layoutNode + virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { return 0; } //TODO virtual pure + + // Allocation failure virtual bool isAllocationFailure() const { return false; } virtual TreeNode * failedAllocationStaticNode() { assert(false); diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 9d7556fa4..b8340fad4 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -6,17 +6,11 @@ namespace Poincare { -static inline int min(int i, int j) { return i < j ? i : j; } -static inline int max(int i, int j) { return i > j ? i : j; } - -class Cursor; - template class TreeReference { friend class TreeNode; friend class AdditionNode; friend class ExpressionNode; - friend class Cursor; template friend class TreeReference; template @@ -37,10 +31,6 @@ public: inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } - void setTo(const TreeReference & tr) { - setIdentifierAndRetain(tr.identifier()); - } - TreeReference clone() const { TreeNode * myNode = node(); if (myNode->isAllocationFailure()) { @@ -59,48 +49,40 @@ public: node()->release(); } } + operator TreeReference() const { return TreeReference(this->node()); } - bool isDefined() const { return m_identifier >= 0 && node() != nullptr; } - bool isAllocationFailure() const { return node()->isAllocationFailure(); } - - int nodeRetainCount() const { return node()->retainCount(); } - void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } - void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } - - operator TreeReference() const { - return TreeReference(this->node()); - } - + int identifier() const { return m_identifier; } + TreeNode * node() const { return TreePool::sharedPool()->node(m_identifier); } T * typedNode() const { // TODO: Here, assert that the node type is indeed T // ?? Might be allocation failure, not T return static_cast(node()); } - TreeNode * node() const { - return TreePool::sharedPool()->node(m_identifier); - } + bool isDefined() const { return m_identifier >= 0 && node() != nullptr; } //TODO m_identifier != -1 + bool isAllocationFailure() const { return node()->isAllocationFailure(); } - int identifier() const { return m_identifier; } + int nodeRetainCount() const { return node()->retainCount(); } + void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } + void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } + + + + // Serialization + bool needsParenthesisWithParent(TreeReference parentRef) { return node()->needsParenthesisWithParent(parentRef.node()); } + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { + return node()->writeTextInBuffer(buffer, bufferSize, numberOfSignificantDigits); + } // Hierarchy - int numberOfChildren() const { - return node()->numberOfChildren(); - } - - TreeReference parent() const { - return TreeReference(node()->parentTree()); - } - - TreeReference treeChildAtIndex(int i) const { - return TreeReference(node()->childTreeAtIndex(i)); - } + bool hasChild(TreeReference t) const { return node()->hasChild(t.node()); }; + int numberOfChildren() const { return node()->numberOfChildren(); } + TreeReference parent() const { return TreeReference(node()->parentTree()); } + TreeReference treeChildAtIndex(int i) const { return TreeReference(node()->childTreeAtIndex(i)); } // Hierarchy operations - void addChild(TreeReference t) { - return addChildAtIndex(t, 0); - } + void addChild(TreeReference t) { return addChildAtIndex(t, 0); } void addChildAtIndex(TreeReference t, int index) { if (node()->isAllocationFailure()) { @@ -202,8 +184,8 @@ public: if (i == j) { return; } - int firstChildIndex = min(i, j); - int secondChildIndex = max(i, j); + int firstChildIndex = i < j ? i : j; + int secondChildIndex = i > j ? i : j; TreeReference firstChild = treeChildAtIndex(firstChildIndex); TreeReference secondChild = treeChildAtIndex(secondChildIndex); TreeNode * firstChildNode = firstChild.node(); @@ -242,6 +224,9 @@ protected: node()->retain(); } private: + void setTo(const TreeReference & tr) { + setIdentifierAndRetain(tr.identifier()); + } int m_identifier; }; diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 15d1503fe..4268bc074 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -3,7 +3,7 @@ namespace Poincare { -static inline KDCoordinate max(KDCoordinate c1, KDCoordinate c2) { return c1 > c2 ? c1 : c2; } +static inline KDCoordinate maxCoordinate(KDCoordinate c1, KDCoordinate c2) { return c1 > c2 ? c1 : c2; } int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (numberOfChildren() == 0) { @@ -13,7 +13,7 @@ int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int n buffer[0] = 0; return 0; } - return LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); + return LayoutEngine::writeInfixTreeRefTextInBuffer(TreeRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, ""); } void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { @@ -64,16 +64,16 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR } } -KDSize HorizontalLayoutNode::computeSize() { +void HorizontalLayoutNode::computeSize() { assert(!m_sized); KDCoordinate totalWidth = 0; KDCoordinate maxUnderBaseline = 0; KDCoordinate maxAboveBaseline = 0; - for (LayoutNode * l : directChildren()) { - KDSize childSize = l->size(); + for (LayoutNode * l : children()) { + KDSize childSize = l->layoutSize(); totalWidth += childSize.width(); - maxUnderBaseline = max(maxUnderBaseline, childSize.height() - l->baseline()); - maxAboveBaseline = max(maxAboveBaseline, l->baseline()); + maxUnderBaseline = maxCoordinate(maxUnderBaseline, childSize.height() - l->baseline()); + maxAboveBaseline = maxCoordinate(maxAboveBaseline, l->baseline()); } m_frame.setSize(KDSize(totalWidth, maxUnderBaseline + maxAboveBaseline)); m_sized = true; @@ -82,8 +82,8 @@ KDSize HorizontalLayoutNode::computeSize() { void HorizontalLayoutNode::computeBaseline() { assert(!m_baselined); m_baseline = 0; - for (LayoutNode * l : directChildren()) { - m_baseline = max(m_baseline, l->baseline()); + for (LayoutNode * l : children()) { + m_baseline = maxCoordinate(m_baseline, l->baseline()); } m_baselined = true; } @@ -94,8 +94,8 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { int index = indexOfChild(l); assert(index > -1); if (index > 0) { - LayoutNode * previousChild = child(index-1); - x = previousChild->origin().x() + previousChild->size().width(); + LayoutNode * previousChild = childAtIndex(index-1); + x = previousChild->origin().x() + previousChild->layoutSize().width(); } KDCoordinate y = baseline() - l->baseline(); return KDPoint(x, y); diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 15f7c9d61..8a82ba026 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -186,6 +186,76 @@ int LayoutEngine::writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expr return numberOfChar; } +/* LayoutReference to Text */ +int LayoutEngine::writeInfixTreeRefTextInBuffer( + const TreeRef treeRef, + char * buffer, + int bufferSize, + int numberOfDigits, + const char * operatorName, + int firstChildIndex, + int lastChildIndex) +{ + // If buffer has size 0 or 1, put a zero if it fits and return + assert(treeRef.isDefined()); + if (bufferSize == 0) { + return -1; + } + + buffer[bufferSize-1] = 0; // Null-terminate the buffer + if (bufferSize == 1) { + return 0; + } + + // Get some information on the TreeRef + int numberOfChar = 0; + int numberOfOperands = treeRef.numberOfChildren(); + assert(numberOfOperands > 0); + + // Write the first child, with parentheses if needed + writeChildTreeInBuffer(treeRef.treeChildAtIndex(firstChildIndex), treeRef, buffer, bufferSize, numberOfDigits, &numberOfChar); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + // For all remaining children: + int lastIndex = lastChildIndex < 0 ? numberOfOperands - 1 : lastChildIndex; + for (int i = firstChildIndex + 1; i < lastIndex+1; i++) { + // Write the operator + numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + // Write the child, with parentheses if needed + writeChildTreeInBuffer(treeRef.treeChildAtIndex(i), treeRef, buffer, bufferSize, numberOfDigits, &numberOfChar); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + } + + // Null-terminate the buffer + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void LayoutEngine::writeChildTreeInBuffer(TreeRef childRef, TreeRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar) { + // Write the child with parentheses if needed + bool addParentheses = childRef.needsParenthesisWithParent(parentRef); + if (addParentheses) { + buffer[*numberOfChar++] = '('; //TODO ok ? + if (*numberOfChar >= bufferSize-1) { + return; + } + } + *numberOfChar += childRef.writeTextInBuffer(buffer + *numberOfChar, bufferSize - *numberOfChar, numberOfDigits); + if (*numberOfChar >= bufferSize-1) { + return; + } + if (addParentheses) { + buffer[*numberOfChar++] = ')'; + } +} + + int LayoutEngine::writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite) { if (bufferSize == 0) { return -1; diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index ff3aace35..2e607c4c4 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace Poincare { @@ -65,4 +66,9 @@ TreeNode * LayoutNode::FailedAllocationStaticNode() { return LayoutRef::FailedAllocationStaticNode(); } +// Tree navigation +LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { + return LayoutCursor(cursor->layoutReference()); +} + } diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index eb04ed627..d701e7a41 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace Poincare { @@ -21,6 +22,11 @@ LayoutCursor LayoutReference::cursor() const { return LayoutCursor(this->typedNode()); } +template<> +LayoutCursor LayoutRef::equivalentCursor(LayoutCursor * cursor) { + return this->typedNode()->equivalentCursor(cursor); +} + template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; From a5ebab4bc1a2a39d7513323f33116ac2a219778a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 14:56:15 +0200 Subject: [PATCH 084/156] [poincare] Continue adapting LayoutField --- escher/include/escher/expression_view.h | 7 ++++ escher/src/expression_view.cpp | 7 ++++ escher/src/layout_field.cpp | 40 +++++++++---------- .../include/poincare/horizontal_layout_node.h | 2 + poincare/include/poincare/layout_cursor.h | 35 +++++++++++++++- poincare/include/poincare/layout_node.h | 6 +++ poincare/include/poincare/layout_reference.h | 15 ++++++- poincare/include/poincare/tree_reference.h | 2 - 8 files changed, 90 insertions(+), 24 deletions(-) diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index c6104debc..d391d3ba5 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -4,6 +4,7 @@ #include #include #include +#include /* This class does not handle the expression layout as the size of the layout is * needed to compute the size of table cells hosting the expression. As the size @@ -15,8 +16,13 @@ class ExpressionView : public View { public: ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); + Poincare::ExpressionLayout * expressionLayout() const; void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + + Poincare::LayoutRef layoutRef() const { return m_layoutRef; } + void setLayoutRef(Poincare::LayoutRef layoutRef); + void drawRect(KDContext * ctx, KDRect rect) const override; void setBackgroundColor(KDColor backgroundColor); void setTextColor(KDColor textColor); @@ -32,6 +38,7 @@ private: * the expression view (without cloning it). The named controller is then * responsible for freeing the expression layout when required. */ Poincare::ExpressionLayout * m_expressionLayout; + Poincare::LayoutRef m_layoutRef; float m_horizontalAlignment; float m_verticalAlignment; KDColor m_textColor; diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 0bcd59b7e..0c935bece 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -4,6 +4,7 @@ using namespace Poincare; ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) : m_expressionLayout(nullptr), + m_layoutRef(nullptr), m_horizontalAlignment(horizontalAlignment), m_verticalAlignment(verticalAlignment), m_textColor(textColor), @@ -11,6 +12,7 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen { } +//TODO remove ExpressionLayout * ExpressionView::expressionLayout() const { return m_expressionLayout; } @@ -20,6 +22,11 @@ void ExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) { markRectAsDirty(bounds()); } +void ExpressionView::setLayoutRef(LayoutRef layoutR) { + m_layoutRef = layoutR; + markRectAsDirty(bounds()); +} + void ExpressionView::setBackgroundColor(KDColor backgroundColor) { if (m_backgroundColor != backgroundColor) { m_backgroundColor = backgroundColor; diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 1b0882e4e..031022da1 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -156,7 +156,7 @@ bool LayoutField::privateHandleEvent(Ion::Events::Event event) { } if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { setEditing(true); - m_contentView.cursor()->setPLayoutReference(layoutRef()); + m_contentView.cursor()->setLayoutReference(layoutRef()); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); return true; } @@ -190,25 +190,25 @@ bool LayoutField::privateHandleEvent(Ion::Events::Event event) { bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { LayoutCursor result; if (event == Ion::Events::Left) { - result = m_contentView.cursor()->cursorOnLeft(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::MoveDirection::Left, shouldRecomputeLayout); } else if (event == Ion::Events::Right) { - result = m_contentView.cursor()->cursorOnRight(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::MoveDirection::Right, shouldRecomputeLayout); } else if (event == Ion::Events::Up) { - result = m_contentView.cursor()->cursorAbove(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::MoveDirection::Up, shouldRecomputeLayout); } else if (event == Ion::Events::Down) { - result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout); + result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::MoveDirection::Down, shouldRecomputeLayout); } else if (event == Ion::Events::ShiftLeft) { *shouldRecomputeLayout = true; - if (m_contentView.cursor()->layoutReference()->removeGreySquaresFromAllMatrixAncestors()) { + if (m_contentView.cursor()->layoutReference().removeGreySquaresFromAllMatrixAncestors()) { *shouldRecomputeLayout = true; } - result.setPointedLayoutRef(layoutRef()); + result.setLayoutReference(layoutRef()); result.setPosition(LayoutCursor::Position::Left); } else if (event == Ion::Events::ShiftRight) { - if (m_contentView.cursor()->layoutReference()->removeGreySquaresFromAllMatrixAncestors()) { + if (m_contentView.cursor()->layoutReference().removeGreySquaresFromAllMatrixAncestors()) { *shouldRecomputeLayout = true; } - result.setPointedLayoutRef(layoutRef()); + result.setLayoutReference(layoutRef()); result.setPosition(LayoutCursor::Position::Right); } if (result.isDefined()) { @@ -219,8 +219,8 @@ bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * should } void LayoutField::scrollRightOfLayout(LayoutRef layoutR) { - KDRect layoutRect(layout.absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layout.size()); - scrollToBaselinedRect(layoutRect, layout.baseline()); + KDRect layoutRect(layoutR.absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layoutR.layoutSize()); + scrollToBaselinedRect(layoutRect, layoutR.baseline()); } void LayoutField::scrollToBaselinedRect(KDRect rect, KDCoordinate baseline) { @@ -238,28 +238,28 @@ void LayoutField::insertLayoutAtCursor(LayoutRef layoutR, LayoutRef pointedLayou return; } m_contentView.cursor()->showEmptyLayoutIfNeeded(); - bool layoutWillBeMerged = layoutR->isHorizontal(); - LayoutRef lastMergedLayoutChild = layoutWillBeMerged ? layout.child(layout.numberOfChildren()-1) : nullptr; - m_contentView.cursor()->addLayoutAndMoveCursor(layout); + bool layoutWillBeMerged = layoutR.isHorizontal(); + LayoutRef lastMergedLayoutChild = layoutWillBeMerged ? layoutR.childAtIndex(layoutR.numberOfChildren()-1) : LayoutRef(nullptr); + m_contentView.cursor()->addLayoutAndMoveCursor(layoutR); if (!forceCursorRightOfLayout) { - if (pointedLayoutR.isDefined() && (pointedLayout != layout || !layoutWillBeMerged)) { - m_contentView.cursor()->setPointedLayoutRef(pointedLayoutR); + if (pointedLayoutR.isDefined() && (!layoutWillBeMerged || pointedLayoutR != layoutR)) { + m_contentView.cursor()->setLayoutReference(pointedLayoutR); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } else if (!layoutWillBeMerged) { - m_contentView.cursor()->setPointedLayoutRef(layout.layoutToPointWhenInserting()); + m_contentView.cursor()->setLayoutReference(layoutR.layoutToPointWhenInserting()); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } } else if (!layoutWillBeMerged) { - m_contentView.cursor()->setPointedLayoutRef(layout); + m_contentView.cursor()->setLayoutReference(layoutR); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } m_contentView.cursor()->layoutReference().addGreySquaresToAllMatrixAncestors(); m_contentView.cursor()->hideEmptyLayoutIfNeeded(); reload(); if (!layoutWillBeMerged) { - scrollRightOfLayout(layout); + scrollRightOfLayout(layoutR); } else { - assert(lastMergedLayoutChild != nullptr); + assert(lastMergedLayoutChild.isDefined()); scrollRightOfLayout(lastMergedLayoutChild); } scrollToCursor(); diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 750db81c3..f6dcc9bab 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -17,6 +17,8 @@ public: m_numberOfChildren(0) {} + bool isHorizontal() const override { return true; } + // LayoutNode int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 87512e658..d5363eb62 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -13,11 +13,23 @@ class LayoutCursor { public: constexpr static KDCoordinate k_cursorWidth = 1; + enum class MoveDirection { + Left, + Right, + Up, + Down + }; + enum class Position { Left, Right }; + LayoutCursor() : + m_layoutRef(nullptr), + m_position(Position::Right) + {} + LayoutCursor(LayoutRef layoutR, Position position = Position::Right) : m_layoutRef(layoutR.node()), m_position(position) @@ -51,6 +63,9 @@ public: void setPosition(Position position) { m_position = position; } int cursorHeight() { return 1; } //TODO int baseline() { return 1; } //TODO + LayoutCursor clone() const { + return LayoutCursor(m_layoutRef, m_position); + } /* Comparison */ bool isEquivalentTo(LayoutCursor cursor); @@ -59,11 +74,28 @@ public: KDPoint middleLeftPoint(); /* Move */ + void move(MoveDirection direction, bool * shouldRecomputeLayout) { + if (direction == MoveDirection::Left) { + moveLeft(shouldRecomputeLayout); + } else if (direction == MoveDirection::Right) { + moveRight(shouldRecomputeLayout); + } else if (direction == MoveDirection::Up) { + moveAbove(shouldRecomputeLayout); + } else if (direction == MoveDirection::Down) { + moveUnder(shouldRecomputeLayout); + } else { + assert(false); + } + } void moveLeft(bool * shouldRecomputeLayout); void moveRight(bool * shouldRecomputeLayout); void moveAbove(bool * shouldRecomputeLayout); void moveUnder(bool * shouldRecomputeLayout); - + LayoutCursor cursorAtDirection(MoveDirection direction, bool * shouldRecomputeLayout) { + LayoutCursor result = clone(); + result.move(direction, shouldRecomputeLayout); + return result; + } /* Layout modification */ void clearLayout() {} //TODO void addFractionLayoutAndCollapseSiblings() {} //TODO @@ -77,6 +109,7 @@ public: void performBackspace() {} //TODO bool showEmptyLayoutIfNeeded() { return false; } //TODO bool hideEmptyLayoutIfNeeded() { return false; } //TODO + void addLayoutAndMoveCursor(LayoutRef l) {} //TODO private: LayoutCursor(LayoutNode * node, Position position = Position::Right) : diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 132d5831d..13ad7061c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -22,7 +22,9 @@ public: { } + virtual bool hasText() const { return false; } //TODO virtual char XNTChar() const { return 'x'; } + virtual bool isHorizontal() const { return false; } // Rendering void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); @@ -53,6 +55,10 @@ public: virtual void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) {} virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); //TODO + // Tree modification + bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO + bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO + virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO protected: // Iterators class Iterator { diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 389b4c5d3..90070ce42 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -19,6 +19,16 @@ public: operator LayoutReference() const { return LayoutReference(this->node()); } + LayoutReference& operator=(LayoutReference& lr) { + this->setTo(lr); + return *this; + } + LayoutReference& operator=(const LayoutReference& lr) { + this->setTo(lr); + return *this; + } + inline bool operator==(LayoutReference l) { return this->identifier() == l.identifier(); } + inline bool operator!=(LayoutReference l) { return this->identifier() != l.identifier(); } static TreeNode * FailedAllocationStaticNode(); @@ -33,6 +43,7 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } + bool isHorizontal() const { return this->typedNode()->isHorizontal(); } bool hasText() { return this->typedNode()->hasText(); } char XNTChar() const { return this->typedNode()->XNTChar(); } KDSize layoutSize() { return this->typedNode()->layoutSize(); } @@ -41,7 +52,9 @@ public: KDCoordinate baseline() { return this->typedNode()->baseline(); } LayoutCursor equivalentCursor(LayoutCursor * cursor); void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } - + bool removeGreySquaresFromAllMatrixAncestors() { return this->typedNode()->removeGreySquaresFromAllMatrixAncestors(); } + bool addGreySquaresToAllMatrixAncestors() { return this->typedNode()->addGreySquaresToAllMatrixAncestors(); } + LayoutReference layoutToPointWhenInserting() { return LayoutReference(this->typedNode()->layoutToPointWhenInserting()); } }; typedef LayoutReference LayoutRef; diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index b8340fad4..78b37c5db 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -66,8 +66,6 @@ public: void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } - - // Serialization bool needsParenthesisWithParent(TreeReference parentRef) { return node()->needsParenthesisWithParent(parentRef.node()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { From f579e9581585ca7b4c9e3298f1f03b7654fce3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 17:33:06 +0200 Subject: [PATCH 085/156] [poincare] Start removing ExpressionLayout --- apps/calculation/calculation.cpp | 29 ++++----- apps/calculation/calculation.h | 6 +- apps/calculation/history_view_cell.cpp | 36 +++-------- apps/calculation/history_view_cell.h | 9 ++- .../scrollable_expression_view.cpp | 4 +- apps/calculation/scrollable_expression_view.h | 2 +- apps/shared/expression_model.cpp | 25 ++++---- apps/shared/expression_model.h | 4 +- .../expression_model_list_controller.cpp | 7 ++- ...lable_exact_approximate_expressions_cell.h | 6 +- ...ble_exact_approximate_expressions_view.cpp | 27 ++++---- ...lable_exact_approximate_expressions_view.h | 8 +-- apps/shared/sum_graph_controller.cpp | 33 ++++------ apps/shared/sum_graph_controller.h | 3 +- apps/variable_box_controller.cpp | 16 ++--- apps/variable_box_controller.h | 2 +- apps/variable_box_leaf_cell.cpp | 4 +- apps/variable_box_leaf_cell.h | 2 +- escher/include/escher/clipboard.h | 2 +- .../include/escher/even_odd_expression_cell.h | 2 +- escher/include/escher/expression_table_cell.h | 2 +- escher/include/escher/highlight_cell.h | 5 +- escher/src/clipboard.cpp | 4 +- escher/src/layout_field.cpp | 3 +- escher/src/selectable_table_view.cpp | 6 +- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/arc_cosine.h | 6 +- poincare/include/poincare/arc_sine.h | 6 +- poincare/include/poincare/arc_tangent.h | 6 +- .../include/poincare/binomial_coefficient.h | 2 +- poincare/include/poincare/ceiling.h | 2 +- poincare/include/poincare/char_layout_node.h | 5 +- poincare/include/poincare/complex.h | 6 +- poincare/include/poincare/complex_argument.h | 6 +- .../include/poincare/confidence_interval.h | 6 +- poincare/include/poincare/conjugate.h | 2 +- poincare/include/poincare/cosine.h | 6 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/derivative.h | 6 +- poincare/include/poincare/determinant.h | 6 +- poincare/include/poincare/division.h | 2 +- poincare/include/poincare/division_quotient.h | 6 +- .../include/poincare/division_remainder.h | 6 +- poincare/include/poincare/empty_expression.h | 2 +- poincare/include/poincare/equal.h | 2 +- poincare/include/poincare/expression.h | 6 +- poincare/include/poincare/factor.h | 6 +- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/floor.h | 5 +- poincare/include/poincare/frac_part.h | 6 +- poincare/include/poincare/global_context.h | 4 +- .../include/poincare/great_common_divisor.h | 6 +- .../include/poincare/hyperbolic_arc_cosine.h | 6 +- .../include/poincare/hyperbolic_arc_sine.h | 6 +- .../include/poincare/hyperbolic_arc_tangent.h | 6 +- poincare/include/poincare/hyperbolic_cosine.h | 6 +- poincare/include/poincare/hyperbolic_sine.h | 8 ++- .../include/poincare/hyperbolic_tangent.h | 6 +- poincare/include/poincare/imaginary_part.h | 6 +- poincare/include/poincare/integer.h | 6 +- poincare/include/poincare/integral.h | 2 +- poincare/include/poincare/layout_engine.h | 12 ++-- poincare/include/poincare/layout_node.h | 1 + poincare/include/poincare/layout_reference.h | 1 + .../include/poincare/least_common_multiple.h | 6 +- poincare/include/poincare/logarithm.h | 2 +- poincare/include/poincare/matrix.h | 2 +- poincare/include/poincare/matrix_dimension.h | 6 +- poincare/include/poincare/matrix_inverse.h | 6 +- poincare/include/poincare/matrix_trace.h | 6 +- poincare/include/poincare/matrix_transpose.h | 6 +- poincare/include/poincare/multiplication.h | 2 +- .../include/poincare/naperian_logarithm.h | 6 +- poincare/include/poincare/nth_root.h | 2 +- poincare/include/poincare/opposite.h | 2 +- poincare/include/poincare/parenthesis.h | 2 +- .../include/poincare/permute_coefficient.h | 6 +- poincare/include/poincare/power.h | 3 +- .../include/poincare/prediction_interval.h | 7 ++- poincare/include/poincare/randint.h | 7 ++- poincare/include/poincare/random.h | 6 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/real_part.h | 6 +- poincare/include/poincare/round.h | 6 +- poincare/include/poincare/sequence.h | 2 +- .../include/poincare/simplification_root.h | 4 +- poincare/include/poincare/sine.h | 6 +- poincare/include/poincare/square_root.h | 2 +- poincare/include/poincare/store.h | 2 +- poincare/include/poincare/subtraction.h | 6 +- poincare/include/poincare/symbol.h | 2 +- poincare/include/poincare/tangent.h | 7 ++- poincare/include/poincare/tree_reference.h | 1 + poincare/include/poincare/undefined.h | 2 +- poincare/src/absolute_value.cpp | 6 +- poincare/src/binomial_coefficient.cpp | 8 ++- poincare/src/ceiling.cpp | 8 ++- poincare/src/char_layout_node.cpp | 6 ++ poincare/src/complex.cpp | 13 ++-- poincare/src/conjugate.cpp | 8 ++- poincare/src/decimal.cpp | 8 ++- poincare/src/division.cpp | 7 ++- poincare/src/empty_expression.cpp | 6 +- poincare/src/equal.cpp | 7 ++- poincare/src/expression.cpp | 2 +- poincare/src/factorial.cpp | 7 ++- poincare/src/floor.cpp | 7 ++- poincare/src/global_context.cpp | 29 +++++---- poincare/src/integer.cpp | 8 ++- poincare/src/integral.cpp | 7 ++- poincare/src/layout_engine.cpp | 62 +++++++++++++------ poincare/src/logarithm.cpp | 7 ++- poincare/src/matrix.cpp | 7 ++- poincare/src/multiplication.cpp | 5 +- poincare/src/nth_root.cpp | 5 +- poincare/src/opposite.cpp | 9 ++- poincare/src/parenthesis.cpp | 7 ++- poincare/src/power.cpp | 7 ++- poincare/src/rational.cpp | 7 ++- poincare/src/sequence.cpp | 7 ++- poincare/src/square_root.cpp | 7 ++- poincare/src/store.cpp | 8 ++- poincare/src/symbol.cpp | 8 ++- poincare/src/undefined.cpp | 8 ++- 125 files changed, 494 insertions(+), 359 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index a38f4ff36..dcb26d668 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -66,21 +66,18 @@ void Calculation::setContent(const char * c, Context * context, Expression * ans KDCoordinate Calculation::height(Context * context) { if (m_height < 0) { - ExpressionLayout * inputLayout = createInputLayout(); - KDCoordinate inputHeight = inputLayout->size().height(); - delete inputLayout; - Poincare::ExpressionLayout * approximateLayout = createApproximateOutputLayout(context); - KDCoordinate approximateOutputHeight = approximateLayout->size().height(); + LayoutRef inputLayout = createInputLayout(); + KDCoordinate inputHeight = inputLayout.layoutSize().height(); + LayoutRef approximateLayout = createApproximateOutputLayout(context); + KDCoordinate approximateOutputHeight = approximateLayout.layoutSize().height(); if (shouldOnlyDisplayApproximateOutput(context)) { m_height = inputHeight+approximateOutputHeight; } else { - Poincare::ExpressionLayout * exactLayout = createExactOutputLayout(context); - KDCoordinate exactOutputHeight = exactLayout->size().height(); - KDCoordinate outputHeight = max(exactLayout->baseline(), approximateLayout->baseline()) + max(exactOutputHeight-exactLayout->baseline(), approximateOutputHeight-approximateLayout->baseline()); - delete exactLayout; + LayoutRef exactLayout = createExactOutputLayout(context); + KDCoordinate exactOutputHeight = exactLayout.layoutSize().height(); + KDCoordinate outputHeight = max(exactLayout.baseline(), approximateLayout.baseline()) + max(exactOutputHeight-exactLayout.baseline(), approximateOutputHeight-approximateLayout.baseline()); m_height = inputHeight + outputHeight; } - delete approximateLayout; } return m_height; } @@ -104,11 +101,11 @@ Expression * Calculation::input() { return m_input; } -ExpressionLayout * Calculation::createInputLayout() { +LayoutRef Calculation::createInputLayout() { if (input() != nullptr) { return input()->createLayout(PrintFloat::Mode::Decimal, Expression::ComplexFormat::Cartesian); } - return nullptr; + return LayoutRef(nullptr); } bool Calculation::isEmpty() { @@ -156,11 +153,11 @@ Expression * Calculation::exactOutput(Context * context) { return m_exactOutput; } -ExpressionLayout * Calculation::createExactOutputLayout(Context * context) { +LayoutRef Calculation::createExactOutputLayout(Context * context) { if (exactOutput(context) != nullptr) { return exactOutput(context)->createLayout(); } - return nullptr; + return LayoutRef(nullptr); } Expression * Calculation::approximateOutput(Context * context) { @@ -178,11 +175,11 @@ Expression * Calculation::approximateOutput(Context * context) { return m_approximateOutput; } -ExpressionLayout * Calculation::createApproximateOutputLayout(Context * context) { +LayoutRef Calculation::createApproximateOutputLayout(Context * context) { if (approximateOutput(context) != nullptr) { return approximateOutput(context)->createLayout(); } - return nullptr; + return LayoutRef(nullptr); } bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index 68f692876..f626207a5 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -29,11 +29,11 @@ public: const char * exactOutputText(); const char * approximateOutputText(); Poincare::Expression * input(); - Poincare::ExpressionLayout * createInputLayout(); + Poincare::LayoutRef createInputLayout(); Poincare::Expression * approximateOutput(Poincare::Context * context); Poincare::Expression * exactOutput(Poincare::Context * context); - Poincare::ExpressionLayout * createExactOutputLayout(Poincare::Context * context); - Poincare::ExpressionLayout * createApproximateOutputLayout(Poincare::Context * context); + Poincare::LayoutRef createExactOutputLayout(Poincare::Context * context); + Poincare::LayoutRef createApproximateOutputLayout(Poincare::Context * context); bool isEmpty(); void tidy(); bool shouldOnlyDisplayApproximateOutput(Poincare::Context * context); diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index eea40852e..b6e4a645a 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -18,25 +18,10 @@ HistoryViewCell::HistoryViewCell(Responder * parentResponder) : { } -HistoryViewCell::~HistoryViewCell() { - if (m_inputLayout != nullptr) { - delete m_inputLayout; - m_inputLayout = nullptr; - } - if (m_exactOutputLayout != nullptr) { - delete m_exactOutputLayout; - m_exactOutputLayout = nullptr; - } - if (m_approximateOutputLayout != nullptr) { - delete m_approximateOutputLayout; - m_approximateOutputLayout = nullptr; - } -} - Shared::ScrollableExactApproximateExpressionsView * HistoryViewCell::outputView() { return &m_scrollableOutputView; - } + void HistoryViewCell::setEven(bool even) { EvenOddCell::setEven(even); m_inputView.setBackgroundColor(backgroundColor()); @@ -57,11 +42,11 @@ void HistoryViewCell::setHighlighted(bool highlight) { reloadScroll(); } -Poincare::ExpressionLayout * HistoryViewCell::expressionLayout() const { +Poincare::LayoutRef HistoryViewCell::layoutRef() const { if (m_selectedSubviewType == SubviewType::Input) { return m_inputLayout; } else { - return m_scrollableOutputView.expressionLayout(); + return m_scrollableOutputView.layoutRef(); } } @@ -109,27 +94,20 @@ void HistoryViewCell::layoutSubviews() { } void HistoryViewCell::setCalculation(Calculation * calculation) { - if (m_inputLayout) { - delete m_inputLayout; - } m_inputLayout = calculation->createInputLayout(); - m_inputView.setExpressionLayout(m_inputLayout); + m_inputView.setLayoutRef(m_inputLayout); App * calculationApp = (App *)app(); /* Both output expressions have to be updated at the same time. Otherwise, * when updating one layout, if the second one still points to a deleted * layout, calling to layoutSubviews() would fail. */ - if (m_exactOutputLayout) { - delete m_exactOutputLayout; - m_exactOutputLayout = nullptr; + if (m_exactOutputLayout.isDefined()) { + m_exactOutputLayout = Poincare::LayoutRef(nullptr); } if (!calculation->shouldOnlyDisplayApproximateOutput(calculationApp->localContext())) { m_exactOutputLayout = calculation->createExactOutputLayout(calculationApp->localContext()); } - if (m_approximateOutputLayout) { - delete m_approximateOutputLayout; - } m_approximateOutputLayout = calculation->createApproximateOutputLayout(calculationApp->localContext()); - Poincare::ExpressionLayout * outputExpressions[2] = {m_approximateOutputLayout, m_exactOutputLayout}; + Poincare::LayoutRef outputExpressions[2] = {m_approximateOutputLayout, m_exactOutputLayout}; m_scrollableOutputView.setExpressions(outputExpressions); I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(calculationApp->localContext()) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual; m_scrollableOutputView.setEqualMessage(equalMessage); diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index c581c3e21..4f7e060e6 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -15,7 +15,6 @@ public: Output }; HistoryViewCell(Responder * parentResponder); - ~HistoryViewCell(); void reloadCell() override; void reloadScroll(); void setEven(bool even) override; @@ -23,7 +22,7 @@ public: Responder * responder() override { return this; } - Poincare::ExpressionLayout * expressionLayout() const override; + Poincare::LayoutRef layoutRef() const override; KDColor backgroundColor() const override; void setCalculation(Calculation * calculation); int numberOfSubviews() const override; @@ -37,9 +36,9 @@ public: Shared::ScrollableExactApproximateExpressionsView * outputView(); private: constexpr static KDCoordinate k_resultWidth = 80; - Poincare::ExpressionLayout * m_inputLayout; - Poincare::ExpressionLayout * m_exactOutputLayout; - Poincare::ExpressionLayout * m_approximateOutputLayout; + Poincare::LayoutRef m_inputLayout; + Poincare::LayoutRef m_exactOutputLayout; + Poincare::LayoutRef m_approximateOutputLayout; ScrollableExpressionView m_inputView; Shared::ScrollableExactApproximateExpressionsView m_scrollableOutputView; SubviewType m_selectedSubviewType; diff --git a/apps/calculation/scrollable_expression_view.cpp b/apps/calculation/scrollable_expression_view.cpp index 70e10b526..a67639df0 100644 --- a/apps/calculation/scrollable_expression_view.cpp +++ b/apps/calculation/scrollable_expression_view.cpp @@ -10,8 +10,8 @@ ScrollableExpressionView::ScrollableExpressionView(Responder * parentResponder) { } -void ScrollableExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) { - m_expressionView.setExpressionLayout(expressionLayout); +void ScrollableExpressionView::setLayoutRef(LayoutRef layoutRef) { + m_expressionView.setLayoutRef(layoutRef); layoutSubviews(); } diff --git a/apps/calculation/scrollable_expression_view.h b/apps/calculation/scrollable_expression_view.h index 38ae2d8d4..2e3281833 100644 --- a/apps/calculation/scrollable_expression_view.h +++ b/apps/calculation/scrollable_expression_view.h @@ -8,7 +8,7 @@ namespace Calculation { class ScrollableExpressionView : public ScrollableView, public ScrollViewDataSource { public: ScrollableExpressionView(Responder * parentResponder); - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + void setLayoutRef(Poincare::LayoutRef layoutRef); void setBackgroundColor(KDColor backgroundColor) override; KDSize minimalSizeForOptimalDisplay() const override; private: diff --git a/apps/shared/expression_model.cpp b/apps/shared/expression_model.cpp index b962212d5..edcce43ff 100644 --- a/apps/shared/expression_model.cpp +++ b/apps/shared/expression_model.cpp @@ -10,16 +10,15 @@ namespace Shared { ExpressionModel::ExpressionModel() : m_text{0}, m_expression(nullptr), - m_layout(nullptr) + m_layoutRef(nullptr) { } ExpressionModel::~ExpressionModel() { /* We cannot call tidy here because tidy is a virtual function and does not * do the same thing for all children class. */ - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; + if (m_layoutRef.isDefined()) { + m_layoutRef = LayoutRef(nullptr); } if (m_expression != nullptr) { delete m_expression; @@ -44,15 +43,15 @@ Poincare::Expression * ExpressionModel::expression(Poincare::Context * context) return m_expression; } -Poincare::ExpressionLayout * ExpressionModel::layout() { - if (m_layout == nullptr) { +LayoutRef ExpressionModel::layoutRef() { + if (!m_layoutRef.isDefined()) { Expression * nonSimplifiedExpression = Expression::parse(m_text); if (nonSimplifiedExpression != nullptr) { - m_layout = nonSimplifiedExpression->createLayout(PrintFloat::Mode::Decimal); + m_layoutRef = nonSimplifiedExpression->createLayout(PrintFloat::Mode::Decimal); delete nonSimplifiedExpression; } } - return m_layout; + return m_layoutRef; } bool ExpressionModel::isDefined() { @@ -68,9 +67,8 @@ void ExpressionModel::setContent(const char * c) { /* We cannot call tidy here because tidy is a virtual function and does not * do the same thing for all children class. And here we want to delete only * the m_layout and m_expression. */ - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; + if (m_layoutRef.isDefined()) { + m_layoutRef = LayoutRef(nullptr); } if (m_expression != nullptr) { delete m_expression; @@ -79,9 +77,8 @@ void ExpressionModel::setContent(const char * c) { } void ExpressionModel::tidy() { - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; + if (m_layoutRef.isDefined()) { + m_layoutRef = LayoutRef(nullptr); } if (m_expression != nullptr) { delete m_expression; diff --git a/apps/shared/expression_model.h b/apps/shared/expression_model.h index eca8b3c44..4ad4e9c0c 100644 --- a/apps/shared/expression_model.h +++ b/apps/shared/expression_model.h @@ -17,7 +17,7 @@ public: ExpressionModel(ExpressionModel&& other) = delete; const char * text() const; Poincare::Expression * expression(Poincare::Context * context) const; - Poincare::ExpressionLayout * layout(); + Poincare::LayoutRef layoutRef(); /* Here, isDefined is the exact contrary of isEmpty. However, for Sequence * inheriting from ExpressionModel, isEmpty and isDefined have not exactly * opposite meaning. For instance, u(n+1)=u(n) & u(0) = ... is not empty and @@ -35,7 +35,7 @@ private: static_assert((k_dataLengthInBytes & 0x3) == 0, "The expression model data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 char m_text[k_expressionBufferSize]; mutable Poincare::Expression * m_expression; - mutable Poincare::ExpressionLayout * m_layout; + mutable Poincare::LayoutRef m_layoutRef; }; } diff --git a/apps/shared/expression_model_list_controller.cpp b/apps/shared/expression_model_list_controller.cpp index 77b374454..3eb4ee778 100644 --- a/apps/shared/expression_model_list_controller.cpp +++ b/apps/shared/expression_model_list_controller.cpp @@ -23,17 +23,18 @@ KDCoordinate ExpressionModelListController::expressionRowHeight(int j) { return Metric::StoreRowHeight; } ExpressionModel * m = modelStore()->modelAtIndex(j); - if (m->layout() == nullptr) { + if (!m->layoutRef().isDefined()) { return Metric::StoreRowHeight; } - KDCoordinate modelSize = m->layout()->size().height(); + KDCoordinate modelSize = m->layoutRef().layoutSize().height(); return modelSize + Metric::StoreRowHeight - KDText::charSize().height(); } void ExpressionModelListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell; ExpressionModel * m = modelStore()->modelAtIndex(j); - myCell->setExpressionLayout(m->layout()); + myCell->setExpressionLayout(nullptr); //TODO + //myCell->setExpressionLayout(m->layout()); } /* Responder */ diff --git a/apps/shared/scrollable_exact_approximate_expressions_cell.h b/apps/shared/scrollable_exact_approximate_expressions_cell.h index 0c49a48a7..0baaec24b 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_cell.h +++ b/apps/shared/scrollable_exact_approximate_expressions_cell.h @@ -9,8 +9,8 @@ namespace Shared { class ScrollableExactApproximateExpressionsCell : public ::EvenOddCell, public Responder { public: ScrollableExactApproximateExpressionsCell(Responder * parentResponder = nullptr); - void setExpressions(Poincare::ExpressionLayout ** expressionsLayout) { - return m_view.setExpressions(expressionsLayout); + void setExpressions(Poincare::LayoutRef * layoutRefs) { + return m_view.setExpressions(layoutRefs); // TODO rename setLayouts } void setEqualMessage(I18n::Message equalSignMessage) { return m_view.setEqualMessage(equalSignMessage); @@ -22,7 +22,7 @@ public: Responder * responder() override { return this; } - Poincare::ExpressionLayout * expressionLayout() const override { return m_view.expressionLayout(); } + Poincare::LayoutRef layoutRef() const override { return m_view.layoutRef(); } void didBecomeFirstResponder() override; constexpr static KDCoordinate k_margin = 5; private: diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.cpp b/apps/shared/scrollable_exact_approximate_expressions_view.cpp index cb352ae6b..8276592b3 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.cpp +++ b/apps/shared/scrollable_exact_approximate_expressions_view.cpp @@ -49,8 +49,8 @@ KDSize ScrollableExactApproximateExpressionsView::ContentCell::minimalSizeForOpt return approximateExpressionSize; } KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); - KDCoordinate exactBaseline = m_exactExpressionView.expressionLayout()->baseline(); - KDCoordinate approximateBaseline = m_approximateExpressionView.expressionLayout()->baseline(); + KDCoordinate exactBaseline = m_exactExpressionView.layoutRef().baseline(); + KDCoordinate approximateBaseline = m_approximateExpressionView.layoutRef().baseline(); KDCoordinate height = max(exactBaseline, approximateBaseline) + max(exactExpressionSize.height()-exactBaseline, approximateExpressionSize.height()-approximateBaseline); KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); return KDSize(exactExpressionSize.width()+approximateSignSize.width()+approximateExpressionSize.width()+2*k_digitHorizontalMargin, height); @@ -61,16 +61,16 @@ void ScrollableExactApproximateExpressionsView::ContentCell::setSelectedSubviewT setHighlighted(isHighlighted()); } -Poincare::ExpressionLayout * ScrollableExactApproximateExpressionsView::ContentCell::expressionLayout() const { +Poincare::LayoutRef ScrollableExactApproximateExpressionsView::ContentCell::layoutRef() const { if (m_selectedSubviewType == SubviewType::ExactOutput) { - return m_exactExpressionView.expressionLayout(); + return m_exactExpressionView.layoutRef(); } else { - return m_approximateExpressionView.expressionLayout(); + return m_approximateExpressionView.layoutRef(); } } int ScrollableExactApproximateExpressionsView::ContentCell::numberOfSubviews() const { - if (m_exactExpressionView.expressionLayout() != nullptr) { + if (m_exactExpressionView.layoutRef().isDefined()) { return 3; } return 1; @@ -88,8 +88,8 @@ void ScrollableExactApproximateExpressionsView::ContentCell::layoutSubviews() { m_approximateExpressionView.setFrame(KDRect(0, 0, approximateExpressionSize.width(), height)); return; } - KDCoordinate exactBaseline = m_exactExpressionView.expressionLayout()->baseline(); - KDCoordinate approximateBaseline = m_approximateExpressionView.expressionLayout()->baseline(); + KDCoordinate exactBaseline = m_exactExpressionView.layoutRef().baseline(); + KDCoordinate approximateBaseline = m_approximateExpressionView.layoutRef().baseline(); KDCoordinate baseline = max(exactBaseline, approximateBaseline); KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); @@ -103,9 +103,10 @@ ScrollableExactApproximateExpressionsView::ScrollableExactApproximateExpressions m_contentCell() { } -void ScrollableExactApproximateExpressionsView::setExpressions(ExpressionLayout ** expressionsLayout) { - m_contentCell.approximateExpressionView()->setExpressionLayout(expressionsLayout[0]); - m_contentCell.exactExpressionView()->setExpressionLayout(expressionsLayout[1]); + +void ScrollableExactApproximateExpressionsView::setExpressions(Poincare::LayoutRef * layoutRefs) { + m_contentCell.approximateExpressionView()->setLayoutRef(layoutRefs[0]); + m_contentCell.exactExpressionView()->setLayoutRef(layoutRefs[1]); m_contentCell.layoutSubviews(); } @@ -114,7 +115,7 @@ void ScrollableExactApproximateExpressionsView::setEqualMessage(I18n::Message eq } void ScrollableExactApproximateExpressionsView::didBecomeFirstResponder() { - if (m_contentCell.exactExpressionView()->expressionLayout() == nullptr) { + if (!m_contentCell.exactExpressionView()->layoutRef().isDefined()) { setSelectedSubviewType(SubviewType::ApproximativeOutput); } else { setSelectedSubviewType(SubviewType::ExactOutput); @@ -122,7 +123,7 @@ void ScrollableExactApproximateExpressionsView::didBecomeFirstResponder() { } bool ScrollableExactApproximateExpressionsView::handleEvent(Ion::Events::Event event) { - if (m_contentCell.exactExpressionView()->expressionLayout() == nullptr) { + if (!m_contentCell.exactExpressionView()->layoutRef().isDefined()) { return ScrollableView::handleEvent(event); } bool rightExpressionIsVisible = minimalSizeForOptimalDisplay().width() - m_contentCell.approximateExpressionView()->minimalSizeForOptimalDisplay().width() - m_manualScrollingOffset.x() < bounds().width() diff --git a/apps/shared/scrollable_exact_approximate_expressions_view.h b/apps/shared/scrollable_exact_approximate_expressions_view.h index 5a7081187..759d1c1e6 100644 --- a/apps/shared/scrollable_exact_approximate_expressions_view.h +++ b/apps/shared/scrollable_exact_approximate_expressions_view.h @@ -15,7 +15,7 @@ public: ::EvenOddCell * evenOddCell() { return &m_contentCell; } - void setExpressions(Poincare::ExpressionLayout ** expressionsLayout); + void setExpressions(Poincare::LayoutRef * layoutRefs); void setEqualMessage(I18n::Message equalSignMessage); SubviewType selectedSubviewType() { return m_contentCell.selectedSubviewType(); @@ -26,8 +26,8 @@ public: void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; KDSize minimalSizeForOptimalDisplay() const override; - Poincare::ExpressionLayout * expressionLayout() const { - return m_contentCell.expressionLayout(); + Poincare::LayoutRef layoutRef() const { + return m_contentCell.layoutRef(); } private: class ContentCell : public ::EvenOddCell { @@ -52,7 +52,7 @@ private: void setSelectedSubviewType(SubviewType subviewType); void layoutSubviews() override; int numberOfSubviews() const override; - Poincare::ExpressionLayout * expressionLayout() const override; + Poincare::LayoutRef layoutRef() const override; private: View * subviewAtIndex(int index) override; constexpr static KDCoordinate k_digitHorizontalMargin = 10; diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index 49a31a458..fcbff39a8 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -202,7 +202,7 @@ bool SumGraphController::handleEnter() { SumGraphController::LegendView::LegendView(SumGraphController * controller, char sumSymbol) : m_sum(0.0f, 0.5f, KDColorBlack, Palette::GreyMiddle), - m_sumLayout(nullptr), + m_sumLayoutRef(nullptr), m_legend(KDText::FontSize::Small, I18n::Message::Default, 0.0f, 0.5f, KDColorBlack, Palette::GreyMiddle), m_editableZone(controller, m_draftText, m_draftText, TextField::maxBufferSize(), controller, false, KDText::FontSize::Small, 0.0f, 0.5f, KDColorBlack, Palette::GreyMiddle), m_sumSymbol(sumSymbol) @@ -210,13 +210,6 @@ SumGraphController::LegendView::LegendView(SumGraphController * controller, char m_draftText[0] = 0; } -SumGraphController::LegendView::~LegendView() { - if (m_sumLayout != nullptr) { - delete m_sumLayout; - m_sumLayout = nullptr; - } -} - void SumGraphController::LegendView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(bounds(), Palette::GreyMiddle); } @@ -238,28 +231,26 @@ void SumGraphController::LegendView::setEditableZone(double d) { void SumGraphController::LegendView::setSumSymbol(Step step, double start, double end, double result, ExpressionLayout * functionLayout) { assert(step == Step::Result || functionLayout == nullptr); - if (m_sumLayout) { - delete m_sumLayout; - m_sumLayout = nullptr; - } const char sigma[] = {' ', m_sumSymbol}; if (step == Step::FirstParameter) { - m_sumLayout = LayoutEngine::createStringLayout(sigma, sizeof(sigma)); + m_sumLayoutRef = LayoutEngine::createStringLayout(sigma, sizeof(sigma)); } else if (step == Step::SecondParameter) { char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - m_sumLayout = new CondensedSumLayout( + m_sumLayoutRef = LayoutEngine::createStringLayout(sigma, sizeof(sigma));/* TODO new CondensedSumLayout( LayoutEngine::createStringLayout(sigma, sizeof(sigma)), LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small), new EmptyLayout(EmptyLayout::Color::Yellow, false, KDText::FontSize::Small, false), - false); + false); */ } else { + m_sumLayoutRef = LayoutEngine::createStringLayout(sigma, sizeof(sigma)); +/* TODO char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; PrintFloat::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - ExpressionLayout * start = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + ExpressionLayout * start = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); PrintFloat::convertFloatToText(end, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, PrintFloat::Mode::Decimal); - ExpressionLayout * end = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); - m_sumLayout = new CondensedSumLayout( + ExpressionLayout * end = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); + m_sumLayoutRef = new CondensedSumLayout( LayoutEngine::createStringLayout(sigma, sizeof(sigma)), start, end, @@ -269,10 +260,10 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl PrintFloat::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); childrenLayouts[2] = LayoutEngine::createStringLayout(buffer, strlen(buffer), KDText::FontSize::Small); childrenLayouts[1] = functionLayout; - childrenLayouts[0] = m_sumLayout; - m_sumLayout = new HorizontalLayout(childrenLayouts, 3, false); + childrenLayouts[0] = m_sumLayoutRef; + m_sumLayoutRef = new HorizontalLayout(childrenLayouts, 3, false);*/ } - m_sum.setExpressionLayout(m_sumLayout); + m_sum.setLayoutRef(m_sumLayoutRef); if (step == Step::Result) { m_sum.setAlignment(0.5f, 0.5f); } else { diff --git a/apps/shared/sum_graph_controller.h b/apps/shared/sum_graph_controller.h index 98a110957..e40a74bf8 100644 --- a/apps/shared/sum_graph_controller.h +++ b/apps/shared/sum_graph_controller.h @@ -49,7 +49,6 @@ private: class LegendView : public View { public: LegendView(SumGraphController * controller, char sumSymbol); - ~LegendView(); LegendView(const LegendView& other) = delete; LegendView(LegendView&& other) = delete; LegendView& operator=(const LegendView& other) = delete; @@ -71,7 +70,7 @@ private: void layoutSubviews() override; void layoutSubviews(Step step); ExpressionView m_sum; - Poincare::ExpressionLayout * m_sumLayout; + Poincare::LayoutRef m_sumLayoutRef; MessageTextView m_legend; TextField m_editableZone; char m_draftText[TextField::maxBufferSize()]; diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 02a8ea27a..e17506dfc 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -148,16 +148,16 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl if (evaluation) { /* TODO: implement list contexts */ // TODO: handle matrix and scalar! - ExpressionLayout * layout = expressionLayoutForIndex(index); + LayoutRef layoutR = layoutRefForIndex(index); const Matrix * matrixEvaluation = static_cast(evaluation); - myCell->setExpressionLayout(layout); + myCell->setLayoutRef(layoutR); char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1]; int numberOfChars = PrintFloat::convertFloatToText(matrixEvaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, PrintFloat::Mode::Decimal); buffer[numberOfChars++] = 'x'; PrintFloat::convertFloatToText(matrixEvaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, PrintFloat::Mode::Decimal); myCell->setSubtitle(buffer); } else { - myCell->setExpressionLayout(nullptr); + myCell->setLayoutRef(LayoutRef(nullptr)); myCell->setSubtitle(I18n::translate(I18n::Message::Empty)); } } @@ -166,9 +166,9 @@ KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index) if (m_currentPage == Page::RootMenu || m_currentPage == Page::Scalar) { return Metric::ToolboxRowHeight; } - ExpressionLayout * expressionLayout = expressionLayoutForIndex(index); - if (expressionLayout) { - return expressionLayout->size().height()+k_leafMargin; + LayoutRef layoutR = layoutRefForIndex(index); + if (layoutR.isDefined()) { + return layoutR.layoutSize().height()+k_leafMargin; } return Metric::ToolboxRowHeight; } @@ -252,10 +252,10 @@ const Expression * VariableBoxController::ContentViewController::expressionForIn return nullptr; } -ExpressionLayout * VariableBoxController::ContentViewController::expressionLayoutForIndex(int index) { +LayoutRef VariableBoxController::ContentViewController::layoutRefForIndex(int index) { if (m_currentPage == Page::Matrix) { const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); - return m_context->expressionLayoutForSymbol(&symbol); + return m_context->layoutRefForSymbol(&symbol); } #if LIST_VARIABLES if (m_currentPage == Page::List) { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 2ada661ea..22c36e1b1 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -53,7 +53,7 @@ private: void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); const Poincare::Expression * expressionForIndex(int index); - Poincare::ExpressionLayout * expressionLayoutForIndex(int index); + Poincare::LayoutRef layoutRefForIndex(int index); Poincare::GlobalContext * m_context; Responder * m_sender; int m_firstSelectedRow; diff --git a/apps/variable_box_leaf_cell.cpp b/apps/variable_box_leaf_cell.cpp index 2fe428367..6123ca501 100644 --- a/apps/variable_box_leaf_cell.cpp +++ b/apps/variable_box_leaf_cell.cpp @@ -76,8 +76,8 @@ void VariableBoxLeafCell::setSubtitle(const char * text) { layoutSubviews(); } -void VariableBoxLeafCell::setExpressionLayout(ExpressionLayout * expressionLayout) { - m_expressionView.setExpressionLayout(expressionLayout); +void VariableBoxLeafCell::setLayoutRef(LayoutRef layoutRef) { + m_expressionView.setLayoutRef(layoutRef); } void VariableBoxLeafCell::drawRect(KDContext * ctx, KDRect rect) const { diff --git a/apps/variable_box_leaf_cell.h b/apps/variable_box_leaf_cell.h index dcff304ef..e021fab17 100644 --- a/apps/variable_box_leaf_cell.h +++ b/apps/variable_box_leaf_cell.h @@ -11,7 +11,7 @@ public: void reloadCell() override; void setLabel(const char * text); void setSubtitle(const char * text); - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + void setLayoutRef(Poincare::LayoutRef layoutRef); void drawRect(KDContext * ctx, KDRect rect) const override; const char * text() const override { return m_labelView.text(); diff --git a/escher/include/escher/clipboard.h b/escher/include/escher/clipboard.h index ad7135cc6..0a9c5e58d 100644 --- a/escher/include/escher/clipboard.h +++ b/escher/include/escher/clipboard.h @@ -8,7 +8,7 @@ class Clipboard { public: static Clipboard * sharedClipboard(); void store(const char * storedText); - void store(Poincare::ExpressionLayout * layout); + void store(Poincare::LayoutRef layoutR); const char * storedText(); void reset(); private: diff --git a/escher/include/escher/even_odd_expression_cell.h b/escher/include/escher/even_odd_expression_cell.h index dc6dd2e56..3d7380c8c 100644 --- a/escher/include/escher/even_odd_expression_cell.h +++ b/escher/include/escher/even_odd_expression_cell.h @@ -17,7 +17,7 @@ public: void setAlignment(float horizontalAlignment, float verticalAlignment); void setLeftMargin(KDCoordinate margin); void setRightMargin(KDCoordinate margin); - Poincare::ExpressionLayout * expressionLayout() const override { return m_expressionView.expressionLayout(); } + Poincare::LayoutRef layoutRef() const override { return m_expressionView.layoutRef(); } void drawRect(KDContext * ctx, KDRect rect) const override; protected: int numberOfSubviews() const override; diff --git a/escher/include/escher/expression_table_cell.h b/escher/include/escher/expression_table_cell.h index d0b9e01be..da87ab8ee 100644 --- a/escher/include/escher/expression_table_cell.h +++ b/escher/include/escher/expression_table_cell.h @@ -10,7 +10,7 @@ public: View * labelView() const override; void setHighlighted(bool highlight) override; void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); - Poincare::ExpressionLayout * expressionLayout() const override { return m_labelExpressionView.expressionLayout(); } + Poincare::LayoutRef layoutRef() const override { return m_labelExpressionView.layoutRef(); } private: ExpressionView m_labelExpressionView; }; diff --git a/escher/include/escher/highlight_cell.h b/escher/include/escher/highlight_cell.h index 7f87db90b..a9ad67969 100644 --- a/escher/include/escher/highlight_cell.h +++ b/escher/include/escher/highlight_cell.h @@ -4,6 +4,7 @@ #include #include #include +#include class HighlightCell : public View { public: @@ -17,8 +18,8 @@ public: virtual const char * text() const { return nullptr; } - virtual Poincare::ExpressionLayout * expressionLayout() const { - return nullptr; + virtual Poincare::LayoutRef layoutRef() const { + return Poincare::LayoutRef(nullptr); } protected: bool m_highlighted; diff --git a/escher/src/clipboard.cpp b/escher/src/clipboard.cpp index 5d18289d9..9445e668d 100644 --- a/escher/src/clipboard.cpp +++ b/escher/src/clipboard.cpp @@ -10,8 +10,8 @@ void Clipboard::store(const char * storedText) { strlcpy(m_textBuffer, storedText, TextField::maxBufferSize()); } -void Clipboard::store(Poincare::ExpressionLayout * layout) { - layout->writeTextInBuffer(m_textBuffer, TextField::maxBufferSize(), Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits()); +void Clipboard::store(Poincare::LayoutRef layoutR) { + layoutR.writeTextInBuffer(m_textBuffer, TextField::maxBufferSize(), Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits()); } const char * Clipboard::storedText() { diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 031022da1..c3167b742 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -93,7 +93,8 @@ bool LayoutField::handleEventWithText(const char * text, bool indentation, bool } else if (resultLayoutRef.isHorizontal()) { /* If the layout is horizontal, pick the first open parenthesis. For now, * all horizontal layouts in MathToolbox have parentheses. */ - for (LayoutRef l : resultLayoutRef.directChildren()) { + for (int i = 0; i < resultLayoutRef.numberOfChildren(); i++) { + LayoutRef l = resultLayoutRef.childAtIndex(i); if (l.isLeftParenthesis()) { pointedLayoutRef = l; break; diff --git a/escher/src/selectable_table_view.cpp b/escher/src/selectable_table_view.cpp index 58178070e..62ecf73ac 100644 --- a/escher/src/selectable_table_view.cpp +++ b/escher/src/selectable_table_view.cpp @@ -128,9 +128,9 @@ bool SelectableTableView::handleEvent(Ion::Events::Event event) { Clipboard::sharedClipboard()->store(text); return true; } - Poincare::ExpressionLayout * layout = cell->expressionLayout(); - if (layout) { - Clipboard::sharedClipboard()->store(layout); + Poincare::LayoutRef layoutR = cell->layoutRef(); + if (layoutR.isDefined()) { + Clipboard::sharedClipboard()->store(layoutR); return true; } } diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index c5b75d48d..7ea0090cb 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -16,7 +16,7 @@ public: private: Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "abs"); } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index aa00d6313..00b8ad601 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -32,7 +32,7 @@ public: private: /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 71ae77674..e3731a648 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 3aa871d05..0ec4295da 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index e915ab332..dd0c197a4 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index b5085bb67..35b58a631 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -15,7 +15,7 @@ public: private: constexpr static int k_maxNValue = 300; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "binomial"); } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index e55e96f8c..3080c7ed9 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -14,7 +14,7 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); } diff --git a/poincare/include/poincare/char_layout_node.h b/poincare/include/poincare/char_layout_node.h index c45796efb..37e2aa50a 100644 --- a/poincare/include/poincare/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -2,7 +2,6 @@ #define POINCARE_CHAR_LAYOUT_NODE_H #include -#include #include #include @@ -19,9 +18,7 @@ public: void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } // LayoutNode - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { - return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); - } + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 47545eaa3..44b47aaf2 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -43,7 +43,7 @@ public: private: Complex(T a, T b); /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; /* Simplification */ static Expression * CreateDecimal(T f); Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; @@ -54,8 +54,8 @@ private: /* convertComplexToText and convertFloatToTextPrivate return the string length * of the buffer (does not count the 0 last char)*/ int convertComplexToText(char * buffer, int bufferSize, int numberOfSignificantDigits, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, char multiplicationSign) const; - ExpressionLayout * createPolarLayout(PrintFloat::Mode floatDisplayMode) const; - ExpressionLayout * createCartesianLayout(PrintFloat::Mode floatDisplayMode) const; + //ExpressionLayout * createPolarLayout(PrintFloat::Mode floatDisplayMode) const; + //ExpressionLayout * createCartesianLayout(PrintFloat::Mode floatDisplayMode) const; T m_a; T m_b; }; diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 14d283528..02352b066 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index f4e815703..4acaf340a 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -3,6 +3,7 @@ #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index e43767171..db77c2994 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -14,7 +14,7 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "conj"); } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index b19ec7bad..8f059c4d0 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -6,6 +6,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -19,8 +20,9 @@ public: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 52f25d4ec..65d929039 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -31,7 +31,7 @@ private: int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override; /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context& context, AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 85e10c3a4..9cc0d0f29 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -15,8 +16,9 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 7db860bc1..9cff27f3b 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 0337ec310..460787667 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -20,7 +20,7 @@ public: private: /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "/"); } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 318d09c0e..6747d284a 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 05a79ea73..dce48e7c2 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index 09d1cbb9d..495c13682 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -17,7 +17,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/equal.h b/poincare/include/poincare/equal.h index 14d775f23..7ff8d3e39 100644 --- a/poincare/include/poincare/equal.h +++ b/poincare/include/poincare/equal.h @@ -19,7 +19,7 @@ private: /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "="); } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 90cc058fa..3f100b2b5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -1,7 +1,7 @@ #ifndef POINCARE_EXPRESSION_H #define POINCARE_EXPRESSION_H -#include +#include #include extern "C" { #include @@ -249,7 +249,7 @@ public: bool isEqualToItsApproximationLayout(Expression * approximation, int bufferSize, int numberOfSignificantDigits, Context & context); /* Layout Engine */ - ExpressionLayout * createLayout(PrintFloat::Mode floatDisplayMode = PrintFloat::Mode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted + LayoutRef createLayout(PrintFloat::Mode floatDisplayMode = PrintFloat::Mode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; /* Simplification */ @@ -315,7 +315,7 @@ private: //TODO: What should be the implementation for complex? virtual int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { return 0; } /* Layout Engine */ - virtual ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const = 0; + virtual LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const = 0; /* Simplification */ Expression * deepBeautify(Context & context, AngleUnit angleUnit); Expression * deepReduce(Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 4ded7f021..8de7892b9 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -7,6 +7,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -17,8 +18,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 35c04b3fe..2f7842a69 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -15,7 +15,7 @@ private: constexpr static int k_maxOperandValue = 100; /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Simplication */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 8a4196f32..c64bd8612 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,9 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { - return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); } const char * name() const { return "floor"; } /* Simplification */ diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 2fb4f6d88..a55d70db6 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index d6c4d480a..e25775c1c 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -22,7 +22,7 @@ public: /* The expression recorded in global context is already a expression. * Otherwise, we would need the context and the angle unit to evaluate it */ const Expression * expressionForSymbol(const Symbol * symbol) override; - ExpressionLayout * expressionLayoutForSymbol(const Symbol * symbol); + LayoutRef layoutRefForSymbol(const Symbol * symbol); void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override; static constexpr uint16_t k_maxNumberOfScalarExpressions = 26; static constexpr uint16_t k_maxNumberOfListExpressions = 10; @@ -33,7 +33,7 @@ private: Complex * m_expressions[k_maxNumberOfScalarExpressions]; Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; /* Matrix layout memoization */ - ExpressionLayout * m_matrixLayout[k_maxNumberOfMatrixExpressions]; + LayoutRef m_matrixLayouts[k_maxNumberOfMatrixExpressions]; Complex m_pi; Complex m_e; Complex m_i; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 83d8f5d9e..0540535b4 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 8bc94757e..4ae9ec6e2 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 41f7ac7bc..2596b6b1d 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 1beaa2947..8cd59453f 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index a3325b86f..aa21b03b8 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -15,8 +16,9 @@ public: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 83b4c5f2f..f85dedca0 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -15,11 +16,12 @@ public: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { - return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); } const char * name() const { return "sinh"; } /* Simplification */ diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 4ec0dabed..e18ae5700 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -15,8 +16,9 @@ public: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 2c5757b7b..064c395a4 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index af28e53c1..565d6267c 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -7,7 +7,9 @@ namespace Poincare { class ExpressionLayout; - +/*class LayoutNode; +class LayoutReference; +*/ /* All algorithm should be improved with: * Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */ @@ -52,7 +54,7 @@ public: // Layout int writeTextInBuffer(char * buffer, int bufferSize) const; - ExpressionLayout * createLayout() const; + //LayoutReference createLayout() const; // Approximation template T approximate() const; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 2c3ab3f98..0c24d7a05 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -16,7 +16,7 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "int"); } diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 1256621cc..8481c13f6 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -2,20 +2,20 @@ #define POINCARE_LAYOUT_ENGINE_H #include -#include +#include namespace Poincare { class LayoutEngine { public: - /* Expression to ExpressionLayout */ - static ExpressionLayout * createInfixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); - static ExpressionLayout * createPrefixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + /* Expression to LayoutRef */ + static LayoutRef createInfixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + static LayoutRef createPrefixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); /* Create special layouts */ - static ExpressionLayout * createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout); - static ExpressionLayout * createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large); + static LayoutRef createParenthesedLayout(LayoutRef layout, bool cloneLayout); + static LayoutRef createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large); static ExpressionLayout * createLogLayout(ExpressionLayout * argument, ExpressionLayout * index); /* Expression to Text */ diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 13ad7061c..f93a4338c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -25,6 +25,7 @@ public: virtual bool hasText() const { return false; } //TODO virtual char XNTChar() const { return 'x'; } virtual bool isHorizontal() const { return false; } + virtual bool isLeftParenthesis() const { return false; } // Rendering void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 90070ce42..5737ce1d3 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -44,6 +44,7 @@ public: } bool isHorizontal() const { return this->typedNode()->isHorizontal(); } + bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } bool hasText() { return this->typedNode()->hasText(); } char XNTChar() const { return this->typedNode()->XNTChar(); } KDSize layoutSize() { return this->typedNode()->layoutSize(); } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index eddf83d93..8da3cef98 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index ded4cce79..aa4221d3d 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -15,7 +15,7 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "log"); } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 4115b6b06..b7962e77b 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -41,7 +41,7 @@ private: /* rowCanonize turns a matrix in its reduced row echelon form. */ void rowCanonize(Context & context, AngleUnit angleUnit, Multiplication * m = nullptr); /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index f6b608b4c..71655e449 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO +// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 0acae6ef6..675b56875 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Evaluation */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO +// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 14b140ad6..710d3ce6a 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 42ad6455a..c0b3e09db 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 18ec2a876..d2edd226a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -35,7 +35,7 @@ private: Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 89a5173d1..244041555 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index dfd8f5392..3a5c35c05 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -14,7 +14,7 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, "root"); } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 809aa4c43..a83dc3df4 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -18,7 +18,7 @@ public: private: /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index e3589c1d1..ee9965a67 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -15,7 +15,7 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, ""); } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 63ad49a78..9ed509d0e 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -4,6 +4,7 @@ #include #include #include +#include //TODO remove namespace Poincare { @@ -15,8 +16,9 @@ public: private: constexpr static int k_maxNValue = 100; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO +// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index a87b668dd..a074c0d9b 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Poincare { @@ -30,7 +31,7 @@ private: /* Property */ Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; bool needParenthesisWithParent(const Expression * e) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index bccc77f8c..2f3fc7adb 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -3,6 +3,8 @@ #include #include +#include +#include //TODO remove namespace Poincare { @@ -14,8 +16,9 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 39d99e031..8eb650f8c 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -3,6 +3,8 @@ #include #include +#include +#include //TODO remove namespace Poincare { @@ -13,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO +// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 537b89106..1b61d1e0c 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -17,8 +18,9 @@ public: private: Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + /*return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());*/ } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 075a43060..13b8241b6 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -43,7 +43,7 @@ public: static int NaturalOrder(const Rational & i, const Rational & j); private: bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 16b6fdfd4..d4fe41f81 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index fa0bd81da..cb26f2c48 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -14,8 +15,9 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 6815ce4f4..88f1a0064 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -10,7 +10,7 @@ namespace Poincare { class Sequence : public StaticHierarchy<3> { using StaticHierarchy<3>::StaticHierarchy; private: - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); } diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index f692eda8c..049224c6c 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -20,8 +20,8 @@ public: Expression * clone() const override { return nullptr; } int polynomialDegree(char symbolName) const override { return -1; } Type type() const override { return Expression::Type::SimplificationRoot; } - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return nullptr; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutRef(nullptr); //TODO } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return 0; } Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 0c4fa57e3..da9e2debe 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Poincare { @@ -18,8 +19,9 @@ public: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO +// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 52b9f33f4..065b1541f 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -14,7 +14,7 @@ public: Expression * clone() const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index f47b8e342..1e0d915e9 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -18,7 +18,7 @@ private: /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Evalutation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 6d611b6bb..223962455 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -17,8 +18,9 @@ public: private: /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + return CharLayoutRef('a'); //TODO + // return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index edd1d1cd1..2cf4259f4 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -67,7 +67,7 @@ private: /* Comparison */ int simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const override; /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 640a2fad3..6606029b7 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -4,7 +4,7 @@ #include #include #include - +#include namespace Poincare { @@ -16,8 +16,9 @@ public: float characteristicXRange(Context & context, AngleUnit angleUnit = AngleUnit::Default) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { + //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return CharLayoutRef('a'); //TODO } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 78b37c5db..0ffead61e 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -65,6 +65,7 @@ public: int nodeRetainCount() const { return node()->retainCount(); } void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } + int numberOfDescendants(bool includeSelf) const { return node()->numberOfDescendants(includeSelf);} // Serialization bool needsParenthesisWithParent(TreeReference parentRef) { return node()->needsParenthesisWithParent(parentRef.node()); } diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index a0b1a0b24..857cbbb2c 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -14,7 +14,7 @@ public: int polynomialDegree(char symbolName) const override; private: /* Layout */ - ExpressionLayout * privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; + LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 5751149b8..773eac040 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "layout/absolute_value_layout.h" +#include extern "C" { #include @@ -24,10 +24,10 @@ Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUn return this; } -ExpressionLayout * AbsoluteValue::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef AbsoluteValue::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); + return CharLayoutRef('a'); //TODO } Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 51c0c62ba..777cf4f94 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -3,6 +3,7 @@ #include #include #include "layout/binomial_coefficient_layout.h" +#include extern "C" { #include @@ -72,14 +73,15 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl return replaceWith(new Rational(result), true); } -ExpressionLayout * BinomialCoefficient::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef BinomialCoefficient::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new BinomialCoefficientLayout( operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), false); -} +*/} template Expression * BinomialCoefficient::templatedApproximate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 4d8af70bb..a3feb6b03 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -8,6 +8,7 @@ extern "C" { #include } +#include namespace Poincare { @@ -59,10 +60,11 @@ Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(std::ceil(c.a())); } -ExpressionLayout * Ceiling::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Ceiling::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new CeilingLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false); -} +*/} } diff --git a/poincare/src/char_layout_node.cpp b/poincare/src/char_layout_node.cpp index 5bcaec05d..5723207f8 100644 --- a/poincare/src/char_layout_node.cpp +++ b/poincare/src/char_layout_node.cpp @@ -1,7 +1,13 @@ #include +#include namespace Poincare { +// LayoutNode +int CharLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); +} + void CharLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { if (cursor->position() == LayoutCursor::Position::Right) { cursor->setPosition(LayoutCursor::Position::Left); diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 7ca360614..0f02dc3d6 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -20,6 +20,8 @@ extern "C" { #include } +#include + namespace Poincare { template @@ -213,13 +215,14 @@ Complex::Complex(T a, T b) : } template -ExpressionLayout * Complex::privateCreateLayout(PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Complex::privateCreateLayout(PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); if (complexFormat == Expression::ComplexFormat::Polar) { return createPolarLayout(floatDisplayMode); } return createCartesianLayout(floatDisplayMode); -} +*/} template Expression * Complex::CreateDecimal(T f) { @@ -306,7 +309,7 @@ int Complex::convertComplexToText(char * buffer, int bufferSize, int numberOf return numberOfChars; } -template +/*template ExpressionLayout * Complex::createPolarLayout(PrintFloat::Mode floatDisplayMode) const { char bufferBase[PrintFloat::k_maxFloatBufferLength+2]; int numberOfCharInBase = 0; @@ -349,7 +352,7 @@ ExpressionLayout * Complex::createCartesianLayout(PrintFloat::Mode floatDispl char buffer[PrintFloat::k_maxComplexBufferLength]; int numberOfChars = convertComplexToText(buffer, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode, Expression::ComplexFormat::Cartesian, Ion::Charset::MiddleDot); return LayoutEngine::createStringLayout(buffer, numberOfChars); -} +}*/ template class Complex; template class Complex; diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 57461ae00..d27f96ac6 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -2,6 +2,7 @@ #include #include #include "layout/conjugate_layout.h" +#include extern "C" { #include @@ -19,11 +20,12 @@ Expression * Conjugate::clone() const { return a; } -ExpressionLayout * Conjugate::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Conjugate::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); -} +*/} Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { Expression * e = Expression::shallowReduce(context, angleUnit); diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 305049255..654d2c43a 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -9,6 +9,7 @@ extern "C" { #include } +#include namespace Poincare { @@ -217,8 +218,9 @@ bool Decimal::needParenthesisWithParent(const Expression * e) const { return e->isOfType(types, 7); } -ExpressionLayout * Decimal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - char buffer[k_maxBufferSize]; +LayoutRef Decimal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*char buffer[k_maxBufferSize]; int numberOfChars = convertToText(buffer, k_maxBufferSize, floatDisplayMode, PrintFloat::k_numberOfStoredSignificantDigits); return LayoutEngine::createStringLayout(buffer, numberOfChars); } @@ -241,7 +243,7 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { } else { denominator = Integer::Power(Integer(10), Integer(numberOfDigits-1-m_exponent)); } - return replaceWith(new Rational(numerator, denominator), true); + return replaceWith(new Rational(numerator, denominator), true);*/ } Expression * Decimal::shallowBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index de9b576a8..4e54be4a7 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -97,13 +97,14 @@ Complex Division::compute(const Complex c, const Complex d) { return Complex::Cartesian((temp*aa + ab) / norm, (temp*bb + ba) / norm); } -ExpressionLayout * Division::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Division::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); const Expression * numerator = operand(0)->type() == Type::Parenthesis ? operand(0)->operand(0) : operand(0); const Expression * denominator = operand(1)->type() == Type::Parenthesis ? operand(1)->operand(0) : operand(1); return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat), false); -} +*/} template Matrix * Division::computeOnComplexAndMatrix(const Complex * c, const Matrix * n) { Matrix * inverse = n->createApproximateInverse(); diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index 9e416269c..13d22f174 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -2,6 +2,7 @@ #include #include #include +#include extern "C" { #include @@ -17,8 +18,9 @@ int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize, int number return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, Ion::Charset::Empty); } -ExpressionLayout * EmptyExpression::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return new EmptyLayout(); +LayoutRef EmptyExpression::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + // return new EmptyLayout(); } template Complex * EmptyExpression::templatedApproximate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index 58db799c9..ee9e35a3d 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -50,14 +50,15 @@ Expression * Equal::shallowReduce(Context& context, AngleUnit angleUnit) { return this; } -ExpressionLayout * Equal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Equal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(); result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); result->addChildAtIndex(new CharLayout('='), result->numberOfChildren()); result->addOrMergeChildAtIndex(operand(1)->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), false); - return result; + return result;*/ } template diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 22e30cfcd..6f3450c75 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -345,7 +345,7 @@ bool Expression::isEqualToItsApproximationLayout(Expression * approximation, int /* Layout */ -ExpressionLayout * Expression::createLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Expression::createLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case PrintFloat::Mode::Default: switch (complexFormat) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index bb1c048b7..983c4f6bc 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -11,6 +11,7 @@ extern "C" { #include } #include +#include namespace Poincare { @@ -92,13 +93,15 @@ Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) return Complex::Float(std::round(result)); } -ExpressionLayout * Factorial::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Factorial::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(); result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); result->addChildAtIndex(new CharLayout('!'), result->numberOfChildren()); return result; +*/ } int Factorial::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index fa9b02daa..a8302a05b 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -56,10 +56,11 @@ Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(std::floor(c.a())); } -ExpressionLayout * Floor::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Floor::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO +/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new FloorLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false); + return new FloorLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false);*/ } } diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index 479e61cfe..835eadf58 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -8,6 +8,17 @@ namespace Poincare { GlobalContext::GlobalContext() : + m_matrixLayouts{ + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr), + LayoutRef(nullptr)}, //TODO find better way to initialize m_pi(Complex::Float(M_PI)), m_e(Complex::Float(M_E)), m_i(Complex::Cartesian(0.0, 1.0)) @@ -17,7 +28,6 @@ GlobalContext::GlobalContext() : } for (int i = 0; i < k_maxNumberOfMatrixExpressions ; i++) { m_matrixExpressions[i] = nullptr; - m_matrixLayout[i] = nullptr; } } @@ -33,10 +43,6 @@ GlobalContext::~GlobalContext() { delete m_matrixExpressions[i]; } m_matrixExpressions[i] = nullptr; - if (m_matrixLayout[i] != nullptr) { - delete m_matrixLayout[i]; - } - m_matrixLayout[i] = nullptr; } } @@ -78,13 +84,13 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { return m_expressions[index]; } -ExpressionLayout * GlobalContext::expressionLayoutForSymbol(const Symbol * symbol) { +LayoutRef GlobalContext::layoutRefForSymbol(const Symbol * symbol) { if (symbol->isMatrixSymbol()) { int index = symbolIndex(symbol); - if (m_matrixLayout[index] == nullptr && m_matrixExpressions[index] != nullptr) { - m_matrixLayout[index] = m_matrixExpressions[index]->createLayout(); + if (!m_matrixLayouts[index].isDefined() && m_matrixExpressions[index] != nullptr) { + m_matrixLayouts[index] = m_matrixExpressions[index]->createLayout(); } - return m_matrixLayout[index]; + return m_matrixLayouts[index]; } return nullptr; } @@ -99,9 +105,8 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co delete m_matrixExpressions[indexMatrix]; m_matrixExpressions[indexMatrix] = nullptr; } - if (m_matrixLayout[indexMatrix] != nullptr) { - delete m_matrixLayout[indexMatrix]; - m_matrixLayout[indexMatrix] = nullptr; + if (m_matrixLayouts[indexMatrix] != nullptr) { + m_matrixLayouts[indexMatrix] = LayoutRef(nullptr); } if (evaluation != nullptr) { if (evaluation->type() == Expression::Type::Complex) { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index a55a19dac..d69de58ed 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include extern "C" { @@ -600,11 +601,14 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { return size; } -ExpressionLayout * Integer::createLayout() const { +/*LayoutRef Integer::createLayout() const { + return CharLayoutRef('a'); //TODO +/* char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); return LayoutEngine::createStringLayout(buffer, numberOfChars); -} + +}*/ template float Poincare::Integer::approximate() const; template double Poincare::Integer::approximate() const; diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 3246ee5fd..2c24f3844 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -10,6 +10,7 @@ extern "C" { } #include "layout/integral_layout.h" #include "layout/horizontal_layout.h" +#include namespace Poincare { @@ -66,7 +67,9 @@ Complex * Integral::templatedApproximate(Context & context, AngleUnit angleUn return new Complex(Complex::Float(result)); } -ExpressionLayout * Integral::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Integral::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new IntegralLayout( @@ -74,7 +77,7 @@ ExpressionLayout * Integral::privateCreateLayout(PrintFloat::Mode floatDisplayMo operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), false); -} +*/} template T Integral::functionValueAtAbscissa(T x, Context & context, AngleUnit angleUnit) const { diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 8a82ba026..153177c0e 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -4,18 +4,29 @@ #include "layout/left_parenthesis_layout.h" #include "layout/right_parenthesis_layout.h" #include "layout/vertical_offset_layout.h" +#include +#include + extern "C" { #include } namespace Poincare { -ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { +LayoutRef LayoutEngine::createInfixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != Expression::ComplexFormat::Default); int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); - HorizontalLayout * result = new HorizontalLayout(); + HorizontalLayoutRef result; + result.addChildAtIndex(expression->operand(0)->createLayout(), 0); + for (int i = 1; i < numberOfOperands; i++) { + result.addChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result.numberOfChildren()); + result.addChildAtIndex( + expression->operand(i)->createLayout(floatDisplayMode, complexFormat), + result.numberOfChildren()); + } + /* result->addOrMergeChildAtIndex(expression->operand(0)->createLayout(), 0, true); for (int i = 1; i < numberOfOperands; i++) { result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result->numberOfChildren(), true); @@ -24,16 +35,30 @@ ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression createParenthesedLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), false) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), true); - } + }*/ return result; } -ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { +LayoutRef LayoutEngine::createPrefixLayout(const Expression * expression, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != Expression::ComplexFormat::Default); - HorizontalLayout * result = new HorizontalLayout(); - + HorizontalLayoutRef result; // Add the operator name. + result.addChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0); + + // Create the layout of arguments separated by commas. + HorizontalLayoutRef args; + int numberOfOperands = expression->numberOfOperands(); + if (numberOfOperands > 0) { + args.addChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0); + for (int i = 1; i < numberOfOperands; i++) { + args.addChildAtIndex(CharLayoutRef(','), args.numberOfChildren()); + args.addChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args.numberOfChildren()); + } + } + // Add the parenthesed arguments. + result.addChildAtIndex(createParenthesedLayout(args, false), result.numberOfChildren()); + /*// Add the operator name. result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); // Create the layout of arguments separated by commas. @@ -49,35 +74,36 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio } } // Add the parenthesed arguments. - result->addOrMergeChildAtIndex(createParenthesedLayout(args, false), result->numberOfChildren(), true); + result->addOrMergeChildAtIndex(createParenthesedLayout(args, false), result->numberOfChildren(), true);*/ return result; } -ExpressionLayout * LayoutEngine::createParenthesedLayout(ExpressionLayout * layout, bool cloneLayout) { - HorizontalLayout * result = new HorizontalLayout(); - result->addChildAtIndex(new LeftParenthesisLayout(), 0); - if (layout != nullptr) { - result->addOrMergeChildAtIndex(cloneLayout ? layout->clone() : layout, 1, true); +LayoutRef LayoutEngine::createParenthesedLayout(LayoutRef layoutRef, bool cloneLayout) { + HorizontalLayoutRef result; + result.addChildAtIndex(CharLayoutRef('('), 0); + if (layoutRef.isDefined()) { + result.addChildAtIndex(cloneLayout ? layoutRef.clone() : layoutRef, 1); } - result->addChildAtIndex(new RightParenthesisLayout(), result->numberOfChildren()); + result.addChildAtIndex(CharLayoutRef(')'), result.numberOfChildren()); return result; } -ExpressionLayout * LayoutEngine::createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize) { +LayoutRef LayoutEngine::createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize) { assert(bufferSize > 0); - HorizontalLayout * resultLayout = new HorizontalLayout(); + HorizontalLayoutRef resultLayout; for (int i = 0; i < bufferSize; i++) { - resultLayout->addChildAtIndex(new CharLayout(buffer[i], fontSize), i); + resultLayout.addChildAtIndex(CharLayoutRef(buffer[i], fontSize), i); } return resultLayout; } ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, ExpressionLayout * index) { - HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); + return nullptr; + /*HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(index, VerticalOffsetLayout::Type::Subscript, false); resultLayout->addChildAtIndex(offsetLayout, resultLayout->numberOfChildren()); resultLayout->addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout->numberOfChildren(), true); - return resultLayout; + return resultLayout;*/ } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index a8e979dc0..d7ddc1f53 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -228,13 +228,14 @@ Expression * Logarithm::templatedApproximate(Context& context, AngleUnit angleUn return new Complex(result); } -ExpressionLayout * Logarithm::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Logarithm::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); if (numberOfOperands() == 1) { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } - return LayoutEngine::createLogLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); + return LayoutEngine::createLogLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat));*/ } } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 2b3e0f52f..e567f0e66 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -164,8 +164,9 @@ void Matrix::rowCanonize(Context & context, AngleUnit angleUnit, Multiplication } } -ExpressionLayout * Matrix::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Matrix::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout ** childrenLayouts = new ExpressionLayout * [numberOfOperands()]; for (int i = 0; i < numberOfOperands(); i++) { @@ -173,7 +174,7 @@ ExpressionLayout * Matrix::privateCreateLayout(PrintFloat::Mode floatDisplayMode } ExpressionLayout * layout = new MatrixLayout(childrenLayouts, numberOfRows(), numberOfColumns(), false); delete [] childrenLayouts; - return layout; + return layout;*/ } int Matrix::rank(Context & context, AngleUnit angleUnit, bool inPlace) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 860f30ff4..532af5ad8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -85,9 +85,12 @@ bool Multiplication::needParenthesisWithParent(const Expression * e) const { return e->isOfType(types, 3); } -ExpressionLayout * Multiplication::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Multiplication::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO +/* const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, middleDotString); +*/ } int Multiplication::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 8f8005aec..3a32a88c6 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -38,10 +38,13 @@ Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { return p->shallowReduce(context, angleUnit); } -ExpressionLayout * NthRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef NthRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), false); +*/ } template diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 249ad84ce..dedce8527 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -12,6 +12,8 @@ extern "C" { #include } +#include + namespace Poincare { Expression::Type Opposite::type() const { @@ -66,8 +68,9 @@ Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { return m->shallowReduce(context, angleUnit); } -ExpressionLayout * Opposite::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Opposite::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO +/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(new CharLayout('-'), false); if (operand(0)->type() == Type::Opposite) { @@ -76,7 +79,7 @@ ExpressionLayout * Opposite::privateCreateLayout(PrintFloat::Mode floatDisplayMo result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); } return result; - +*/ } int Opposite::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 09240a108..e990da75d 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -21,10 +22,12 @@ int Parenthesis::polynomialDegree(char symbolName) const { return operand(0)->polynomialDegree(symbolName); } -ExpressionLayout * Parenthesis::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Parenthesis::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('('); //TODO +/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); + return LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false);*/ } Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index b20c500c4..28dcdcb34 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -175,8 +175,9 @@ bool Power::needParenthesisWithParent(const Expression * e) const { return e->isOfType(types, 2); } -ExpressionLayout * Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); const Expression * indiceOperand = m_operands[1]; // Delete eventual parentheses of the indice in the pretty print @@ -190,7 +191,7 @@ ExpressionLayout * Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, VerticalOffsetLayout::Type::Superscript, false), result->numberOfChildren()); - return result; + return result;*/ } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 03e9c1954..aa2117b9a 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include "layout/fraction_layout.h" +#include namespace Poincare { @@ -151,13 +152,15 @@ bool Rational::needParenthesisWithParent(const Expression * e) const { return e->isOfType(types, 3); } -ExpressionLayout * Rational::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Rational::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* ExpressionLayout * numeratorLayout = m_numerator.createLayout(); if (m_denominator.isOne()) { return numeratorLayout; } ExpressionLayout * denominatorLayout = m_denominator.createLayout(); - return new FractionLayout(numeratorLayout, denominatorLayout, false); + return new FractionLayout(numeratorLayout, denominatorLayout, false);*/ } int Rational::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 07aeb5159..d0dcef341 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -3,6 +3,7 @@ #include #include #include +#include extern "C" { #include #include @@ -11,10 +12,12 @@ extern "C" { namespace Poincare { -ExpressionLayout * Sequence::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Sequence::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO +/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return createSequenceLayoutWithArgumentLayouts(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat)); +*/ } template diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 7b8105b7a..683137a27 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -8,6 +8,7 @@ extern "C" { } #include #include +#include namespace Poincare { @@ -49,10 +50,12 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { return p->shallowReduce(context, angleUnit); } -ExpressionLayout * SquareRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef SquareRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); +*/ } } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 31164a008..098b69a3d 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -9,6 +9,7 @@ extern "C" { #include #include "layout/char_layout.h" #include "layout/horizontal_layout.h" +#include namespace Poincare { @@ -34,14 +35,15 @@ Expression * Store::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(editableOperand(1), true)->shallowReduce(context, angleUnit); } -ExpressionLayout * Store::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != PrintFloat::Mode::Default); +LayoutRef Store::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO + /*assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); HorizontalLayout * result = new HorizontalLayout(); result->addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0, false); result->addChildAtIndex(new CharLayout(Ion::Charset::Sto), result->numberOfChildren()); result->addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), false); - return result; + return result;*/ } template diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 21a349b6a..9730df9df 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -12,6 +12,8 @@ #include "layout/horizontal_layout.h" #include "layout/vertical_offset_layout.h" +#include + #include #include @@ -244,7 +246,9 @@ char Symbol::name() const { return m_name; } -ExpressionLayout * Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { +LayoutRef Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + return CharLayoutRef('a'); //TODO +/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); if (m_name == SpecialSymbols::Ans) { @@ -289,7 +293,7 @@ ExpressionLayout * Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode if (isMatrixSymbol() || isSeriesSymbol(m_name) || isRegressionSymbol(m_name)) { return LayoutEngine::createStringLayout(textForSpecialSymbols(m_name), 2); } - return LayoutEngine::createStringLayout(&m_name, 1); + return LayoutEngine::createStringLayout(&m_name, 1);*/ } int Symbol::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index c5600b15c..678854151 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include @@ -24,10 +25,11 @@ template Complex * Undefined::templatedApproximate(Context& conte return new Complex(Complex::Float(NAN)); } -ExpressionLayout * Undefined::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - char buffer[16]; +LayoutRef Undefined::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { + /*char buffer[16]; int numberOfChars = PrintFloat::convertFloatToText(NAN, buffer, 16, 1, floatDisplayMode); - return LayoutEngine::createStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars);*/ + return CharLayoutRef('a'); //TODO } int Undefined::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { From 880c3e59def97f49df6eaee20a6352286cdf6c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 18:09:43 +0200 Subject: [PATCH 086/156] [poincare] Continue removing layouts --- apps/calculation/app.cpp | 10 +- apps/calculation/app.h | 2 +- .../edit_expression_controller.cpp | 32 +- apps/calculation/edit_expression_controller.h | 27 +- apps/shared/Makefile | 2 +- apps/shared/expression_field_delegate_app.cpp | 42 +-- apps/shared/expression_field_delegate_app.h | 12 +- .../expression_layout_field_delegate.cpp | 31 -- .../shared/expression_layout_field_delegate.h | 23 -- .../expression_model_list_controller.cpp | 3 +- apps/shared/layout_field_delegate.cpp | 31 ++ apps/shared/layout_field_delegate.h | 23 ++ escher/Makefile | 3 - escher/include/escher.h | 4 +- .../include/escher/even_odd_expression_cell.h | 2 +- escher/include/escher/expression_field.h | 10 +- .../include/escher/expression_layout_field.h | 81 ----- .../escher/expression_layout_field_delegate.h | 19 -- escher/include/escher/expression_table_cell.h | 2 +- escher/include/escher/expression_view.h | 8 +- escher/include/escher/input_view_controller.h | 27 +- ...e_table_cell_with_chevron_and_expression.h | 2 +- escher/src/even_odd_expression_cell.cpp | 4 +- escher/src/expression_field.cpp | 36 +-- escher/src/expression_layout_field.cpp | 303 ------------------ .../expression_layout_field_content_view.cpp | 74 ----- escher/src/expression_table_cell.cpp | 4 +- escher/src/expression_view.cpp | 23 +- escher/src/input_view_controller.cpp | 36 +-- ...table_cell_with_chevron_and_expression.cpp | 4 +- poincare/include/poincare/layout_reference.h | 4 + poincare/src/decimal.cpp | 4 +- 32 files changed, 190 insertions(+), 698 deletions(-) delete mode 100644 apps/shared/expression_layout_field_delegate.cpp delete mode 100644 apps/shared/expression_layout_field_delegate.h create mode 100644 apps/shared/layout_field_delegate.cpp create mode 100644 apps/shared/layout_field_delegate.h delete mode 100644 escher/include/escher/expression_layout_field.h delete mode 100644 escher/include/escher/expression_layout_field_delegate.h delete mode 100644 escher/src/expression_layout_field.cpp delete mode 100644 escher/src/expression_layout_field_content_view.cpp diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 39a61eef1..e7af450d4 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -65,18 +65,18 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e return false; } -bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) { +bool App::layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) { + if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(layoutField, event)) { return true; } - if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { - if (!expressionLayoutField->hasText()) { + if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event)) { + if (!layoutField->hasText()) { return true; } int bufferLength = Calculation::k_printedExpressionSize; char bufferForParsing[bufferLength]; - expressionLayoutField->writeTextInBuffer(bufferForParsing, bufferLength); + layoutField->writeTextInBuffer(bufferForParsing, bufferLength); if (!textInputIsCorrect(bufferForParsing)) { displayWarning(I18n::Message::SyntaxError); diff --git a/apps/calculation/app.h b/apps/calculation/app.h index dea3fdca7..47fbf40f7 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -29,7 +29,7 @@ public: }; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textInputIsCorrect(const char * text); - bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; + bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override; const char * XNT() override; private: App(Container * container, Snapshot * snapshot); diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 8628ef192..72f238d33 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -10,19 +10,15 @@ using namespace Poincare; namespace Calculation { -EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : View(), m_mainView(subview), - m_layout(new Poincare::HorizontalLayout()), - m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate) + m_layoutR(Poincare::HorizontalLayoutRef()), + m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layoutR, textFieldDelegate, layoutFieldDelegate) { m_textBody[0] = 0; } -EditExpressionController::ContentView::~ContentView() { - delete m_layout; -} - View * EditExpressionController::ContentView::subviewAtIndex(int index) { assert(index >= 0 && index < numberOfSubviews()); if (index == 0) { @@ -92,22 +88,22 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField) return inputViewDidAbortEditing(textField->text()); } -bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) { +bool EditExpressionController::layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) { + if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event) && !layoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) { return inputViewDidReceiveEvent(event); } - return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); + return expressionFieldDelegateApp()->layoutFieldDidReceiveEvent(layoutField, event); } -bool EditExpressionController::expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, ExpressionLayout * layout, Ion::Events::Event event) { - return inputViewDidFinishEditing(nullptr, layout); +bool EditExpressionController::layoutFieldDidFinishEditing(::LayoutField * layoutField, LayoutRef layoutR, Ion::Events::Event event) { + return inputViewDidFinishEditing(nullptr, layoutR); } -bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) { +bool EditExpressionController::layoutFieldDidAbortEditing(::LayoutField * layoutField) { return inputViewDidAbortEditing(nullptr); } -void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) { +void EditExpressionController::layoutFieldDidChangeSize(::LayoutField * layoutField) { /* Reload the view only if the ExpressionField height actually changes, i.e. * not if the height is already maximal and stays maximal. */ if (view()) { @@ -157,14 +153,14 @@ bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event } -bool EditExpressionController::inputViewDidFinishEditing(const char * text, ExpressionLayout * layout) { +bool EditExpressionController::inputViewDidFinishEditing(const char * text, LayoutRef layoutR) { App * calculationApp = (App *)app(); - if (layout == nullptr) { + if (!layoutR.isDefined()) { assert(text); strlcpy(m_cacheBuffer, text, Calculation::k_printedExpressionSize); } else { - assert(layout); - layout->writeTextInBuffer(m_cacheBuffer, Calculation::k_printedExpressionSize); + assert(layoutR.isDefined()); + layoutR.writeTextInBuffer(m_cacheBuffer, Calculation::k_printedExpressionSize); } m_calculationStore->push(m_cacheBuffer, calculationApp->localContext()); m_historyController->reload(); diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index f9fef4487..fb8837eb0 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -2,10 +2,10 @@ #define CALCULATION_EDIT_EXPRESSION_CONTROLLER_H #include -#include +#include #include "expression_field.h" #include "../shared/text_field_delegate.h" -#include "../shared/expression_layout_field_delegate.h" +#include "../shared/layout_field_delegate.h" #include "history_controller.h" #include "calculation_store.h" @@ -13,7 +13,7 @@ namespace Calculation { class HistoryController; /* TODO: implement a split view */ -class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate { +class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::LayoutFieldDelegate { public: EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore); void didBecomeFirstResponder() override; @@ -26,21 +26,16 @@ public: bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(::TextField * textField) override; - /* ExpressionLayoutFieldDelegate */ - bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - bool expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override; - bool expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) override; - void expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) override; + /* LayoutFieldDelegate */ + bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override; + bool layoutFieldDidFinishEditing(::LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override; + bool layoutFieldDidAbortEditing(::LayoutField * layoutField) override; + void layoutFieldDidChangeSize(::LayoutField * layoutField) override; private: class ContentView : public View { public: - ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); - ~ContentView(); - ContentView(const ContentView& other) = delete; - ContentView(ContentView&& other) = delete; - ContentView& operator=(const ContentView& other) = delete; - ContentView& operator=(ContentView&& other) = delete; + ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate); void reload(); TableView * mainView() { return m_mainView; } ExpressionField * expressionField() { return &m_expressionField; } @@ -52,14 +47,14 @@ private: static constexpr int k_bufferLength = TextField::maxBufferSize(); TableView * m_mainView; char m_textBody[k_bufferLength]; - Poincare::ExpressionLayout * m_layout; + Poincare::LayoutRef m_layoutR; ExpressionField m_expressionField; }; View * loadView() override; void unloadView(View * view) override; void reloadView(); bool inputViewDidReceiveEvent(Ion::Events::Event event); - bool inputViewDidFinishEditing(const char * text, Poincare::ExpressionLayout * layout); + bool inputViewDidFinishEditing(const char * text, Poincare::LayoutRef layoutR); bool inputViewDidAbortEditing(const char * text); Shared::TextFieldDelegateApp * textFieldDelegateApp() override; Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index dcf909c56..74629216b 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -10,7 +10,6 @@ app_objs += $(addprefix apps/shared/,\ double_pair_store.o\ editable_cell_table_view_controller.o\ expression_field_delegate_app.o\ - expression_layout_field_delegate.o\ expression_model.o\ expression_model_list_controller.o\ expression_model_store.o\ @@ -36,6 +35,7 @@ app_objs += $(addprefix apps/shared/,\ interval.o\ interval_parameter_controller.o\ language_controller.o\ + layout_field_delegate.o\ list_parameter_controller.o\ margin_even_odd_message_text_cell.o\ memoized_curve_view_range.o\ diff --git a/apps/shared/expression_field_delegate_app.cpp b/apps/shared/expression_field_delegate_app.cpp index 005a6169d..c7c04f597 100644 --- a/apps/shared/expression_field_delegate_app.cpp +++ b/apps/shared/expression_field_delegate_app.cpp @@ -9,31 +9,31 @@ namespace Shared { ExpressionFieldDelegateApp::ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) : TextFieldDelegateApp(container, snapshot, rootViewController), - ExpressionLayoutFieldDelegate() + LayoutFieldDelegate() { } -char ExpressionFieldDelegateApp::privateXNT(ExpressionLayoutField * expressionLayoutField) { - char xntCharFromLayout = expressionLayoutField->XNTChar(); +char ExpressionFieldDelegateApp::privateXNT(LayoutField * layoutField) { + char xntCharFromLayout = layoutField->XNTChar(); if (xntCharFromLayout != Ion::Charset::Empty) { return xntCharFromLayout; } return XNT()[0]; } -bool ExpressionFieldDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { +bool ExpressionFieldDelegateApp::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } -bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) { - if (!expressionLayoutField->hasText()) { - expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); +bool ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) { + if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event)) { + if (!layoutField->hasText()) { + layoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } char buffer[TextField::maxBufferSize()]; int bufferSize = TextField::maxBufferSize(); - int length = expressionLayoutField->writeTextInBuffer(buffer, bufferSize); + int length = layoutField->writeTextInBuffer(buffer, bufferSize); Expression * exp = Expression::parse(buffer); if (exp != nullptr) { delete exp; @@ -45,33 +45,33 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression return true; } if (exp == nullptr) { - expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError); + layoutField->app()->displayWarning(I18n::Message::SyntaxError); return true; } } if (event == Ion::Events::Var) { - if (!expressionLayoutField->isEditing()) { - expressionLayoutField->setEditing(true); + if (!layoutField->isEditing()) { + layoutField->setEditing(true); } - AppsContainer * appsContainer = (AppsContainer *)expressionLayoutField->app()->container(); + AppsContainer * appsContainer = (AppsContainer *)layoutField->app()->container(); VariableBoxController * variableBoxController = appsContainer->variableBoxController(); - variableBoxController->setSender(expressionLayoutField); - expressionLayoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + variableBoxController->setSender(layoutField); + layoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); return true; } if (event == Ion::Events::XNT) { - if (!expressionLayoutField->isEditing()) { - expressionLayoutField->setEditing(true); + if (!layoutField->isEditing()) { + layoutField->setEditing(true); } - const char xnt[2] = {privateXNT(expressionLayoutField), 0}; - return expressionLayoutField->handleEventWithText(xnt); + const char xnt[2] = {privateXNT(layoutField), 0}; + return layoutField->handleEventWithText(xnt); } return false; } -Toolbox * ExpressionFieldDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { +Toolbox * ExpressionFieldDelegateApp::toolboxForLayoutField(LayoutField * layoutField) { Toolbox * toolbox = container()->mathToolbox(); - toolbox->setSender(expressionLayoutField); + toolbox->setSender(layoutField); return toolbox; } diff --git a/apps/shared/expression_field_delegate_app.h b/apps/shared/expression_field_delegate_app.h index 264492a87..6fa2ef03e 100644 --- a/apps/shared/expression_field_delegate_app.h +++ b/apps/shared/expression_field_delegate_app.h @@ -2,18 +2,18 @@ #define SHARED_EXPRESSION_FIELD_DELEGATE_APP_H #include "text_field_delegate_app.h" -#include +#include namespace Shared { -class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public ExpressionLayoutFieldDelegate { +class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public LayoutFieldDelegate { public: virtual ~ExpressionFieldDelegateApp() = default; - bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; + bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override; + virtual bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override; + Toolbox * toolboxForLayoutField(LayoutField * layoutField) override; protected: - char privateXNT(ExpressionLayoutField * expressionLayoutField); + char privateXNT(LayoutField * layoutField); ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController); }; diff --git a/apps/shared/expression_layout_field_delegate.cpp b/apps/shared/expression_layout_field_delegate.cpp deleted file mode 100644 index 31099bd12..000000000 --- a/apps/shared/expression_layout_field_delegate.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "expression_layout_field_delegate.h" - -using namespace Poincare; - -namespace Shared { - -bool ExpressionLayoutFieldDelegate::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - return expressionFieldDelegateApp()->expressionLayoutFieldShouldFinishEditing(expressionLayoutField, event); -} - -bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); -} - -bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, ExpressionLayout * layout, Ion::Events::Event event) { - return expressionFieldDelegateApp()->expressionLayoutFieldDidFinishEditing(expressionLayoutField, layout, event); -} - -bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { - return expressionFieldDelegateApp()->expressionLayoutFieldDidAbortEditing(expressionLayoutField); -} - -void ExpressionLayoutFieldDelegate::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { - return expressionFieldDelegateApp()->expressionLayoutFieldDidChangeSize(expressionLayoutField); -} - -Toolbox * ExpressionLayoutFieldDelegate::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { - return expressionFieldDelegateApp()->toolboxForExpressionLayoutField(expressionLayoutField); -} - -} diff --git a/apps/shared/expression_layout_field_delegate.h b/apps/shared/expression_layout_field_delegate.h deleted file mode 100644 index f933593ef..000000000 --- a/apps/shared/expression_layout_field_delegate.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H -#define SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H - -#include -#include "expression_field_delegate_app.h" - -namespace Shared { - -class ExpressionLayoutFieldDelegate : public ::ExpressionLayoutFieldDelegate { -public: - bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override; - bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override; - void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override; - Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; -private: - virtual ExpressionFieldDelegateApp * expressionFieldDelegateApp() = 0; -}; - -} - -#endif diff --git a/apps/shared/expression_model_list_controller.cpp b/apps/shared/expression_model_list_controller.cpp index 3eb4ee778..0cda0150a 100644 --- a/apps/shared/expression_model_list_controller.cpp +++ b/apps/shared/expression_model_list_controller.cpp @@ -33,8 +33,7 @@ KDCoordinate ExpressionModelListController::expressionRowHeight(int j) { void ExpressionModelListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell; ExpressionModel * m = modelStore()->modelAtIndex(j); - myCell->setExpressionLayout(nullptr); //TODO - //myCell->setExpressionLayout(m->layout()); + myCell->setLayoutRef(m->layoutRef()); } /* Responder */ diff --git a/apps/shared/layout_field_delegate.cpp b/apps/shared/layout_field_delegate.cpp new file mode 100644 index 000000000..2c163e15b --- /dev/null +++ b/apps/shared/layout_field_delegate.cpp @@ -0,0 +1,31 @@ +#include "layout_field_delegate.h" + +using namespace Poincare; + +namespace Shared { + +bool LayoutFieldDelegate::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) { + return expressionFieldDelegateApp()->layoutFieldShouldFinishEditing(layoutField, event); +} + +bool LayoutFieldDelegate::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) { + return expressionFieldDelegateApp()->layoutFieldDidReceiveEvent(layoutField, event); +} + +bool LayoutFieldDelegate::layoutFieldDidFinishEditing(LayoutField * layoutField, LayoutRef layoutR, Ion::Events::Event event) { + return expressionFieldDelegateApp()->layoutFieldDidFinishEditing(layoutField, layoutR, event); +} + +bool LayoutFieldDelegate::layoutFieldDidAbortEditing(LayoutField * layoutField) { + return expressionFieldDelegateApp()->layoutFieldDidAbortEditing(layoutField); +} + +void LayoutFieldDelegate::layoutFieldDidChangeSize(LayoutField * layoutField) { + return expressionFieldDelegateApp()->layoutFieldDidChangeSize(layoutField); +} + +Toolbox * LayoutFieldDelegate::toolboxForLayoutField(LayoutField * layoutField) { + return expressionFieldDelegateApp()->toolboxForLayoutField(layoutField); +} + +} diff --git a/apps/shared/layout_field_delegate.h b/apps/shared/layout_field_delegate.h new file mode 100644 index 000000000..7e197ee8c --- /dev/null +++ b/apps/shared/layout_field_delegate.h @@ -0,0 +1,23 @@ +#ifndef SHARED_LAYOUT_FIELD_DELEGATE_H +#define SHARED_LAYOUT_FIELD_DELEGATE_H + +#include +#include "expression_field_delegate_app.h" + +namespace Shared { + +class LayoutFieldDelegate : public ::LayoutFieldDelegate { +public: + bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override; + bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override; + bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override; + bool layoutFieldDidAbortEditing(LayoutField * layoutField) override; + void layoutFieldDidChangeSize(LayoutField * layoutField) override; + Toolbox * toolboxForLayoutField(LayoutField * layoutField) override; +private: + virtual ExpressionFieldDelegateApp * expressionFieldDelegateApp() = 0; +}; + +} + +#endif diff --git a/escher/Makefile b/escher/Makefile index 671ada2d8..a36a4fbdc 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -30,7 +30,6 @@ objs += $(addprefix escher/src/,\ input_view_controller.o\ key_view.o\ layout_field.o\ - layout_field_content_view.o\ list_view_data_source.o\ message_table_cell.o\ message_table_cell_with_buffer.o\ @@ -52,8 +51,6 @@ objs += $(addprefix escher/src/,\ scroll_view_data_source.o\ scroll_view_indicator.o\ scrollable_view.o\ - expression_layout_field.o\ - expression_layout_field_content_view.o\ selectable_table_view.o\ selectable_table_view_data_source.o\ selectable_table_view_delegate.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index 578eb9585..6aa58b473 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -53,8 +55,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/escher/include/escher/even_odd_expression_cell.h b/escher/include/escher/even_odd_expression_cell.h index 3d7380c8c..de197b70d 100644 --- a/escher/include/escher/even_odd_expression_cell.h +++ b/escher/include/escher/even_odd_expression_cell.h @@ -10,7 +10,7 @@ public: KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); void setEven(bool even) override; void setHighlighted(bool highlight) override; - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + void setLayoutRef(Poincare::LayoutRef layoutRef); void setBackgroundColor(KDColor backgroundColor); void setTextColor(KDColor textColor); KDSize minimalSizeForOptimalDisplay() const override; diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h index 4638bb682..9336b0540 100644 --- a/escher/include/escher/expression_field.h +++ b/escher/include/escher/expression_field.h @@ -1,15 +1,15 @@ #ifndef ESCHER_EXPRESSION_FIELD_H #define ESCHER_EXPRESSION_FIELD_H -#include -#include +#include +#include #include #include -#include +#include class ExpressionField : public Responder, public View { public: - ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::LayoutRef layout, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate); void setEditing(bool isEditing, bool reinitDraftBuffer = true); bool isEditing() const; @@ -44,7 +44,7 @@ private: KDCoordinate inputViewHeight() const; KDCoordinate maximalHeight() const; TextField m_textField; - ExpressionLayoutField m_expressionLayoutField; + LayoutField m_layoutField; char * m_textBuffer; int m_textBufferLength; }; diff --git a/escher/include/escher/expression_layout_field.h b/escher/include/escher/expression_layout_field.h deleted file mode 100644 index ad797d672..000000000 --- a/escher/include/escher/expression_layout_field.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_H -#define ESCHER_EXPRESSION_LAYOUT_FIELD_H - -#include -#include -#include -#include -#include -#include -#include -#include - -class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource { -public: - ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr); - void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; } - bool isEditing() const; - void setEditing(bool isEditing); - void clearLayout(); - void scrollToCursor(); - void reload(); - bool hasText() const; - int writeTextInBuffer(char * buffer, int bufferLength); - bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; - Poincare::ExpressionLayout * expressionLayout() const; - char XNTChar(); - void setBackgroundColor(KDColor c) override; - - /* Responder */ - Toolbox * toolbox() override; - bool handleEvent(Ion::Events::Event event) override; - - bool expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event); - - /* View */ - KDSize minimalSizeForOptimalDisplay() const override; - -protected: - virtual bool privateHandleEvent(Ion::Events::Event event); - bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout); -private: - constexpr static int k_maxNumberOfLayouts = 152; - static_assert(k_maxNumberOfLayouts == TextField::maxBufferSize(), "Maximal number of layouts in a layout field should be equal to max number of char in text field"); - void scrollRightOfLayout(Poincare::ExpressionLayout * layout); - void scrollToBaselinedRect(KDRect rect, KDCoordinate baseline); - void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout, bool forceCursorRightOfLayout = false); - - class ContentView : public View { - public: - ContentView(Poincare::ExpressionLayout * expressionLayout); - bool isEditing() const { return m_isEditing; } - void setEditing(bool isEditing); - void setBackgroundColor(KDColor c); - void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; } - void cursorPositionChanged(); - KDRect cursorRect(); - Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; } - const ExpressionView * expressionView() const { return &m_expressionView; } - ExpressionView * editableExpressionView() { return &m_expressionView; } - void clearLayout(); - /* View */ - KDSize minimalSizeForOptimalDisplay() const override; - private: - enum class Position { - Top, - Bottom - }; - int numberOfSubviews() const override { return 2; } - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - void layoutCursorSubview(); - Poincare::ExpressionLayoutCursor m_cursor; - ExpressionView m_expressionView; - TextCursorView m_cursorView; - bool m_isEditing; - }; - ContentView m_contentView; - ExpressionLayoutFieldDelegate * m_delegate; -}; - -#endif diff --git a/escher/include/escher/expression_layout_field_delegate.h b/escher/include/escher/expression_layout_field_delegate.h deleted file mode 100644 index 90d68f033..000000000 --- a/escher/include/escher/expression_layout_field_delegate.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H -#define ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H - -#include -#include - -class ExpressionLayoutField; - -class ExpressionLayoutFieldDelegate { -public: - virtual bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0; - virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0; - virtual bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) { return false; } - virtual bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { return false; } - virtual void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) {} - virtual Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) = 0; -}; - -#endif diff --git a/escher/include/escher/expression_table_cell.h b/escher/include/escher/expression_table_cell.h index da87ab8ee..c81e09118 100644 --- a/escher/include/escher/expression_table_cell.h +++ b/escher/include/escher/expression_table_cell.h @@ -9,7 +9,7 @@ public: ExpressionTableCell(Layout layout = Layout::Horizontal); View * labelView() const override; void setHighlighted(bool highlight) override; - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + void setLayoutRef(Poincare::LayoutRef layoutR); Poincare::LayoutRef layoutRef() const override { return m_labelExpressionView.layoutRef(); } private: ExpressionView m_labelExpressionView; diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index d391d3ba5..e34b779e4 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -16,13 +16,8 @@ class ExpressionView : public View { public: ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); - - Poincare::ExpressionLayout * expressionLayout() const; - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); - Poincare::LayoutRef layoutRef() const { return m_layoutRef; } void setLayoutRef(Poincare::LayoutRef layoutRef); - void drawRect(KDContext * ctx, KDRect rect) const override; void setBackgroundColor(KDColor backgroundColor); void setTextColor(KDColor textColor); @@ -37,8 +32,7 @@ private: * layout is always possessed by a controller which only gives a pointer to * the expression view (without cloning it). The named controller is then * responsible for freeing the expression layout when required. */ - Poincare::ExpressionLayout * m_expressionLayout; - Poincare::LayoutRef m_layoutRef; + mutable Poincare::LayoutRef m_layoutRef; // TODO find better way to have minimalSizeForOptimalDisplay const float m_horizontalAlignment; float m_verticalAlignment; KDColor m_textColor; diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h index 8dd6757f7..84fcf1468 100644 --- a/escher/include/escher/input_view_controller.h +++ b/escher/include/escher/input_view_controller.h @@ -2,7 +2,7 @@ #define ESCHER_INPUT_VIEW_CONTROLLER_H #include -#include +#include #include #include #include @@ -12,9 +12,9 @@ /* TODO Implement a split view. Because we use a modal view, the main view is * redrawn underneath the modal view, which is visible and ugly. */ -class InputViewController : public ModalViewController, TextFieldDelegate, ExpressionLayoutFieldDelegate { +class InputViewController : public ModalViewController, TextFieldDelegate, LayoutFieldDelegate { public: - InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); + InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate); void edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction); const char * textBody(); void abortEditionAndDismiss(); @@ -26,19 +26,18 @@ public: bool textFieldDidAbortEditing(TextField * textField) override; Toolbox * toolboxForTextInput(TextInput * textInput) override; - /* ExpressionLayoutFieldDelegate */ - bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override; - bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override; - bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override; - void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override; - Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; + /* LayoutFieldDelegate */ + bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override; + bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override; + bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override; + bool layoutFieldDidAbortEditing(LayoutField * layoutField) override; + void layoutFieldDidChangeSize(LayoutField * layoutField) override; + Toolbox * toolboxForLayoutField(LayoutField * layoutField) override; private: class ExpressionFieldController : public ViewController { public: - ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate); - ~ExpressionFieldController(); + ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate); ExpressionFieldController(const ExpressionFieldController& other) = delete; ExpressionFieldController(ExpressionFieldController&& other) = delete; ExpressionFieldController& operator=(const ExpressionFieldController& other) = delete; @@ -48,7 +47,7 @@ private: ExpressionField * expressionField() { return &m_expressionField; } private: static constexpr int k_bufferLength = TextField::maxBufferSize(); - Poincare::ExpressionLayout * m_layout; + Poincare::LayoutRef m_layout; char m_textBuffer[k_bufferLength]; ExpressionField m_expressionField; }; @@ -58,7 +57,7 @@ private: Invocation m_successAction; Invocation m_failureAction; TextFieldDelegate * m_textFieldDelegate; - ExpressionLayoutFieldDelegate * m_expressionLayoutFieldDelegate; + LayoutFieldDelegate * m_layoutFieldDelegate; bool m_inputViewHeightIsMaximal; }; diff --git a/escher/include/escher/message_table_cell_with_chevron_and_expression.h b/escher/include/escher/message_table_cell_with_chevron_and_expression.h index ae8b45c7d..0156a5c36 100644 --- a/escher/include/escher/message_table_cell_with_chevron_and_expression.h +++ b/escher/include/escher/message_table_cell_with_chevron_and_expression.h @@ -9,7 +9,7 @@ public: MessageTableCellWithChevronAndExpression(I18n::Message message = (I18n::Message)0, KDText::FontSize size = KDText::FontSize::Small); View * subAccessoryView() const override; void setHighlighted(bool highlight) override; - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); + void setLayoutRef(Poincare::LayoutRef layoutR); private: ExpressionView m_subtitleView; }; diff --git a/escher/src/even_odd_expression_cell.cpp b/escher/src/even_odd_expression_cell.cpp index fa56c2cbd..5ebe03bb7 100644 --- a/escher/src/even_odd_expression_cell.cpp +++ b/escher/src/even_odd_expression_cell.cpp @@ -23,8 +23,8 @@ void EvenOddExpressionCell::setEven(bool even) { m_expressionView.setBackgroundColor(backgroundColor()); } -void EvenOddExpressionCell::setExpressionLayout(ExpressionLayout * expressionLayout) { - m_expressionView.setExpressionLayout(expressionLayout); +void EvenOddExpressionCell::setLayoutRef(LayoutRef layoutR) { + m_expressionView.setLayoutRef(layoutR); } void EvenOddExpressionCell::setBackgroundColor(KDColor backgroundColor) { diff --git a/escher/src/expression_field.cpp b/escher/src/expression_field.cpp index 2f12f49d9..4450d1f6c 100644 --- a/escher/src/expression_field.cpp +++ b/escher/src/expression_field.cpp @@ -2,11 +2,11 @@ #include #include -ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::LayoutRef layout, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : Responder(parentResponder), View(), m_textField(parentResponder, textBuffer, textBuffer, textBufferLength, textFieldDelegate, false, KDText::FontSize::Large, 0.0f, 0.5f, KDColorBlack, KDColorWhite), - m_expressionLayoutField(parentResponder, layout, expressionLayoutFieldDelegate), + m_layoutField(parentResponder, layout, layoutFieldDelegate), m_textBuffer(textBuffer), m_textBufferLength(textBufferLength) { @@ -15,9 +15,9 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, m_textField.setBackgroundColor(KDColorWhite); m_textField.setColorsBackground(true); // Initialize layout field - m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); - m_expressionLayoutField.setBackgroundColor(KDColorWhite); - m_expressionLayoutField.setColorsBackground(true); + m_layoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin); + m_layoutField.setBackgroundColor(KDColorWhite); + m_layoutField.setColorsBackground(true); } void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { @@ -25,19 +25,19 @@ void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) { m_textField.setEditing(isEditing, reinitDraftBuffer); } else { if (reinitDraftBuffer) { - m_expressionLayoutField.clearLayout(); + m_layoutField.clearLayout(); } - m_expressionLayoutField.setEditing(isEditing); + m_layoutField.setEditing(isEditing); } } bool ExpressionField::isEditing() const { - return editionIsInTextField() ? m_textField.isEditing() : m_expressionLayoutField.isEditing(); + return editionIsInTextField() ? m_textField.isEditing() : m_layoutField.isEditing(); } const char * ExpressionField::text() { if (!editionIsInTextField()) { - m_expressionLayoutField.writeTextInBuffer(m_textBuffer, m_textBufferLength); + m_layoutField.writeTextInBuffer(m_textBuffer, m_textBufferLength); } return m_textBuffer; } @@ -46,8 +46,8 @@ void ExpressionField::setText(const char * text) { if (editionIsInTextField()) { m_textField.setText(text); } else { - m_expressionLayoutField.clearLayout(); - m_expressionLayoutField.handleEventWithText(text, false, true); + m_layoutField.clearLayout(); + m_layoutField.handleEventWithText(text, false, true); } } @@ -56,17 +56,17 @@ View * ExpressionField::subviewAtIndex(int index) { if (editionIsInTextField()) { return &m_textField; } - return &m_expressionLayoutField; + return &m_layoutField; } void ExpressionField::layoutSubviews() { KDRect inputViewFrame(0, k_separatorThickness, bounds().width(), bounds().height() - k_separatorThickness); if (editionIsInTextField()) { m_textField.setFrame(inputViewFrame); - m_expressionLayoutField.setFrame(KDRectZero); + m_layoutField.setFrame(KDRectZero); return; } - m_expressionLayoutField.setFrame(inputViewFrame); + m_layoutField.setFrame(inputViewFrame); m_textField.setFrame(KDRectZero); } @@ -81,7 +81,7 @@ void ExpressionField::drawRect(KDContext * ctx, KDRect rect) const { } bool ExpressionField::handleEvent(Ion::Events::Event event) { - return editionIsInTextField() ? m_textField.handleEvent(event) : m_expressionLayoutField.handleEvent(event); + return editionIsInTextField() ? m_textField.handleEvent(event) : m_layoutField.handleEvent(event); } KDSize ExpressionField::minimalSizeForOptimalDisplay() const { @@ -93,7 +93,7 @@ bool ExpressionField::editionIsInTextField() const { } bool ExpressionField::isEmpty() const { - return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_expressionLayoutField.hasText(); + return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_layoutField.hasText(); } bool ExpressionField::heightIsMaximal() const { @@ -104,7 +104,7 @@ bool ExpressionField::handleEventWithText(const char * text, bool indentation, b if (editionIsInTextField()) { return m_textField.handleEventWithText(text, indentation, forceCursorRightOfText); } else { - return m_expressionLayoutField.handleEventWithText(text, indentation, forceCursorRightOfText); + return m_layoutField.handleEventWithText(text, indentation, forceCursorRightOfText); } } @@ -112,7 +112,7 @@ KDCoordinate ExpressionField::inputViewHeight() const { return k_separatorThickness + (editionIsInTextField() ? k_textFieldHeight : min(maximalHeight(), - max(k_textFieldHeight, m_expressionLayoutField.minimalSizeForOptimalDisplay().height() + 2*k_verticalMargin ))); + max(k_textFieldHeight, m_layoutField.minimalSizeForOptimalDisplay().height() + 2*k_verticalMargin ))); } KDCoordinate ExpressionField::maximalHeight() const { diff --git a/escher/src/expression_layout_field.cpp b/escher/src/expression_layout_field.cpp deleted file mode 100644 index f32337381..000000000 --- a/escher/src/expression_layout_field.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) : - ScrollableView(parentResponder, &m_contentView, this), - m_contentView(expressionLayout), - m_delegate(delegate) -{ -} - -bool ExpressionLayoutField::isEditing() const { - return m_contentView.isEditing(); -} - -void ExpressionLayoutField::setEditing(bool isEditing) { - m_contentView.setEditing(isEditing); -} - -void ExpressionLayoutField::clearLayout() { - m_contentView.clearLayout(); -} - -void ExpressionLayoutField::scrollToCursor() { - scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline()); -} - -Toolbox * ExpressionLayoutField::toolbox() { - if (m_delegate) { - return m_delegate->toolboxForExpressionLayoutField(this); - } - return nullptr; -} - -bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) { - bool didHandleEvent = false; - bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded(); - bool moveEventChangedLayout = false; - if (privateHandleMoveEvent(event, &moveEventChangedLayout)) { - if (!isEditing()) { - setEditing(true); - } - shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout; - didHandleEvent = true; - } else if (privateHandleEvent(event)) { - shouldRecomputeLayout = true; - didHandleEvent = true; - } - if (didHandleEvent) { - shouldRecomputeLayout = m_contentView.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout; - if (!shouldRecomputeLayout) { - m_contentView.cursorPositionChanged(); - scrollToCursor(); - } else { - reload(); - } - return true; - } - m_contentView.cursor()->hideEmptyLayoutIfNeeded(); - return false; -} - -bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event) { - return m_delegate->expressionLayoutFieldShouldFinishEditing(this, event); -} - -KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const { - KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay(); - return KDSize(contentViewSize.width(), contentViewSize.height()); -} - -bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) { - Poincare::ExpressionLayoutCursor result; - if (event == Ion::Events::Left) { - result = m_contentView.cursor()->cursorOnLeft(shouldRecomputeLayout); - } else if (event == Ion::Events::Right) { - result = m_contentView.cursor()->cursorOnRight(shouldRecomputeLayout); - } else if (event == Ion::Events::Up) { - result = m_contentView.cursor()->cursorAbove(shouldRecomputeLayout); - } else if (event == Ion::Events::Down) { - result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout); - } else if (event == Ion::Events::ShiftLeft) { - *shouldRecomputeLayout = true; - if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) { - *shouldRecomputeLayout = true; - } - result.setPointedExpressionLayout(expressionLayout()); - result.setPosition(Poincare::ExpressionLayoutCursor::Position::Left); - } else if (event == Ion::Events::ShiftRight) { - if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) { - *shouldRecomputeLayout = true; - } - result.setPointedExpressionLayout(expressionLayout()); - result.setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - } - if (result.isDefined()) { - m_contentView.setCursor(result); - return true; - } - return false; -} - -bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) { - if (m_delegate && m_delegate->expressionLayoutFieldDidReceiveEvent(this, event)) { - return true; - } - if (Responder::handleEvent(event)) { - /* The only event Responder handles is 'Toolbox' displaying. In that case, - * the ExpressionLayoutField is forced into editing mode. */ - if (!isEditing()) { - setEditing(true); - } - return true; - } - if (isEditing() && expressionLayoutFieldShouldFinishEditing(event)) { - setEditing(false); - if (m_delegate->expressionLayoutFieldDidFinishEditing(this, expressionLayout(), event)) { - clearLayout(); - } - return true; - } - if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) { - setEditing(true); - m_contentView.cursor()->setPointedExpressionLayout(expressionLayout()); - m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - return true; - } - if (event == Ion::Events::Back && isEditing()) { - clearLayout(); - setEditing(false); - m_delegate->expressionLayoutFieldDidAbortEditing(this); - return true; - } - if (event.hasText() || event == Ion::Events::Paste || event == Ion::Events::Backspace) { - if (!isEditing()) { - setEditing(true); - } - if (event.hasText()) { - handleEventWithText(event.text()); - } else if (event == Ion::Events::Paste) { - handleEventWithText(Clipboard::sharedClipboard()->storedText(), false, true); - } else { - assert(event == Ion::Events::Backspace); - m_contentView.cursor()->performBackspace(); - } - return true; - } - if (event == Ion::Events::Clear && isEditing()) { - clearLayout(); - return true; - } - return false; -} - -void ExpressionLayoutField::reload() { - KDSize previousSize = minimalSizeForOptimalDisplay(); - expressionLayout()->invalidAllSizesPositionsAndBaselines(); - KDSize newSize = minimalSizeForOptimalDisplay(); - if (m_delegate && previousSize.height() != newSize.height()) { - m_delegate->expressionLayoutFieldDidChangeSize(this); - } - m_contentView.cursorPositionChanged(); - scrollToCursor(); - markRectAsDirty(bounds()); -} - -bool ExpressionLayoutField::hasText() const { - return expressionLayout()->hasText(); -} - -int ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) { - return expressionLayout()->writeTextInBuffer(buffer, bufferLength); -} - -bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { - if (text[0] == 0) { - // The text is empty - return true; - } - - int currentNumberOfLayouts = m_contentView.expressionView()->numberOfLayouts(); - if (currentNumberOfLayouts >= k_maxNumberOfLayouts - 6) { - /* We add -6 because in some cases (Ion::Events::Division, - * Ion::Events::Exp...) we let the layout cursor handle the layout insertion - * and these events may add at most 6 layouts (e.g *10^•). */ - return true; - } - - // Handle special cases - if (strcmp(text, Ion::Events::Division.text()) == 0) { - m_contentView.cursor()->addFractionLayoutAndCollapseSiblings(); - } else if (strcmp(text, Ion::Events::Exp.text()) == 0) { - m_contentView.cursor()->addEmptyExponentialLayout(); - } else if (strcmp(text, Ion::Events::Power.text()) == 0) { - m_contentView.cursor()->addEmptyPowerLayout(); - } else if (strcmp(text, Ion::Events::Sqrt.text()) == 0) { - m_contentView.cursor()->addEmptySquareRootLayout(); - } else if (strcmp(text, Ion::Events::Square.text()) == 0) { - m_contentView.cursor()->addEmptySquarePowerLayout(); - } else if (strcmp(text, Ion::Events::EE.text()) == 0) { - m_contentView.cursor()->addEmptyTenPowerLayout(); - } else if ((strcmp(text, "[") == 0) || (strcmp(text, "]") == 0)) { - m_contentView.cursor()->addEmptyMatrixLayout(); - } else { - Poincare::Expression * resultExpression = Poincare::Expression::parse(text); - if (resultExpression == nullptr) { - m_contentView.cursor()->insertText(text); - return true; - } - Poincare::ExpressionLayout * resultLayout = resultExpression->createLayout(); - delete resultExpression; - if (currentNumberOfLayouts + resultLayout->numberOfDescendants(true) >= k_maxNumberOfLayouts) { - delete resultLayout; - return true; - } - // Find the pointed layout. - Poincare::ExpressionLayout * pointedLayout = nullptr; - if (strcmp(text, I18n::translate(I18n::Message::RandomCommandWithArg)) == 0) { - /* Special case: if the text is "random()", the cursor should not be set - * inside the parentheses. */ - pointedLayout = resultLayout; - } else if (resultLayout->isHorizontal()) { - /* If the layout is horizontal, pick the first open parenthesis. For now, - * all horizontal layouts in MathToolbox have parentheses. */ - for (int i = 0; i < resultLayout->numberOfChildren(); i++) { - if (resultLayout->editableChild(i)->isLeftParenthesis()) { - pointedLayout = resultLayout->editableChild(i); - break; - } - } - } - /* Insert the layout. If pointedLayout is nullptr, the cursor will be on the - * right of the inserted layout. */ - insertLayoutAtCursor(resultLayout, pointedLayout, forceCursorRightOfText); - } - return true; -} - -Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() const { - return m_contentView.expressionView()->expressionLayout(); -} - -char ExpressionLayoutField::XNTChar() { - return m_contentView.cursor()->pointedExpressionLayout()->XNTChar(); -} - -void ExpressionLayoutField::setBackgroundColor(KDColor c) { - ScrollableView::setBackgroundColor(c); - m_contentView.setBackgroundColor(c); -} - -void ExpressionLayoutField::scrollRightOfLayout(Poincare::ExpressionLayout * layout) { - KDRect layoutRect(layout->absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layout->size()); - scrollToBaselinedRect(layoutRect, layout->baseline()); -} - -void ExpressionLayoutField::scrollToBaselinedRect(KDRect rect, KDCoordinate baseline) { - scrollToContentRect(rect, true); - // Show the rect area around its baseline - KDCoordinate underBaseline = rect.height() - baseline; - KDCoordinate minAroundBaseline = min(baseline, underBaseline); - minAroundBaseline = min(minAroundBaseline, bounds().height() / 2); - KDRect balancedRect(rect.x(), rect.y() + baseline - minAroundBaseline, rect.width(), 2 * minAroundBaseline); - scrollToContentRect(balancedRect, true); -} - -void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout, bool forceCursorRightOfLayout) { - if (layout == nullptr) { - return; - } - m_contentView.cursor()->showEmptyLayoutIfNeeded(); - bool layoutWillBeMerged = layout->isHorizontal(); - Poincare::ExpressionLayout * lastMergedLayoutChild = layoutWillBeMerged ? layout->editableChild(layout->numberOfChildren()-1) : nullptr; - m_contentView.cursor()->addLayoutAndMoveCursor(layout); - if (!forceCursorRightOfLayout) { - if (pointedLayout != nullptr && (pointedLayout != layout || !layoutWillBeMerged)) { - m_contentView.cursor()->setPointedExpressionLayout(pointedLayout); - m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - } else if (!layoutWillBeMerged) { - m_contentView.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting()); - m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - } - } else if (!layoutWillBeMerged) { - m_contentView.cursor()->setPointedExpressionLayout(layout); - m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); - } - m_contentView.cursor()->pointedExpressionLayout()->addGreySquaresToAllMatrixAncestors(); - m_contentView.cursor()->hideEmptyLayoutIfNeeded(); - reload(); - if (!layoutWillBeMerged) { - scrollRightOfLayout(layout); - } else { - assert(lastMergedLayoutChild != nullptr); - scrollRightOfLayout(lastMergedLayoutChild); - } - scrollToCursor(); -} diff --git a/escher/src/expression_layout_field_content_view.cpp b/escher/src/expression_layout_field_content_view.cpp deleted file mode 100644 index 8b4c5b0d6..000000000 --- a/escher/src/expression_layout_field_content_view.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -using namespace Poincare; - -ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) : - m_cursor(expressionLayout, ExpressionLayoutCursor::Position::Right), - m_expressionView(0.0f, 0.5f, KDColorBlack, KDColorWhite), - m_cursorView(), - m_isEditing(false) -{ - m_expressionView.setExpressionLayout(expressionLayout); -} - -void ExpressionLayoutField::ContentView::setEditing(bool isEditing) { - m_isEditing = isEditing; - markRectAsDirty(bounds()); - layoutSubviews(); -} - -void ExpressionLayoutField::ContentView::setBackgroundColor(KDColor c) { - m_expressionView.setBackgroundColor(c); -} - -void ExpressionLayoutField::ContentView::cursorPositionChanged() { - layoutCursorSubview(); -} - -KDRect ExpressionLayoutField::ContentView::cursorRect() { - return m_cursorView.frame(); -} - -void ExpressionLayoutField::ContentView::clearLayout() { - m_cursor.clearLayout(); -} - -KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const { - KDSize evSize = m_expressionView.minimalSizeForOptimalDisplay(); - return KDSize(evSize.width() + ExpressionLayoutCursor::k_cursorWidth, evSize.height()); -} - -View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) { - assert(index >= 0 && index < 2); - View * m_views[] = {&m_expressionView, &m_cursorView}; - return m_views[index]; -} - -void ExpressionLayoutField::ContentView::layoutSubviews() { - m_expressionView.setFrame(bounds()); - layoutCursorSubview(); -} - -void ExpressionLayoutField::ContentView::layoutCursorSubview() { - if (!m_isEditing) { - m_cursorView.setFrame(KDRectZero); - return; - } - KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin(); - ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayout(); - ExpressionLayoutCursor::Position cursorPosition = m_cursor.position(); - ExpressionLayoutCursor eqCursor = pointedLayout->equivalentCursor(m_cursor); - if (pointedLayout->hasChild(eqCursor.pointedExpressionLayout())) { - pointedLayout = eqCursor.pointedExpressionLayout(); - cursorPosition = eqCursor.position(); - } - KDPoint cursoredExpressionViewOrigin = pointedLayout->absoluteOrigin(); - KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x(); - if (cursorPosition == ExpressionLayoutCursor::Position::Right) { - cursorX += pointedLayout->size().width(); - } - KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayout->baseline() - m_cursor.baseline()); - m_cursorView.setFrame(KDRect(cursorTopLeftPosition, ExpressionLayoutCursor::k_cursorWidth, m_cursor.cursorHeight())); -} diff --git a/escher/src/expression_table_cell.cpp b/escher/src/expression_table_cell.cpp index 2d27687ec..6dfbbb321 100644 --- a/escher/src/expression_table_cell.cpp +++ b/escher/src/expression_table_cell.cpp @@ -18,7 +18,7 @@ void ExpressionTableCell::setHighlighted(bool highlight) { m_labelExpressionView.setBackgroundColor(backgroundColor); } -void ExpressionTableCell::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) { - m_labelExpressionView.setExpressionLayout(expressionLayout); +void ExpressionTableCell::setLayoutRef(Poincare::LayoutRef layoutR) { + m_labelExpressionView.setLayoutRef(layoutR); layoutSubviews(); } diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 0c935bece..60e7cff3f 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -3,7 +3,6 @@ using namespace Poincare; ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) : - m_expressionLayout(nullptr), m_layoutRef(nullptr), m_horizontalAlignment(horizontalAlignment), m_verticalAlignment(verticalAlignment), @@ -12,16 +11,6 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen { } -//TODO remove -ExpressionLayout * ExpressionView::expressionLayout() const { - return m_expressionLayout; -} - -void ExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) { - m_expressionLayout = expressionLayout; - markRectAsDirty(bounds()); -} - void ExpressionView::setLayoutRef(LayoutRef layoutR) { m_layoutRef = layoutR; markRectAsDirty(bounds()); @@ -48,18 +37,18 @@ void ExpressionView::setAlignment(float horizontalAlignment, float verticalAlign } int ExpressionView::numberOfLayouts() const { - return m_expressionLayout->numberOfDescendants(true); + return m_layoutRef.numberOfDescendants(true); } KDSize ExpressionView::minimalSizeForOptimalDisplay() const { - if (m_expressionLayout == nullptr) { + if (!m_layoutRef.isDefined()) { return KDSizeZero; } - return m_expressionLayout->size(); + return m_layoutRef.layoutSize(); } KDPoint ExpressionView::drawingOrigin() const { - KDSize expressionSize = m_expressionLayout->size(); + KDSize expressionSize = m_layoutRef.layoutSize(); return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), max(0, (m_frame.height() - expressionSize.height())/2)); } @@ -69,7 +58,7 @@ KDPoint ExpressionView::absoluteDrawingOrigin() const { void ExpressionView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, m_backgroundColor); - if (m_expressionLayout != nullptr) { - m_expressionLayout->draw(ctx, drawingOrigin(), m_textColor, m_backgroundColor); + if (m_layoutRef.isDefined()) { + m_layoutRef.draw(ctx, drawingOrigin(), m_textColor, m_backgroundColor); } } diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp index b73d77c38..9545bcb96 100644 --- a/escher/src/input_view_controller.cpp +++ b/escher/src/input_view_controller.cpp @@ -1,32 +1,28 @@ #include #include #include -#include +#include #include -InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : ViewController(parentResponder), - m_layout(new Poincare::HorizontalLayout()), - m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate) + m_layout(Poincare::HorizontalLayoutRef()), + m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, layoutFieldDelegate) { m_textBuffer[0] = 0; } -InputViewController::ExpressionFieldController::~ExpressionFieldController() { - delete m_layout; -} - void InputViewController::ExpressionFieldController::didBecomeFirstResponder() { app()->setFirstResponder(&m_expressionField); } -InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) : +InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : ModalViewController(parentResponder, child), m_expressionFieldController(this, this, this), m_successAction(Invocation(nullptr, nullptr)), m_failureAction(Invocation(nullptr, nullptr)), m_textFieldDelegate(textFieldDelegate), - m_expressionLayoutFieldDelegate(expressionLayoutFieldDelegate), + m_layoutFieldDelegate(layoutFieldDelegate), m_inputViewHeightIsMaximal(false) { } @@ -74,27 +70,27 @@ Toolbox * InputViewController::toolboxForTextInput(TextInput * input) { return m_textFieldDelegate->toolboxForTextInput(input); } -bool InputViewController::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { +bool InputViewController::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) { return event == Ion::Events::OK || event == Ion::Events::EXE; } -bool InputViewController::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) { - return m_expressionLayoutFieldDelegate->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event); +bool InputViewController::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) { + return m_layoutFieldDelegate->layoutFieldDidReceiveEvent(layoutField, event); } -bool InputViewController::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) { +bool InputViewController::layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) { inputViewDidFinishEditing(); - m_expressionLayoutFieldDelegate->expressionLayoutFieldDidFinishEditing(expressionLayoutField, layout, event); + m_layoutFieldDelegate->layoutFieldDidFinishEditing(layoutField, layoutR, event); return true; } -bool InputViewController::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { +bool InputViewController::layoutFieldDidAbortEditing(LayoutField * layoutField) { inputViewDidAbortEditing(); - m_expressionLayoutFieldDelegate->expressionLayoutFieldDidAbortEditing(expressionLayoutField); + m_layoutFieldDelegate->layoutFieldDidAbortEditing(layoutField); return true; } -void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) { +void InputViewController::layoutFieldDidChangeSize(LayoutField * layoutField) { /* Reload the view only if the ExpressionField height actually changes, i.e. * not if the height is already maximal and stays maximal. */ bool newInputViewHeightIsMaximal = m_expressionFieldController.expressionField()->heightIsMaximal(); @@ -104,8 +100,8 @@ void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutFie } } -Toolbox * InputViewController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) { - return m_expressionLayoutFieldDelegate->toolboxForExpressionLayoutField(expressionLayoutField); +Toolbox * InputViewController::toolboxForLayoutField(LayoutField * layoutField) { + return m_layoutFieldDelegate->toolboxForLayoutField(layoutField); } void InputViewController::inputViewDidFinishEditing() { diff --git a/escher/src/message_table_cell_with_chevron_and_expression.cpp b/escher/src/message_table_cell_with_chevron_and_expression.cpp index 9d8dc1cb0..a77bf3af3 100644 --- a/escher/src/message_table_cell_with_chevron_and_expression.cpp +++ b/escher/src/message_table_cell_with_chevron_and_expression.cpp @@ -17,8 +17,8 @@ void MessageTableCellWithChevronAndExpression::setHighlighted(bool highlight) { m_subtitleView.setBackgroundColor(backgroundColor); } -void MessageTableCellWithChevronAndExpression::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) { - m_subtitleView.setExpressionLayout(expressionLayout); +void MessageTableCellWithChevronAndExpression::setLayoutRef(Poincare::LayoutRef layoutR) { + m_subtitleView.setLayoutRef(layoutR); reloadCell(); layoutSubviews(); } diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 5737ce1d3..91a1b852f 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -43,6 +43,10 @@ public: TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } + void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite) { + return this->typedNode()->draw(ctx, p, expressionColor, backgroundColor); + } + bool isHorizontal() const { return this->typedNode()->isHorizontal(); } bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } bool hasText() { return this->typedNode()->hasText(); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 654d2c43a..478a858b8 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -222,7 +222,7 @@ LayoutRef Decimal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, Comple return CharLayoutRef('a'); //TODO /*char buffer[k_maxBufferSize]; int numberOfChars = convertToText(buffer, k_maxBufferSize, floatDisplayMode, PrintFloat::k_numberOfStoredSignificantDigits); - return LayoutEngine::createStringLayout(buffer, numberOfChars); + return LayoutEngine::createStringLayout(buffer, numberOfChars);*/ } Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { @@ -243,7 +243,7 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { } else { denominator = Integer::Power(Integer(10), Integer(numberOfDigits-1-m_exponent)); } - return replaceWith(new Rational(numerator, denominator), true);*/ + return replaceWith(new Rational(numerator, denominator), true); } Expression * Decimal::shallowBeautify(Context & context, AngleUnit angleUnit) { From f4ffa06add353dbce2bd12d9d9fc0402032cd3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 18:37:09 +0200 Subject: [PATCH 087/156] [poincare] Add LayoutCursor::cursorHeight() --- poincare/include/poincare/layout_cursor.h | 7 +++--- poincare/include/poincare/tree_reference.h | 1 + poincare/src/layout_cursor.cpp | 26 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index d5363eb62..ba89fb659 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -61,7 +61,7 @@ public: } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } - int cursorHeight() { return 1; } //TODO + KDCoordinate cursorHeight(); int baseline() { return 1; } //TODO LayoutCursor clone() const { return LayoutCursor(m_layoutRef, m_position); @@ -112,11 +112,12 @@ public: void addLayoutAndMoveCursor(LayoutRef l) {} //TODO private: + constexpr static KDCoordinate k_cursorHeight = 18; LayoutCursor(LayoutNode * node, Position position = Position::Right) : m_layoutRef(node), m_position(position) - { - } + {} + KDCoordinate layoutHeight(); LayoutRef m_layoutRef; Position m_position; }; diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 0ffead61e..9193120d2 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -75,6 +75,7 @@ public: // Hierarchy bool hasChild(TreeReference t) const { return node()->hasChild(t.node()); }; + bool hasSibling(TreeReference t) const { return node()->hasSibling(t.node()); }; int numberOfChildren() const { return node()->numberOfChildren(); } TreeReference parent() const { return TreeReference(node()->parentTree()); } TreeReference treeChildAtIndex(int i) const { return TreeReference(node()->childTreeAtIndex(i)); } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 544ca6a09..5be1a3240 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -4,6 +4,13 @@ namespace Poincare { +/* Getters and setters */ + +KDCoordinate LayoutCursor::cursorHeight() { + KDCoordinate height = layoutHeight(); + return height == 0 ? k_cursorHeight : height; +} + /* Comparison */ bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { @@ -37,4 +44,23 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { layoutReference().typedNode()->moveCursorDown(this, shouldRecomputeLayout); } +/* Private */ + +KDCoordinate LayoutCursor::layoutHeight() { + LayoutRef equivalentLayoutRef = m_layoutRef.equivalentCursor(this).layoutReference(); + if (m_layoutRef.hasChild(equivalentLayoutRef)) { + return equivalentLayoutRef.layoutSize().height(); + } + KDCoordinate pointedLayoutHeight = m_layoutRef.layoutSize().height(); + if (m_layoutRef.hasSibling(equivalentLayoutRef)) { + KDCoordinate equivalentLayoutHeight = equivalentLayoutRef.layoutSize().height(); + KDCoordinate pointedLayoutBaseline = m_layoutRef.baseline(); + KDCoordinate equivalentLayoutBaseline = equivalentLayoutRef.baseline(); + return max(pointedLayoutBaseline, equivalentLayoutBaseline) + + max(pointedLayoutHeight - pointedLayoutBaseline, equivalentLayoutHeight - equivalentLayoutBaseline); + } + return pointedLayoutHeight; + +} + } From e7b2589ec8203700c4fb653e44f75876093a207b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 3 Jul 2018 18:44:07 +0200 Subject: [PATCH 088/156] [poincare] Add LayoutCursor::baseline() --- poincare/include/poincare/layout_cursor.h | 2 +- poincare/src/layout_cursor.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index ba89fb659..cf24f8533 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -62,7 +62,7 @@ public: Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } KDCoordinate cursorHeight(); - int baseline() { return 1; } //TODO + KDCoordinate baseline(); LayoutCursor clone() const { return LayoutCursor(m_layoutRef, m_position); } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 5be1a3240..3386f5883 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -11,6 +11,20 @@ KDCoordinate LayoutCursor::cursorHeight() { return height == 0 ? k_cursorHeight : height; } +KDCoordinate LayoutCursor::baseline() { + if (layoutHeight() == 0) { + return k_cursorHeight/2; + } + KDCoordinate layoutBaseline = m_layoutRef.baseline(); + LayoutRef equivalentLayoutRef = m_layoutRef.equivalentCursor(this).layoutReference(); + if (m_layoutRef.hasChild(equivalentLayoutRef)) { + return equivalentLayoutRef.baseline(); + } else if (m_layoutRef.hasSibling(equivalentLayoutRef)) { + return max(layoutBaseline, equivalentLayoutRef.baseline()); + } + return layoutBaseline; +} + /* Comparison */ bool LayoutCursor::isEquivalentTo(LayoutCursor cursor) { From 6a77da86f7978719ea8c50cd2436a094b118ffc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 4 Jul 2018 09:54:34 +0200 Subject: [PATCH 089/156] Better handling of TreeRef to nullptr --- poincare/include/poincare/tree_pool.h | 1 + poincare/include/poincare/tree_reference.h | 75 +++++++++++++++++----- poincare/src/tree_pool.cpp | 3 + 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index e88ed52a4..61fecbea2 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -11,6 +11,7 @@ namespace Poincare { class TreePool { friend class TreeNode; public: + static constexpr int NoNodeIdentifier = -1; static TreePool * sharedPool(); // Node diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 9193120d2..2048d5d27 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -32,6 +32,9 @@ public: inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } TreeReference clone() const { + if (!isDefined()){ + return TreeReference(nullptr); + } TreeNode * myNode = node(); if (myNode->isAllocationFailure()) { int allocationFailureNodeId = myNode->allocationFailureNodeIdentifier(); @@ -43,7 +46,7 @@ public: } ~TreeReference() { - if (m_identifier >= 0) { + if (isDefined()) { assert(node()); assert(node()->identifier() == m_identifier); node()->release(); @@ -59,32 +62,64 @@ public: return static_cast(node()); } - bool isDefined() const { return m_identifier >= 0 && node() != nullptr; } //TODO m_identifier != -1 - bool isAllocationFailure() const { return node()->isAllocationFailure(); } + bool isDefined() const { return m_identifier != TreePool::NoNodeIdentifier && node() != nullptr; } + bool isAllocationFailure() const { return isDefined() && node()->isAllocationFailure(); } - int nodeRetainCount() const { return node()->retainCount(); } - void incrementNumberOfChildren(int increment = 1) { return node()->incrementNumberOfChildren(increment); } - void decrementNumberOfChildren(int decrement = 1) { return node()->decrementNumberOfChildren(decrement); } - int numberOfDescendants(bool includeSelf) const { return node()->numberOfDescendants(includeSelf);} + int nodeRetainCount() const { + assert(isDefined()); + return node()->retainCount(); + } + void incrementNumberOfChildren(int increment = 1) { + assert(isDefined()); + node()->incrementNumberOfChildren(increment); + } + void decrementNumberOfChildren(int decrement = 1) { + assert(isDefined()); + node()->decrementNumberOfChildren(decrement); + } + int numberOfDescendants(bool includeSelf) const { + assert(isDefined()); + return node()->numberOfDescendants(includeSelf); + } // Serialization - bool needsParenthesisWithParent(TreeReference parentRef) { return node()->needsParenthesisWithParent(parentRef.node()); } + bool needsParenthesisWithParent(TreeReference parentRef) { + assert(isDefined()); + return node()->needsParenthesisWithParent(parentRef.node()); + } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { + assert(isDefined()); return node()->writeTextInBuffer(buffer, bufferSize, numberOfSignificantDigits); } // Hierarchy - bool hasChild(TreeReference t) const { return node()->hasChild(t.node()); }; - bool hasSibling(TreeReference t) const { return node()->hasSibling(t.node()); }; - int numberOfChildren() const { return node()->numberOfChildren(); } - TreeReference parent() const { return TreeReference(node()->parentTree()); } - TreeReference treeChildAtIndex(int i) const { return TreeReference(node()->childTreeAtIndex(i)); } + bool hasChild(TreeReference t) const { + assert(isDefined()); + return node()->hasChild(t.node()); + } + bool hasSibling(TreeReference t) const { + assert(isDefined()); + return node()->hasSibling(t.node()); + } + int numberOfChildren() const { + assert(isDefined()); + return node()->numberOfChildren(); + } + TreeReference parent() const { + assert(isDefined()); + return TreeReference(node()->parentTree()); + } + TreeReference treeChildAtIndex(int i) const { + assert(isDefined()); + return TreeReference(node()->childTreeAtIndex(i)); + } // Hierarchy operations void addChild(TreeReference t) { return addChildAtIndex(t, 0); } void addChildAtIndex(TreeReference t, int index) { + assert(isDefined()); if (node()->isAllocationFailure()) { return; } @@ -109,18 +144,21 @@ public: } void removeChild(TreeReference t) { + assert(isDefined()); TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); t.node()->release(); node()->decrementNumberOfChildren(); } void removeChildren() { + assert(isDefined()); node()->releaseChildren(); TreePool::sharedPool()->moveChildren(node(), TreePool::sharedPool()->last()); node()->eraseNumberOfChildren(); } void replaceWith(TreeReference t) { + assert(isDefined()); TreeReference p = parent(); if (p.isDefined()) { p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); @@ -128,6 +166,7 @@ public: } void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { + assert(isDefined()); if (newChild.isAllocationFailure()) { replaceWithAllocationFailure(); return; @@ -145,6 +184,7 @@ public: } void replaceWithAllocationFailure() { + assert(isDefined()); TreeReference p = parent(); bool hasParent = p.isDefined(); int indexInParentNode = hasParent ? node()->indexInParent() : -1; @@ -179,6 +219,7 @@ public: } void swapChildren(int i, int j) { + assert(isDefined()); assert(i >= 0 && i < numberOfChildren()); assert(j >= 0 && j < numberOfChildren()); if (i == j) { @@ -207,7 +248,7 @@ public: TreeReference(TreeNode * node) { // TODO Make this protected if (node == nullptr) { - m_identifier = -1; + m_identifier = TreePool::NoNodeIdentifier; } else { setIdentifierAndRetain(node->identifier()); } @@ -225,7 +266,11 @@ protected: } private: void setTo(const TreeReference & tr) { - setIdentifierAndRetain(tr.identifier()); + if (tr.isDefined()) { + setIdentifierAndRetain(tr.identifier()); + } else { + m_identifier = -1; + } } int m_identifier; }; diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index b547b1f00..a23188271 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -10,6 +10,9 @@ TreePool * TreePool::sharedPool() { } TreeNode * TreePool::node(int identifier) const { + if (identifier == NoNodeIdentifier) { + return nullptr; + } if (identifier < 0) { int index = indexOfStaticNode(identifier); assert(index >= 0 && index < MaxNumberOfStaticNodes); From 2eba0825d288674cf11ce582cd8e2963e4adac0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 4 Jul 2018 11:53:26 +0200 Subject: [PATCH 090/156] [poincare] Translate methods to new tree structure --- .../include/poincare/horizontal_layout_node.h | 7 +- poincare/include/poincare/layout_cursor.h | 5 +- poincare/include/poincare/layout_node.h | 9 ++ poincare/include/poincare/layout_reference.h | 58 ++++++---- poincare/include/poincare/tree_node.h | 6 +- poincare/include/poincare/tree_reference.h | 5 +- poincare/src/horizontal_layout_node.cpp | 103 ++++++++++++++++++ poincare/src/layout_cursor.cpp | 16 +++ poincare/src/layout_node.cpp | 69 ++++++++++++ poincare/src/tree_node.cpp | 2 +- 10 files changed, 246 insertions(+), 34 deletions(-) diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index f6dcc9bab..8b60dbaea 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -17,9 +17,11 @@ public: m_numberOfChildren(0) {} - bool isHorizontal() const override { return true; } + void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren); + void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren); // LayoutNode + bool isHorizontal() const override { return true; } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; @@ -46,7 +48,10 @@ protected: KDPoint positionOfChild(LayoutNode * l) override; private: + void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + void privateRemoveChildAtIndex(int index, bool forceRemove); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} + int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); int m_numberOfChildren; }; diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index cf24f8533..04e014c21 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -50,7 +50,6 @@ public: bool isDefined() const { return m_layoutRef.isDefined(); } - /* Getters and setters */ LayoutRef layoutReference() { return m_layoutRef; } int layoutIdentifier() { return m_layoutRef.identifier(); } @@ -97,7 +96,6 @@ public: return result; } /* Layout modification */ - void clearLayout() {} //TODO void addFractionLayoutAndCollapseSiblings() {} //TODO void addEmptyExponentialLayout() {} //TODO void addEmptyPowerLayout() {} //TODO @@ -109,7 +107,8 @@ public: void performBackspace() {} //TODO bool showEmptyLayoutIfNeeded() { return false; } //TODO bool hideEmptyLayoutIfNeeded() { return false; } //TODO - void addLayoutAndMoveCursor(LayoutRef l) {} //TODO + void addLayoutAndMoveCursor(LayoutRef l); + void clearLayout(); private: constexpr static KDCoordinate k_cursorHeight = 18; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index f93a4338c..004d80337 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -25,7 +25,10 @@ public: virtual bool hasText() const { return false; } //TODO virtual char XNTChar() const { return 'x'; } virtual bool isHorizontal() const { return false; } + virtual bool isEmpty() const { return false; } virtual bool isLeftParenthesis() const { return false; } + virtual bool isVerticalOffset() const { return false; } + virtual bool mustHaveLeftSibling() const { return false; } // Rendering void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); @@ -48,6 +51,7 @@ public: // Hierarchy LayoutNode * parent() const { return static_cast(parentTree()); } LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } + LayoutNode * root() { return static_cast(rootTree()); } // Tree navigation virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} @@ -57,9 +61,13 @@ public: virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); //TODO // Tree modification + void addSibling(LayoutCursor * cursor, LayoutNode * sibling); + void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling); + void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO + LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild) {return nullptr; } //TODO protected: // Iterators class Iterator { @@ -102,6 +110,7 @@ protected: bool m_positioned; bool m_sized; private: + virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; }; diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 91a1b852f..dc4f9f403 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -14,11 +14,10 @@ class LayoutReference : public TreeReference { public: using TreeReference::TreeReference; - /* Allow every LayoutReference to be transformed into a - * LayoutReference, i.e. Layout */ - operator LayoutReference() const { - return LayoutReference(this->node()); - } + // Operators + + // Allow every LayoutReference to be transformed into a LayoutRef + operator LayoutReference() const { return LayoutReference(this->node()); } LayoutReference& operator=(LayoutReference& lr) { this->setTo(lr); return *this; @@ -30,36 +29,49 @@ public: inline bool operator==(LayoutReference l) { return this->identifier() == l.identifier(); } inline bool operator!=(LayoutReference l) { return this->identifier() != l.identifier(); } - static TreeNode * FailedAllocationStaticNode(); + // Rendering + void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite) { + return this->typedNode()->draw(ctx, p, expressionColor, backgroundColor); + } + KDSize layoutSize() { return this->typedNode()->layoutSize(); } + KDPoint layoutOrigin() { return this->typedNode()->layoutOrigin(); } + KDPoint absoluteOrigin() { return this->typedNode()->absoluteOrigin(); } + KDCoordinate baseline() { return this->typedNode()->baseline(); } + void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } + // Layout properties + bool isHorizontal() const { return this->typedNode()->isHorizontal(); } + bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } + bool hasText() { return this->typedNode()->hasText(); } + char XNTChar() const { return this->typedNode()->XNTChar(); } + + // Layout modification + bool removeGreySquaresFromAllMatrixAncestors() { return this->typedNode()->removeGreySquaresFromAllMatrixAncestors(); } + bool addGreySquaresToAllMatrixAncestors() { return this->typedNode()->addGreySquaresToAllMatrixAncestors(); } + LayoutReference layoutToPointWhenInserting() { return LayoutReference(this->typedNode()->layoutToPointWhenInserting()); } + + // Cursor LayoutCursor cursor() const; + LayoutCursor equivalentCursor(LayoutCursor * cursor); + + // Hierarchy LayoutReference childAtIndex(int i) { TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); return LayoutReference(treeRefChild.node()); } + LayoutReference root() { return LayoutReference(this->typedNode()->root()); } + // Hierarchy modification void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } + void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } //TODO + void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO + LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); //TODO - void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite) { - return this->typedNode()->draw(ctx, p, expressionColor, backgroundColor); - } - - bool isHorizontal() const { return this->typedNode()->isHorizontal(); } - bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } - bool hasText() { return this->typedNode()->hasText(); } - char XNTChar() const { return this->typedNode()->XNTChar(); } - KDSize layoutSize() { return this->typedNode()->layoutSize(); } - KDPoint layoutOrigin() { return this->typedNode()->layoutOrigin(); } - KDPoint absoluteOrigin() { return this->typedNode()->absoluteOrigin(); } - KDCoordinate baseline() { return this->typedNode()->baseline(); } - LayoutCursor equivalentCursor(LayoutCursor * cursor); - void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } - bool removeGreySquaresFromAllMatrixAncestors() { return this->typedNode()->removeGreySquaresFromAllMatrixAncestors(); } - bool addGreySquaresToAllMatrixAncestors() { return this->typedNode()->addGreySquaresToAllMatrixAncestors(); } - LayoutReference layoutToPointWhenInserting() { return LayoutReference(this->typedNode()->layoutToPointWhenInserting()); } + // Allocation failure + static TreeNode * FailedAllocationStaticNode(); }; typedef LayoutReference LayoutRef; diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 5ffec60c8..5df3cf9db 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -35,9 +35,7 @@ public: } } - virtual const char * description() const { - return "UNKNOWN"; - } + virtual const char * description() const { return "UNKNOWN";} // Serialization virtual bool needsParenthesisWithParent(TreeNode * parentNode) { return false; } //TODO virtual pure and override on expresionNode/layoutNode @@ -66,7 +64,7 @@ public: // Hierarchy TreeNode * parentTree() const; - TreeNode * editableRootTree(); + TreeNode * rootTree(); virtual int numberOfChildren() const = 0; virtual void incrementNumberOfChildren(int increment = 1) {} //TODO Put an assert false virtual void decrementNumberOfChildren(int decrement = 1) {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ? diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 2048d5d27..19aeeb527 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -234,10 +234,11 @@ public: TreePool::sharedPool()->move(secondChild.node(), firstChildNode); } - void mergeChildren(TreeReference t) { + void mergeChildrenAtIndex(TreeReference t, int i) { + assert(i >= 0 && i <= numberOfChildren()); // Steal operands int numberOfNewChildren = t.numberOfChildren(); - TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()->next()); + TreePool::sharedPool()->moveChildren(t.node(), node()->childTreeAtIndex(i)->nextSibling()); t.node()->eraseNumberOfChildren(); // If t is a child, remove it if (node()->hasChild(t.node())) { diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 4268bc074..6e7c23384 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -5,6 +5,26 @@ namespace Poincare { static inline KDCoordinate maxCoordinate(KDCoordinate c1, KDCoordinate c2) { return c1 > c2 ? c1 : c2; } +void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren) { + if (l->isHorizontal()) { + mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren); + } else { + addChildAtIndex(l, index); + } +} + +void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int index, bool removeEmptyChildren) { + /* Remove any empty child that would be next to the inserted layout. + * If the layout to insert starts with a vertical offset layout, any empty + * layout child directly on the left of the inserted layout (if there is one) + * should not be removed: it will be the base for the VerticalOffsetLayout. */ + bool shouldRemoveOnLeft = h->numberOfChildren() == 0 ? true : !(h->childAtIndex(0)->mustHaveLeftSibling()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); + + // Merge the horizontal layout + LayoutRef(this).mergeChildrenAtIndex(LayoutRef(h), newIndex); +} + int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (numberOfChildren() == 0) { if (bufferSize == 0) { @@ -101,4 +121,87 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { return KDPoint(x, y); } +// Private + +void HorizontalLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { + int childrenCount = numberOfChildren(); + // Add the "sibling" as a child. + if (cursor->position() == LayoutCursor::Position::Left) { + int indexForInsertion = 0; + /* If the first child is empty, remove it before adding the layout, unless + * the new sibling needs the empty layout as a base. */ + if (childrenCount > 0 && childAtIndex(0)->isEmpty()) { + if (sibling->mustHaveLeftSibling()) { + indexForInsertion = 1; + } else { + /* We force the removal of the child even followed by a neighbourg + * requiring a left sibling as we are about to add a sibling in first + * position anyway. */ + privateRemoveChildAtIndex(0, true); + } + } + if (moveCursor) { + if (childrenCount > indexForInsertion) { + cursor->setLayoutNode(childAtIndex(indexForInsertion)); + } else { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Right); + } + } + addOrMergeChildAtIndex(sibling, indexForInsertion, false); + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // If the last child is empty, remove it before adding the layout. + if (childrenCount > 0 && childAtIndex(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { + /* Force remove the last child. */ + privateRemoveChildAtIndex(childrenCount - 1, true); + childrenCount--; + } + addOrMergeChildAtIndex(sibling, childrenCount, false); + if (moveCursor) { + cursor->setLayoutNode(this); + } +} + +void HorizontalLayoutNode::privateRemoveChildAtIndex(int index, bool forceRemove) { + /* Remove the child before potentially adding an EmptyLayout. Indeed, adding + * a new child would remove any EmptyLayout surrounding the new child and in + * the case the child to be removed was an Empty layout, it would result in + * removing it twice if we remove it afterwards. */ + removeChild(childAtIndex(index)); + /* If the child to remove is at index 0 and its right sibling must have a left + * sibling (e.g. it is a VerticalOffsetLayout), replace the child with an + * EmptyLayout instead of removing it. */ + + /*if (!forceRemove && index == 0 && numberOfChildren() > 0 && child(0)->mustHaveLeftSibling()) { + addChildAtIndex(new EmptyLayout(), 0); + }*/ //TODO +} + +int HorizontalLayoutNode::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { + int currentNumberOfChildren = numberOfChildren(); + assert(index >= 0 && index <= currentNumberOfChildren); + int newIndex = index; + /* If empty, remove the child that would be on the right of the inserted + * layout. */ + if (newIndex < currentNumberOfChildren) { + LayoutNode * c = childAtIndex(newIndex); + if (c->isEmpty()) { + removeChild(c); + currentNumberOfChildren--; + } + } + /* If empty, remove the child that would be on the left of the inserted + * layout. */ + if (shouldRemoveOnLeft && newIndex - 1 >= 0 && newIndex - 1 <= currentNumberOfChildren -1) { + LayoutNode * c = childAtIndex(newIndex - 1); + if (c->isEmpty()) { + removeChild(c); + newIndex = index - 1; + } + } + return newIndex; +} + } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 3386f5883..7a0d39673 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -58,6 +58,22 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { layoutReference().typedNode()->moveCursorDown(this, shouldRecomputeLayout); } +/* Layout modification */ +void LayoutCursor::addLayoutAndMoveCursor(LayoutRef l) { + bool layoutWillBeMerged = l.isHorizontal(); + m_layoutRef.addSiblingAndMoveCursor(this, l); //TODO + if (!layoutWillBeMerged) { + l.collapseSiblingsAndMoveCursor(this); + } +} + +void LayoutCursor::clearLayout() { + LayoutRef rootLayoutR = m_layoutRef.root(); + assert(rootLayoutR.isHorizontal()); + rootLayoutR.removeChildren(); + m_layoutRef = rootLayoutR; +} + /* Private */ KDCoordinate LayoutCursor::layoutHeight() { diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 2e607c4c4..bf5177fdb 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -71,4 +72,72 @@ LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { return LayoutCursor(cursor->layoutReference()); } +// Tree modification +void LayoutNode::addSibling(LayoutCursor * cursor, LayoutNode * sibling) { + privateAddSibling(cursor, sibling, false); +} + +void LayoutNode::addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling) { + privateAddSibling(cursor, sibling, true); +} + +// Private + +void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { + /* The layout must have a parent, because HorizontalLayout overrides + * privateAddSibling and only an HorizontalLayout can be the root layout. */ + LayoutNode * p = parent(); + assert(p != nullptr); + if (p->isHorizontal()) { + int indexInParent = p->indexOfChild(this); + int siblingIndex = cursor->position() == LayoutCursor::Position::Left ? indexInParent : indexInParent + 1; + + /* Special case: If the neighbour sibling is a VerticalOffsetLayout, let it + * handle the insertion of the new sibling. Do not enter the special case if + * "this" is a VerticalOffsetLayout, to avoid an infinite loop. */ + if (!isVerticalOffset()) { + LayoutNode * neighbour = nullptr; + if (cursor->position() == LayoutCursor::Position::Left && indexInParent > 0) { + neighbour = p->childAtIndex(indexInParent - 1); + } else if (cursor->position() ==LayoutCursor::Position::Right && indexInParent < p->numberOfChildren() - 1) { + neighbour = p->childAtIndex(indexInParent + 1); + } + if (neighbour != nullptr && neighbour->isVerticalOffset()) { + cursor->setLayoutNode(neighbour); + cursor->setPosition(cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left); + if (moveCursor) { + neighbour->addSiblingAndMoveCursor(cursor, sibling); + } else { + neighbour->addSibling(cursor, sibling); + } + return; + } + } + + // Else, let the parent add the sibling. + if (moveCursor) { + if (siblingIndex < p->numberOfChildren()) { + cursor->setLayoutNode(p->childAtIndex(siblingIndex)); + cursor->setPosition(LayoutCursor::Position::Left); + } else { + cursor->setLayoutNode(p); + cursor->setPosition(LayoutCursor::Position::Right); + } + } + static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true); //TODO + return; + } + LayoutNode * juxtapositionLayout = nullptr; + if (cursor->position() == LayoutCursor::Position::Left) { + juxtapositionLayout = replaceWithJuxtapositionOf(sibling, this); //TODO + } else { + assert(cursor->position() == LayoutCursor::Position::Right); + juxtapositionLayout = replaceWithJuxtapositionOf(this, sibling); + } + if (moveCursor) { + cursor->setLayoutNode(juxtapositionLayout); + cursor->setPosition(LayoutCursor::Position::Right); + } +} + } diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 56c863bb3..ce92e7e09 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -81,7 +81,7 @@ TreeNode * TreeNode::parentTree() const { #endif } -TreeNode * TreeNode::editableRootTree() { +TreeNode * TreeNode::rootTree() { for (TreeNode * root : TreePool::sharedPool()->roots()) { if (hasAncestor(root, true)) { return root; From 07e7c3279d50f64b1b00247c1d15d475bfcc7a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 4 Jul 2018 15:55:11 +0200 Subject: [PATCH 091/156] [poincare] Put back integer layout creation --- .../include/poincare/allocation_failed_layout_node.h | 1 + poincare/include/poincare/integer.h | 9 +++++---- poincare/include/poincare/tree_reference.h | 10 +++++++++- poincare/src/integer.cpp | 7 ++----- poincare/src/rational.cpp | 6 +++--- poincare/src/tree_node.cpp | 3 +++ 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 37c4fe2f7..195184796 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -29,6 +29,7 @@ protected: } private: + void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override {} void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} }; diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 565d6267c..e940044c4 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -7,9 +7,10 @@ namespace Poincare { class ExpressionLayout; -/*class LayoutNode; -class LayoutReference; -*/ +template +class LayoutReference; +class LayoutNode; + /* All algorithm should be improved with: * Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */ @@ -54,7 +55,7 @@ public: // Layout int writeTextInBuffer(char * buffer, int bufferSize) const; - //LayoutReference createLayout() const; + LayoutReference createLayout() const; // Approximation template T approximate() const; diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 19aeeb527..c004128f9 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -123,6 +123,10 @@ public: if (node()->isAllocationFailure()) { return; } + if (t.isAllocationFailure()) { + replaceWithAllocationFailure(); + return; + } assert(index >= 0 && index <= numberOfChildren()); // Retain t before detaching it, else it might get destroyed @@ -238,7 +242,11 @@ public: assert(i >= 0 && i <= numberOfChildren()); // Steal operands int numberOfNewChildren = t.numberOfChildren(); - TreePool::sharedPool()->moveChildren(t.node(), node()->childTreeAtIndex(i)->nextSibling()); + if (i < numberOfChildren()) { + TreePool::sharedPool()->moveChildren(t.node(), node()->childTreeAtIndex(i)); + } else { + TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()->next()); + } t.node()->eraseNumberOfChildren(); // If t is a child, remove it if (node()->hasChild(t.node())) { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index d69de58ed..e78269cc1 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -601,14 +601,11 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { return size; } -/*LayoutRef Integer::createLayout() const { - return CharLayoutRef('a'); //TODO -/* +LayoutRef Integer::createLayout() const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); return LayoutEngine::createStringLayout(buffer, numberOfChars); - -}*/ +} template float Poincare::Integer::approximate() const; template double Poincare::Integer::approximate() const; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index aa2117b9a..7d14e300d 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -153,12 +153,12 @@ bool Rational::needParenthesisWithParent(const Expression * e) const { } LayoutRef Rational::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /* - ExpressionLayout * numeratorLayout = m_numerator.createLayout(); + LayoutRef numeratorLayout = m_numerator.createLayout(); if (m_denominator.isOne()) { return numeratorLayout; } + return CharLayoutRef('a'); //TODO + /* ExpressionLayout * denominatorLayout = m_denominator.createLayout(); return new FractionLayout(numeratorLayout, denominatorLayout, false);*/ } diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index ce92e7e09..7ff83bcac 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -76,6 +76,9 @@ TreeNode * TreeNode::parentTree() const { return node; } } + if (isAllocationFailure()) { + return nullptr; + } assert(false); return nullptr; #endif From d1bdc7e2d5526bff213f7bcb2e6e16f57b1b7872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 4 Jul 2018 17:43:37 +0200 Subject: [PATCH 092/156] [poincare] Fix tree retain count --- escher/src/layout_field.cpp | 2 +- poincare/include/poincare/layout_cursor.h | 12 +++++++++--- poincare/include/poincare/tree_reference.h | 14 +++++++++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index c3167b742..164bd5237 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -246,7 +246,7 @@ void LayoutField::insertLayoutAtCursor(LayoutRef layoutR, LayoutRef pointedLayou if (pointedLayoutR.isDefined() && (!layoutWillBeMerged || pointedLayoutR != layoutR)) { m_contentView.cursor()->setLayoutReference(pointedLayoutR); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); - } else if (!layoutWillBeMerged) { + } else if (!layoutWillBeMerged ) { //&& !layoutR.isAllocationFailure()) { m_contentView.cursor()->setLayoutReference(layoutR.layoutToPointWhenInserting()); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 04e014c21..bc47143bf 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -53,10 +53,16 @@ public: /* Getters and setters */ LayoutRef layoutReference() { return m_layoutRef; } int layoutIdentifier() { return m_layoutRef.identifier(); } - void setLayoutReference(LayoutRef r) { m_layoutRef = r; } + void setLayoutReference(LayoutRef r) { + if (r != m_layoutRef) { + m_layoutRef = r; + } + } void setLayoutNode(LayoutNode * n) { - m_layoutRef.node()->release(); - m_layoutRef = LayoutRef(n); + if (n != m_layoutRef.node()) { + m_layoutRef.node()->release(); + m_layoutRef = LayoutRef(n); + } } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index c004128f9..c3b5b76c1 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -18,8 +18,8 @@ class TreeReference { template friend class LayoutReference; public: - TreeReference(const TreeReference & tr) { setTo(tr); } - TreeReference(TreeReference&& tr) { setTo(tr); } + TreeReference(const TreeReference & tr) : m_identifier(TreePool::NoNodeIdentifier) { setTo(tr); } + TreeReference(TreeReference&& tr) : m_identifier(TreePool::NoNodeIdentifier) { setTo(tr); } TreeReference& operator=(const TreeReference& tr) { setTo(tr); return *this; @@ -275,10 +275,18 @@ protected: } private: void setTo(const TreeReference & tr) { + if (*this == tr) { + return; + } + TreeNode * currentNode = node(); + bool releaseNode = isDefined(); if (tr.isDefined()) { setIdentifierAndRetain(tr.identifier()); } else { - m_identifier = -1; + m_identifier = TreePool::NoNodeIdentifier; + } + if (releaseNode) { + currentNode->release(); } } int m_identifier; From 9e1b7792f767585bf8dfa2e90b05292730efa9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 10:35:05 +0200 Subject: [PATCH 093/156] [poincare] LayoutNode::hasText --- poincare/include/poincare/layout_node.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 004d80337..6ceba949d 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -22,7 +22,15 @@ public: { } - virtual bool hasText() const { return false; } //TODO + 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()){ + return false; + } + int numChildren = numberOfChildren(); + return !(isHorizontal() && (numChildren == 0 || (numChildren == 1 && !const_cast(this)->childAtIndex(0)->hasText()))); + } virtual char XNTChar() const { return 'x'; } virtual bool isHorizontal() const { return false; } virtual bool isEmpty() const { return false; } From a0c427076f56d7def9b5994ab7b7d2a9015805b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 10:59:19 +0200 Subject: [PATCH 094/156] [apps/claculation] Remove duplicate layout reference --- apps/calculation/edit_expression_controller.cpp | 3 +-- apps/calculation/edit_expression_controller.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/calculation/edit_expression_controller.cpp b/apps/calculation/edit_expression_controller.cpp index 72f238d33..6c3d19a3d 100644 --- a/apps/calculation/edit_expression_controller.cpp +++ b/apps/calculation/edit_expression_controller.cpp @@ -13,8 +13,7 @@ namespace Calculation { EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) : View(), m_mainView(subview), - m_layoutR(Poincare::HorizontalLayoutRef()), - m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layoutR, textFieldDelegate, layoutFieldDelegate) + m_expressionField(parentResponder, m_textBody, k_bufferLength, Poincare::HorizontalLayoutRef(), textFieldDelegate, layoutFieldDelegate) { m_textBody[0] = 0; } diff --git a/apps/calculation/edit_expression_controller.h b/apps/calculation/edit_expression_controller.h index fb8837eb0..8a2880f2c 100644 --- a/apps/calculation/edit_expression_controller.h +++ b/apps/calculation/edit_expression_controller.h @@ -47,7 +47,6 @@ private: static constexpr int k_bufferLength = TextField::maxBufferSize(); TableView * m_mainView; char m_textBody[k_bufferLength]; - Poincare::LayoutRef m_layoutR; ExpressionField m_expressionField; }; View * loadView() override; From 85ca01a7dc156ce53174f75ccfddeefa5e6e28f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 11:00:18 +0200 Subject: [PATCH 095/156] [build] Change debug flag from Og to O0 This flag caused lldb problems --- build/defaults.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/defaults.mak b/build/defaults.mak index e90a2b158..e7b364888 100644 --- a/build/defaults.mak +++ b/build/defaults.mak @@ -8,7 +8,7 @@ CXXFLAGS = -std=c++11 -fno-exceptions -fno-rtti -fno-threadsafe-statics # Flags - Optimizations ifeq ($(DEBUG),1) -SFLAGS = -Og -g +SFLAGS = -O0 -g else SFLAGS = -Os endif From 401aa39e2670a9f314a006004a9bb66709cc027b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 11:34:07 +0200 Subject: [PATCH 096/156] [poincare] Fix LayoutCursor --- poincare/include/poincare/layout_cursor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index bc47143bf..92fc79c3e 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -60,7 +60,6 @@ public: } void setLayoutNode(LayoutNode * n) { if (n != m_layoutRef.node()) { - m_layoutRef.node()->release(); m_layoutRef = LayoutRef(n); } } From 48aac1c908c19c9cafba5aca4b3443213803290c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 11:34:49 +0200 Subject: [PATCH 097/156] [poincare] LayoutCursor::insertText --- poincare/include/poincare/layout_cursor.h | 2 +- poincare/include/poincare/layout_node.h | 2 +- poincare/include/poincare/layout_reference.h | 3 +- poincare/src/layout_cursor.cpp | 57 ++++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 92fc79c3e..4733e9012 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -108,10 +108,10 @@ public: void addEmptySquarePowerLayout() {} //TODO void addEmptyTenPowerLayout() {} //TODO void addEmptyMatrixLayout() {} //TODO - void insertText(const char * text) {} //TODO void performBackspace() {} //TODO bool showEmptyLayoutIfNeeded() { return false; } //TODO bool hideEmptyLayoutIfNeeded() { return false; } //TODO + void insertText(const char * text); void addLayoutAndMoveCursor(LayoutRef l); void clearLayout(); diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 6ceba949d..dadc3c457 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -29,7 +29,7 @@ public: return false; } int numChildren = numberOfChildren(); - return !(isHorizontal() && (numChildren == 0 || (numChildren == 1 && !const_cast(this)->childAtIndex(0)->hasText()))); + return !(isHorizontal() && (numChildren == 0 || (numChildren == 1 && !(const_cast(this)->childAtIndex(0)->hasText())))); } virtual char XNTChar() const { return 'x'; } virtual bool isHorizontal() const { return false; } diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index dc4f9f403..6bc059334 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -66,7 +66,8 @@ public: void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } //TODO + void addSibling(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSibling(cursor, sibling.typedNode()); } + void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); //TODO diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 7a0d39673..33b1aba1d 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include namespace Poincare { @@ -59,6 +61,61 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { } /* Layout modification */ +void LayoutCursor::insertText(const char * text) { + int textLength = strlen(text); + if (textLength <= 0) { + return; + } + LayoutRef newChild(nullptr); + LayoutRef pointedChild(nullptr); + bool specialUnderScore = false; + for (int i = 0; i < textLength; i++) { + if (text[i] == Ion::Charset::Empty) { + continue; + } + if (text[i] == Ion::Charset::MultiplicationSign) { + newChild = CharLayoutRef(Ion::Charset::MiddleDot); + } else if (text[i] == '(') { + newChild = CharLayoutRef('('); //TODO + if (!pointedChild.isDefined()) { + pointedChild = newChild; + } + } else if (text[i] == ')') { + newChild = CharLayoutRef(')'); //TODO + } else if (text[i] == '_') { + specialUnderScore = (i < textLength) && (text[i+1] == '{'); + if (!specialUnderScore) { + newChild = CharLayoutRef('_'); + } else { + continue; + } + } else if (text[i] == '{' && specialUnderScore) { + newChild = CharLayoutRef('('); //TODO ?? Was a char layout before, not a parenthesis left + } else if (text[i] == '}' && specialUnderScore) { + newChild = CharLayoutRef(')'); //TODO + specialUnderScore = false; + } + /* We never insert text with brackets for now. Removing this code saves the + * binary file 2K. */ +#if 0 + else if (text[i] == '[') { + newChild = LeftSquareBracketLayoutRef(); + } else if (text[i] == ']') { + newChild = RightSquareBracketLayoutRef(); + } +#endif + else { + newChild = CharLayoutRef(text[i]); + } + m_layoutRef.addSibling(this, newChild); + m_layoutRef = newChild; + m_position = Position::Right; + } + if (pointedChild.isDefined()) { + m_layoutRef = pointedChild; + } +} + void LayoutCursor::addLayoutAndMoveCursor(LayoutRef l) { bool layoutWillBeMerged = l.isHorizontal(); m_layoutRef.addSiblingAndMoveCursor(this, l); //TODO From 93f07c1fb834556bd77136dd6e8dd6a7da8ae9b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 12:01:48 +0200 Subject: [PATCH 098/156] [poincare] HorizontalLayout::moveCursorRight --- poincare/src/horizontal_layout_node.cpp | 50 +++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 6e7c23384..d2e961c74 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -77,11 +77,53 @@ void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRe } void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { - //TODO - LayoutNode * parentNode = parent(); - if (parentNode != nullptr) { - parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + if (this == cursor->layoutReference().node()) { + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left + int childrenCount = numberOfChildren(); + LayoutNode * parentNode = parent(); + if (childrenCount == 0) { + // If there are no children, go Right and ask the parent + cursor->setPosition(LayoutCursor::Position::Right); + if (parentNode != nullptr) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } + return; + } + /* If there is at least one child, set the cursor to the first child and + * move it Right */ + LayoutNode * firstChild = childAtIndex(0); + assert(firstChild != nullptr); + cursor->setLayoutNode(firstChild); + return firstChild->moveCursorRight(cursor, shouldRecomputeLayout); } + + // Case: The cursor is Right of a child. + assert(cursor->position() == LayoutCursor::Position::Right); + int childIndex = indexOfChild(cursor->layoutReference().node()); + assert(childIndex >= 0); + if (childIndex == numberOfChildren() - 1) { + // Case: the child is the rightmost. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode) { + cursor->setLayoutNode(this); + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } + return; + } + /* Case: the child is not the rightmost. Go to its right sibling and move + * Right. */ + cursor->setLayoutNode(childAtIndex(childIndex+1)); + cursor->setPosition(LayoutCursor::Position::Left); + return childAtIndex(childIndex+1)->moveCursorRight(cursor, shouldRecomputeLayout); } void HorizontalLayoutNode::computeSize() { From 8a3be2bac392db9005185fcaa1aeedb7f8dd0283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 14:26:44 +0200 Subject: [PATCH 099/156] [poincare] LayoutReference::deleteBeforeCursor --- .../include/poincare/horizontal_layout_node.h | 3 ++ poincare/include/poincare/layout_cursor.h | 4 +- poincare/include/poincare/layout_node.h | 2 + poincare/include/poincare/layout_reference.h | 2 + poincare/src/horizontal_layout_node.cpp | 54 +++++++++++++++++++ poincare/src/layout_node.cpp | 42 +++++++++++++++ poincare/src/layout_reference.cpp | 1 + 7 files changed, 107 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 8b60dbaea..9169daa21 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -17,8 +17,11 @@ public: m_numberOfChildren(0) {} + // Tree modification void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren); void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren); + void deleteBeforeCursor(LayoutCursor * cursor) override; + void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override; // LayoutNode bool isHorizontal() const override { return true; } diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 4733e9012..41afc22b0 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -108,9 +108,11 @@ public: void addEmptySquarePowerLayout() {} //TODO void addEmptyTenPowerLayout() {} //TODO void addEmptyMatrixLayout() {} //TODO - void performBackspace() {} //TODO bool showEmptyLayoutIfNeeded() { return false; } //TODO bool hideEmptyLayoutIfNeeded() { return false; } //TODO + void performBackspace() { + m_layoutRef.deleteBeforeCursor(this); + } void insertText(const char * text); void addLayoutAndMoveCursor(LayoutRef l); void clearLayout(); diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index dadc3c457..88e055c34 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -71,6 +71,8 @@ public: // Tree modification void addSibling(LayoutCursor * cursor, LayoutNode * sibling); void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling); + virtual void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor); + virtual void deleteBeforeCursor(LayoutCursor * cursor); void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 6bc059334..1129194e9 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -46,6 +46,7 @@ public: char XNTChar() const { return this->typedNode()->XNTChar(); } // Layout modification + void deleteBeforeCursor(LayoutCursor * cursor) { return this->typedNode()->deleteBeforeCursor(cursor); } bool removeGreySquaresFromAllMatrixAncestors() { return this->typedNode()->removeGreySquaresFromAllMatrixAncestors(); } bool addGreySquaresToAllMatrixAncestors() { return this->typedNode()->addGreySquaresToAllMatrixAncestors(); } LayoutReference layoutToPointWhenInserting() { return LayoutReference(this->typedNode()->layoutToPointWhenInserting()); } @@ -68,6 +69,7 @@ public: } void addSibling(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSibling(cursor, sibling.typedNode()); } void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } + void removeChildAndMoveCursor(LayoutReference l, LayoutCursor * cursor) { return this->typedNode()->removeChildAndMoveCursor(l.typedNode(), cursor); } void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); //TODO diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index d2e961c74..5069327ce 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -25,6 +25,60 @@ void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int in LayoutRef(this).mergeChildrenAtIndex(LayoutRef(h), newIndex); } +void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + LayoutNode * p = parent(); + if (p == nullptr + && cursor->layoutReference().node() == this + && (cursor->position() == LayoutCursor::Position::Left + || numberOfChildren() == 0)) + { + /* Case: Left and this is the main layout or Right and this is the main + * layout with no children. Return. */ + return; + } + if (cursor->position() == LayoutCursor::Position::Left) { + int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); + if (indexOfPointedLayout >= 0) { + /* Case: Left of a child. + * Point Right of the previous child. If there is no previous child, point + * Left of this. Perform another backspace. */ + if (indexOfPointedLayout == 0) { + cursor->setLayoutNode(this); + } else { + assert(indexOfPointedLayout > 0); + cursor->setLayoutNode(childAtIndex(indexOfPointedLayout - 1)); + cursor->setPosition(LayoutCursor::Position::Right); + } + cursor->performBackspace(); + return; + } + } + assert(cursor->layoutReference().node() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Point to the last child and perform backspace. + cursor->setLayoutNode(childAtIndex(numberOfChildren() - 1)); + cursor->performBackspace(); + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + +void HorizontalLayoutNode::removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) { + if (numberOfChildren() == 1) { + assert(childAtIndex(0) == l); + LayoutNode * p = parent(); + if (p != nullptr) { + p->removeChildAndMoveCursor(this, cursor); + } else { + removeChild(l); + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + } + return; + } + LayoutNode::removeChildAndMoveCursor(l, cursor); +} + int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { if (numberOfChildren() == 0) { if (bufferSize == 0) { diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index bf5177fdb..d355a0cc6 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -81,6 +81,48 @@ void LayoutNode::addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sib privateAddSibling(cursor, sibling, true); } +void LayoutNode::removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) { + assert(hasChild(l)); + int index = indexOfChild(l); + removeChild(l); + if (index < numberOfChildren()) { + cursor->setLayoutNode(childAtIndex(index)); + cursor->setPosition(LayoutCursor::Position::Left); + } else { + int newPointedLayoutIndex = index - 1; + assert(newPointedLayoutIndex >= 0); + assert(newPointedLayoutIndex < numberOfChildren()); + cursor->setLayoutNode(childAtIndex(newPointedLayoutIndex)); + cursor->setPosition(LayoutCursor::Position::Right); + } +} + +void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); + if (indexOfPointedLayout >= 0) { + // Case: The pointed layout is a child. Move Left. + assert(cursor->position() == LayoutCursor::Position::Left); + bool shouldRecomputeLayout = false; + cursor->moveLeft(&shouldRecomputeLayout); + return; + } + assert(cursor->layoutReference().node() == this); + LayoutNode * p = parent(); + // Case: this is the pointed layout. + if (p == nullptr) { + // Case: No parent. Return. + return; + } + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Ask the parent. + p->deleteBeforeCursor(cursor); + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // Case: Right. Delete the layout. + p->removeChildAndMoveCursor(this, cursor); +} + // Private void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index d701e7a41..787955725 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -17,6 +17,7 @@ TreeNode * LayoutRef::FailedAllocationStaticNode() { return &FailureNode; } +// Cursor template LayoutCursor LayoutReference::cursor() const { return LayoutCursor(this->typedNode()); 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 100/156] [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 From 6518fd3f47523eba582060b07f5dd85dc8e968cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 15:18:15 +0200 Subject: [PATCH 101/156] [poincare] LayoutReference::replaceWithJuxtapositionOf --- poincare/include/poincare/layout_node.h | 2 +- poincare/include/poincare/layout_reference.h | 9 +++++---- poincare/src/layout_node.cpp | 4 ++++ poincare/src/layout_reference.cpp | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index cde6a11ee..0988cb586 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -77,7 +77,7 @@ public: bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO - LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild) {return nullptr; } //TODO + LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild); protected: // Iterators class Iterator { diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 1129194e9..63ffcc653 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -55,15 +55,16 @@ public: LayoutCursor cursor() const; LayoutCursor equivalentCursor(LayoutCursor * cursor); - // Hierarchy - + // Tree LayoutReference childAtIndex(int i) { TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); return LayoutReference(treeRefChild.node()); } + int indexInParent() const { return this->typedNode()->indexInParent(); } LayoutReference root() { return LayoutReference(this->typedNode()->root()); } + LayoutReference parent() { return LayoutReference(this->typedNode()->parent()); } - // Hierarchy modification + // Tree modification void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } @@ -71,7 +72,7 @@ public: void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } void removeChildAndMoveCursor(LayoutReference l, LayoutCursor * cursor) { return this->typedNode()->removeChildAndMoveCursor(l.typedNode(), cursor); } void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO - LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); //TODO + LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); // Allocation failure static TreeNode * FailedAllocationStaticNode(); diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 623afba0e..5a48be246 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -125,6 +125,10 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { p->removeChildAndMoveCursor(this, cursor); } +LayoutNode * LayoutNode::replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild) { + return (LayoutRef(this).replaceWithJuxtapositionOf(LayoutRef(leftChild), LayoutRef(rightChild))).typedNode(); +} + // Private void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 787955725..0d8035993 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -28,6 +29,22 @@ LayoutCursor LayoutRef::equivalentCursor(LayoutCursor * cursor) { return this->typedNode()->equivalentCursor(cursor); } +// Tree modification +template<> +LayoutReference LayoutRef::replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild) { + LayoutReference p = parent(); + assert(p.isDefined()); + assert(!p.isHorizontal()); + /* One of the children to juxtapose might be "this", so we first have to + * replace "this" with an horizontal layout, then add "this" to the layout. */ + LayoutReference horizontalLayoutR = HorizontalLayoutRef(); + int index = indexInParent(); + horizontalLayoutR.addChildAtIndex(leftChild, 0); + horizontalLayoutR.addChildAtIndex(rightChild, 1); + p.addChildAtIndex(horizontalLayoutR, index); + return horizontalLayoutR; +} + template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; From a82d72fff807f02f0ce2f2461f1e8a484ccbf6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 17:15:56 +0200 Subject: [PATCH 102/156] [poincare] LayoutNode::replaceChild --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + .../include/poincare/horizontal_layout_node.h | 3 + poincare/include/poincare/layout_node.h | 9 +- poincare/include/poincare/layout_reference.h | 16 ++- poincare/include/poincare/tree_node.h | 4 +- poincare/include/poincare/tree_reference.h | 9 ++ poincare/src/horizontal_layout_node.cpp | 98 +++++++++++++++++++ poincare/src/layout_node.cpp | 23 +++++ poincare/src/layout_reference.cpp | 4 +- poincare/src/tree_node.cpp | 18 ++-- 11 files changed, 173 insertions(+), 13 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index 66abfc415..a874f8e7f 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -5,6 +5,7 @@ SFLAGS += -Ipoincare/include objs += $(addprefix poincare/src/,\ char_layout_node.o\ + empty_layout_node.o\ horizontal_layout_node.o\ layout_cursor.o\ layout_node.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 00e756870..5fa0199b3 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 527313246..62c69f4ac 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -31,6 +31,8 @@ public: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void replaceChild(LayoutNode * oldChild, LayoutNode * newChild) override; + void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; // TreeNode size_t size() const override { return sizeof(HorizontalLayoutNode); } @@ -55,6 +57,7 @@ protected: private: void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + void privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); void privateRemoveChildAtIndex(int index, bool forceRemove); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 0988cb586..7cee22ae2 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -77,8 +77,16 @@ public: bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO + LayoutNode * replaceWith(LayoutNode * newChild); + LayoutNode * replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild); + virtual void replaceChild(LayoutNode * oldChild, LayoutNode * newChild); + virtual void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); + protected: + // Tree modification + virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); + // Iterators class Iterator { public: @@ -120,7 +128,6 @@ protected: bool m_positioned; bool m_sized; private: - virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; }; diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 63ffcc653..525da71a8 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -65,14 +65,24 @@ public: LayoutReference parent() { return LayoutReference(this->typedNode()->parent()); } // Tree modification - void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { - TreeReference::replaceChildAtIndex(oldChildIndex, newChild); + // Replace + void replaceChild(LayoutReference oldChild, LayoutReference newChild) { TreeReference::replaceChild(oldChild, newChild); } + void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } + void replaceChildAndMoveCursor(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor) { this->typedNode()->replaceChildAndMoveCursor(oldChild.typedNode(), newChild.typedNode(), cursor); } + LayoutReference replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { + LayoutReference p = parent(); + assert(p.isDefined()); + p.replaceChildAndMoveCursor(*this, newChild, cursor); + return newChild; } + LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); + // Add void addSibling(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSibling(cursor, sibling.typedNode()); } void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } + //Remove void removeChildAndMoveCursor(LayoutReference l, LayoutCursor * cursor) { return this->typedNode()->removeChildAndMoveCursor(l.typedNode(), cursor); } + // Collapse void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO - LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); // Allocation failure static TreeNode * FailedAllocationStaticNode(); diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 5df3cf9db..17d07d86e 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -153,9 +153,11 @@ public: } // Hierarchy operations - void replaceWithAllocationFailure(); void addChildAtIndex(TreeNode * t, int index); void removeChild(TreeNode * t); + void removeChildAtIndex(int index) { return removeChild(childTreeAtIndex(index)); } + void replaceChildTree(TreeNode * t, TreeNode * newChild); + void replaceWithAllocationFailure(); protected: TreeNode() : diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index c3b5b76c1..e4c1e5662 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -113,6 +113,11 @@ public: assert(isDefined()); return TreeReference(node()->childTreeAtIndex(i)); } + int indexOfChild(TreeReference t) const { + assert(isDefined()); + return node()->indexOfChild(t.node()); + } + // Hierarchy operations @@ -169,6 +174,10 @@ public: } } + void replaceChild(TreeReference oldChild, TreeReference newChild) { + replaceChildAtIndex(indexOfChild(oldChild), newChild); + } + void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { assert(isDefined()); if (newChild.isAllocationFailure()) { diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 8743e54a8..e794a5fba 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -215,6 +215,15 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR return childAtIndex(childIndex+1)->moveCursorRight(cursor, shouldRecomputeLayout); } +void HorizontalLayoutNode::replaceChild(LayoutNode * oldChild, LayoutNode * newChild) { + privateReplaceChild(oldChild, newChild, nullptr); +} + +void HorizontalLayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { + privateReplaceChild(oldChild, newChild, cursor); +} + + // Protected void HorizontalLayoutNode::computeSize() { @@ -297,6 +306,95 @@ void HorizontalLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * } } +void HorizontalLayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { + if (oldChild == newChild) { + return; + } + int oldChildIndex = indexOfChild(oldChild); + if (newChild->isEmpty()) { + if (numberOfChildren() > 1) { + /* If the new layout is empty and the horizontal layout has other + * children, just remove the old child. */ + removeChild(oldChild); + if (cursor != nullptr) { + if (oldChildIndex == 0) { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + } else { + cursor->setLayoutNode(childAtIndex(oldChildIndex -1)); + cursor->setPosition(LayoutCursor::Position::Right); + } + } + return; + } + /* The old layout was the only horizontal layout child, so if this has a + * a parent, replace this with the new empty layout. */ + LayoutNode * p = parent(); + if (p != nullptr) { + if (cursor) { + replaceWithAndMoveCursor(newChild, cursor); + } else { + replaceWith(newChild); + } + return; + } + /* This is the main horizontal layout, the old child is its only child and + * the new child is Empty: remove the old child and delete the new child. */ + assert(p == nullptr); + removeChild(oldChild); + if (cursor != nullptr) { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + } + return; + } + /* If the new child is also an horizontal layout, steal the children of the + * new layout then destroy it. */ + bool oldWasAncestorOfNewLayout = newChild->hasAncestor(oldChild, false); + if (newChild->isHorizontal()) { + int indexForInsertion = indexOfChild(oldChild); + if (cursor != nullptr) { + /* If the old layout is not an ancestor of the new layout, or if the + * cursor was on the right of the new layout, place the cursor on the + * right of the new layout, which is left of the next sibling or right of + * the parent. */ + if (!oldWasAncestorOfNewLayout || cursor->position() == LayoutCursor::Position::Right) { + if (oldChildIndex == numberOfChildren() - 1) { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Right); + } else { + cursor->setLayoutNode(childAtIndex(oldChildIndex + 1)); + cursor->setPosition(LayoutCursor::Position::Left); + } + } else { + /* Else place the cursor on the left of the new layout, which is right + * of the previous sibling or left of the parent. */ + if (oldChildIndex == 0) { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + } else { + cursor->setLayoutNode(childAtIndex(oldChildIndex - 1)); + cursor->setPosition(LayoutCursor::Position::Right); + } + } + } + bool oldChildRemovedAtMerge = oldChild->isEmpty(); + mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); + if (!oldChildRemovedAtMerge) { + removeChildAtIndex(indexForInsertion); + } + return; + } + // Else, just replace the child. + if (cursor != nullptr && !oldWasAncestorOfNewLayout) { + cursor->setPosition(LayoutCursor::Position::Right); + } + LayoutNode::replaceChild(oldChild, newChild); + if (cursor != nullptr) { + cursor->setLayoutNode(newChild); + } +} + void HorizontalLayoutNode::privateRemoveChildAtIndex(int index, bool forceRemove) { /* Remove the child before potentially adding an EmptyLayout. Indeed, adding * a new child would remove any EmptyLayout surrounding the new child and in diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 5a48be246..c5a94466f 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -125,10 +125,33 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { p->removeChildAndMoveCursor(this, cursor); } +LayoutNode * LayoutNode::replaceWith(LayoutNode * newChild) { + LayoutRef newRef(newChild); + LayoutRef(this).replaceWith(newRef); + return newRef.typedNode(); +} + +void LayoutNode::replaceChild(LayoutNode * oldChild, LayoutNode * newChild) { + LayoutRef(this).replaceChild(LayoutRef(oldChild), LayoutRef(newChild)); +} + +LayoutNode * LayoutNode::replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor) { + return (LayoutRef(this).replaceWithAndMoveCursor(LayoutRef(newChild), cursor)).typedNode(); +} + LayoutNode * LayoutNode::replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild) { return (LayoutRef(this).replaceWithJuxtapositionOf(LayoutRef(leftChild), LayoutRef(rightChild))).typedNode(); } +void LayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { + assert(hasChild(oldChild)); + if (!newChild->hasAncestor(oldChild, false)) { + cursor->setPosition(LayoutCursor::Position::Right); + } + replaceChild(oldChild, newChild); + cursor->setLayoutNode(newChild); +} + // Private void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 0d8035993..5c80b53d1 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -35,8 +35,8 @@ LayoutReference LayoutRef::replaceWithJuxtapositionOf(LayoutReferenc LayoutReference p = parent(); assert(p.isDefined()); assert(!p.isHorizontal()); - /* One of the children to juxtapose might be "this", so we first have to - * replace "this" with an horizontal layout, then add "this" to the layout. */ + /* One of the children to juxtapose might be "this", so we cannot just call + * replaceWith. */ LayoutReference horizontalLayoutR = HorizontalLayoutRef(); int index = indexInParent(); horizontalLayoutR.addChildAtIndex(leftChild, 0); diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 7ff83bcac..83fb47cd6 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -184,12 +184,6 @@ bool TreeNode::hasSibling(const TreeNode * e) const { return false; } -void TreeNode::replaceWithAllocationFailure() { - TreeRef t(this); - t.replaceWithAllocationFailure(); - // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? -} - void TreeNode::addChildAtIndex(TreeNode * t, int index) { TreeRef tr(this); tr.addChildAtIndex(TreeRef(t), index); @@ -200,4 +194,16 @@ void TreeNode::removeChild(TreeNode * t) { tr.removeChild(TreeRef(t)); } +void TreeNode::replaceChildTree(TreeNode * t, TreeNode * newChild) { + int oldChildIndex = indexOfChild(t); + addChildAtIndex(newChild, oldChildIndex + 1); + removeChild(t); +} + +void TreeNode::replaceWithAllocationFailure() { + TreeRef t(this); + t.replaceWithAllocationFailure(); + // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? +} + } From 40c8271af886033953984c3b15ce7443cb05103f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 18:02:20 +0200 Subject: [PATCH 103/156] [poincare] TreeNode::addChild->addChildTree --- .../include/poincare/horizontal_layout_node.h | 6 ++--- poincare/include/poincare/tree_node.h | 3 +-- poincare/include/poincare/tree_reference.h | 6 ++--- poincare/src/horizontal_layout_node.cpp | 2 +- poincare/src/layout_engine.cpp | 26 +++++++++---------- poincare/src/layout_reference.cpp | 6 ++--- poincare/src/tree_node.cpp | 6 ++--- 7 files changed, 27 insertions(+), 28 deletions(-) diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 62c69f4ac..2b1340a3a 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -68,12 +68,12 @@ class HorizontalLayoutRef : public LayoutReference { public: HorizontalLayoutRef() : LayoutReference() {} HorizontalLayoutRef(LayoutRef l) : LayoutReference() { - addChild(l); + addChildTree(l); } HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference() { - addChild(l2); - addChild(l1); + addChildTree(l2); + addChildTree(l1); } }; diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 17d07d86e..9cfe8dd31 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -153,12 +153,11 @@ public: } // Hierarchy operations - void addChildAtIndex(TreeNode * t, int index); + void addChildTreeAtIndex(TreeNode * t, int index); void removeChild(TreeNode * t); void removeChildAtIndex(int index) { return removeChild(childTreeAtIndex(index)); } void replaceChildTree(TreeNode * t, TreeNode * newChild); void replaceWithAllocationFailure(); - protected: TreeNode() : m_identifier(-1), diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index e4c1e5662..bcf7a1f6d 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -121,9 +121,9 @@ public: // Hierarchy operations - void addChild(TreeReference t) { return addChildAtIndex(t, 0); } + void addChildTree(TreeReference t) { return addChildTreeAtIndex(t, 0); } - void addChildAtIndex(TreeReference t, int index) { + void addChildTreeAtIndex(TreeReference t, int index) { assert(isDefined()); if (node()->isAllocationFailure()) { return; @@ -225,7 +225,7 @@ public: * no longer retaining the node. When we add this node to the parent, it * will retain it and increment the retain count. */ newAllocationFailureNode->setReferenceCounter(currentRetainCount - 1); - p.addChildAtIndex(newAllocationFailureNode, indexInParentNode); + p.addChildTreeAtIndex(newAllocationFailureNode, indexInParentNode); } else { newAllocationFailureNode->setReferenceCounter(currentRetainCount); } diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index e794a5fba..a93e13027 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -42,7 +42,7 @@ void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, boo if (l->isHorizontal()) { mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren); } else { - addChildAtIndex(l, index); + addChildTreeAtIndex(l, index); } } diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 153177c0e..fc096b3de 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -19,10 +19,10 @@ LayoutRef LayoutEngine::createInfixLayout(const Expression * expression, PrintFl int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); HorizontalLayoutRef result; - result.addChildAtIndex(expression->operand(0)->createLayout(), 0); + result.addChildTreeAtIndex(expression->operand(0)->createLayout(), 0); for (int i = 1; i < numberOfOperands; i++) { - result.addChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result.numberOfChildren()); - result.addChildAtIndex( + result.addChildTreeAtIndex(createStringLayout(operatorName, strlen(operatorName)), result.numberOfChildren()); + result.addChildTreeAtIndex( expression->operand(i)->createLayout(floatDisplayMode, complexFormat), result.numberOfChildren()); } @@ -44,20 +44,20 @@ LayoutRef LayoutEngine::createPrefixLayout(const Expression * expression, PrintF assert(complexFormat != Expression::ComplexFormat::Default); HorizontalLayoutRef result; // Add the operator name. - result.addChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0); + result.addChildTreeAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0); // Create the layout of arguments separated by commas. HorizontalLayoutRef args; int numberOfOperands = expression->numberOfOperands(); if (numberOfOperands > 0) { - args.addChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0); + args.addChildTreeAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0); for (int i = 1; i < numberOfOperands; i++) { - args.addChildAtIndex(CharLayoutRef(','), args.numberOfChildren()); - args.addChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args.numberOfChildren()); + args.addChildTreeAtIndex(CharLayoutRef(','), args.numberOfChildren()); + args.addChildTreeAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), args.numberOfChildren()); } } // Add the parenthesed arguments. - result.addChildAtIndex(createParenthesedLayout(args, false), result.numberOfChildren()); + result.addChildTreeAtIndex(createParenthesedLayout(args, false), result.numberOfChildren()); /*// Add the operator name. result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); @@ -69,7 +69,7 @@ LayoutRef LayoutEngine::createPrefixLayout(const Expression * expression, PrintF HorizontalLayout * horizontalArgs = static_cast(args); horizontalArgs->addOrMergeChildAtIndex(expression->operand(0)->createLayout(floatDisplayMode, complexFormat), 0, true); for (int i = 1; i < numberOfOperands; i++) { - horizontalArgs->addChildAtIndex(new CharLayout(','), args->numberOfChildren()); + horizontalArgs->addChildTreeAtIndex(new CharLayout(','), args->numberOfChildren()); horizontalArgs->addOrMergeChildAtIndex(expression->operand(i)->createLayout(floatDisplayMode, complexFormat), horizontalArgs->numberOfChildren(), true); } } @@ -80,11 +80,11 @@ LayoutRef LayoutEngine::createPrefixLayout(const Expression * expression, PrintF LayoutRef LayoutEngine::createParenthesedLayout(LayoutRef layoutRef, bool cloneLayout) { HorizontalLayoutRef result; - result.addChildAtIndex(CharLayoutRef('('), 0); + result.addChildTreeAtIndex(CharLayoutRef('('), 0); if (layoutRef.isDefined()) { - result.addChildAtIndex(cloneLayout ? layoutRef.clone() : layoutRef, 1); + result.addChildTreeAtIndex(cloneLayout ? layoutRef.clone() : layoutRef, 1); } - result.addChildAtIndex(CharLayoutRef(')'), result.numberOfChildren()); + result.addChildTreeAtIndex(CharLayoutRef(')'), result.numberOfChildren()); return result; } @@ -92,7 +92,7 @@ LayoutRef LayoutEngine::createStringLayout(const char * buffer, int bufferSize, assert(bufferSize > 0); HorizontalLayoutRef resultLayout; for (int i = 0; i < bufferSize; i++) { - resultLayout.addChildAtIndex(CharLayoutRef(buffer[i], fontSize), i); + resultLayout.addChildTreeAtIndex(CharLayoutRef(buffer[i], fontSize), i); } return resultLayout; } diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 5c80b53d1..131f7a7f1 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -39,9 +39,9 @@ LayoutReference LayoutRef::replaceWithJuxtapositionOf(LayoutReferenc * replaceWith. */ LayoutReference horizontalLayoutR = HorizontalLayoutRef(); int index = indexInParent(); - horizontalLayoutR.addChildAtIndex(leftChild, 0); - horizontalLayoutR.addChildAtIndex(rightChild, 1); - p.addChildAtIndex(horizontalLayoutR, index); + horizontalLayoutR.addChildTreeAtIndex(leftChild, 0); + horizontalLayoutR.addChildTreeAtIndex(rightChild, 1); + p.addChildTreeAtIndex(horizontalLayoutR, index); return horizontalLayoutR; } diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 83fb47cd6..41f128d3d 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -184,9 +184,9 @@ bool TreeNode::hasSibling(const TreeNode * e) const { return false; } -void TreeNode::addChildAtIndex(TreeNode * t, int index) { +void TreeNode::addChildTreeAtIndex(TreeNode * t, int index) { TreeRef tr(this); - tr.addChildAtIndex(TreeRef(t), index); + tr.addChildTreeAtIndex(TreeRef(t), index); } void TreeNode::removeChild(TreeNode * t) { @@ -196,7 +196,7 @@ void TreeNode::removeChild(TreeNode * t) { void TreeNode::replaceChildTree(TreeNode * t, TreeNode * newChild) { int oldChildIndex = indexOfChild(t); - addChildAtIndex(newChild, oldChildIndex + 1); + addChildTreeAtIndex(newChild, oldChildIndex + 1); removeChild(t); } From fa8da9b238fdf1cc6d196eef8cdd4c2097b46e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 5 Jul 2018 18:02:47 +0200 Subject: [PATCH 104/156] [poincare] Clean LayoutNode --- poincare/include/poincare/layout_node.h | 28 ++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 7cee22ae2..ca6f55ed5 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -10,6 +10,14 @@ class LayoutCursor; class LayoutNode : public TreeNode { public: + enum class VerticalDirection { + Up, + Down + }; + enum class HorizontalDirection { + Left, + Right + }; // Constructor LayoutNode() : @@ -56,7 +64,7 @@ public: return AllocationFailureNodeIdentifier(); } - // Hierarchy + // Tree LayoutNode * parent() const { return static_cast(parentTree()); } LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } LayoutNode * root() { return static_cast(rootTree()); } @@ -69,19 +77,25 @@ public: virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); // Tree modification + // Add void addSibling(LayoutCursor * cursor, LayoutNode * sibling); void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling); - virtual void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor); - virtual void deleteBeforeCursor(LayoutCursor * cursor); - void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO - bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO - bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO - virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO + // Replace LayoutNode * replaceWith(LayoutNode * newChild); LayoutNode * replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild); virtual void replaceChild(LayoutNode * oldChild, LayoutNode * newChild); virtual void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); + // Remove + virtual void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor); + // Collapse + virtual void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} + // User input + virtual void deleteBeforeCursor(LayoutCursor * cursor); + + bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO + bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO + virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO protected: // Tree modification From 785df118dc100b7fe8ffd2637e9800727b03631d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 11:35:52 +0200 Subject: [PATCH 105/156] [poincare] Fix layout insertion --- escher/src/layout_field.cpp | 7 ++++--- poincare/src/layout_cursor.cpp | 6 ++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 164bd5237..1b540c601 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -243,14 +243,15 @@ void LayoutField::insertLayoutAtCursor(LayoutRef layoutR, LayoutRef pointedLayou LayoutRef lastMergedLayoutChild = layoutWillBeMerged ? layoutR.childAtIndex(layoutR.numberOfChildren()-1) : LayoutRef(nullptr); m_contentView.cursor()->addLayoutAndMoveCursor(layoutR); if (!forceCursorRightOfLayout) { - if (pointedLayoutR.isDefined() && (!layoutWillBeMerged || pointedLayoutR != layoutR)) { + if (pointedLayoutR.isDefined() && pointedLayoutR.parent().isDefined() && (!layoutWillBeMerged || pointedLayoutR != layoutR)) { + // Make sure the layout was inserted (its parent is not nullptr) m_contentView.cursor()->setLayoutReference(pointedLayoutR); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); - } else if (!layoutWillBeMerged ) { //&& !layoutR.isAllocationFailure()) { + } else if (!layoutWillBeMerged && layoutR.parent().isDefined()) { //&& !layoutR.isAllocationFailure()) { m_contentView.cursor()->setLayoutReference(layoutR.layoutToPointWhenInserting()); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } - } else if (!layoutWillBeMerged) { + } else if (!layoutWillBeMerged && layoutR.parent().isDefined()) { m_contentView.cursor()->setLayoutReference(layoutR); m_contentView.cursor()->setPosition(LayoutCursor::Position::Right); } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 33b1aba1d..8107810f8 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -107,11 +107,9 @@ void LayoutCursor::insertText(const char * text) { else { newChild = CharLayoutRef(text[i]); } - m_layoutRef.addSibling(this, newChild); - m_layoutRef = newChild; - m_position = Position::Right; + m_layoutRef.addSiblingAndMoveCursor(this, newChild); } - if (pointedChild.isDefined()) { + if (pointedChild.isDefined() && pointedChild.parent().isDefined()) { m_layoutRef = pointedChild; } } From be62c3c4337cfb722f454c00f5297ea9994a7b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 11:36:18 +0200 Subject: [PATCH 106/156] [poincare] Add methods to layouts --- .../poincare/allocation_failed_layout_node.h | 2 + poincare/include/poincare/layout_cursor.h | 9 +- poincare/include/poincare/layout_node.h | 76 +++++-- poincare/src/layout_cursor.cpp | 2 +- poincare/src/layout_node.cpp | 199 +++++++++++++++++- 5 files changed, 258 insertions(+), 30 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 7b39e6f7b..1e9a46b52 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -14,6 +14,8 @@ public: assert(false); return 0; } + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); } void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override { } void deleteBeforeCursor(LayoutCursor * cursor) override { } diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index ae2cd0d9e..b31b99a47 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -38,6 +38,11 @@ public: m_position(position) {} + LayoutCursor(LayoutNode * node, Position position = Position::Right) : + m_layoutRef(node), + m_position(position) + {} //TODO make this private and friend class layout_node + /* Debug */ void log() { #if TREE_LOG @@ -124,10 +129,6 @@ public: private: constexpr static KDCoordinate k_cursorHeight = 18; - LayoutCursor(LayoutNode * node, Position position = Position::Right) : - m_layoutRef(node), - m_position(position) - {} KDCoordinate layoutHeight(); LayoutRef m_layoutRef; Position m_position; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index ca6f55ed5..e82b177ad 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -30,22 +31,6 @@ public: { } - bool hasText() const { - /* 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(); - return !(isHorizontal() && (numChildren == 0 || (numChildren == 1 && !(const_cast(this)->childAtIndex(0)->hasText())))); - } - virtual char XNTChar() const { return 'x'; } - virtual bool isHorizontal() const { return false; } - virtual bool isEmpty() const { return false; } - virtual bool isLeftParenthesis() const { return false; } - virtual bool isVerticalOffset() const { return false; } - virtual bool mustHaveLeftSibling() const { return false; } - // Rendering void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); KDPoint origin(); @@ -70,10 +55,12 @@ public: LayoutNode * root() { return static_cast(rootTree()); } // Tree navigation - virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {} - 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 void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; + virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) = 0; + virtual void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + virtual void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false); + void moveCursorUpInDescendants(LayoutCursor * cursor, bool * shouldRecomputeLayout); + void moveCursorDownInDescendants(LayoutCursor * cursor, bool * shouldRecomputeLayout); virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); // Tree modification @@ -93,13 +80,46 @@ public: // User input virtual void deleteBeforeCursor(LayoutCursor * cursor); - bool removeGreySquaresFromAllMatrixAncestors() { return false; } //TODO - bool addGreySquaresToAllMatrixAncestors() { return false; } //TODO - virtual LayoutNode * layoutToPointWhenInserting() { return this; } //TODO + // Other + virtual LayoutNode * layoutToPointWhenInserting() { + return numberOfChildren() > 0 ? childAtIndex(0) : this; + } + bool removeGreySquaresFromAllMatrixAncestors() { return changeGreySquaresOfAllMatrixAncestors(true); } + bool addGreySquaresToAllMatrixAncestors() { return changeGreySquaresOfAllMatrixAncestors(false); } + bool hasText() const; + virtual bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return true; } + /* isCollapsable is used when adding a sibling fraction: should the layout be + * inserted in the numerator (or denominator)? For instance, 1+2|3-4 should + * become 1+ 2/3 - 4 when pressing "Divide": a CharLayout is collapsable if + * its char is not +, -, or *. */ + virtual bool canBeOmittedMultiplicationLeftFactor() const; + virtual bool canBeOmittedMultiplicationRightFactor() const; + /* canBeOmittedMultiplicationLeftFactor and RightFactor return true if the + * layout, next to another layout, might be the factor of a multiplication + * with an omitted multiplication sign. For instance, an absolute value layout + * returns true, because |3|2 means |3|*2. A '+' CharLayout returns false, + * because +'something' nevers means +*'something'. */ + virtual bool mustHaveLeftSibling() const { return false; } + virtual bool isVerticalOffset() const { return false; } + /* For now, mustHaveLeftSibling and isVerticalOffset behave the same, but code + * is clearer with different names. */ + virtual bool isHorizontal() const { return false; } + virtual bool isLeftParenthesis() const { return false; } + virtual bool isRightParenthesis() const { return false; } + virtual bool isLeftBracket() const { return false; } + virtual bool isRightBracket() const { return false; } + virtual bool isEmpty() const { return false; } + virtual bool isMatrix() const { return false; } + virtual bool hasUpperLeftIndex() const { return false; } + virtual char XNTChar() const { + LayoutNode * p = parent(); + return p == nullptr ? Ion::Charset::Empty : p->XNTChar(); + } protected: // Tree modification virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); + void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); // Iterators class Iterator { @@ -142,7 +162,17 @@ protected: bool m_positioned; bool m_sized; private: + virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + void moveCursorInDescendantsVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout); + void scoreCursorInDescendantsVertically ( + VerticalDirection direction, + LayoutCursor * cursor, + bool * shouldRecomputeLayout, + LayoutNode ** childResult, + void * resultPosition, + int * resultScore); virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) = 0; + bool changeGreySquaresOfAllMatrixAncestors(bool add); }; } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 8107810f8..7244529d8 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -116,7 +116,7 @@ void LayoutCursor::insertText(const char * text) { void LayoutCursor::addLayoutAndMoveCursor(LayoutRef l) { bool layoutWillBeMerged = l.isHorizontal(); - m_layoutRef.addSiblingAndMoveCursor(this, l); //TODO + m_layoutRef.addSiblingAndMoveCursor(this, l); if (!layoutWillBeMerged) { l.collapseSiblingsAndMoveCursor(this); } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index c5a94466f..d2b529516 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace Poincare { @@ -68,6 +69,22 @@ TreeNode * LayoutNode::FailedAllocationStaticNode() { } // Tree navigation +void LayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + moveCursorVertically(VerticalDirection::Up, cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void LayoutNode::moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + moveCursorVertically(VerticalDirection::Down, cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void LayoutNode::moveCursorUpInDescendants(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + return moveCursorInDescendantsVertically(VerticalDirection::Up, cursor, shouldRecomputeLayout); +} + +void LayoutNode::moveCursorDownInDescendants(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + return moveCursorInDescendantsVertically(VerticalDirection::Down, cursor, shouldRecomputeLayout); +} + LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { // Only HorizontalLayout may have no parent, and it overloads this method assert(parent()); @@ -152,6 +169,34 @@ void LayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * n cursor->setLayoutNode(newChild); } +// Other +bool LayoutNode::hasText() const { + /* 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(); + return !(isHorizontal() && (numChildren == 0 || (numChildren == 1 && !(const_cast(this)->childAtIndex(0)->hasText())))); +} + +bool LayoutNode::canBeOmittedMultiplicationLeftFactor() const { + /* WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + * isCollapsable is true too. If isCollapsable changes, it might not be the + * case anymore so make sure to modify this function if needed. */ + int numberOfOpenParentheses = 0; + return isCollapsable(&numberOfOpenParentheses, true); +} + +bool LayoutNode::canBeOmittedMultiplicationRightFactor() const { + /* WARNING: canBeOmittedMultiplicationLeftFactor is true when and only when + * isCollapsable is true and isVerticalOffset is false. If one of these + * functions changes, it might not be the case anymore so make sure to modify + * canBeOmittedMultiplicationRightFactor if needed. */ + int numberOfOpenParentheses = 0; + return isCollapsable(&numberOfOpenParentheses, false) && !isVerticalOffset(); +} + // Private void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { @@ -195,12 +240,12 @@ void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, cursor->setPosition(LayoutCursor::Position::Right); } } - static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true); //TODO + static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true); return; } LayoutNode * juxtapositionLayout = nullptr; if (cursor->position() == LayoutCursor::Position::Left) { - juxtapositionLayout = replaceWithJuxtapositionOf(sibling, this); //TODO + juxtapositionLayout = replaceWithJuxtapositionOf(sibling, this); } else { assert(cursor->position() == LayoutCursor::Position::Right); juxtapositionLayout = replaceWithJuxtapositionOf(this, sibling); @@ -211,4 +256,154 @@ void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, } } +void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex) { + LayoutNode * p = parent(); + if (p == nullptr || !p->isHorizontal()) { + return; + } + int indexInParent = p->indexOfChild(this); + int numberOfSiblings = p->numberOfChildren(); + int numberOfOpenParenthesis = 0; + bool canCollapse = true; + LayoutNode * absorbingChild = childAtIndex(absorbingChildIndex); + if (!absorbingChild || !absorbingChild->isHorizontal()) { + return; + } + HorizontalLayoutNode * horizontalAbsorbingChild = static_cast(absorbingChild); + if (direction == HorizontalDirection::Right && indexInParent < numberOfSiblings - 1) { + canCollapse = !(p->childAtIndex(indexInParent+1)->mustHaveLeftSibling()); + } + LayoutNode * sibling = nullptr; + bool forceCollapse = false; + while (canCollapse) { + if (direction == HorizontalDirection::Right && indexInParent == numberOfSiblings - 1) { + break; + } + if (direction == HorizontalDirection::Left && indexInParent == 0) { + break; + } + int siblingIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; + sibling = p->childAtIndex(siblingIndex); + /* Even if forceCollapse is true, isCollapsable should be called to update + * the number of open parentheses. */ + bool shouldCollapse = sibling->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left); + if (shouldCollapse || forceCollapse) { + /* If the collapse direction is Left and the next sibling to be collapsed + * must have a left sibling, force the collapsing of this needed left + * sibling. */ + forceCollapse = direction == HorizontalDirection::Left && sibling->mustHaveLeftSibling(); + p->removeChildAtIndex(siblingIndex); + int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; + horizontalAbsorbingChild->addOrMergeChildAtIndex(sibling, newIndex, true); + numberOfSiblings--; + if (direction == HorizontalDirection::Left) { + indexInParent--; + } + } else { + break; + } + } +} + +// Private + +void LayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (!equivalentPositionVisited) { + LayoutCursor cursorEquivalent = equivalentCursor(cursor); + if (cursorEquivalent.isDefined()) { + cursor->setLayoutReference(cursorEquivalent.layoutReference()); + cursor->setPosition(cursorEquivalent.position()); + if (direction == VerticalDirection::Up) { + cursor->layoutNode()->moveCursorUp(cursor, shouldRecomputeLayout, true); + } else { + cursor->layoutNode()->moveCursorDown(cursor, shouldRecomputeLayout, true); + } + return; + } + } + LayoutNode * p = parent(); + if (p != nullptr) { + if (direction == VerticalDirection::Up) { + p->moveCursorUp(cursor, shouldRecomputeLayout, true); + } else { + p->moveCursorDown(cursor, shouldRecomputeLayout, true); + } + return; + } + cursor->setLayoutNode(nullptr); +} + +void LayoutNode::moveCursorInDescendantsVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout) { + LayoutNode * chilResult = nullptr; + LayoutNode ** childResultPtr = &chilResult; + LayoutCursor::Position resultPosition = LayoutCursor::Position::Left; + /* The distance between the cursor and its next position cannot be greater + * than this initial value of score. */ + int resultScore = Ion::Display::Width*Ion::Display::Width + Ion::Display::Height*Ion::Display::Height; + + scoreCursorInDescendantsVertically(direction, cursor, shouldRecomputeLayout, childResultPtr, &resultPosition, &resultScore); + + // If there is a valid result + if (*childResultPtr != nullptr) { + *shouldRecomputeLayout = chilResult->addGreySquaresToAllMatrixAncestors(); + } + cursor->setLayoutNode(chilResult); + cursor->setPosition(resultPosition); +} + +void LayoutNode::scoreCursorInDescendantsVertically ( + VerticalDirection direction, + LayoutCursor * cursor, + bool * shouldRecomputeLayout, + LayoutNode ** childResult, + void * resultPosition, + int * resultScore) +{ + LayoutCursor::Position * castedResultPosition = static_cast(resultPosition); + KDPoint cursorMiddleLeft = cursor->middleLeftPoint(); + bool layoutIsUnderOrAbove = direction == VerticalDirection::Up ? m_frame.isAbove(cursorMiddleLeft) : m_frame.isUnder(cursorMiddleLeft); + bool layoutContains = m_frame.contains(cursorMiddleLeft); + + if (layoutIsUnderOrAbove) { + // Check the distance to a Left cursor. + int currentDistance = LayoutCursor(this, LayoutCursor::Position::Left).middleLeftPoint().squareDistanceTo(cursorMiddleLeft); + if (currentDistance <= *resultScore ){ + *childResult = this; + *castedResultPosition = LayoutCursor::Position::Left; + *resultScore = currentDistance; + } + + // Check the distance to a Right cursor. + currentDistance = LayoutCursor(this, LayoutCursor::Position::Right).middleLeftPoint().squareDistanceTo(cursorMiddleLeft); + if (currentDistance < *resultScore) { + *childResult = this; + *castedResultPosition = LayoutCursor::Position::Right; + *resultScore = currentDistance; + } + } + if (layoutIsUnderOrAbove || layoutContains) { + int childIndex = 0; + while (childAtIndex(childIndex++)) { + childAtIndex(childIndex-1)->scoreCursorInDescendantsVertically(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); + } + } +} + +bool LayoutNode::changeGreySquaresOfAllMatrixAncestors(bool add) { + bool changedSquares = false; + LayoutNode * currentAncestor = parent(); + while (currentAncestor != nullptr) { + /*if (currentAncestor->isMatrix()) { + if (add) { + static_cast(currentAncestor)->addGreySquares(); + } else { + static_cast(currentAncestor)->removeGreySquares(); + } + changedSquares = true; + }*/ //TODO + currentAncestor = currentAncestor->parent(); + } + return changedSquares; +} + } From 9f3bf7995501ce8952eeb57ba8826885d3cc8469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 13:40:36 +0200 Subject: [PATCH 107/156] [poincare] Add methods on LayoutCursor --- poincare/include/poincare/layout_cursor.h | 49 +++++++++++--------- poincare/include/poincare/layout_reference.h | 1 + poincare/src/layout_cursor.cpp | 31 +++++++++++++ 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index b31b99a47..d8032c665 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -43,22 +43,14 @@ public: m_position(position) {} //TODO make this private and friend class layout_node - /* Debug */ - void log() { -#if TREE_LOG - printf("Pointed Layout id %d, cursor position ", m_layoutRef.identifier()); - if (m_position == Position::Left) { - printf("Left"); - } else { - printf("Right"); - } - printf("\n"); -#endif + LayoutCursor clone() const { + return LayoutCursor(m_layoutRef, m_position); } + // Definition bool isDefined() const { return m_layoutRef.isDefined(); } - /* Getters and setters */ + // Getters and setters LayoutRef layoutReference() { return m_layoutRef; } LayoutNode * layoutNode() { return m_layoutRef.typedNode(); } // TODO Make private + friend classes ? @@ -77,9 +69,7 @@ public: void setPosition(Position position) { m_position = position; } KDCoordinate cursorHeight(); KDCoordinate baseline(); - LayoutCursor clone() const { - return LayoutCursor(m_layoutRef, m_position); - } + /* Comparison */ bool isEquivalentTo(LayoutCursor cursor); @@ -110,26 +100,41 @@ public: result.move(direction, shouldRecomputeLayout); return result; } + /* Layout modification */ - void addFractionLayoutAndCollapseSiblings() {} //TODO void addEmptyExponentialLayout() {} //TODO + void addEmptyMatrixLayout() {} //TODO void addEmptyPowerLayout() {} //TODO void addEmptySquareRootLayout() {} //TODO void addEmptySquarePowerLayout() {} //TODO void addEmptyTenPowerLayout() {} //TODO - void addEmptyMatrixLayout() {} //TODO - bool showEmptyLayoutIfNeeded() { return false; } //TODO - bool hideEmptyLayoutIfNeeded() { return false; } //TODO - void performBackspace() { - m_layoutRef.deleteBeforeCursor(this); - } + void addFractionLayoutAndCollapseSiblings() {} //TODO + void addXNTCharLayout() {} //TODO void insertText(const char * text); void addLayoutAndMoveCursor(LayoutRef l); + bool showEmptyLayoutIfNeeded() { return privateShowHideEmptyLayoutIfNeeded(true); } + bool hideEmptyLayoutIfNeeded() { return privateShowHideEmptyLayoutIfNeeded(false); } + void performBackspace() { m_layoutRef.deleteBeforeCursor(this); } void clearLayout(); + // Debug + void log() { +#if TREE_LOG + printf("Pointed Layout id %d, cursor position ", m_layoutRef.identifier()); + if (m_position == Position::Left) { + printf("Left"); + } else { + printf("Right"); + } + printf("\n"); +#endif + } + private: constexpr static KDCoordinate k_cursorHeight = 18; KDCoordinate layoutHeight(); + bool baseForNewPowerLayout() { return false; } //TODO + bool privateShowHideEmptyLayoutIfNeeded(bool show); LayoutRef m_layoutRef; Position m_position; }; diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 525da71a8..342b9a679 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -40,6 +40,7 @@ public: void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } // Layout properties + bool isEmpty() const { return this->typedNode()->isEmpty(); } bool isHorizontal() const { return this->typedNode()->isHorizontal(); } bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } bool hasText() { return this->typedNode()->hasText(); } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 7244529d8..21407c932 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace Poincare { @@ -148,4 +149,34 @@ KDCoordinate LayoutCursor::layoutHeight() { } +bool LayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { + /* Find Empty layouts adjacent to the cursor: Check the pointed layout and the + * equivalent cursor positions */ + LayoutRef adjacentEmptyLayout(nullptr); + + if (m_layoutRef.isEmpty()) { + // Check the pointed layout + adjacentEmptyLayout = m_layoutRef; + } else { + // Check the equivalent cursor position + LayoutRef equivalentPointedLayout = m_layoutRef.equivalentCursor(this).layoutReference(); + if (equivalentPointedLayout.isDefined() && equivalentPointedLayout.isEmpty()) { + adjacentEmptyLayout = equivalentPointedLayout; + } + } + + if (!adjacentEmptyLayout.isDefined()) { + return false; + } + /* Change the visibility of the neighbouring empty layout: it might be either + * an EmptyLayout or an HorizontalLayout with one child only, and this child + * is an EmptyLayout. */ + if (adjacentEmptyLayout.isHorizontal()) { + static_cast(adjacentEmptyLayout.childAtIndex(0).node())->setVisible(show); + } else { + static_cast(adjacentEmptyLayout.node())->setVisible(show); + } + return true; +} + } From d7ff09782655d4b683c48c6f59e3701864d2717f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 14:03:43 +0200 Subject: [PATCH 108/156] [poincare] EmptyLayoutNode --- poincare/include/poincare/empty_layout_node.h | 94 ++++++++++++++++ poincare/src/empty_layout_node.cpp | 101 ++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 poincare/include/poincare/empty_layout_node.h create mode 100644 poincare/src/empty_layout_node.cpp diff --git a/poincare/include/poincare/empty_layout_node.h b/poincare/include/poincare/empty_layout_node.h new file mode 100644 index 000000000..0c1b2f163 --- /dev/null +++ b/poincare/include/poincare/empty_layout_node.h @@ -0,0 +1,94 @@ +#ifndef POINCARE_EMPTY_LAYOUT_NODE_H +#define POINCARE_EMPTY_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class EmptyLayoutNode : public LayoutNode { +public: + enum class Color { + Yellow, + Grey + }; + + EmptyLayoutNode(Color color = Color::Yellow, bool visible = true, KDText::FontSize fontSize = KDText::FontSize::Large, bool margins = true) : + LayoutNode(), + m_isVisible(visible), + m_color(color), + m_fontSize(fontSize), + m_margins(margins) + {} + + // EmptyLayout + Color color() const { return m_color; } + void setColor(Color color) { m_color = color; } + bool isVisible() const { return m_isVisible; } + void setVisible(bool visible) { m_isVisible = visible; } + void setMargins(bool margins) { m_margins = margins; } + void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } + + // LayoutNode + bool isEmpty() const override { return true; } + void deleteBeforeCursor(LayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + + // TreeNode + size_t size() const override { return sizeof(EmptyLayoutNode); } + int numberOfChildren() const override { return 0; } +#if TREE_LOG + const char * description() const override { return "Empty"; } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override { + assert(false); + return KDPointZero; + } +private: + constexpr static KDCoordinate k_marginWidth = 1; + constexpr static KDCoordinate k_marginHeight = 3; + constexpr static KDCoordinate k_lineThickness = 1; + KDCoordinate height() const { return KDText::charSize(m_fontSize).height() - 2*k_marginHeight; } + KDCoordinate width() const { return KDText::charSize(m_fontSize).width() - 2*k_marginWidth; } + + // LayoutNode + //LayoutCursor cursorVerticalOf(VerticalDirection direction, LayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; //TODO + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + + bool m_isVisible; + Color m_color; + KDText::FontSize m_fontSize; + bool m_margins; +}; + +class EmptyLayoutRef : public LayoutReference { +public: + EmptyLayoutRef(EmptyLayoutNode::Color color = EmptyLayoutNode::Color::Yellow, bool visible = true, KDText::FontSize fontSize = KDText::FontSize::Large, bool margins = true) : + LayoutReference() + { + if (!(this->node()->isAllocationFailure())) { + this->typedNode()->setColor(color); + this->typedNode()->setVisible(visible); + this->typedNode()->setFontSize(fontSize); + this->typedNode()->setMargins(margins); + } + } + void setVisible(bool visible) { + if (!(this->node()->isAllocationFailure())) { + this->typedNode()->setVisible(visible); + } + } +}; + +} + +#endif diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp new file mode 100644 index 000000000..5ea49c27f --- /dev/null +++ b/poincare/src/empty_layout_node.cpp @@ -0,0 +1,101 @@ +#include +//#include "matrix_layout.h" //TODO ? +#include +#include +#include + +namespace Poincare { + +void EmptyLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + cursor->setPosition(LayoutCursor::Position::Left); + LayoutNode * p = parent(); + if (p != nullptr) { + return p->deleteBeforeCursor(cursor); + } +} + +void EmptyLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->layoutNode() == this); + // Ask the parent. + LayoutNode * p = parent(); + if (p != nullptr) { + cursor->setPosition(LayoutCursor::Position::Left); + p->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void EmptyLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->layoutNode() == this); + // Ask the parent. + LayoutNode * p = parent(); + if (p != nullptr) { + cursor->setPosition(LayoutCursor::Position::Right); + p->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +int EmptyLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; +} + +void EmptyLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + if (m_isVisible) { + KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); + } +} + +void EmptyLayoutNode::computeSize() { + assert(!m_sized); + KDCoordinate sizeWidth = m_isVisible ? width() + 2*(m_margins ? k_marginWidth : 0) : 0; + m_frame.setSize(KDSize(sizeWidth, height() + 2*(m_margins ? k_marginHeight : 0))); + m_sized = true; +} + +void EmptyLayoutNode::computeBaseline() { + assert(!m_baselined); + m_baseline = (m_margins ? k_marginHeight : 0) + height()/2; + m_baselined = true; +} + +void EmptyLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { + Color currentColor = m_color; + int currentIndexInParent = indexInParent(); + if (sibling->mustHaveLeftSibling()) { + m_color = Color::Yellow; + LayoutNode::privateAddSibling(cursor, sibling, moveCursor); + } else { + if (moveCursor) { + replaceWithAndMoveCursor(sibling, cursor); + } else { + replaceWith(sibling); + } + } + /* if (currentColor == Color::Grey) { + // The parent is a MatrixLayout. + static_cast(parent())->newRowOrColumnAtIndex(indexInParent); + }*/ + //TODO and maybe put first so that "replace" works +} + +#if 0 +LayoutCursor EmptyLayoutNode::cursorVerticalOf(VerticalDirection direction, LayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + /* The two cursor positions around an EmptyLayoutNode are equivalent, so both + * should be checked. */ + assert(cursor->layoutReference() == this); + LayoutCursor cursorResult = LayoutNode::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, equivalentPositionVisited); + if (cursorResult.isDefined()) { + return cursorResult; + } + LayoutCursor::Position newPosition = cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left; + cursor->setPosition(newPosition); + return LayoutNode::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, false); +} +#endif + +} From 9e000c5b45ed2d2e0ade196c24a6522fd929b981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 15:07:49 +0200 Subject: [PATCH 109/156] [poincare] Fix cursor position when adding allocation failure --- .../include/poincare/horizontal_layout_node.h | 4 +- poincare/include/poincare/layout_node.h | 4 +- poincare/src/horizontal_layout_node.cpp | 35 +++++++-- poincare/src/layout_node.cpp | 75 +++++++++++++------ 4 files changed, 86 insertions(+), 32 deletions(-) diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 2b1340a3a..0fd126371 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -21,8 +21,8 @@ public: LayoutCursor equivalentCursor(LayoutCursor * cursor) override; // Tree modification - void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren); - void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren); + void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); // TODO remove default nullptr value + void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); void deleteBeforeCursor(LayoutCursor * cursor) override; void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index e82b177ad..d1c91116c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -65,12 +65,13 @@ public: // Tree modification // Add + void addChildAtIndex(LayoutNode * l, int index, LayoutCursor * cursor); void addSibling(LayoutCursor * cursor, LayoutNode * sibling); void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling); // Replace LayoutNode * replaceWith(LayoutNode * newChild); LayoutNode * replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); - LayoutNode * replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild); + void replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild, LayoutCursor * cursor = nullptr); //TODO remove default virtual void replaceChild(LayoutNode * oldChild, LayoutNode * newChild); virtual void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); // Remove @@ -162,6 +163,7 @@ protected: bool m_positioned; bool m_sized; private: + void privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); void moveCursorInDescendantsVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout); void scoreCursorInDescendantsVertically ( diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index a93e13027..98ab80a5e 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -38,15 +38,15 @@ LayoutCursor HorizontalLayoutNode::equivalentCursor(LayoutCursor * cursor) { // Tree modification -void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren) { +void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { if (l->isHorizontal()) { - mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren); + mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren, cursor); } else { - addChildTreeAtIndex(l, index); + addChildAtIndex(l, index, cursor); } } -void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int index, bool removeEmptyChildren) { +void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int index, bool removeEmptyChildren, LayoutCursor * cursor) { /* Remove any empty child that would be next to the inserted layout. * If the layout to insert starts with a vertical offset layout, any empty * layout child directly on the left of the inserted layout (if there is one) @@ -54,8 +54,28 @@ void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int in bool shouldRemoveOnLeft = h->numberOfChildren() == 0 ? true : !(h->childAtIndex(0)->mustHaveLeftSibling()); int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); + LayoutRef nextPointedLayout(nullptr); + LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; + if (index < numberOfChildren()) { + nextPointedLayout = LayoutRef(childAtIndex(index)); + nextPosition = LayoutCursor::Position::Left; + } else { + nextPointedLayout = LayoutRef(this); + nextPosition = LayoutCursor::Position::Right; + } + // Merge the horizontal layout - LayoutRef(this).mergeChildrenAtIndex(LayoutRef(h), newIndex); + LayoutRef thisRef = LayoutRef(this); + thisRef.mergeChildrenAtIndex(LayoutRef(h), newIndex); + + if (cursor != nullptr) { + if (!thisRef.isAllocationFailure()) { + cursor->setLayoutReference(nextPointedLayout); + cursor->setPosition(nextPosition); + } else { + cursor->setLayoutReference(thisRef); + } + } } void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { @@ -389,9 +409,10 @@ void HorizontalLayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode if (cursor != nullptr && !oldWasAncestorOfNewLayout) { cursor->setPosition(LayoutCursor::Position::Right); } - LayoutNode::replaceChild(oldChild, newChild); if (cursor != nullptr) { - cursor->setLayoutNode(newChild); + LayoutNode::replaceChildAndMoveCursor(oldChild, newChild, cursor); + } else { + LayoutNode::replaceChild(oldChild, newChild); } } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index d2b529516..430efd449 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -92,6 +92,31 @@ LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { } // Tree modification +void LayoutNode::addChildAtIndex(LayoutNode * l, int index, LayoutCursor * cursor) { + LayoutRef thisRef(this); + + LayoutRef nextPointedLayout(nullptr); + LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; + if (index < numberOfChildren()) { + nextPointedLayout = LayoutRef(childAtIndex(index)); + nextPosition = LayoutCursor::Position::Left; + } else { + nextPointedLayout = LayoutRef(this); + nextPosition = LayoutCursor::Position::Right; + } + + addChildTreeAtIndex(l, index); + + if (cursor != nullptr) { + if (thisRef.isAllocationFailure()) { + cursor->setLayoutReference(thisRef); + } else { + cursor->setLayoutReference(nextPointedLayout); + cursor->setPosition(nextPosition); + } + } +} + void LayoutNode::addSibling(LayoutCursor * cursor, LayoutNode * sibling) { privateAddSibling(cursor, sibling, false); } @@ -149,15 +174,24 @@ LayoutNode * LayoutNode::replaceWith(LayoutNode * newChild) { } void LayoutNode::replaceChild(LayoutNode * oldChild, LayoutNode * newChild) { - LayoutRef(this).replaceChild(LayoutRef(oldChild), LayoutRef(newChild)); + privateReplaceChild(oldChild, newChild, nullptr); } LayoutNode * LayoutNode::replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor) { return (LayoutRef(this).replaceWithAndMoveCursor(LayoutRef(newChild), cursor)).typedNode(); } -LayoutNode * LayoutNode::replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild) { - return (LayoutRef(this).replaceWithJuxtapositionOf(LayoutRef(leftChild), LayoutRef(rightChild))).typedNode(); +void LayoutNode::replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild, LayoutCursor * cursor) { + LayoutRef thisRef = LayoutRef(this); + LayoutRef juxtapositionLayout = thisRef.replaceWithJuxtapositionOf(LayoutRef(leftChild), LayoutRef(rightChild)); + if (cursor != nullptr) { + if (thisRef.isAllocationFailure()) { + cursor->setLayoutReference(thisRef); + } else { + cursor->setLayoutReference(juxtapositionLayout); + cursor->setPosition(LayoutCursor::Position::Right); + } + } } void LayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { @@ -165,8 +199,7 @@ void LayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * n if (!newChild->hasAncestor(oldChild, false)) { cursor->setPosition(LayoutCursor::Position::Right); } - replaceChild(oldChild, newChild); - cursor->setLayoutNode(newChild); + privateReplaceChild(oldChild, newChild, cursor); } // Other @@ -231,28 +264,14 @@ void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, } // Else, let the parent add the sibling. - if (moveCursor) { - if (siblingIndex < p->numberOfChildren()) { - cursor->setLayoutNode(p->childAtIndex(siblingIndex)); - cursor->setPosition(LayoutCursor::Position::Left); - } else { - cursor->setLayoutNode(p); - cursor->setPosition(LayoutCursor::Position::Right); - } - } - static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true); + static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true, cursor); return; } - LayoutNode * juxtapositionLayout = nullptr; if (cursor->position() == LayoutCursor::Position::Left) { - juxtapositionLayout = replaceWithJuxtapositionOf(sibling, this); + replaceWithJuxtapositionOf(sibling, this, cursor); } else { assert(cursor->position() == LayoutCursor::Position::Right); - juxtapositionLayout = replaceWithJuxtapositionOf(this, sibling); - } - if (moveCursor) { - cursor->setLayoutNode(juxtapositionLayout); - cursor->setPosition(LayoutCursor::Position::Right); + replaceWithJuxtapositionOf(this, sibling, cursor); } } @@ -307,6 +326,18 @@ void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbin // Private +void LayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { + LayoutRef thisRef = LayoutRef(this); + thisRef.replaceChild(LayoutRef(oldChild), LayoutRef(newChild)); + if (cursor != nullptr) { + if (thisRef.isAllocationFailure()) { + cursor->setLayoutReference(thisRef); + } else { + cursor->setLayoutNode(newChild); + } + } +} + void LayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (!equivalentPositionVisited) { LayoutCursor cursorEquivalent = equivalentCursor(cursor); From 74e4a83e59cc4a27398cf9c3ed32bdb1b496a9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 15:15:42 +0200 Subject: [PATCH 110/156] [poincare] Add methods on LayoutCursor --- poincare/include/poincare/layout_cursor.h | 4 +-- poincare/src/layout_cursor.cpp | 40 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index d8032c665..6f247a548 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -109,7 +109,7 @@ public: void addEmptySquarePowerLayout() {} //TODO void addEmptyTenPowerLayout() {} //TODO void addFractionLayoutAndCollapseSiblings() {} //TODO - void addXNTCharLayout() {} //TODO + void addXNTCharLayout(); void insertText(const char * text); void addLayoutAndMoveCursor(LayoutRef l); bool showEmptyLayoutIfNeeded() { return privateShowHideEmptyLayoutIfNeeded(true); } @@ -133,7 +133,7 @@ public: private: constexpr static KDCoordinate k_cursorHeight = 18; KDCoordinate layoutHeight(); - bool baseForNewPowerLayout() { return false; } //TODO + bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); LayoutRef m_layoutRef; Position m_position; diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 21407c932..20bb41cda 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -62,6 +62,10 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { } /* Layout modification */ +void LayoutCursor::addXNTCharLayout() { + m_layoutRef.addSiblingAndMoveCursor(this, CharLayoutRef(m_layoutRef.XNTChar())); +} + void LayoutCursor::insertText(const char * text) { int textLength = strlen(text); if (textLength <= 0) { @@ -149,6 +153,42 @@ KDCoordinate LayoutCursor::layoutHeight() { } +bool LayoutCursor::baseForNewPowerLayout() { + /* Returns true if the layout on the left of the pointed layout is suitable to + * be the base of a new power layout: the base layout should be anything but + * an horizontal layout with no child. */ + if (m_position == Position::Right) { + return !(m_layoutRef.isHorizontal() && m_layoutRef.numberOfChildren() == 0); + } else { + assert(m_position == Position::Left); + if (m_layoutRef.isHorizontal()) { + return false; + } + if (m_layoutRef.isEmpty()) { + /* If the cursor is on the left of an EmptyLayout, move it to its right, + * make sure it is yellow, and this EmptyLayout will be the base of the + * new power layout. */ + m_position = Position::Right; + if (static_cast(m_layoutRef.node())->color() == EmptyLayoutNode::Color::Grey) { + static_cast(m_layoutRef.node())->setColor(EmptyLayoutNode::Color::Yellow); + LayoutRef p = m_layoutRef.parent(); + int idxInParent = p.indexOfChild(m_layoutRef); + assert(idxInParent >= 0); + //TODO static_cast(p.node())->newRowOrColumnAtIndex(idxInParent); + } + return true; + } + LayoutCursor equivalentLayoutCursor = m_layoutRef.equivalentCursor(this); + if (!equivalentLayoutCursor.layoutReference().isDefined() + || (equivalentLayoutCursor.layoutReference().isHorizontal() + && equivalentLayoutCursor.position() == Position::Left)) + { + return false; + } + return true; + } +} + bool LayoutCursor::privateShowHideEmptyLayoutIfNeeded(bool show) { /* Find Empty layouts adjacent to the cursor: Check the pointed layout and the * equivalent cursor positions */ From f9a1c8f9f50634bb9c37cf51627eb4ddf390a882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Jul 2018 15:25:47 +0200 Subject: [PATCH 111/156] [poincare] Empty and Char Layout translation end --- poincare/include/poincare/char_layout_node.h | 1 + poincare/include/poincare/empty_layout_node.h | 2 +- poincare/include/poincare/layout_cursor.h | 4 ++++ poincare/include/poincare/layout_node.h | 2 +- poincare/src/char_layout_node.cpp | 17 +++++++++++++++++ poincare/src/empty_layout_node.cpp | 12 ++++++------ 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/char_layout_node.h b/poincare/include/poincare/char_layout_node.h index 37e2aa50a..fccfea8d0 100644 --- a/poincare/include/poincare/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -21,6 +21,7 @@ public: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; // TreeNode size_t size() const override { return sizeof(CharLayoutNode); } diff --git a/poincare/include/poincare/empty_layout_node.h b/poincare/include/poincare/empty_layout_node.h index 0c1b2f163..4825e220b 100644 --- a/poincare/include/poincare/empty_layout_node.h +++ b/poincare/include/poincare/empty_layout_node.h @@ -60,7 +60,7 @@ private: KDCoordinate width() const { return KDText::charSize(m_fontSize).width() - 2*k_marginWidth; } // LayoutNode - //LayoutCursor cursorVerticalOf(VerticalDirection direction, LayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; //TODO + void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 6f247a548..a1f50707f 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -65,6 +65,10 @@ public: m_layoutRef = LayoutRef(n); } } + void setTo(LayoutCursor * other) { + m_layoutRef = other->layoutReference(); + m_position = other->position(); + } Position position() const { return m_position; } void setPosition(Position position) { m_position = position; } KDCoordinate cursorHeight(); diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index d1c91116c..160fb6d32 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -121,6 +121,7 @@ protected: // Tree modification virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); + virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); // Iterators class Iterator { @@ -164,7 +165,6 @@ protected: bool m_sized; private: void privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); - virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); void moveCursorInDescendantsVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout); void scoreCursorInDescendantsVertically ( VerticalDirection direction, diff --git a/poincare/src/char_layout_node.cpp b/poincare/src/char_layout_node.cpp index 5723207f8..6992bb2c6 100644 --- a/poincare/src/char_layout_node.cpp +++ b/poincare/src/char_layout_node.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace Poincare { @@ -30,6 +31,22 @@ void CharLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecompu } } +bool CharLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis <= 0 + && (m_char == '+' + || m_char == '-' + || m_char == '*' + || m_char == Ion::Charset::MultiplicationSign + || m_char == Ion::Charset::MiddleDot + || m_char == Ion::Charset::Sto + || m_char == '=' + || m_char == ',')) + { + return false; + } + return true; +} + // Sizing and positioning void CharLayoutNode::computeSize() { assert(!m_sized); diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 5ea49c27f..4431287ef 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -83,19 +83,19 @@ void EmptyLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibl //TODO and maybe put first so that "replace" works } -#if 0 -LayoutCursor EmptyLayoutNode::cursorVerticalOf(VerticalDirection direction, LayoutCursor cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { +void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { /* The two cursor positions around an EmptyLayoutNode are equivalent, so both * should be checked. */ assert(cursor->layoutReference() == this); - LayoutCursor cursorResult = LayoutNode::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, equivalentPositionVisited); + LayoutCursor cursorResult = cursor->clone(); + moveCursorVertically(direction, &cursorResult, shouldRecomputeLayout, equivalentPositionVisited); if (cursorResult.isDefined()) { - return cursorResult; + cursor->setTo(&cursorResult); + return; } LayoutCursor::Position newPosition = cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left; cursor->setPosition(newPosition); - return LayoutNode::cursorVerticalOf(direction, cursor, shouldRecomputeLayout, false); + LayoutNode::moveCursorVertically(direction, cursor, shouldRecomputeLayout, false); } -#endif } From 3eabf77ed50a0fc308e49d88516e345302895e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Jul 2018 14:27:55 +0200 Subject: [PATCH 112/156] [poincare] Templatize iterators on TreeNode --- poincare/include/poincare/layout_node.h | 29 +++----------------- poincare/include/poincare/tree_node.h | 35 ++++++++++++++----------- poincare/include/poincare/tree_pool.h | 12 ++++----- 3 files changed, 28 insertions(+), 48 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 160fb6d32..fb6b52d0d 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -49,6 +49,8 @@ public: return AllocationFailureNodeIdentifier(); } + LayoutNode * next() const override { return static_cast(TreeNode::next()); } + LayoutNode * nextSibling() const override { return static_cast(TreeNode::nextSibling()); } // Tree LayoutNode * parent() const { return static_cast(parentTree()); } LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } @@ -123,32 +125,7 @@ protected: void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); - // Iterators - class Iterator { - public: - Iterator(LayoutNode * node) : m_node(node) {} - LayoutNode * operator*() { return m_node; } - bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } - protected: - LayoutNode * m_node; - }; - class DirectChildren { - public: - DirectChildren(LayoutNode * node) : m_node(node) {} - class Iterator : public LayoutNode::Iterator { - public: - using LayoutNode::Iterator::Iterator; - Iterator & operator++() { - m_node = static_cast(m_node->nextSibling()); - return *this; - } - }; - Iterator begin() const { return Iterator(static_cast(m_node->next())); } - Iterator end() const { return Iterator(static_cast(m_node->nextSibling())); } - private: - LayoutNode * m_node; - }; - DirectChildren children() { return DirectChildren(this); } + Direct children() { return Direct(this); } // Sizing and positioning virtual void computeSize() = 0; diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 9cfe8dd31..677f1dc90 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -78,59 +78,62 @@ public: bool hasAncestor(const TreeNode * node, bool includeSelf) const; bool hasSibling(const TreeNode * e) const; + template class Iterator { public: - Iterator(const TreeNode * node) : m_node(const_cast(node)) {} - TreeNode * operator*() { return m_node; } + Iterator(const T * node) : m_node(const_cast(node)) {} + T * operator*() { return m_node; } bool operator!=(const Iterator& it) const { return (m_node != it.m_node); } protected: - TreeNode * m_node; + T * m_node; }; + template class Direct { public: - Direct(const TreeNode * node) : m_node(const_cast(node)) {} - class Iterator : public TreeNode::Iterator { + Direct(const T * node) : m_node(const_cast(node)) {} + class Iterator : public TreeNode::Iterator { public: - using TreeNode::Iterator::Iterator; + using TreeNode::Iterator::Iterator; Iterator & operator++() { - m_node = m_node->nextSibling(); + this->m_node = this->m_node->nextSibling(); return *this; } }; Iterator begin() const { return Iterator(m_node->next()); } Iterator end() const { return Iterator(m_node->nextSibling()); } private: - TreeNode * m_node; + T * m_node; }; + template class DepthFirst { public: DepthFirst(const TreeNode * node) : m_node(const_cast(node)) {} - class Iterator : public TreeNode::Iterator { + class Iterator : public TreeNode::Iterator { public: - using TreeNode::Iterator::Iterator; + using TreeNode::Iterator::Iterator; Iterator & operator++() { - m_node = m_node->next(); + this->m_node = this->m_node->next(); return *this; } }; Iterator begin() const { return Iterator(m_node->next()); } Iterator end() const { return Iterator(m_node->nextSibling()); } private: - TreeNode * m_node; + T * m_node; }; - Direct directChildren() const { return Direct(this); } - DepthFirst depthFirstChildren() const { return DepthFirst(this); } + Direct directChildren() const { return Direct(this); } + DepthFirst depthFirstChildren() const { return DepthFirst(this); } - TreeNode * next() const { + virtual TreeNode * next() const { // Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler. // Unfortunately, we want TreeNode to have a VARIABLE size return reinterpret_cast(reinterpret_cast(const_cast(this)) + size()); } - TreeNode * nextSibling() const { + virtual TreeNode * nextSibling() const { int remainingNodesToVisit = numberOfChildren(); TreeNode * node = const_cast(this)->next(); while (remainingNodesToVisit > 0) { diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 61fecbea2..c9360e8d0 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -106,9 +106,9 @@ private: class AllPool { public: AllPool(TreeNode * node) : m_node(node) {} - class Iterator : public TreeNode::Iterator { + class Iterator : public TreeNode::Iterator { public: - using TreeNode::Iterator::Iterator; + using TreeNode::Iterator::Iterator; Iterator & operator++() { m_node = m_node->next(); return *this; @@ -124,9 +124,9 @@ private: class Roots { public: Roots(TreeNode * node) : m_node(node) {} - class Iterator : public TreeNode::Iterator { + class Iterator : public TreeNode::Iterator { public: - using TreeNode::Iterator::Iterator; + using TreeNode::Iterator::Iterator; Iterator & operator++() { m_node = m_node->nextSibling(); return *this; @@ -139,8 +139,8 @@ private: }; Roots roots() { return Roots(*(begin())); } - TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } - TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } + TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } TreePool() : m_cursor(m_buffer) { } From 1e5994b9268b2cbf9081f4af7655e9d99fc94fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Jul 2018 16:14:38 +0200 Subject: [PATCH 113/156] [tree] Fix memove32 --- poincare/src/tree_pool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index a23188271..54838b660 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -23,7 +23,8 @@ TreeNode * TreePool::node(int identifier) const { } static void memmove32(uint32_t * dst, uint32_t * src, size_t len) { - if (dst > src) { + if (src < dst && dst < src + len) { + /* Copy backwards to avoid overwrites */ src += len; dst += len; while (len--) { From 30a2b681fa1b7be6e8e25aa82c645e166978c84d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Jul 2018 16:18:33 +0200 Subject: [PATCH 114/156] [tree] Clean some allocationFailureNode methods on TreeNode --- apps/tree/expression_node.h | 6 ------ poincare/include/poincare/layout_node.h | 6 ------ poincare/include/poincare/tree_node.h | 10 +++------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/apps/tree/expression_node.h b/apps/tree/expression_node.h index 536fa8f37..fa88b5cfe 100644 --- a/apps/tree/expression_node.h +++ b/apps/tree/expression_node.h @@ -36,12 +36,6 @@ public: // Allocation failure static TreeNode * FailedAllocationStaticNode(); - static int AllocationFailureNodeIdentifier() { - return FailedAllocationStaticNode()->identifier(); - } - int allocationFailureNodeIdentifier() override { - return AllocationFailureNodeIdentifier(); - } TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } // Hierarchy diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index fb6b52d0d..10e159afe 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -42,12 +42,6 @@ public: // TreeNode static TreeNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } - static int AllocationFailureNodeIdentifier() { - return FailedAllocationStaticNode()->identifier(); - } - int allocationFailureNodeIdentifier() override { - return AllocationFailureNodeIdentifier(); - } LayoutNode * next() const override { return static_cast(TreeNode::next()); } LayoutNode * nextSibling() const override { return static_cast(TreeNode::nextSibling()); } diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 677f1dc90..cad2af8c8 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -43,13 +43,9 @@ public: // Allocation failure virtual bool isAllocationFailure() const { return false; } - virtual TreeNode * failedAllocationStaticNode() { - assert(false); - return nullptr; - } - virtual int allocationFailureNodeIdentifier() { - assert(false); - return -1; + virtual TreeNode * failedAllocationStaticNode() = 0; + int allocationFailureNodeIdentifier() { + return failedAllocationStaticNode()->identifier(); } // Node operations From 18bd8ea21bc5a684eb461d7037ba0c6ed64c8f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Jul 2018 17:10:03 +0200 Subject: [PATCH 115/156] [tree] SerializableNode and Ref --- apps/tree/expression_node.h | 4 +-- apps/tree/expression_reference.h | 12 +++---- poincare/Makefile | 6 ++-- poincare/include/poincare.h | 2 ++ poincare/include/poincare/layout_engine.h | 6 ++-- poincare/include/poincare/layout_node.h | 6 ++-- poincare/include/poincare/layout_reference.h | 8 ++--- poincare/include/poincare/serializable_node.h | 19 ++++++++++ .../include/poincare/serializable_reference.h | 35 +++++++++++++++++++ poincare/include/poincare/tree_node.h | 6 ---- poincare/include/poincare/tree_reference.h | 10 ------ poincare/src/horizontal_layout_node.cpp | 2 +- poincare/src/layout_engine.cpp | 16 ++++----- 13 files changed, 87 insertions(+), 45 deletions(-) create mode 100644 poincare/include/poincare/serializable_node.h create mode 100644 poincare/include/poincare/serializable_reference.h diff --git a/apps/tree/expression_node.h b/apps/tree/expression_node.h index fa88b5cfe..08cf1dfcd 100644 --- a/apps/tree/expression_node.h +++ b/apps/tree/expression_node.h @@ -1,10 +1,10 @@ #ifndef EXPRESSION_NODE_H #define EXPRESSION_NODE_H -#include "tree_node.h" +#include #include -class ExpressionNode : public TreeNode { +class ExpressionNode : public SerializableNode { public: enum class Type : uint8_t { AllocationFailure = 0, diff --git a/apps/tree/expression_reference.h b/apps/tree/expression_reference.h index e9ce93dd6..947727e8c 100644 --- a/apps/tree/expression_reference.h +++ b/apps/tree/expression_reference.h @@ -1,15 +1,15 @@ -#ifndef EXPRESSION_REFERENCE_H -#define EXPRESSION_REFERENCE_H +#ifndef POINCARE_EXPRESSION_REFERENCE_H +#define POINCARE_EXPRESSION_REFERENCE_H -#include "tree_reference.h" -#include "expression_node.h" +#include +#include #include template -class ExpressionReference : public TreeReference { +class ExpressionReference : public SerializableReference { public: - using TreeReference::TreeReference; + using SerializableReference::SerializableReference; /* Allow every ExpressionReference to be transformed into an * ExpressionReference, i.e. ExpressionRef */ diff --git a/poincare/Makefile b/poincare/Makefile index a874f8e7f..9c3d83e95 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -2,6 +2,10 @@ SFLAGS += -Ipoincare/include #include poincare/src/simplify/Makefile #include poincare/src/simplification/Makefile +objs += $(addprefix poincare/src/,\ + tree_node.o\ + tree_pool.o\ +) objs += $(addprefix poincare/src/,\ char_layout_node.o\ @@ -92,8 +96,6 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ - tree_node.o\ - tree_pool.o\ trigonometry.o\ undefined.o\ variable_context.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 5fa0199b3..869b79e98 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -72,6 +72,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 8481c13f6..0e790c9e7 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -53,8 +53,8 @@ public: bool writeFirstChild = true); /* LayoutReference to Text */ - static int writeInfixTreeRefTextInBuffer( - const TreeRef treeRef, + static int writeInfixSerializableRefTextInBuffer( + const SerializableRef serializableRef, char * buffer, int bufferSize, int numberOfDigits, @@ -71,7 +71,7 @@ private: static int writeInfixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, int firstChildIndex, int lastChildIndex, ChildNeedsParenthesis childNeedsParenthesis); static int writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expression * expression, const ExpressionLayout * expressionLayout, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName, bool writeFirstChild = true); - static void writeChildTreeInBuffer(TreeRef childRef, TreeRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar); + static void writeChildTreeInBuffer(SerializableRef childRef, SerializableRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar); }; } diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 10e159afe..b7a1f71c7 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -1,7 +1,7 @@ #ifndef POINCARE_LAYOUT_NODE_H #define POINCARE_LAYOUT_NODE_H -#include +#include #include #include @@ -9,7 +9,7 @@ namespace Poincare { class LayoutCursor; -class LayoutNode : public TreeNode { +class LayoutNode : public SerializableNode { public: enum class VerticalDirection { Up, @@ -22,7 +22,7 @@ public: // Constructor LayoutNode() : - TreeNode(), + SerializableNode(), m_baseline(0), m_frame(KDRectZero), m_baselined(false), diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 342b9a679..868217d4b 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -1,18 +1,18 @@ #ifndef POINCARE_LAYOUT_REFERENCE_H #define POINCARE_LAYOUT_REFERENCE_H -#include "tree_reference.h" -#include "layout_node.h" +#include +#include namespace Poincare { class LayoutCursor; template -class LayoutReference : public TreeReference { +class LayoutReference : public SerializableReference { friend class LayoutCursor; public: - using TreeReference::TreeReference; + using SerializableReference::SerializableReference; // Operators diff --git a/poincare/include/poincare/serializable_node.h b/poincare/include/poincare/serializable_node.h new file mode 100644 index 000000000..d1e5da497 --- /dev/null +++ b/poincare/include/poincare/serializable_node.h @@ -0,0 +1,19 @@ +#ifndef POINCARE_SERIALIZABLE_NODE_H +#define POINCARE_SERIALIZABLE_NODE_H + +#include +#include + +namespace Poincare { + +class SerializableNode : public TreeNode { +public: + using TreeNode::TreeNode; + virtual bool needsParenthesisWithParent(SerializableNode * parentNode) { return false; } //TODO + virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const = 0; + +}; + +} + +#endif diff --git a/poincare/include/poincare/serializable_reference.h b/poincare/include/poincare/serializable_reference.h new file mode 100644 index 000000000..db6998885 --- /dev/null +++ b/poincare/include/poincare/serializable_reference.h @@ -0,0 +1,35 @@ +#ifndef POINCARE_SERIALIZABLE_REFERENCE_H +#define POINCARE_SERIALIZABLE_REFERENCE_H + +#include +#include + +namespace Poincare { + +template +class SerializableReference : public TreeReference { +public: + using TreeReference::TreeReference; + + // Serialization + bool needsParenthesisWithParent(SerializableReference parentRef) { + assert(this->isDefined()); + return this->typedNode()->needsParenthesisWithParent(parentRef.typedNode()); + } + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { + assert(this->isDefined()); + return this->typedNode()->writeTextInBuffer(buffer, bufferSize, numberOfSignificantDigits); + } + + // Tree + SerializableReference serializableChildAtIndex(int i) { + TreeReference treeRefChild = TreeReference::treeChildAtIndex(i); + return SerializableReference(treeRefChild.node()); + } +}; + +typedef SerializableReference SerializableRef; + +} + +#endif diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index cad2af8c8..9a28f50a1 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -1,8 +1,6 @@ #ifndef POINCARE_TREE_NODE_H #define POINCARE_TREE_NODE_H -#include - #include #include #include @@ -37,10 +35,6 @@ public: virtual const char * description() const { return "UNKNOWN";} - // Serialization - virtual bool needsParenthesisWithParent(TreeNode * parentNode) { return false; } //TODO virtual pure and override on expresionNode/layoutNode - virtual int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { return 0; } //TODO virtual pure - // Allocation failure virtual bool isAllocationFailure() const { return false; } virtual TreeNode * failedAllocationStaticNode() = 0; diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index bcf7a1f6d..fdcacf249 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -82,16 +82,6 @@ public: return node()->numberOfDescendants(includeSelf); } - // Serialization - bool needsParenthesisWithParent(TreeReference parentRef) { - assert(isDefined()); - return node()->needsParenthesisWithParent(parentRef.node()); - } - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { - assert(isDefined()); - return node()->writeTextInBuffer(buffer, bufferSize, numberOfSignificantDigits); - } - // Hierarchy bool hasChild(TreeReference t) const { assert(isDefined()); diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 98ab80a5e..7f8ac7d61 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -142,7 +142,7 @@ int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int n buffer[0] = 0; return 0; } - return LayoutEngine::writeInfixTreeRefTextInBuffer(TreeRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, ""); + return LayoutEngine::writeInfixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, ""); } void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index fc096b3de..e3c8ff6ec 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -213,8 +213,8 @@ int LayoutEngine::writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expr } /* LayoutReference to Text */ -int LayoutEngine::writeInfixTreeRefTextInBuffer( - const TreeRef treeRef, +int LayoutEngine::writeInfixSerializableRefTextInBuffer( + const SerializableRef serializableRef, char * buffer, int bufferSize, int numberOfDigits, @@ -223,7 +223,7 @@ int LayoutEngine::writeInfixTreeRefTextInBuffer( int lastChildIndex) { // If buffer has size 0 or 1, put a zero if it fits and return - assert(treeRef.isDefined()); + assert(serializableRef.isDefined()); if (bufferSize == 0) { return -1; } @@ -233,13 +233,13 @@ int LayoutEngine::writeInfixTreeRefTextInBuffer( return 0; } - // Get some information on the TreeRef + // Get some information on the SerializableRef int numberOfChar = 0; - int numberOfOperands = treeRef.numberOfChildren(); + int numberOfOperands = serializableRef.numberOfChildren(); assert(numberOfOperands > 0); // Write the first child, with parentheses if needed - writeChildTreeInBuffer(treeRef.treeChildAtIndex(firstChildIndex), treeRef, buffer, bufferSize, numberOfDigits, &numberOfChar); + writeChildTreeInBuffer((const_cast(&serializableRef))->serializableChildAtIndex(firstChildIndex), serializableRef, buffer, bufferSize, numberOfDigits, &numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } @@ -252,7 +252,7 @@ int LayoutEngine::writeInfixTreeRefTextInBuffer( return bufferSize-1; } // Write the child, with parentheses if needed - writeChildTreeInBuffer(treeRef.treeChildAtIndex(i), treeRef, buffer, bufferSize, numberOfDigits, &numberOfChar); + writeChildTreeInBuffer((const_cast(&serializableRef))->serializableChildAtIndex(i), serializableRef, buffer, bufferSize, numberOfDigits, &numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } @@ -263,7 +263,7 @@ int LayoutEngine::writeInfixTreeRefTextInBuffer( return numberOfChar; } -void LayoutEngine::writeChildTreeInBuffer(TreeRef childRef, TreeRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar) { +void LayoutEngine::writeChildTreeInBuffer(SerializableRef childRef, SerializableRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar) { // Write the child with parentheses if needed bool addParentheses = childRef.needsParenthesisWithParent(parentRef); if (addParentheses) { From ddddafe626e9add77d7dbccc7be4a9605eef1f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Jul 2018 13:39:27 +0200 Subject: [PATCH 116/156] [tree] Put pool modification methods in references, not nodes --- .../poincare/allocation_failed_layout_node.h | 6 +- poincare/include/poincare/empty_layout_node.h | 2 +- .../include/poincare/horizontal_layout_node.h | 30 +-- poincare/include/poincare/layout_node.h | 22 +- poincare/include/poincare/layout_reference.h | 29 ++- poincare/include/poincare/tree_node.h | 6 - poincare/include/poincare/tree_reference.h | 24 +- poincare/src/empty_layout_node.cpp | 21 +- poincare/src/horizontal_layout_node.cpp | 217 +++++++++--------- poincare/src/layout_cursor.cpp | 6 +- poincare/src/layout_node.cpp | 138 +---------- poincare/src/layout_reference.cpp | 127 +++++++++- poincare/src/tree_node.cpp | 22 -- 13 files changed, 309 insertions(+), 341 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 1e9a46b52..33156c2ee 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -17,7 +17,6 @@ public: void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {} LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); } - void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override { } void deleteBeforeCursor(LayoutCursor * cursor) override { } // TreeNode @@ -36,7 +35,10 @@ protected: } private: - void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override {} + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; } + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override { return false; } + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override { return false; } + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} }; diff --git a/poincare/include/poincare/empty_layout_node.h b/poincare/include/poincare/empty_layout_node.h index 4825e220b..7951275fb 100644 --- a/poincare/include/poincare/empty_layout_node.h +++ b/poincare/include/poincare/empty_layout_node.h @@ -62,7 +62,7 @@ private: // LayoutNode void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; - void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; bool m_isVisible; Color m_color; diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 0fd126371..fb7debd70 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -21,18 +21,20 @@ public: LayoutCursor equivalentCursor(LayoutCursor * cursor) override; // Tree modification - void addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); // TODO remove default nullptr value - void mergeChildrenAtIndex(HorizontalLayoutNode * horizontalLayout, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); void deleteBeforeCursor(LayoutCursor * cursor) override; - void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) override; + + // SerializableNode + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; // LayoutNode bool isHorizontal() const override { return true; } - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; - void replaceChild(LayoutNode * oldChild, LayoutNode * newChild) override; - void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; + + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override; + void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) override; + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; // TreeNode size_t size() const override { return sizeof(HorizontalLayoutNode); } @@ -56,25 +58,27 @@ protected: KDPoint positionOfChild(LayoutNode * l) override; private: - void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; - void privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); - void privateRemoveChildAtIndex(int index, bool forceRemove); void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} - int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); int m_numberOfChildren; }; class HorizontalLayoutRef : public LayoutReference { public: HorizontalLayoutRef() : LayoutReference() {} + HorizontalLayoutRef(TreeNode * hNode) : LayoutReference(hNode) {} HorizontalLayoutRef(LayoutRef l) : LayoutReference() { - addChildTree(l); + addChildTreeAtIndex(l, 0); } HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference() { - addChildTree(l2); - addChildTree(l1); + addChildTreeAtIndex(l1, 0); + addChildTreeAtIndex(l2, 1); } + + void addOrMergeChildAtIndex(LayoutRef l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); + void mergeChildrenAtIndex(HorizontalLayoutRef h, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); +private: + int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); }; } diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index b7a1f71c7..0719a8a71 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -45,6 +45,7 @@ public: LayoutNode * next() const override { return static_cast(TreeNode::next()); } LayoutNode * nextSibling() const override { return static_cast(TreeNode::nextSibling()); } + // Tree LayoutNode * parent() const { return static_cast(parentTree()); } LayoutNode * childAtIndex(int i) { return static_cast(childTreeAtIndex(i)); } @@ -60,18 +61,6 @@ public: virtual LayoutCursor equivalentCursor(LayoutCursor * cursor); // Tree modification - // Add - void addChildAtIndex(LayoutNode * l, int index, LayoutCursor * cursor); - void addSibling(LayoutCursor * cursor, LayoutNode * sibling); - void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling); - // Replace - LayoutNode * replaceWith(LayoutNode * newChild); - LayoutNode * replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); - void replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild, LayoutCursor * cursor = nullptr); //TODO remove default - virtual void replaceChild(LayoutNode * oldChild, LayoutNode * newChild); - virtual void replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); - // Remove - virtual void removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor); // Collapse virtual void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} // User input @@ -113,11 +102,17 @@ public: return p == nullptr ? Ion::Charset::Empty : p->XNTChar(); } + // TODO: put private + virtual bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { return true; } + virtual bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); + virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { return true; } + virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} protected: // Tree modification - virtual void privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor); void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + LayoutNode * privateReplaceWith(LayoutNode * newChild); + LayoutNode * privateReplaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); Direct children() { return Direct(this); } @@ -135,7 +130,6 @@ protected: bool m_positioned; bool m_sized; private: - void privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); void moveCursorInDescendantsVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout); void scoreCursorInDescendantsVertically ( VerticalDirection direction, diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 868217d4b..95006c09e 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -40,8 +40,10 @@ public: void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } // Layout properties + bool mustHaveLeftSibling() const { return this->typedNode()->mustHaveLeftSibling(); } bool isEmpty() const { return this->typedNode()->isEmpty(); } bool isHorizontal() const { return this->typedNode()->isHorizontal(); } + bool isVerticalOffset() const { return this->typedNode()->isVerticalOffset(); } bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } bool hasText() { return this->typedNode()->hasText(); } char XNTChar() const { return this->typedNode()->XNTChar(); } @@ -66,27 +68,34 @@ public: LayoutReference parent() { return LayoutReference(this->typedNode()->parent()); } // Tree modification + // Add + void addChildAtIndex(LayoutReference l, int index, LayoutCursor * cursor); + void addSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor); // Replace - void replaceChild(LayoutReference oldChild, LayoutReference newChild) { TreeReference::replaceChild(oldChild, newChild); } void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - void replaceChildAndMoveCursor(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor) { this->typedNode()->replaceChildAndMoveCursor(oldChild.typedNode(), newChild.typedNode(), cursor); } + void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr); LayoutReference replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { LayoutReference p = parent(); assert(p.isDefined()); - p.replaceChildAndMoveCursor(*this, newChild, cursor); + p.replaceChild(*this, newChild, cursor); return newChild; } - LayoutReference replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild); - // Add - void addSibling(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSibling(cursor, sibling.typedNode()); } - void addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutReference sibling) { return this->typedNode()->addSiblingAndMoveCursor(cursor, sibling.typedNode()); } - //Remove - void removeChildAndMoveCursor(LayoutReference l, LayoutCursor * cursor) { return this->typedNode()->removeChildAndMoveCursor(l.typedNode(), cursor); } + void replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild, LayoutCursor * cursor); + // Remove + void removeChild(LayoutReference l, LayoutCursor * cursor, bool force = false); + void removeChildAtIndex(int index, LayoutCursor * cursor, bool force = false) { + return removeChild(childAtIndex(index), cursor, force); + } // Collapse - void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} //TODO + void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) { return this->typedNode()->collapseSiblingsAndMoveCursor(cursor); } // Allocation failure static TreeNode * FailedAllocationStaticNode(); +private: + void privateAddSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor); + bool preprocessAddSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor) { + return this->typedNode()->preprocessAddSibling(cursor, sibling.typedNode(), moveCursor); + } }; typedef LayoutReference LayoutRef; diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 9a28f50a1..379bd0a5a 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -145,12 +145,6 @@ public: return node; } - // Hierarchy operations - void addChildTreeAtIndex(TreeNode * t, int index); - void removeChild(TreeNode * t); - void removeChildAtIndex(int index) { return removeChild(childTreeAtIndex(index)); } - void replaceChildTree(TreeNode * t, TreeNode * newChild); - void replaceWithAllocationFailure(); protected: TreeNode() : m_identifier(-1), diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index fdcacf249..77a9d0328 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -111,8 +111,6 @@ public: // Hierarchy operations - void addChildTree(TreeReference t) { return addChildTreeAtIndex(t, 0); } - void addChildTreeAtIndex(TreeReference t, int index) { assert(isDefined()); if (node()->isAllocationFailure()) { @@ -130,7 +128,7 @@ public: // Detach t from its parent TreeReference tParent = t.parent(); if (tParent.isDefined()) { - tParent.removeChild(t); + tParent.removeTreeChild(t); } // Move t @@ -141,8 +139,14 @@ public: TreePool::sharedPool()->move(t.node(), newChildPosition); node()->incrementNumberOfChildren(); } + void removeTreeChildAtIndex(int i) { + assert(isDefined()); + assert(i >= 0 && i < numberOfChildren()); + TreeReference t = treeChildAtIndex(i); + removeTreeChild(t); + } - void removeChild(TreeReference t) { + void removeTreeChild(TreeReference t) { assert(isDefined()); TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); t.node()->release(); @@ -160,15 +164,15 @@ public: assert(isDefined()); TreeReference p = parent(); if (p.isDefined()) { - p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); + p.replaceTreeChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t); } } - void replaceChild(TreeReference oldChild, TreeReference newChild) { - replaceChildAtIndex(indexOfChild(oldChild), newChild); + void replaceTreeChild(TreeReference oldChild, TreeReference newChild) { + replaceTreeChildAtIndex(indexOfChild(oldChild), newChild); } - void replaceChildAtIndex(int oldChildIndex, TreeReference newChild) { + void replaceTreeChildAtIndex(int oldChildIndex, TreeReference newChild) { assert(isDefined()); if (newChild.isAllocationFailure()) { replaceWithAllocationFailure(); @@ -237,7 +241,7 @@ public: TreePool::sharedPool()->move(secondChild.node(), firstChildNode); } - void mergeChildrenAtIndex(TreeReference t, int i) { + void mergeTreeChildrenAtIndex(TreeReference t, int i) { assert(i >= 0 && i <= numberOfChildren()); // Steal operands int numberOfNewChildren = t.numberOfChildren(); @@ -249,7 +253,7 @@ public: t.node()->eraseNumberOfChildren(); // If t is a child, remove it if (node()->hasChild(t.node())) { - removeChild(t); + removeTreeChild(t); } node()->incrementNumberOfChildren(numberOfNewChildren); } diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 4431287ef..0ab369db2 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -63,24 +63,17 @@ void EmptyLayoutNode::computeBaseline() { m_baselined = true; } -void EmptyLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { - Color currentColor = m_color; - int currentIndexInParent = indexInParent(); +bool EmptyLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { if (sibling->mustHaveLeftSibling()) { m_color = Color::Yellow; - LayoutNode::privateAddSibling(cursor, sibling, moveCursor); - } else { - if (moveCursor) { - replaceWithAndMoveCursor(sibling, cursor); - } else { - replaceWith(sibling); - } } - /* if (currentColor == Color::Grey) { - // The parent is a MatrixLayout. - static_cast(parent())->newRowOrColumnAtIndex(indexInParent); + return true; + /* Color currentColor = m_color; + int currentIndexInParent = indexInParent(); + if (currentColor == Color::Grey) { + // The parent is a MatrixLayout. + static_cast(parent())->newRowOrColumnAtIndex(indexInParent); }*/ - //TODO and maybe put first so that "replace" works } void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 7f8ac7d61..33578abf2 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace Poincare { @@ -38,46 +39,6 @@ LayoutCursor HorizontalLayoutNode::equivalentCursor(LayoutCursor * cursor) { // Tree modification -void HorizontalLayoutNode::addOrMergeChildAtIndex(LayoutNode * l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { - if (l->isHorizontal()) { - mergeChildrenAtIndex(static_cast(l), index, removeEmptyChildren, cursor); - } else { - addChildAtIndex(l, index, cursor); - } -} - -void HorizontalLayoutNode::mergeChildrenAtIndex(HorizontalLayoutNode * h, int index, bool removeEmptyChildren, LayoutCursor * cursor) { - /* Remove any empty child that would be next to the inserted layout. - * If the layout to insert starts with a vertical offset layout, any empty - * layout child directly on the left of the inserted layout (if there is one) - * should not be removed: it will be the base for the VerticalOffsetLayout. */ - bool shouldRemoveOnLeft = h->numberOfChildren() == 0 ? true : !(h->childAtIndex(0)->mustHaveLeftSibling()); - int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); - - LayoutRef nextPointedLayout(nullptr); - LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; - if (index < numberOfChildren()) { - nextPointedLayout = LayoutRef(childAtIndex(index)); - nextPosition = LayoutCursor::Position::Left; - } else { - nextPointedLayout = LayoutRef(this); - nextPosition = LayoutCursor::Position::Right; - } - - // Merge the horizontal layout - LayoutRef thisRef = LayoutRef(this); - thisRef.mergeChildrenAtIndex(LayoutRef(h), newIndex); - - if (cursor != nullptr) { - if (!thisRef.isAllocationFailure()) { - cursor->setLayoutReference(nextPointedLayout); - cursor->setPosition(nextPosition); - } else { - cursor->setLayoutReference(thisRef); - } - } -} - void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { LayoutNode * p = parent(); if (p == nullptr @@ -116,20 +77,17 @@ void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { LayoutNode::deleteBeforeCursor(cursor); } -void HorizontalLayoutNode::removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) { +bool HorizontalLayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { if (numberOfChildren() == 1) { assert(childAtIndex(0) == l); LayoutNode * p = parent(); if (p != nullptr) { - p->removeChildAndMoveCursor(this, cursor); - } else { - removeChild(l); - cursor->setLayoutNode(this); - cursor->setPosition(LayoutCursor::Position::Left); + LayoutRef(p).removeChild(this, cursor); + // WARNING: Do not call "this" afterwards + return false; } - return; } - LayoutNode::removeChildAndMoveCursor(l, cursor); + return true; } // LayoutNode @@ -235,15 +193,6 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR return childAtIndex(childIndex+1)->moveCursorRight(cursor, shouldRecomputeLayout); } -void HorizontalLayoutNode::replaceChild(LayoutNode * oldChild, LayoutNode * newChild) { - privateReplaceChild(oldChild, newChild, nullptr); -} - -void HorizontalLayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { - privateReplaceChild(oldChild, newChild, cursor); -} - - // Protected void HorizontalLayoutNode::computeSize() { @@ -285,8 +234,9 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { // Private -void HorizontalLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { +bool HorizontalLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { int childrenCount = numberOfChildren(); + HorizontalLayoutRef thisRef(this); // Add the "sibling" as a child. if (cursor->position() == LayoutCursor::Position::Left) { int indexForInsertion = 0; @@ -299,74 +249,84 @@ void HorizontalLayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * /* We force the removal of the child even followed by a neighbourg * requiring a left sibling as we are about to add a sibling in first * position anyway. */ - privateRemoveChildAtIndex(0, true); + thisRef.removeChildAtIndex(0, cursor, true); + // WARNING: do not call "this" afterwards } } if (moveCursor) { if (childrenCount > indexForInsertion) { - cursor->setLayoutNode(childAtIndex(indexForInsertion)); + cursor->setLayoutReference(thisRef.childAtIndex(indexForInsertion)); } else { - cursor->setLayoutNode(this); + cursor->setLayoutReference(thisRef); cursor->setPosition(LayoutCursor::Position::Right); } } - addOrMergeChildAtIndex(sibling, indexForInsertion, false); - return; - } - assert(cursor->position() == LayoutCursor::Position::Right); - // If the last child is empty, remove it before adding the layout. - if (childrenCount > 0 && childAtIndex(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { - /* Force remove the last child. */ - privateRemoveChildAtIndex(childrenCount - 1, true); - childrenCount--; - } - addOrMergeChildAtIndex(sibling, childrenCount, false); - if (moveCursor) { - cursor->setLayoutNode(this); + thisRef.addOrMergeChildAtIndex(sibling, indexForInsertion, false); + // WARNING: do not call "this" afterwards + } else { + assert(cursor->position() == LayoutCursor::Position::Right); + // If the last child is empty, remove it before adding the layout. + if (childrenCount > 0 && childAtIndex(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { + /* Force remove the last child. */ + thisRef.removeChildAtIndex(childrenCount - 1, cursor, true); + // WARNING: do not call "this" afterwards + childrenCount--; + } + thisRef.addOrMergeChildAtIndex(sibling, childrenCount, false); + // WARNING: do not call "this" afterwards + if (moveCursor) { + cursor->setLayoutReference(thisRef); + } } + return false; } -void HorizontalLayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { +bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { if (oldChild == newChild) { - return; + return false; } + HorizontalLayoutRef thisRef(this); int oldChildIndex = indexOfChild(oldChild); if (newChild->isEmpty()) { if (numberOfChildren() > 1) { /* If the new layout is empty and the horizontal layout has other * children, just remove the old child. */ - removeChild(oldChild); + thisRef.removeChild(oldChild, nullptr); + // WARNING: do not call "this" afterwards if (cursor != nullptr) { if (oldChildIndex == 0) { - cursor->setLayoutNode(this); + cursor->setLayoutReference(thisRef); cursor->setPosition(LayoutCursor::Position::Left); } else { - cursor->setLayoutNode(childAtIndex(oldChildIndex -1)); + cursor->setLayoutReference(thisRef.childAtIndex(oldChildIndex -1)); cursor->setPosition(LayoutCursor::Position::Right); } } - return; + return false; } /* The old layout was the only horizontal layout child, so if this has a * a parent, replace this with the new empty layout. */ LayoutNode * p = parent(); if (p != nullptr) { if (cursor) { - replaceWithAndMoveCursor(newChild, cursor); + thisRef.replaceWithAndMoveCursor(newChild, cursor); + // WARNING: do not call "this" afterwards } else { - replaceWith(newChild); + thisRef.replaceWith(newChild); + // WARNING: do not call "this" afterwards } - return; + return false; } /* This is the main horizontal layout, the old child is its only child and * the new child is Empty: remove the old child and delete the new child. */ assert(p == nullptr); - removeChild(oldChild); + thisRef.removeChild(oldChild, nullptr); + // WARNING: do not call "this" afterwards if (cursor != nullptr) { - cursor->setLayoutNode(this); + cursor->setLayoutReference(thisRef); cursor->setPosition(LayoutCursor::Position::Left); } - return; + return false; } /* If the new child is also an horizontal layout, steal the children of the * new layout then destroy it. */ @@ -399,57 +359,88 @@ void HorizontalLayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode } } bool oldChildRemovedAtMerge = oldChild->isEmpty(); - mergeChildrenAtIndex(static_cast(newChild), indexForInsertion + 1, true); + thisRef.mergeChildrenAtIndex(HorizontalLayoutRef(newChild), indexForInsertion + 1, true); + // WARNING: do not call "this" afterwards if (!oldChildRemovedAtMerge) { - removeChildAtIndex(indexForInsertion); + thisRef.removeChildAtIndex(indexForInsertion, cursor); } - return; + return false; } // Else, just replace the child. if (cursor != nullptr && !oldWasAncestorOfNewLayout) { cursor->setPosition(LayoutCursor::Position::Right); } - if (cursor != nullptr) { - LayoutNode::replaceChildAndMoveCursor(oldChild, newChild, cursor); - } else { - LayoutNode::replaceChild(oldChild, newChild); + return true; +} + +void HorizontalLayoutNode::didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) { + /* If the child to remove was at index 0 and its right sibling must have a left + * sibling (e.g. a VerticalOffsetLayout), add an empty layout at index 0 */ + + if (!force && index == 0 && numberOfChildren() > 0 && childAtIndex(0)->mustHaveLeftSibling()) { + HorizontalLayoutRef(this).addChildAtIndex(EmptyLayoutRef(), 0, cursor); } } -void HorizontalLayoutNode::privateRemoveChildAtIndex(int index, bool forceRemove) { - /* Remove the child before potentially adding an EmptyLayout. Indeed, adding - * a new child would remove any EmptyLayout surrounding the new child and in - * the case the child to be removed was an Empty layout, it would result in - * removing it twice if we remove it afterwards. */ - removeChild(childAtIndex(index)); - /* If the child to remove is at index 0 and its right sibling must have a left - * sibling (e.g. it is a VerticalOffsetLayout), replace the child with an - * EmptyLayout instead of removing it. */ - - /*if (!forceRemove && index == 0 && numberOfChildren() > 0 && child(0)->mustHaveLeftSibling()) { - addChildAtIndex(new EmptyLayout(), 0); - }*/ //TODO +// HorizontalLayoutRef +void HorizontalLayoutRef::addOrMergeChildAtIndex(LayoutRef l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { + if (l.isHorizontal()) { + mergeChildrenAtIndex(HorizontalLayoutRef(l.node()), index, removeEmptyChildren, cursor); + } else { + addChildAtIndex(l, index, cursor); + } } -int HorizontalLayoutNode::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { +void HorizontalLayoutRef::mergeChildrenAtIndex(HorizontalLayoutRef h, int index, bool removeEmptyChildren, LayoutCursor * cursor) { + /* Remove any empty child that would be next to the inserted layout. + * If the layout to insert starts with a vertical offset layout, any empty + * layout child directly on the left of the inserted layout (if there is one) + * should not be removed: it will be the base for the VerticalOffsetLayout. */ + bool shouldRemoveOnLeft = h.numberOfChildren() == 0 ? true : !(h.childAtIndex(0).mustHaveLeftSibling()); + int newIndex = removeEmptyChildBeforeInsertionAtIndex(index, shouldRemoveOnLeft); + + LayoutRef nextPointedLayout(nullptr); + LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; + if (index < numberOfChildren()) { + nextPointedLayout = childAtIndex(index); + nextPosition = LayoutCursor::Position::Left; + } else { + nextPointedLayout = *this; + nextPosition = LayoutCursor::Position::Right; + } + + // Merge the horizontal layout + TreeRef(node()).mergeTreeChildrenAtIndex(h, newIndex); + + if (cursor != nullptr) { + if (!isAllocationFailure()) { + cursor->setLayoutReference(nextPointedLayout); + cursor->setPosition(nextPosition); + } else { + cursor->setLayoutReference(*this); + } + } +} + +int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { int currentNumberOfChildren = numberOfChildren(); assert(index >= 0 && index <= currentNumberOfChildren); int newIndex = index; /* If empty, remove the child that would be on the right of the inserted * layout. */ if (newIndex < currentNumberOfChildren) { - LayoutNode * c = childAtIndex(newIndex); - if (c->isEmpty()) { - removeChild(c); + LayoutRef c = childAtIndex(newIndex); + if (c.isEmpty()) { + removeChild(c, nullptr); currentNumberOfChildren--; } } /* If empty, remove the child that would be on the left of the inserted * layout. */ if (shouldRemoveOnLeft && newIndex - 1 >= 0 && newIndex - 1 <= currentNumberOfChildren -1) { - LayoutNode * c = childAtIndex(newIndex - 1); - if (c->isEmpty()) { - removeChild(c); + LayoutRef c = childAtIndex(newIndex - 1); + if (c.isEmpty()) { + removeChild(c, nullptr); newIndex = index - 1; } } diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 20bb41cda..865136ba5 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -63,7 +63,7 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { /* Layout modification */ void LayoutCursor::addXNTCharLayout() { - m_layoutRef.addSiblingAndMoveCursor(this, CharLayoutRef(m_layoutRef.XNTChar())); + m_layoutRef.addSibling(this, CharLayoutRef(m_layoutRef.XNTChar()), true); } void LayoutCursor::insertText(const char * text) { @@ -112,7 +112,7 @@ void LayoutCursor::insertText(const char * text) { else { newChild = CharLayoutRef(text[i]); } - m_layoutRef.addSiblingAndMoveCursor(this, newChild); + m_layoutRef.addSibling(this, newChild, true); } if (pointedChild.isDefined() && pointedChild.parent().isDefined()) { m_layoutRef = pointedChild; @@ -121,7 +121,7 @@ void LayoutCursor::insertText(const char * text) { void LayoutCursor::addLayoutAndMoveCursor(LayoutRef l) { bool layoutWillBeMerged = l.isHorizontal(); - m_layoutRef.addSiblingAndMoveCursor(this, l); + m_layoutRef.addSibling(this, l, true); if (!layoutWillBeMerged) { l.collapseSiblingsAndMoveCursor(this); } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 430efd449..46cdc159d 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -92,54 +92,6 @@ LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { } // Tree modification -void LayoutNode::addChildAtIndex(LayoutNode * l, int index, LayoutCursor * cursor) { - LayoutRef thisRef(this); - - LayoutRef nextPointedLayout(nullptr); - LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; - if (index < numberOfChildren()) { - nextPointedLayout = LayoutRef(childAtIndex(index)); - nextPosition = LayoutCursor::Position::Left; - } else { - nextPointedLayout = LayoutRef(this); - nextPosition = LayoutCursor::Position::Right; - } - - addChildTreeAtIndex(l, index); - - if (cursor != nullptr) { - if (thisRef.isAllocationFailure()) { - cursor->setLayoutReference(thisRef); - } else { - cursor->setLayoutReference(nextPointedLayout); - cursor->setPosition(nextPosition); - } - } -} - -void LayoutNode::addSibling(LayoutCursor * cursor, LayoutNode * sibling) { - privateAddSibling(cursor, sibling, false); -} - -void LayoutNode::addSiblingAndMoveCursor(LayoutCursor * cursor, LayoutNode * sibling) { - privateAddSibling(cursor, sibling, true); -} - -void LayoutNode::removeChildAndMoveCursor(LayoutNode * l, LayoutCursor * cursor) { - assert(hasChild(l)); - int index = indexOfChild(l); - removeChild(l); - if (index < numberOfChildren()) { - cursor->setLayoutNode(childAtIndex(index)); - cursor->setPosition(LayoutCursor::Position::Left); - } else { - int newPointedLayoutIndex = index - 1; - assert(newPointedLayoutIndex >= 0); - assert(newPointedLayoutIndex < numberOfChildren()); - cursor->setLayoutNode(childAtIndex(newPointedLayoutIndex)); - cursor->setPosition(LayoutCursor::Position::Right); - } -} void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); @@ -164,42 +116,22 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { } assert(cursor->position() == LayoutCursor::Position::Right); // Case: Right. Delete the layout. - p->removeChildAndMoveCursor(this, cursor); + LayoutRef(p).removeChild(this, cursor); + //WARNING: Do no use "this" afterwards } -LayoutNode * LayoutNode::replaceWith(LayoutNode * newChild) { +LayoutNode * LayoutNode::privateReplaceWith(LayoutNode * newChild) { LayoutRef newRef(newChild); LayoutRef(this).replaceWith(newRef); return newRef.typedNode(); } -void LayoutNode::replaceChild(LayoutNode * oldChild, LayoutNode * newChild) { - privateReplaceChild(oldChild, newChild, nullptr); -} - -LayoutNode * LayoutNode::replaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor) { - return (LayoutRef(this).replaceWithAndMoveCursor(LayoutRef(newChild), cursor)).typedNode(); -} - -void LayoutNode::replaceWithJuxtapositionOf(LayoutNode * leftChild, LayoutNode * rightChild, LayoutCursor * cursor) { - LayoutRef thisRef = LayoutRef(this); - LayoutRef juxtapositionLayout = thisRef.replaceWithJuxtapositionOf(LayoutRef(leftChild), LayoutRef(rightChild)); - if (cursor != nullptr) { - if (thisRef.isAllocationFailure()) { - cursor->setLayoutReference(thisRef); - } else { - cursor->setLayoutReference(juxtapositionLayout); - cursor->setPosition(LayoutCursor::Position::Right); - } - } -} - -void LayoutNode::replaceChildAndMoveCursor(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { +bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { assert(hasChild(oldChild)); if (!newChild->hasAncestor(oldChild, false)) { cursor->setPosition(LayoutCursor::Position::Right); } - privateReplaceChild(oldChild, newChild, cursor); + return true; } // Other @@ -232,50 +164,8 @@ bool LayoutNode::canBeOmittedMultiplicationRightFactor() const { // Private -void LayoutNode::privateAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { - /* The layout must have a parent, because HorizontalLayout overrides - * privateAddSibling and only an HorizontalLayout can be the root layout. */ - LayoutNode * p = parent(); - assert(p != nullptr); - if (p->isHorizontal()) { - int indexInParent = p->indexOfChild(this); - int siblingIndex = cursor->position() == LayoutCursor::Position::Left ? indexInParent : indexInParent + 1; - - /* Special case: If the neighbour sibling is a VerticalOffsetLayout, let it - * handle the insertion of the new sibling. Do not enter the special case if - * "this" is a VerticalOffsetLayout, to avoid an infinite loop. */ - if (!isVerticalOffset()) { - LayoutNode * neighbour = nullptr; - if (cursor->position() == LayoutCursor::Position::Left && indexInParent > 0) { - neighbour = p->childAtIndex(indexInParent - 1); - } else if (cursor->position() ==LayoutCursor::Position::Right && indexInParent < p->numberOfChildren() - 1) { - neighbour = p->childAtIndex(indexInParent + 1); - } - if (neighbour != nullptr && neighbour->isVerticalOffset()) { - cursor->setLayoutNode(neighbour); - cursor->setPosition(cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left); - if (moveCursor) { - neighbour->addSiblingAndMoveCursor(cursor, sibling); - } else { - neighbour->addSibling(cursor, sibling); - } - return; - } - } - - // Else, let the parent add the sibling. - static_cast(p)->addOrMergeChildAtIndex(sibling, siblingIndex, true, cursor); - return; - } - if (cursor->position() == LayoutCursor::Position::Left) { - replaceWithJuxtapositionOf(sibling, this, cursor); - } else { - assert(cursor->position() == LayoutCursor::Position::Right); - replaceWithJuxtapositionOf(this, sibling, cursor); - } -} - void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex) { + //TODO use the ref in this instead of "this" LayoutNode * p = parent(); if (p == nullptr || !p->isHorizontal()) { return; @@ -311,9 +201,9 @@ void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbin * must have a left sibling, force the collapsing of this needed left * sibling. */ forceCollapse = direction == HorizontalDirection::Left && sibling->mustHaveLeftSibling(); - p->removeChildAtIndex(siblingIndex); + /*p->removeChildAtIndex(siblingIndex); int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; - horizontalAbsorbingChild->addOrMergeChildAtIndex(sibling, newIndex, true); + //TODO TODO TODO horizontalAbsorbingChild->privateAddOrMergeChildAtIndex(sibling, newIndex, true); //TODO remove the private call*/ numberOfSiblings--; if (direction == HorizontalDirection::Left) { indexInParent--; @@ -326,18 +216,6 @@ void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbin // Private -void LayoutNode::privateReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { - LayoutRef thisRef = LayoutRef(this); - thisRef.replaceChild(LayoutRef(oldChild), LayoutRef(newChild)); - if (cursor != nullptr) { - if (thisRef.isAllocationFailure()) { - cursor->setLayoutReference(thisRef); - } else { - cursor->setLayoutNode(newChild); - } - } -} - void LayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (!equivalentPositionVisited) { LayoutCursor cursorEquivalent = equivalentCursor(cursor); diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 131f7a7f1..e21a1a91b 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -30,8 +30,24 @@ LayoutCursor LayoutRef::equivalentCursor(LayoutCursor * cursor) { } // Tree modification + template<> -LayoutReference LayoutRef::replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild) { +void LayoutRef::replaceChild(LayoutRef oldChild, LayoutRef newChild, LayoutCursor * cursor) { + if (!typedNode()->willReplaceChild(oldChild.typedNode(), newChild.typedNode(), cursor)) { + return; + } + replaceTreeChild(oldChild, newChild); + if (cursor != nullptr) { + if (isAllocationFailure()) { + cursor->setLayoutReference(*this); + } else { + cursor->setLayoutReference(newChild); + } + } +} + +template<> +void LayoutRef::replaceWithJuxtapositionOf(LayoutRef leftChild, LayoutRef rightChild, LayoutCursor * cursor) { LayoutReference p = parent(); assert(p.isDefined()); assert(!p.isHorizontal()); @@ -42,10 +58,115 @@ LayoutReference LayoutRef::replaceWithJuxtapositionOf(LayoutReferenc horizontalLayoutR.addChildTreeAtIndex(leftChild, 0); horizontalLayoutR.addChildTreeAtIndex(rightChild, 1); p.addChildTreeAtIndex(horizontalLayoutR, index); - return horizontalLayoutR; + + if (cursor != nullptr) { + if (horizontalLayoutR.isAllocationFailure()) { + cursor->setLayoutReference(*this); + } else { + cursor->setLayoutReference(horizontalLayoutR); + cursor->setPosition(LayoutCursor::Position::Right); + } + } +} + +template +void LayoutReference::addChildAtIndex(LayoutRef l, int index, LayoutCursor * cursor) { + LayoutRef nextPointedLayout(nullptr); + LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; + if (index < this->numberOfChildren()) { + nextPointedLayout = this->childAtIndex(index); + nextPosition = LayoutCursor::Position::Left; + } else { + nextPointedLayout = *this; + nextPosition = LayoutCursor::Position::Right; + } + + this->addChildTreeAtIndex(l, index); + + if (cursor != nullptr) { + if (this->isAllocationFailure()) { + cursor->setLayoutReference(*this); + } else { + cursor->setLayoutReference(nextPointedLayout); + cursor->setPosition(nextPosition); + } + } +} + +template<> +void LayoutRef::addSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor) { + if (!typedNode()->willAddSibling(cursor, sibling.typedNode(), moveCursor)) { //TODO + return; + } + /* The layout must have a parent, because HorizontalLayoutRef's + * preprocessAddSibling returns false only an HorizontalLayout can be the + * root layout. */ + LayoutRef p = parent(); + assert(p.isDefined()); + if (p.isHorizontal()) { + int indexInParent = p.indexOfChild(*this); + int siblingIndex = cursor->position() == LayoutCursor::Position::Left ? indexInParent : indexInParent + 1; + + /* Special case: If the neighbour sibling is a VerticalOffsetLayout, let it + * handle the insertion of the new sibling. Do not enter the special case if + * "this" is a VerticalOffsetLayout, to avoid an infinite loop. */ + if (!isVerticalOffset()) { + LayoutRef neighbour(nullptr); + if (cursor->position() == LayoutCursor::Position::Left && indexInParent > 0) { + neighbour = p.childAtIndex(indexInParent - 1); + } else if (cursor->position() ==LayoutCursor::Position::Right && indexInParent < p.numberOfChildren() - 1) { + neighbour = p.childAtIndex(indexInParent + 1); + } + if (neighbour.isDefined() && neighbour.isVerticalOffset()) { + cursor->setLayoutReference(neighbour); + cursor->setPosition(cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left); + neighbour.addSibling(cursor, sibling, moveCursor); + return; + } + } + + // Else, let the parent add the sibling. + HorizontalLayoutRef(p.typedNode()).addOrMergeChildAtIndex(sibling, siblingIndex, true, cursor); + return; + } + if (cursor->position() == LayoutCursor::Position::Left) { + replaceWithJuxtapositionOf(sibling, *this, cursor); + } else { + assert(cursor->position() == LayoutCursor::Position::Right); + replaceWithJuxtapositionOf(*this, sibling, cursor); + } +} + +template +void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force) { + if (!this->typedNode()->willRemoveChild(l.typedNode(), cursor)) { + return; + } + assert(this->hasChild(l)); + int index = this->indexOfChild(l); + this->removeTreeChild(l); + if (index < this->numberOfChildren()) { + cursor->setLayoutReference(this->childAtIndex(index)); + cursor->setPosition(LayoutCursor::Position::Left); + } else { + int newPointedLayoutIndex = index - 1; + assert(newPointedLayoutIndex >= 0); + if (newPointedLayoutIndex < this->numberOfChildren()) { + cursor->setLayoutReference(this->childAtIndex(newPointedLayoutIndex)); + cursor->setPosition(LayoutCursor::Position::Right); + } else { + cursor->setLayoutReference(*this); + cursor->setPosition(LayoutCursor::Position::Right); + + } + } + this->typedNode()->didRemoveChildAtIndex(index, cursor, force); } template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; - +template void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force); +template void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force); +template void LayoutReference::addChildAtIndex(LayoutRef l, int index, LayoutCursor * cursor); +template void LayoutReference::addChildAtIndex(LayoutRef l, int index, LayoutCursor * cursor); } diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 41f128d3d..f0b1c1464 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -184,26 +184,4 @@ bool TreeNode::hasSibling(const TreeNode * e) const { return false; } -void TreeNode::addChildTreeAtIndex(TreeNode * t, int index) { - TreeRef tr(this); - tr.addChildTreeAtIndex(TreeRef(t), index); -} - -void TreeNode::removeChild(TreeNode * t) { - TreeRef tr(this); - tr.removeChild(TreeRef(t)); -} - -void TreeNode::replaceChildTree(TreeNode * t, TreeNode * newChild) { - int oldChildIndex = indexOfChild(t); - addChildTreeAtIndex(newChild, oldChildIndex + 1); - removeChild(t); -} - -void TreeNode::replaceWithAllocationFailure() { - TreeRef t(this); - t.replaceWithAllocationFailure(); - // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? -} - } From b2ea3caefae5a0b42fa825bc47049915bcd5b7a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Jul 2018 17:25:53 +0200 Subject: [PATCH 117/156] [tree] Rename collapseSiblingsAndMoveCursor -> collapseSiblings --- poincare/include/poincare/layout_node.h | 2 +- poincare/include/poincare/layout_reference.h | 2 +- poincare/src/layout_cursor.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 0719a8a71..ef302ecee 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -62,7 +62,7 @@ public: // Tree modification // Collapse - virtual void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) {} + virtual void collapseSiblings(LayoutCursor * cursor) {} // User input virtual void deleteBeforeCursor(LayoutCursor * cursor); diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 95006c09e..42bd86784 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -87,7 +87,7 @@ public: return removeChild(childAtIndex(index), cursor, force); } // Collapse - void collapseSiblingsAndMoveCursor(LayoutCursor * cursor) { return this->typedNode()->collapseSiblingsAndMoveCursor(cursor); } + void collapseSiblings(LayoutCursor * cursor) { return this->typedNode()->collapseSiblings(cursor); } // Allocation failure static TreeNode * FailedAllocationStaticNode(); diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 865136ba5..c88a01723 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -123,7 +123,7 @@ void LayoutCursor::addLayoutAndMoveCursor(LayoutRef l) { bool layoutWillBeMerged = l.isHorizontal(); m_layoutRef.addSibling(this, l, true); if (!layoutWillBeMerged) { - l.collapseSiblingsAndMoveCursor(this); + l.collapseSiblings(this); } } From b8f555e8fd15ef177500ef956347a26b0bcf28ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Jul 2018 17:32:28 +0200 Subject: [PATCH 118/156] [tree] Remove dead code --- poincare/include/poincare/layout_node.h | 7 ++++--- poincare/include/poincare/layout_reference.h | 5 ----- poincare/src/layout_node.cpp | 6 ------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index ef302ecee..02b716091 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -110,10 +110,11 @@ public: protected: // Tree modification void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); - virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); - LayoutNode * privateReplaceWith(LayoutNode * newChild); - LayoutNode * privateReplaceWithAndMoveCursor(LayoutNode * newChild, LayoutCursor * cursor); + // Tree navigation + virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); + + // Tree Direct children() { return Direct(this); } // Sizing and positioning diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 42bd86784..1fce226b2 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -91,11 +91,6 @@ public: // Allocation failure static TreeNode * FailedAllocationStaticNode(); -private: - void privateAddSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor); - bool preprocessAddSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor) { - return this->typedNode()->preprocessAddSibling(cursor, sibling.typedNode(), moveCursor); - } }; typedef LayoutReference LayoutRef; diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 46cdc159d..cc5e955b8 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -120,12 +120,6 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { //WARNING: Do no use "this" afterwards } -LayoutNode * LayoutNode::privateReplaceWith(LayoutNode * newChild) { - LayoutRef newRef(newChild); - LayoutRef(this).replaceWith(newRef); - return newRef.typedNode(); -} - bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { assert(hasChild(oldChild)); if (!newChild->hasAncestor(oldChild, false)) { From d0b88156cdcd921853ce1d14b797d9a4fcc43486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Jul 2018 17:54:27 +0200 Subject: [PATCH 119/156] [poincare/layout] Put collapseSiblings on LayoutRefs --- poincare/include/poincare/layout_node.h | 10 +--- poincare/include/poincare/layout_reference.h | 18 ++++++- poincare/src/layout_node.cpp | 52 -------------------- poincare/src/layout_reference.cpp | 50 +++++++++++++++++++ 4 files changed, 69 insertions(+), 61 deletions(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 02b716091..05f1cb824 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -15,10 +15,6 @@ public: Up, Down }; - enum class HorizontalDirection { - Left, - Right - }; // Constructor LayoutNode() : @@ -62,7 +58,8 @@ public: // Tree modification // Collapse - virtual void collapseSiblings(LayoutCursor * cursor) {} + virtual bool shouldCollapseSiblingsOnLeft() { return false; } + virtual bool shouldCollapseSiblingsOnRight() { return false; } // User input virtual void deleteBeforeCursor(LayoutCursor * cursor); @@ -108,9 +105,6 @@ public: virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { return true; } virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} protected: - // Tree modification - void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); - // Tree navigation virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 1fce226b2..c007344e9 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -45,6 +45,7 @@ public: bool isHorizontal() const { return this->typedNode()->isHorizontal(); } bool isVerticalOffset() const { return this->typedNode()->isVerticalOffset(); } bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return this->typedNode()->isCollapsable(numberOfOpenParenthesis, goingLeft); } bool hasText() { return this->typedNode()->hasText(); } char XNTChar() const { return this->typedNode()->XNTChar(); } @@ -87,10 +88,25 @@ public: return removeChild(childAtIndex(index), cursor, force); } // Collapse - void collapseSiblings(LayoutCursor * cursor) { return this->typedNode()->collapseSiblings(cursor); } + void collapseSiblings(LayoutCursor * cursor) { + int absorbingChildIndex = 0; //TODO + if (this->typedNode()->shouldCollapseSiblingsOnRight()) { + collapseOnDirection(HorizontalDirection::Right, absorbingChildIndex); + } + if (this->typedNode()->shouldCollapseSiblingsOnLeft()) { + collapseOnDirection(HorizontalDirection::Left, absorbingChildIndex); + } + } // Allocation failure static TreeNode * FailedAllocationStaticNode(); +private: + // Tree modification + enum class HorizontalDirection { + Left, + Right + }; + void collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex); }; typedef LayoutReference LayoutRef; diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index cc5e955b8..79e545373 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -158,58 +158,6 @@ bool LayoutNode::canBeOmittedMultiplicationRightFactor() const { // Private -void LayoutNode::collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex) { - //TODO use the ref in this instead of "this" - LayoutNode * p = parent(); - if (p == nullptr || !p->isHorizontal()) { - return; - } - int indexInParent = p->indexOfChild(this); - int numberOfSiblings = p->numberOfChildren(); - int numberOfOpenParenthesis = 0; - bool canCollapse = true; - LayoutNode * absorbingChild = childAtIndex(absorbingChildIndex); - if (!absorbingChild || !absorbingChild->isHorizontal()) { - return; - } - HorizontalLayoutNode * horizontalAbsorbingChild = static_cast(absorbingChild); - if (direction == HorizontalDirection::Right && indexInParent < numberOfSiblings - 1) { - canCollapse = !(p->childAtIndex(indexInParent+1)->mustHaveLeftSibling()); - } - LayoutNode * sibling = nullptr; - bool forceCollapse = false; - while (canCollapse) { - if (direction == HorizontalDirection::Right && indexInParent == numberOfSiblings - 1) { - break; - } - if (direction == HorizontalDirection::Left && indexInParent == 0) { - break; - } - int siblingIndex = direction == HorizontalDirection::Right ? indexInParent+1 : indexInParent-1; - sibling = p->childAtIndex(siblingIndex); - /* Even if forceCollapse is true, isCollapsable should be called to update - * the number of open parentheses. */ - bool shouldCollapse = sibling->isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left); - if (shouldCollapse || forceCollapse) { - /* If the collapse direction is Left and the next sibling to be collapsed - * must have a left sibling, force the collapsing of this needed left - * sibling. */ - forceCollapse = direction == HorizontalDirection::Left && sibling->mustHaveLeftSibling(); - /*p->removeChildAtIndex(siblingIndex); - int newIndex = direction == HorizontalDirection::Right ? absorbingChild->numberOfChildren() : 0; - //TODO TODO TODO horizontalAbsorbingChild->privateAddOrMergeChildAtIndex(sibling, newIndex, true); //TODO remove the private call*/ - numberOfSiblings--; - if (direction == HorizontalDirection::Left) { - indexInParent--; - } - } else { - break; - } - } -} - -// Private - void LayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { if (!equivalentPositionVisited) { LayoutCursor cursorEquivalent = equivalentCursor(cursor); diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index e21a1a91b..a451c0191 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -163,6 +163,56 @@ void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool fo this->typedNode()->didRemoveChildAtIndex(index, cursor, force); } +template <> +void LayoutRef::collapseOnDirection(HorizontalDirection direction, int absorbingChildIndex) { + LayoutRef p = parent(); + if (!p.isDefined() || !p.isHorizontal()) { + return; + } + int idxInParent = p.indexOfChild(*this); + int numberOfSiblings = p.numberOfChildren(); + int numberOfOpenParenthesis = 0; + bool canCollapse = true; + LayoutRef absorbingChild = childAtIndex(absorbingChildIndex); + if (!absorbingChild.isDefined() || !absorbingChild.isHorizontal()) { + return; + } + HorizontalLayoutRef horizontalAbsorbingChild = HorizontalLayoutRef(absorbingChild.node()); + if (direction == HorizontalDirection::Right && idxInParent < numberOfSiblings - 1) { + canCollapse = !(p.childAtIndex(idxInParent+1).mustHaveLeftSibling()); + } + LayoutRef sibling(nullptr); + bool forceCollapse = false; + while (canCollapse) { + if (direction == HorizontalDirection::Right && idxInParent == numberOfSiblings - 1) { + break; + } + if (direction == HorizontalDirection::Left && idxInParent == 0) { + break; + } + int siblingIndex = direction == HorizontalDirection::Right ? idxInParent+1 : idxInParent-1; + sibling = p.childAtIndex(siblingIndex); + /* Even if forceCollapse is true, isCollapsable should be called to update + * the number of open parentheses. */ + bool shouldCollapse = sibling.isCollapsable(&numberOfOpenParenthesis, direction == HorizontalDirection::Left); + if (shouldCollapse || forceCollapse) { + /* If the collapse direction is Left and the next sibling to be collapsed + * must have a left sibling, force the collapsing of this needed left + * sibling. */ + forceCollapse = direction == HorizontalDirection::Left && sibling.mustHaveLeftSibling(); + p.removeChildAtIndex(siblingIndex, nullptr); + int newIndex = direction == HorizontalDirection::Right ? absorbingChild.numberOfChildren() : 0; + horizontalAbsorbingChild.addOrMergeChildAtIndex(sibling, newIndex, true); + numberOfSiblings--; + if (direction == HorizontalDirection::Left) { + idxInParent--; + } + } else { + break; + } + } +} + template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; template void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force); From 8848b0df8b6c4ec719b151989664b51e78f48345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 10:15:52 +0200 Subject: [PATCH 120/156] [poincare/layouts] Clean + complete Horizontal, Char, Empty, AllocaFail --- .../poincare/allocation_failed_layout_node.h | 1 + poincare/include/poincare/char_layout_node.h | 12 +- poincare/include/poincare/empty_layout_node.h | 7 +- .../include/poincare/horizontal_layout_node.h | 28 +-- poincare/include/poincare/layout_node.h | 1 + poincare/src/char_layout_node.cpp | 8 +- poincare/src/empty_layout_node.cpp | 42 ++-- poincare/src/horizontal_layout_node.cpp | 209 +++++++++--------- poincare/src/layout_reference.cpp | 10 +- 9 files changed, 165 insertions(+), 153 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 33156c2ee..75ddeaeb0 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -45,6 +45,7 @@ private: class AllocationFailedLayoutRef : public LayoutReference { public: AllocationFailedLayoutRef() : LayoutReference() {} + AllocationFailedLayoutRef(TreeNode * aNode) : LayoutReference(aNode) {} }; } diff --git a/poincare/include/poincare/char_layout_node.h b/poincare/include/poincare/char_layout_node.h index fccfea8d0..74820f3ae 100644 --- a/poincare/include/poincare/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -9,18 +9,20 @@ namespace Poincare { class CharLayoutNode : public LayoutNode { public: - CharLayoutNode() : + CharLayoutNode(char c = 'a', KDText::FontSize fontSize = KDText::FontSize::Large) : LayoutNode(), - m_char('a'), - m_fontSize(KDText::FontSize::Large) + m_char(c), + m_fontSize(fontSize) {} + + // CharLayout void setChar(char c) { m_char = c; } void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } // LayoutNode - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; // TreeNode @@ -59,6 +61,8 @@ public: this->typedNode()->setFontSize(fontSize); } } + + CharLayoutRef(TreeNode * t) : LayoutReference(t) {} }; } diff --git a/poincare/include/poincare/empty_layout_node.h b/poincare/include/poincare/empty_layout_node.h index 7951275fb..646fd1e0f 100644 --- a/poincare/include/poincare/empty_layout_node.h +++ b/poincare/include/poincare/empty_layout_node.h @@ -31,11 +31,11 @@ public: void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } // LayoutNode - bool isEmpty() const override { return true; } void deleteBeforeCursor(LayoutCursor * cursor) override; - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool isEmpty() const override { return true; } // TreeNode size_t size() const override { return sizeof(EmptyLayoutNode); } @@ -61,8 +61,8 @@ private: // LayoutNode void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) override; - void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; bool m_isVisible; Color m_color; @@ -72,6 +72,7 @@ private: class EmptyLayoutRef : public LayoutReference { public: + EmptyLayoutRef(TreeNode * eNode) : LayoutReference(eNode) {} EmptyLayoutRef(EmptyLayoutNode::Color color = EmptyLayoutNode::Color::Yellow, bool visible = true, KDText::FontSize fontSize = KDText::FontSize::Large, bool margins = true) : LayoutReference() { diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index fb7debd70..1e4824ebd 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -11,30 +11,24 @@ namespace Poincare { * instance, use addOrMergeChildAtIndex to add a LayoutNode safely. */ class HorizontalLayoutNode : public LayoutNode { + template + friend class LayoutReference; public: HorizontalLayoutNode() : LayoutNode(), m_numberOfChildren(0) {} - // Tree navigation - LayoutCursor equivalentCursor(LayoutCursor * cursor) override; - - // Tree modification - void deleteBeforeCursor(LayoutCursor * cursor) override; - - // SerializableNode - int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - // LayoutNode - bool isHorizontal() const override { return true; } void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + LayoutCursor equivalentCursor(LayoutCursor * cursor) override; + void deleteBeforeCursor(LayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; - bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; - bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override; - void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) override; - bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; + bool isHorizontal() const override { return true; } + bool isEmpty() const override { return m_numberOfChildren == 1 && const_cast(this)->childAtIndex(0)->isEmpty(); } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override { return m_numberOfChildren != 0; } // TreeNode size_t size() const override { return sizeof(HorizontalLayoutNode); } @@ -58,11 +52,17 @@ protected: KDPoint positionOfChild(LayoutNode * l) override; private: + bool willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) override; + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override; + void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) override; + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} int m_numberOfChildren; }; class HorizontalLayoutRef : public LayoutReference { + friend class HorizontalLayoutNode; public: HorizontalLayoutRef() : LayoutReference() {} HorizontalLayoutRef(TreeNode * hNode) : LayoutReference(hNode) {} diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 05f1cb824..de6c24189 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -100,6 +100,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 bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { return true; } diff --git a/poincare/src/char_layout_node.cpp b/poincare/src/char_layout_node.cpp index 6992bb2c6..adb8e9d0d 100644 --- a/poincare/src/char_layout_node.cpp +++ b/poincare/src/char_layout_node.cpp @@ -5,10 +5,6 @@ namespace Poincare { // LayoutNode -int CharLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { - return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); -} - void CharLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { if (cursor->position() == LayoutCursor::Position::Right) { cursor->setPosition(LayoutCursor::Position::Left); @@ -31,6 +27,10 @@ void CharLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecompu } } +int CharLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, m_char); +} + bool CharLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { if (*numberOfOpenParenthesis <= 0 && (m_char == '+' diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 0ab369db2..31f2d997b 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -42,14 +42,6 @@ int EmptyLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int number return 0; } -void EmptyLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - if (m_isVisible) { - KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; - ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); - ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); - } -} - void EmptyLayoutNode::computeSize() { assert(!m_sized); KDCoordinate sizeWidth = m_isVisible ? width() + 2*(m_margins ? k_marginWidth : 0) : 0; @@ -63,19 +55,6 @@ void EmptyLayoutNode::computeBaseline() { m_baselined = true; } -bool EmptyLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { - if (sibling->mustHaveLeftSibling()) { - m_color = Color::Yellow; - } - return true; - /* Color currentColor = m_color; - int currentIndexInParent = indexInParent(); - if (currentColor == Color::Grey) { - // The parent is a MatrixLayout. - static_cast(parent())->newRowOrColumnAtIndex(indexInParent); - }*/ -} - void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { /* The two cursor positions around an EmptyLayoutNode are equivalent, so both * should be checked. */ @@ -91,4 +70,25 @@ void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCu LayoutNode::moveCursorVertically(direction, cursor, shouldRecomputeLayout, false); } +bool EmptyLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { + if (sibling->mustHaveLeftSibling()) { + m_color = Color::Yellow; + } + return true; + /* Color currentColor = m_color; + int currentIndexInParent = indexInParent(); + if (currentColor == Color::Grey) { + // The parent is a MatrixLayout. + static_cast(parent())->newRowOrColumnAtIndex(indexInParent); + }*/ +} + +void EmptyLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + if (m_isVisible) { + KDColor fillColor = m_color == Color::Yellow ? Palette::YellowDark : Palette::GreyBright; + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); + ctx->fillRect(KDRect(p.x()+(m_margins ? k_marginWidth : 0), p.y()+(m_margins ? k_marginHeight : 0), width(), height()), fillColor); + } +} + } diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 33578abf2..d970ec45b 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -6,103 +6,8 @@ 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::deleteBeforeCursor(LayoutCursor * cursor) { - LayoutNode * p = parent(); - if (p == nullptr - && cursor->layoutReference().node() == this - && (cursor->position() == LayoutCursor::Position::Left - || numberOfChildren() == 0)) - { - /* Case: Left and this is the main layout or Right and this is the main - * layout with no children. Return. */ - return; - } - if (cursor->position() == LayoutCursor::Position::Left) { - int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); - if (indexOfPointedLayout >= 0) { - /* Case: Left of a child. - * Point Right of the previous child. If there is no previous child, point - * Left of this. Perform another backspace. */ - if (indexOfPointedLayout == 0) { - cursor->setLayoutNode(this); - } else { - assert(indexOfPointedLayout > 0); - cursor->setLayoutNode(childAtIndex(indexOfPointedLayout - 1)); - cursor->setPosition(LayoutCursor::Position::Right); - } - cursor->performBackspace(); - return; - } - } - assert(cursor->layoutReference().node() == this); - if (cursor->position() == LayoutCursor::Position::Right) { - // Case: Right. Point to the last child and perform backspace. - cursor->setLayoutNode(childAtIndex(numberOfChildren() - 1)); - cursor->performBackspace(); - return; - } - LayoutNode::deleteBeforeCursor(cursor); -} - -bool HorizontalLayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { - if (numberOfChildren() == 1) { - assert(childAtIndex(0) == l); - LayoutNode * p = parent(); - if (p != nullptr) { - LayoutRef(p).removeChild(this, cursor); - // WARNING: Do not call "this" afterwards - return false; - } - } - return true; -} - // LayoutNode -int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { - if (numberOfChildren() == 0) { - if (bufferSize == 0) { - return -1; - } - buffer[0] = 0; - return 0; - } - return LayoutEngine::writeInfixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, ""); -} - void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { if (this == cursor->layoutReference().node()) { if (cursor->position() == LayoutCursor::Position::Left) { @@ -193,6 +98,83 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR return childAtIndex(childIndex+1)->moveCursorRight(cursor, shouldRecomputeLayout); } +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); +} + +void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + LayoutNode * p = parent(); + if (p == nullptr + && cursor->layoutReference().node() == this + && (cursor->position() == LayoutCursor::Position::Left + || numberOfChildren() == 0)) + { + /* Case: Left and this is the main layout or Right and this is the main + * layout with no children. Return. */ + return; + } + if (cursor->position() == LayoutCursor::Position::Left) { + int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); + if (indexOfPointedLayout >= 0) { + /* Case: Left of a child. + * Point Right of the previous child. If there is no previous child, point + * Left of this. Perform another backspace. */ + if (indexOfPointedLayout == 0) { + cursor->setLayoutNode(this); + } else { + assert(indexOfPointedLayout > 0); + cursor->setLayoutNode(childAtIndex(indexOfPointedLayout - 1)); + cursor->setPosition(LayoutCursor::Position::Right); + } + cursor->performBackspace(); + return; + } + } + assert(cursor->layoutReference().node() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Point to the last child and perform backspace. + cursor->setLayoutNode(childAtIndex(numberOfChildren() - 1)); + cursor->performBackspace(); + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + +int HorizontalLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + if (numberOfChildren() == 0) { + if (bufferSize == 0) { + return -1; + } + buffer[0] = 0; + return 0; + } + return LayoutEngine::writeInfixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, ""); +} + // Protected void HorizontalLayoutNode::computeSize() { @@ -234,6 +216,11 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { // Private +bool HorizontalLayoutNode::willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { + *index = HorizontalLayoutRef(this).removeEmptyChildBeforeInsertionAtIndex(*index, !childAtIndex(0)->mustHaveLeftSibling()); + return true; +} + bool HorizontalLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { int childrenCount = numberOfChildren(); HorizontalLayoutRef thisRef(this); @@ -281,6 +268,28 @@ bool HorizontalLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * si return false; } +bool HorizontalLayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { + if (numberOfChildren() == 1) { + assert(childAtIndex(0) == l); + LayoutNode * p = parent(); + if (p != nullptr) { + LayoutRef(p).removeChild(this, cursor); + // WARNING: Do not call "this" afterwards + return false; + } + } + return true; +} + +void HorizontalLayoutNode::didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) { + /* If the child to remove was at index 0 and its right sibling must have a left + * sibling (e.g. a VerticalOffsetLayout), add an empty layout at index 0 */ + + if (!force && index == 0 && numberOfChildren() > 0 && childAtIndex(0)->mustHaveLeftSibling()) { + HorizontalLayoutRef(this).addChildAtIndex(EmptyLayoutRef(), 0, cursor); + } +} + bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { if (oldChild == newChild) { return false; @@ -373,16 +382,8 @@ bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * return true; } -void HorizontalLayoutNode::didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) { - /* If the child to remove was at index 0 and its right sibling must have a left - * sibling (e.g. a VerticalOffsetLayout), add an empty layout at index 0 */ - - if (!force && index == 0 && numberOfChildren() > 0 && childAtIndex(0)->mustHaveLeftSibling()) { - HorizontalLayoutRef(this).addChildAtIndex(EmptyLayoutRef(), 0, cursor); - } -} - // HorizontalLayoutRef + void HorizontalLayoutRef::addOrMergeChildAtIndex(LayoutRef l, int index, bool removeEmptyChildren, LayoutCursor * cursor) { if (l.isHorizontal()) { mergeChildrenAtIndex(HorizontalLayoutRef(l.node()), index, removeEmptyChildren, cursor); diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index a451c0191..ae2ef91ae 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -71,17 +71,21 @@ void LayoutRef::replaceWithJuxtapositionOf(LayoutRef leftChild, LayoutRef rightC template void LayoutReference::addChildAtIndex(LayoutRef l, int index, LayoutCursor * cursor) { + int newIndex = index; + if (!this->typedNode()->willAddChildAtIndex(l.typedNode(), &newIndex, cursor)) { + return; + } LayoutRef nextPointedLayout(nullptr); LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; - if (index < this->numberOfChildren()) { - nextPointedLayout = this->childAtIndex(index); + if (newIndex < this->numberOfChildren()) { + nextPointedLayout = this->childAtIndex(newIndex); nextPosition = LayoutCursor::Position::Left; } else { nextPointedLayout = *this; nextPosition = LayoutCursor::Position::Right; } - this->addChildTreeAtIndex(l, index); + this->addChildTreeAtIndex(l, newIndex); if (cursor != nullptr) { if (this->isAllocationFailure()) { From 9d5914a2680985f749158f4183f2660c4e36ada9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 10:30:57 +0200 Subject: [PATCH 121/156] [poincare] Change parameters order in TreePool::move methods --- poincare/include/poincare/tree_pool.h | 6 +++--- poincare/include/poincare/tree_reference.h | 20 ++++++++++---------- poincare/src/tree_pool.cpp | 10 +++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index c9360e8d0..0d32deafc 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -36,8 +36,8 @@ public: return node; } - void move(TreeNode * source, TreeNode * destination); - void moveChildren(TreeNode * sourceParent, TreeNode * destination); + void move(TreeNode * destination, TreeNode * source); + void moveChildren(TreeNode * destination, TreeNode * sourceParent); TreeNode * deepCopy(TreeNode * node) { size_t size = node->deepSize(); @@ -148,7 +148,7 @@ private: void * alloc(size_t size); void dealloc(TreeNode * ptr); bool insert(char * destination, char * source, size_t length); - void moveNodes(TreeNode * source, TreeNode * destination, size_t moveLength); + void moveNodes(TreeNode * destination, TreeNode * source, size_t moveLength); // Identifiers int generateIdentifier() { diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 77a9d0328..b87d97df3 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -136,7 +136,7 @@ public: for (int i = 0; i < index; i++) { newChildPosition = newChildPosition->nextSibling(); } - TreePool::sharedPool()->move(t.node(), newChildPosition); + TreePool::sharedPool()->move(newChildPosition, t.node()); node()->incrementNumberOfChildren(); } void removeTreeChildAtIndex(int i) { @@ -148,7 +148,7 @@ public: void removeTreeChild(TreeReference t) { assert(isDefined()); - TreePool::sharedPool()->move(t.node(), TreePool::sharedPool()->last()); + TreePool::sharedPool()->move(TreePool::sharedPool()->last(), t.node()); t.node()->release(); node()->decrementNumberOfChildren(); } @@ -156,7 +156,7 @@ public: void removeChildren() { assert(isDefined()); node()->releaseChildren(); - TreePool::sharedPool()->moveChildren(node(), TreePool::sharedPool()->last()); + TreePool::sharedPool()->moveChildren(TreePool::sharedPool()->last(), node()); node()->eraseNumberOfChildren(); } @@ -184,9 +184,9 @@ public: } assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = treeChildAtIndex(oldChildIndex); - TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next()); + TreePool::sharedPool()->move(oldChild.node()->next(), newChild.node()); newChild.node()->retain(); - TreePool::sharedPool()->move(oldChild.node(), TreePool::sharedPool()->last()); + TreePool::sharedPool()->move(TreePool::sharedPool()->last(), oldChild.node()); oldChild.node()->release(); } @@ -199,7 +199,7 @@ public: TreeNode * staticAllocFailNode = typedNode()->failedAllocationStaticNode(); // Move the node to the end of the pool and decrease children count of parent - TreePool::sharedPool()->move(node(), TreePool::sharedPool()->last()); + TreePool::sharedPool()->move(TreePool::sharedPool()->last(), node()); if (p.isDefined()) { p.decrementNumberOfChildren(); } @@ -237,8 +237,8 @@ public: TreeReference firstChild = treeChildAtIndex(firstChildIndex); TreeReference secondChild = treeChildAtIndex(secondChildIndex); TreeNode * firstChildNode = firstChild.node(); - TreePool::sharedPool()->move(firstChildNode, secondChild.node()->next()); - TreePool::sharedPool()->move(secondChild.node(), firstChildNode); + TreePool::sharedPool()->move(secondChild.node()->next(), firstChildNode); + TreePool::sharedPool()->move(firstChildNode, secondChild.node()); } void mergeTreeChildrenAtIndex(TreeReference t, int i) { @@ -246,9 +246,9 @@ public: // Steal operands int numberOfNewChildren = t.numberOfChildren(); if (i < numberOfChildren()) { - TreePool::sharedPool()->moveChildren(t.node(), node()->childTreeAtIndex(i)); + TreePool::sharedPool()->moveChildren(node()->childTreeAtIndex(i), t.node()); } else { - TreePool::sharedPool()->moveChildren(t.node(), node()->lastDescendant()->next()); + TreePool::sharedPool()->moveChildren(node()->lastDescendant()->next(), t.node()); } t.node()->eraseNumberOfChildren(); // If t is a child, remove it diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 54838b660..815bf05f5 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -49,17 +49,17 @@ void TreePool::logNodeForIdentifierArray() { #endif } -void TreePool::move(TreeNode * source, TreeNode * destination) { +void TreePool::move(TreeNode * destination, TreeNode * source) { size_t moveSize = source->deepSize(); - moveNodes(source, destination, moveSize); + moveNodes(destination, source, moveSize); } -void TreePool::moveChildren(TreeNode * sourceParent, TreeNode * destination) { +void TreePool::moveChildren(TreeNode * destination, TreeNode * sourceParent) { size_t moveSize = sourceParent->deepSize() - sourceParent->size(); - moveNodes(sourceParent->next(), destination, moveSize); + moveNodes(destination, sourceParent->next(), moveSize); } -void TreePool::moveNodes(TreeNode * source, TreeNode * destination, size_t moveSize) { +void TreePool::moveNodes(TreeNode * destination, TreeNode * source, size_t moveSize) { if (source == destination || moveSize == 0) { return; } From f48c9f53d2a5d4ed6dc8e98c30c375cb9d1a23df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 10:36:00 +0200 Subject: [PATCH 122/156] [poincare] Fix TreeReference::swapChildren --- poincare/include/poincare/tree_reference.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index b87d97df3..41b3cf121 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -236,9 +236,8 @@ public: int secondChildIndex = i > j ? i : j; TreeReference firstChild = treeChildAtIndex(firstChildIndex); TreeReference secondChild = treeChildAtIndex(secondChildIndex); - TreeNode * firstChildNode = firstChild.node(); - TreePool::sharedPool()->move(secondChild.node()->next(), firstChildNode); - TreePool::sharedPool()->move(firstChildNode, secondChild.node()); + TreePool::sharedPool()->move(firstChild.node()->next(), secondChild.node()); + TreePool::sharedPool()->move(treeChildAtIndex(secondChildIndex).next(), firstChild.node()); } void mergeTreeChildrenAtIndex(TreeReference t, int i) { From 4e4c1bb2ad9b736f0920d866bdf7b5c90e6fe2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 10:37:30 +0200 Subject: [PATCH 123/156] [poincare] Fix TreeReference::replaceTreeChildAtIndex --- poincare/include/poincare/tree_reference.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 41b3cf121..ef60f88a8 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -185,7 +185,9 @@ public: assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = treeChildAtIndex(oldChildIndex); TreePool::sharedPool()->move(oldChild.node()->next(), newChild.node()); - newChild.node()->retain(); + if (!p.isDefined()) { + newChild.node()->retain(); + } TreePool::sharedPool()->move(TreePool::sharedPool()->last(), oldChild.node()); oldChild.node()->release(); } From 9951e50a9c23c8f06ea32585b6b38261e32f4cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 10:59:53 +0200 Subject: [PATCH 124/156] [poincare] Use LayoutCursor::layoutNode() --- poincare/src/horizontal_layout_node.cpp | 14 +++++++------- poincare/src/layout_cursor.cpp | 8 ++++---- poincare/src/layout_node.cpp | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index d970ec45b..f3c382c29 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -9,7 +9,7 @@ static inline KDCoordinate maxCoordinate(KDCoordinate c1, KDCoordinate c2) { ret // LayoutNode void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { - if (this == cursor->layoutReference().node()) { + if (this == cursor->layoutNode()) { if (cursor->position() == LayoutCursor::Position::Left) { // Case: Left. Ask the parent. LayoutNode * parentNode = parent(); @@ -49,7 +49,7 @@ void HorizontalLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRe } void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { - if (this == cursor->layoutReference().node()) { + if (this == cursor->layoutNode()) { if (cursor->position() == LayoutCursor::Position::Right) { // Case: Right. Ask the parent. LayoutNode * parentNode = parent(); @@ -80,7 +80,7 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR // Case: The cursor is Right of a child. assert(cursor->position() == LayoutCursor::Position::Right); - int childIndex = indexOfChild(cursor->layoutReference().node()); + int childIndex = indexOfChild(cursor->layoutNode()); assert(childIndex >= 0); if (childIndex == numberOfChildren() - 1) { // Case: the child is the rightmost. Ask the parent. @@ -99,7 +99,7 @@ void HorizontalLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldR } LayoutCursor HorizontalLayoutNode::equivalentCursor(LayoutCursor * cursor) { - if (cursor->layoutReference().node() == this) { + if (cursor->layoutNode() == this) { // First or last child, if any int childrenCount = numberOfChildren(); if (childrenCount == 0) { @@ -129,7 +129,7 @@ LayoutCursor HorizontalLayoutNode::equivalentCursor(LayoutCursor * cursor) { void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { LayoutNode * p = parent(); if (p == nullptr - && cursor->layoutReference().node() == this + && cursor->layoutNode() == this && (cursor->position() == LayoutCursor::Position::Left || numberOfChildren() == 0)) { @@ -138,7 +138,7 @@ void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { return; } if (cursor->position() == LayoutCursor::Position::Left) { - int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); + int indexOfPointedLayout = indexOfChild(cursor->layoutNode()); if (indexOfPointedLayout >= 0) { /* Case: Left of a child. * Point Right of the previous child. If there is no previous child, point @@ -154,7 +154,7 @@ void HorizontalLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { return; } } - assert(cursor->layoutReference().node() == this); + assert(cursor->layoutNode() == this); if (cursor->position() == LayoutCursor::Position::Right) { // Case: Right. Point to the last child and perform backspace. cursor->setLayoutNode(childAtIndex(numberOfChildren() - 1)); diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index c88a01723..2211723de 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -46,19 +46,19 @@ KDPoint LayoutCursor::middleLeftPoint() { /* Move */ void LayoutCursor::moveLeft(bool * shouldRecomputeLayout) { - layoutReference().typedNode()->moveCursorLeft(this, shouldRecomputeLayout); + layoutNode()->moveCursorLeft(this, shouldRecomputeLayout); } void LayoutCursor::moveRight(bool * shouldRecomputeLayout) { - layoutReference().typedNode()->moveCursorRight(this, shouldRecomputeLayout); + layoutNode()->moveCursorRight(this, shouldRecomputeLayout); } void LayoutCursor::moveAbove(bool * shouldRecomputeLayout) { - layoutReference().typedNode()->moveCursorUp(this, shouldRecomputeLayout); + layoutNode()->moveCursorUp(this, shouldRecomputeLayout); } void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { - layoutReference().typedNode()->moveCursorDown(this, shouldRecomputeLayout); + layoutNode()->moveCursorDown(this, shouldRecomputeLayout); } /* Layout modification */ diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 79e545373..ec91b1ba5 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -94,7 +94,7 @@ LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { // Tree modification void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { - int indexOfPointedLayout = indexOfChild(cursor->layoutReference().typedNode()); + int indexOfPointedLayout = indexOfChild(cursor->layoutNode()); if (indexOfPointedLayout >= 0) { // Case: The pointed layout is a child. Move Left. assert(cursor->position() == LayoutCursor::Position::Left); @@ -102,7 +102,7 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { cursor->moveLeft(&shouldRecomputeLayout); return; } - assert(cursor->layoutReference().node() == this); + assert(cursor->layoutNode() == this); LayoutNode * p = parent(); // Case: this is the pointed layout. if (p == nullptr) { From a6f1a2d08d4fede60890f5a7b1b8d07e9e8cb182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 11:12:28 +0200 Subject: [PATCH 125/156] [poincare] Remove unnecessary return value --- poincare/include/poincare/layout_reference.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index c007344e9..3a5a925e5 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -75,11 +75,10 @@ public: // Replace void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr); - LayoutReference replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { + void replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { LayoutReference p = parent(); assert(p.isDefined()); p.replaceChild(*this, newChild, cursor); - return newChild; } void replaceWithJuxtapositionOf(LayoutReference leftChild, LayoutReference rightChild, LayoutCursor * cursor); // Remove From f5f3a548b7de3db9cac1819e7615c9572a3452c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 11:14:21 +0200 Subject: [PATCH 126/156] [poincare] Fix LayoutReference::removeChild --- poincare/src/layout_reference.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index ae2ef91ae..5f1206a10 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -154,8 +154,7 @@ void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool fo cursor->setPosition(LayoutCursor::Position::Left); } else { int newPointedLayoutIndex = index - 1; - assert(newPointedLayoutIndex >= 0); - if (newPointedLayoutIndex < this->numberOfChildren()) { + if (newPointedLayoutIndex >= 0 && newPointedLayoutIndex < this->numberOfChildren()) { cursor->setLayoutReference(this->childAtIndex(newPointedLayoutIndex)); cursor->setPosition(LayoutCursor::Position::Right); } else { From 7cf3210738085e903feaee338b24294025bed4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 14:04:10 +0200 Subject: [PATCH 127/156] [poincare] Add VerticalOffsetLayoutNode --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/layout_cursor.h | 2 +- poincare/include/poincare/layout_engine.h | 10 +- .../poincare/vertical_offset_layout_node.h | 75 +++++ poincare/src/layout_cursor.cpp | 21 ++ poincare/src/layout_engine.cpp | 76 ++++- poincare/src/vertical_offset_layout_node.cpp | 281 ++++++++++++++++++ 8 files changed, 459 insertions(+), 8 deletions(-) create mode 100644 poincare/include/poincare/vertical_offset_layout_node.h create mode 100644 poincare/src/vertical_offset_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 9c3d83e95..9ecd76948 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -14,6 +14,7 @@ objs += $(addprefix poincare/src/,\ layout_cursor.o\ layout_node.o\ layout_reference.o\ + vertical_offset_layout_node.o\ ) objs += $(addprefix poincare/src/,\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 869b79e98..d5d9c49a3 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -86,5 +86,6 @@ #include #include #include +#include #endif diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index a1f50707f..fc35d6610 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -110,7 +110,7 @@ public: void addEmptyMatrixLayout() {} //TODO void addEmptyPowerLayout() {} //TODO void addEmptySquareRootLayout() {} //TODO - void addEmptySquarePowerLayout() {} //TODO + void addEmptySquarePowerLayout(); void addEmptyTenPowerLayout() {} //TODO void addFractionLayoutAndCollapseSiblings() {} //TODO void addXNTCharLayout(); diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index 0e790c9e7..b9ee87f3e 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -52,7 +52,7 @@ public: const char * operatorName, bool writeFirstChild = true); - /* LayoutReference to Text */ + /* SerializableReference to Text */ static int writeInfixSerializableRefTextInBuffer( const SerializableRef serializableRef, char * buffer, @@ -62,6 +62,14 @@ public: int firstChildIndex = 0, int lastChildIndex = -1); + static int writePrefixSerializableRefTextInBuffer( + const SerializableRef serializableRef, + char * buffer, + int bufferSize, + int numberOfDigits, + const char * operatorName, + bool writeFirstChild = true); //TODO + /* Write one char in buffer */ static int writeOneCharInBuffer(char * buffer, int bufferSize, char charToWrite); diff --git a/poincare/include/poincare/vertical_offset_layout_node.h b/poincare/include/poincare/vertical_offset_layout_node.h new file mode 100644 index 000000000..1418d0772 --- /dev/null +++ b/poincare/include/poincare/vertical_offset_layout_node.h @@ -0,0 +1,75 @@ +#ifndef POINCARE_VERTICAL_OFFSET_LAYOUT_NODE_H +#define POINCARE_VERTICAL_OFFSET_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class VerticalOffsetLayoutNode : public LayoutNode { +public: + enum class Type { + Subscript, + Superscript + }; + + VerticalOffsetLayoutNode(Type type = Type::Superscript) : + LayoutNode(), + m_type(type) + {} + + // VerticalOffsetLayoutNode + Type type() const { return m_type; } + void setType(Type type) { m_type = type; } + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void deleteBeforeCursor(LayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool mustHaveLeftSibling() const override { return true; } + bool isVerticalOffset() const override { return true; } + + // TreeNode + size_t size() const override { return sizeof(VerticalOffsetLayoutNode); } + int numberOfChildren() const override { return 1; } +#if TREE_LOG + const char * description() const override { + return m_type == Type::Subscript ? "Subscript" : "Superscript"; + } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override; +private: + constexpr static KDCoordinate k_indiceHeight = 5; + constexpr static KDCoordinate k_separationMargin = 5; + bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} + LayoutNode * indiceLayout() { return childAtIndex(0);} + LayoutNode * baseLayout(); + Type m_type; +}; + +class VerticalOffsetLayoutRef : public LayoutReference { +public: + VerticalOffsetLayoutRef(LayoutRef l, VerticalOffsetLayoutNode::Type type) : + LayoutReference() + { + if (!(this->node()->isAllocationFailure())) { + this->typedNode()->setType(type); + } + addChildTreeAtIndex(l, 0); + } + VerticalOffsetLayoutRef(TreeNode * t) : LayoutReference(t) {} +}; + +} + +#endif diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 2211723de..92a8aefb3 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include #include namespace Poincare { @@ -62,6 +64,25 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { } /* Layout modification */ + +void LayoutCursor::addEmptySquarePowerLayout() { + CharLayoutRef indiceLayout = CharLayoutRef('2'); + VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(indiceLayout, VerticalOffsetLayoutNode::Type::Superscript); + // If there is already a base + if (baseForNewPowerLayout()) { + m_layoutRef.addSibling(this, offsetLayout, false); + m_layoutRef = offsetLayout; + m_position = LayoutCursor::Position::Right; + return; + } + // Else, add an empty base + EmptyLayoutRef child1 = EmptyLayoutRef(); + HorizontalLayoutRef newChild = HorizontalLayoutRef(child1, offsetLayout); + m_layoutRef.addSibling(this, newChild, false); + m_layoutRef = child1; + m_position = LayoutCursor::Position::Right; +} + void LayoutCursor::addXNTCharLayout() { m_layoutRef.addSibling(this, CharLayoutRef(m_layoutRef.XNTChar()), true); } diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index e3c8ff6ec..00816d3d0 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -26,7 +26,7 @@ LayoutRef LayoutEngine::createInfixLayout(const Expression * expression, PrintFl expression->operand(i)->createLayout(floatDisplayMode, complexFormat), result.numberOfChildren()); } - /* + /* TODO result->addOrMergeChildAtIndex(expression->operand(0)->createLayout(), 0, true); for (int i = 1; i < numberOfOperands; i++) { result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), result->numberOfChildren(), true); @@ -59,7 +59,7 @@ LayoutRef LayoutEngine::createPrefixLayout(const Expression * expression, PrintF // Add the parenthesed arguments. result.addChildTreeAtIndex(createParenthesedLayout(args, false), result.numberOfChildren()); /*// Add the operator name. - result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); + * TODO result->addOrMergeChildAtIndex(createStringLayout(operatorName, strlen(operatorName)), 0, true); // Create the layout of arguments separated by commas. ExpressionLayout * args = nullptr; @@ -84,7 +84,7 @@ LayoutRef LayoutEngine::createParenthesedLayout(LayoutRef layoutRef, bool cloneL if (layoutRef.isDefined()) { result.addChildTreeAtIndex(cloneLayout ? layoutRef.clone() : layoutRef, 1); } - result.addChildTreeAtIndex(CharLayoutRef(')'), result.numberOfChildren()); + result.addChildTreeAtIndex(CharLayoutRef(')'), result.numberOfChildren()); //TODO return result; } @@ -98,7 +98,7 @@ LayoutRef LayoutEngine::createStringLayout(const char * buffer, int bufferSize, } ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, ExpressionLayout * index) { - return nullptr; + return nullptr; //TODO /*HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(index, VerticalOffsetLayout::Type::Subscript, false); resultLayout->addChildAtIndex(offsetLayout, resultLayout->numberOfChildren()); @@ -212,7 +212,7 @@ int LayoutEngine::writePrefixExpressionOrExpressionLayoutTextInBuffer(const Expr return numberOfChar; } -/* LayoutReference to Text */ +/* SerializableReference to Text */ int LayoutEngine::writeInfixSerializableRefTextInBuffer( const SerializableRef serializableRef, char * buffer, @@ -222,8 +222,9 @@ int LayoutEngine::writeInfixSerializableRefTextInBuffer( int firstChildIndex, int lastChildIndex) { - // If buffer has size 0 or 1, put a zero if it fits and return assert(serializableRef.isDefined()); + + // If buffer has size 0 or 1, put a zero if it fits and return if (bufferSize == 0) { return -1; } @@ -263,6 +264,69 @@ int LayoutEngine::writeInfixSerializableRefTextInBuffer( return numberOfChar; } +int LayoutEngine::writePrefixSerializableRefTextInBuffer( + const SerializableRef serializableRef, + char * buffer, + int bufferSize, + int numberOfDigits, + const char * operatorName, + bool writeFirstChild) +{ + assert(serializableRef.isDefined()); + + // If buffer has size 0 or 1, put a zero if it fits and return + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } + + // Copy the operator name + int numberOfChar = strlcpy(buffer, operatorName, bufferSize); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + // Add the opening parenthese + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + int childrenCount = serializableRef.numberOfChildren(); + if (childrenCount > 0) { + if (!writeFirstChild) { + assert(childrenCount > 1); + } + int firstChildIndex = writeFirstChild ? 0 : 1; + + // Write the first child + numberOfChar += const_cast(&serializableRef)->serializableChildAtIndex(firstChildIndex).writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfDigits); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + // Write the remaining children, separated with commas + for (int i = firstChildIndex + 1; i < childrenCount; i++) { + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + numberOfChar += const_cast(&serializableRef)->serializableChildAtIndex(i).writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + } + } + + // Add the closing parenthese + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + void LayoutEngine::writeChildTreeInBuffer(SerializableRef childRef, SerializableRef parentRef, char * buffer, int bufferSize, int numberOfDigits, int * numberOfChar) { // Write the child with parentheses if needed bool addParentheses = childRef.needsParenthesisWithParent(parentRef); diff --git a/poincare/src/vertical_offset_layout_node.cpp b/poincare/src/vertical_offset_layout_node.cpp new file mode 100644 index 000000000..fcbf20014 --- /dev/null +++ b/poincare/src/vertical_offset_layout_node.cpp @@ -0,0 +1,281 @@ +#include +#include +#include +//TODO #include "left_parenthesis_layout.h" +//TODO #include "right_parenthesis_layout.h" +#include +#include +#include + +namespace Poincare { + +void VerticalOffsetLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (indiceLayout() != nullptr + && cursor->layoutNode() == indiceLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the indice. Go Left. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Go to the indice. + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + return; + } + // Case: Left. Ask the parent. + assert(cursor->position() == LayoutCursor::Position::Left); + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void VerticalOffsetLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (indiceLayout() != nullptr + && cursor->layoutNode() == indiceLayout() + && cursor->position() == LayoutCursor::Position::Right) + { + // Case: Right of the indice. Go Right. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Go to the indice. + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + return; + } + // Case: Right. Ask the parent. + assert(cursor->position() == LayoutCursor::Position::Right); + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +void VerticalOffsetLayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (m_type == Type::Superscript) { + // Case: Superscript. + if (cursor->isEquivalentTo(LayoutCursor(this, LayoutCursor::Position::Right))) { + // Case: Right. Move to the indice. + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + if (cursor->isEquivalentTo(LayoutCursor(this, LayoutCursor::Position::Left))) { + // Case: Left. Move to the indice. + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + } + /* Case: Subscript, Left or Right of the indice. Put the cursor at the same + * position, pointing this. */ + if (m_type == Type::Subscript + && indiceLayout() != nullptr + && (cursor->isEquivalentTo(LayoutCursor(indiceLayout(), LayoutCursor::Position::Left)) + || cursor->isEquivalentTo(LayoutCursor(indiceLayout(), LayoutCursor::Position::Right)))) + { + cursor->setLayoutNode(this); + return; + } + LayoutNode::moveCursorUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void VerticalOffsetLayoutNode::moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (m_type == Type::Subscript) { + // Case: Subscript. + if (cursor->isEquivalentTo(LayoutCursor(this, LayoutCursor::Position::Right))) { + // Case: Right. Move to the indice. + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + // Case: Left. Move to the indice. + if (cursor->isEquivalentTo(LayoutCursor(this, LayoutCursor::Position::Left))) { + assert(indiceLayout() != nullptr); + cursor->setLayoutNode(indiceLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + } + /* Case: Superscript, Left or Right of the indice. Put the cursor at the same + * position, pointing this. */ + if (m_type == Type::Superscript + && indiceLayout() != nullptr + && cursor->layoutNode() == indiceLayout()) + { + cursor->setLayoutNode(this); + return; + } + LayoutNode::moveCursorDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void VerticalOffsetLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + if (cursor->layoutNode() == indiceLayout()) { + assert(cursor->position() == LayoutCursor::Position::Left); + LayoutRef parentRef(parent()); + LayoutNode * base = baseLayout(); + if (indiceLayout()->isEmpty()) { + int indexInParent = parentRef.typedNode()->indexOfChild(this); + if (base->isEmpty()) { + // Case: Empty base and indice. Remove the base and the indice layouts. + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Right); + parentRef.removeChildAtIndex(indexInParent, cursor); + // WARNING: do not call "this" afterwards + cursor->setLayoutReference(parentRef.childAtIndex(indexInParent-1)); + cursor->setPosition(LayoutCursor::Position::Right); + parentRef.removeChildAtIndex(indexInParent-1, cursor); + return; + } + // Case: Empty indice only. Delete the layout. + cursor->setLayoutNode(base); + cursor->setPosition(LayoutCursor::Position::Right); + parentRef.removeChildAtIndex(indexInParent, cursor); + // WARNING: do not call "this" afterwards + return; + } + // Case: Non-empty indice. Move Left of the VerticalOffsetLayoutNode. + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + if (cursor->layoutNode() == this + && cursor->position() == LayoutCursor::Position::Right) + { + // Case: Right. Move to the indice. + cursor->setLayoutNode(indiceLayout()); + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + +int VerticalOffsetLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + if (m_type == Type::Subscript) { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } + // If the layout is a subscript, write "_{indice}" + int numberOfChar = LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '_'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '{'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += const_cast(this)->indiceLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + numberOfChar += LayoutEngine::writeOneCharInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, '}'); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + return numberOfChar; + } + assert(m_type == Type::Superscript); + // If the layout is a superscript, write "^(indice)" + int numberOfChar = LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "^"); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Add a multiplication if omitted. + int indexInParent = -1; + LayoutNode * parentNode = parent(); + if (parentNode) { + indexInParent = parentNode->indexOfChild(this); + } + if (indexInParent >= 0 && indexInParent < (parentNode->numberOfChildren() - 1) && parentNode->isHorizontal() && parentNode->childAtIndex(indexInParent + 1)->canBeOmittedMultiplicationRightFactor()) { + buffer[numberOfChar++] = Ion::Charset::MiddleDot; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + } + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void VerticalOffsetLayoutNode::computeSize() { + KDSize indiceSize = indiceLayout()->layoutSize(); + KDCoordinate width = indiceSize.width(); + if (m_type == Type::Superscript) { + LayoutNode * parentNode = parent(); + assert(parentNode != nullptr); + assert(parentNode->isHorizontal()); + int idxInParent = parentNode->indexOfChild(this); + if (idxInParent < parentNode->numberOfChildren() - 1 && parentNode->childAtIndex(idxInParent + 1)->hasUpperLeftIndex()) { + width += k_separationMargin; + } + } + KDCoordinate height = baseLayout()->layoutSize().height() - k_indiceHeight + indiceLayout()->layoutSize().height(); + m_frame.setSize(KDSize(width, height)); + m_sized = true; +} + +void VerticalOffsetLayoutNode::computeBaseline() { + if (m_type == Type::Subscript) { + m_baseline = baseLayout()->baseline(); + } else { + m_baseline = indiceLayout()->layoutSize().height() - k_indiceHeight + baseLayout()->baseline(); + } + m_baselined = true; +} + +KDPoint VerticalOffsetLayoutNode::positionOfChild(LayoutNode * child) { + assert(child == indiceLayout()); + if (m_type == Type::Superscript) { + return KDPointZero; + } + assert(m_type == Type::Subscript); + assert(baseLayout()); + return KDPoint(0, baseLayout()->layoutSize().height() - k_indiceHeight); +} + +bool VerticalOffsetLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { + if (sibling->isVerticalOffset()) { + VerticalOffsetLayoutNode * verticalOffsetSibling = static_cast(sibling); + if (verticalOffsetSibling->type() == Type::Superscript) { + LayoutNode * parentNode = parent(); + assert(parentNode->isHorizontal()); + // Add the Left parenthesis + int idxInParent = parentNode->indexOfChild(this); + int leftParenthesisIndex = idxInParent; + //TODO LeftParenthesisLayout * leftParenthesis = new LeftParenthesisLayout(); + int numberOfOpenParenthesis = 0; + while (leftParenthesisIndex > 0 + && parentNode->childAtIndex(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis, true)) + { + leftParenthesisIndex--; + } + //TODO parentNode->addChildAtIndex(leftParenthesis, leftParenthesisIndex); + idxInParent++; + + // Add the Right parenthesis + //TODO RightParenthesisLayout * rightParenthesis = new RightParenthesisLayout(); + if (cursor->position() == LayoutCursor::Position::Right) { + //TODO parentNode->addChildAtIndex(rightParenthesis, idxInParent + 1); + } else { + assert(cursor->position() == LayoutCursor::Position::Left); + //TODO parentNode->addChildAtIndex(rightParenthesis, idxInParent); + } + //TODOcursor->setLayoutNode(rightParenthesis); + } + } + return true; +} + +LayoutNode * VerticalOffsetLayoutNode::baseLayout() { + LayoutNode * parentNode = parent(); + assert(parentNode != nullptr); + int idxInParent = parentNode->indexOfChild(this); + assert(idxInParent > 0); + return parentNode->childAtIndex(idxInParent - 1); +} + +} From 278d44d9520725dc25deadbbf783f8cf6afec554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 16:13:31 +0200 Subject: [PATCH 128/156] [poincare] nullptr cursor handling --- poincare/src/layout_reference.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 5f1206a10..d70b83d17 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -122,15 +122,17 @@ void LayoutRef::addSibling(LayoutCursor * cursor, LayoutReference si neighbour = p.childAtIndex(indexInParent + 1); } if (neighbour.isDefined() && neighbour.isVerticalOffset()) { - cursor->setLayoutReference(neighbour); - cursor->setPosition(cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left); + if (moveCursor) { + cursor->setLayoutReference(neighbour); + cursor->setPosition(cursor->position() == LayoutCursor::Position::Left ? LayoutCursor::Position::Right : LayoutCursor::Position::Left); + } neighbour.addSibling(cursor, sibling, moveCursor); return; } } // Else, let the parent add the sibling. - HorizontalLayoutRef(p.typedNode()).addOrMergeChildAtIndex(sibling, siblingIndex, true, cursor); + HorizontalLayoutRef(p.typedNode()).addOrMergeChildAtIndex(sibling, siblingIndex, true, moveCursor ? cursor : nullptr); return; } if (cursor->position() == LayoutCursor::Position::Left) { @@ -149,18 +151,21 @@ void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool fo assert(this->hasChild(l)); int index = this->indexOfChild(l); this->removeTreeChild(l); - if (index < this->numberOfChildren()) { - cursor->setLayoutReference(this->childAtIndex(index)); - cursor->setPosition(LayoutCursor::Position::Left); - } else { - int newPointedLayoutIndex = index - 1; - if (newPointedLayoutIndex >= 0 && newPointedLayoutIndex < this->numberOfChildren()) { - cursor->setLayoutReference(this->childAtIndex(newPointedLayoutIndex)); - cursor->setPosition(LayoutCursor::Position::Right); + if (cursor) { + if (index < this->numberOfChildren()) { + LayoutRef newCursorRef = this->childAtIndex(index); + cursor->setLayoutReference(newCursorRef); + cursor->setPosition(LayoutCursor::Position::Left); } else { - cursor->setLayoutReference(*this); - cursor->setPosition(LayoutCursor::Position::Right); + int newPointedLayoutIndex = index - 1; + if (newPointedLayoutIndex >= 0 && newPointedLayoutIndex < this->numberOfChildren()) { + cursor->setLayoutReference(this->childAtIndex(newPointedLayoutIndex)); + cursor->setPosition(LayoutCursor::Position::Right); + } else { + cursor->setLayoutReference(*this); + cursor->setPosition(LayoutCursor::Position::Right); + } } } this->typedNode()->didRemoveChildAtIndex(index, cursor, force); From d5d22cd88b3a58196a7d79e03fea06d7427d3e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 16:14:08 +0200 Subject: [PATCH 129/156] [poincare] Fix HorizontalLayoutRef --- poincare/src/horizontal_layout_node.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index f3c382c29..bdfa8d9b2 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -217,7 +217,9 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { // Private bool HorizontalLayoutNode::willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { - *index = HorizontalLayoutRef(this).removeEmptyChildBeforeInsertionAtIndex(*index, !childAtIndex(0)->mustHaveLeftSibling()); + if (m_numberOfChildren > 0) { + *index = HorizontalLayoutRef(this).removeEmptyChildBeforeInsertionAtIndex(*index, !childAtIndex(0)->mustHaveLeftSibling()); + } return true; } @@ -441,7 +443,7 @@ int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool if (shouldRemoveOnLeft && newIndex - 1 >= 0 && newIndex - 1 <= currentNumberOfChildren -1) { LayoutRef c = childAtIndex(newIndex - 1); if (c.isEmpty()) { - removeChild(c, nullptr); + removeChild(c, nullptr, true); newIndex = index - 1; } } From 0f502e505a4857f7d57714f5a98cd254a37fb44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 16:15:17 +0200 Subject: [PATCH 130/156] [poincare] Fix replaceWithJuxtapositionOf --- poincare/src/layout_reference.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index d70b83d17..b283555b4 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -53,20 +53,11 @@ void LayoutRef::replaceWithJuxtapositionOf(LayoutRef leftChild, LayoutRef rightC assert(!p.isHorizontal()); /* One of the children to juxtapose might be "this", so we cannot just call * replaceWith. */ - LayoutReference horizontalLayoutR = HorizontalLayoutRef(); - int index = indexInParent(); - horizontalLayoutR.addChildTreeAtIndex(leftChild, 0); - horizontalLayoutR.addChildTreeAtIndex(rightChild, 1); - p.addChildTreeAtIndex(horizontalLayoutR, index); - - if (cursor != nullptr) { - if (horizontalLayoutR.isAllocationFailure()) { - cursor->setLayoutReference(*this); - } else { - cursor->setLayoutReference(horizontalLayoutR); - cursor->setPosition(LayoutCursor::Position::Right); - } - } + HorizontalLayoutRef horizontalLayoutR; + p.replaceChild(*this, horizontalLayoutR, cursor); + horizontalLayoutR.addOrMergeChildAtIndex(leftChild, 0, false); + horizontalLayoutR.addOrMergeChildAtIndex(rightChild, 1, false); + TreePool::sharedPool()->log(); } template From 004e2d5d60beb3591f769972ef0dd8ba6aea0451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 16:40:18 +0200 Subject: [PATCH 131/156] [poincare] Fix HorizontalLayoutRef::mergeChildrenAtIndex --- poincare/src/horizontal_layout_node.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index bdfa8d9b2..7ac7cf111 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -404,8 +404,8 @@ void HorizontalLayoutRef::mergeChildrenAtIndex(HorizontalLayoutRef h, int index, LayoutRef nextPointedLayout(nullptr); LayoutCursor::Position nextPosition = LayoutCursor::Position::Left; - if (index < numberOfChildren()) { - nextPointedLayout = childAtIndex(index); + if (newIndex < numberOfChildren()) { + nextPointedLayout = childAtIndex(newIndex); nextPosition = LayoutCursor::Position::Left; } else { nextPointedLayout = *this; From 8318a5cd3afbd27e50ccaf5a59dda2c66687980a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 17:10:33 +0200 Subject: [PATCH 132/156] [poincare] Fix LayoutNode::origin typo --- poincare/src/layout_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index ec91b1ba5..de07be39f 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -18,7 +18,7 @@ void LayoutNode::draw(KDContext * ctx, KDPoint p, KDColor expressionColor, KDCol KDPoint LayoutNode::origin() { LayoutNode * p = parent(); - if (p != nullptr) { + if (p == nullptr) { return absoluteOrigin(); } else { return KDPoint(absoluteOrigin().x() - p->absoluteOrigin().x(), From fca5a5c76fc75fe2bf175329ec068a4938468531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 17:26:28 +0200 Subject: [PATCH 133/156] [poincare] Fix TreeReference::setTo --- poincare/include/poincare/tree_reference.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index ef60f88a8..c084e5e04 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -279,7 +279,9 @@ protected: } private: void setTo(const TreeReference & tr) { - if (*this == tr) { + /* We cannot use (*this)==tr because tr would need to be casted to + * TreeReference, which calls setTo and triggers an infinite loop */ + if (identifier() == tr.identifier()) { return; } TreeNode * currentNode = node(); From 2255a2ceab208fcdedb34175e5d7a4b10b43702b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 17:28:48 +0200 Subject: [PATCH 134/156] [poincare] Remove some debug logging --- poincare/src/layout_reference.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index b283555b4..8d101b730 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -57,7 +57,6 @@ void LayoutRef::replaceWithJuxtapositionOf(LayoutRef leftChild, LayoutRef rightC p.replaceChild(*this, horizontalLayoutR, cursor); horizontalLayoutR.addOrMergeChildAtIndex(leftChild, 0, false); horizontalLayoutR.addOrMergeChildAtIndex(rightChild, 1, false); - TreePool::sharedPool()->log(); } template From ea10652831c12e3dc8220f120c46c36c851247b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 18:01:34 +0200 Subject: [PATCH 135/156] [poincare] Fix TreeRef methods --- poincare/include/poincare/tree_reference.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index c084e5e04..d4e0d4bdc 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -184,7 +184,7 @@ public: } assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren()); TreeReference oldChild = treeChildAtIndex(oldChildIndex); - TreePool::sharedPool()->move(oldChild.node()->next(), newChild.node()); + TreePool::sharedPool()->move(oldChild.node()->nextSibling(), newChild.node()); if (!p.isDefined()) { newChild.node()->retain(); } @@ -238,8 +238,8 @@ public: int secondChildIndex = i > j ? i : j; TreeReference firstChild = treeChildAtIndex(firstChildIndex); TreeReference secondChild = treeChildAtIndex(secondChildIndex); - TreePool::sharedPool()->move(firstChild.node()->next(), secondChild.node()); - TreePool::sharedPool()->move(treeChildAtIndex(secondChildIndex).next(), firstChild.node()); + TreePool::sharedPool()->move(firstChild.node()->nextSibling(), secondChild.node()); + TreePool::sharedPool()->move(treeChildAtIndex(secondChildIndex).nextSibling(), firstChild.node()); } void mergeTreeChildrenAtIndex(TreeReference t, int i) { From 285537075d1d4986b548d37cd0e781d4c87dc216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Jul 2018 18:02:06 +0200 Subject: [PATCH 136/156] [poincare] By default, Layout::removeChild replaces it with EmptyLayout --- poincare/include/poincare/layout_node.h | 2 +- poincare/include/poincare/layout_reference.h | 1 + poincare/src/layout_node.cpp | 5 +++++ poincare/src/layout_reference.cpp | 6 ++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index de6c24189..c853cab93 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -103,7 +103,7 @@ public: virtual bool willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { return true; } virtual bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { return true; } virtual bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); - virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { return true; } + virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor); virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} protected: // Tree navigation diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 3a5a925e5..d74b0cafd 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -75,6 +75,7 @@ public: // Replace void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr); + void replaceChildWithEmpty(LayoutReference oldChild, LayoutCursor * cursor = nullptr); void replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { LayoutReference p = parent(); assert(p.isDefined()); diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index de07be39f..8c2349cb5 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -128,6 +128,11 @@ bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, return true; } +bool LayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { + LayoutRef(this).replaceChildWithEmpty(l, cursor); + return false; +} + // Other bool LayoutNode::hasText() const { /* A layout has text if it is not empty or an allocation failure and it is diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 8d101b730..18237e7be 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,11 @@ void LayoutRef::replaceChild(LayoutRef oldChild, LayoutRef newChild, LayoutCurso } } +template<> +void LayoutRef::replaceChildWithEmpty(LayoutRef oldChild, LayoutCursor * cursor) { + replaceChild(oldChild, EmptyLayoutRef(), cursor); +} + template<> void LayoutRef::replaceWithJuxtapositionOf(LayoutRef leftChild, LayoutRef rightChild, LayoutCursor * cursor) { LayoutReference p = parent(); From dc18f5968847cbd0f1b9aa454feaa62fb294afc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 10:01:10 +0200 Subject: [PATCH 137/156] [poincare] Rename replaceWithAndMoveCursor -> replaceWith --- poincare/include/poincare/layout_reference.h | 2 +- poincare/src/horizontal_layout_node.cpp | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index d74b0cafd..3249ab209 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -76,7 +76,7 @@ public: void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr); void replaceChildWithEmpty(LayoutReference oldChild, LayoutCursor * cursor = nullptr); - void replaceWithAndMoveCursor(LayoutReference newChild, LayoutCursor * cursor) { + void replaceWith(LayoutReference newChild, LayoutCursor * cursor) { LayoutReference p = parent(); assert(p.isDefined()); p.replaceChild(*this, newChild, cursor); diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 7ac7cf111..531a39b96 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -319,13 +319,8 @@ bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * * a parent, replace this with the new empty layout. */ LayoutNode * p = parent(); if (p != nullptr) { - if (cursor) { - thisRef.replaceWithAndMoveCursor(newChild, cursor); - // WARNING: do not call "this" afterwards - } else { - thisRef.replaceWith(newChild); - // WARNING: do not call "this" afterwards - } + thisRef.replaceWith(newChild, cursor); + // WARNING: do not call "this" afterwards return false; } /* This is the main horizontal layout, the old child is its only child and From 1aeebaa2f027bad4e7a1349574e024a17bacbcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 10:02:05 +0200 Subject: [PATCH 138/156] [poincare] Fix EmptyLayoutNode::willAddSibling --- poincare/src/empty_layout_node.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 31f2d997b..6956b87d1 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -73,8 +73,12 @@ void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCu bool EmptyLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { if (sibling->mustHaveLeftSibling()) { m_color = Color::Yellow; + return true; + } else { + LayoutRef(this).replaceWith(LayoutRef(sibling), cursor); + // WARNING: do not call "this" afterwards + return false; } - return true; /* Color currentColor = m_color; int currentIndexInParent = indexInParent(); if (currentColor == Color::Grey) { From 5ad469c6548ac0f763b189d6cae2ef99ecf8f40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 10:26:39 +0200 Subject: [PATCH 139/156] [poincare] Better handling of cursor when adding square power --- poincare/src/layout_cursor.cpp | 8 ++------ poincare/src/layout_node.cpp | 3 ++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 92a8aefb3..1d1deff58 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -70,17 +70,13 @@ void LayoutCursor::addEmptySquarePowerLayout() { VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(indiceLayout, VerticalOffsetLayoutNode::Type::Superscript); // If there is already a base if (baseForNewPowerLayout()) { - m_layoutRef.addSibling(this, offsetLayout, false); - m_layoutRef = offsetLayout; - m_position = LayoutCursor::Position::Right; + m_layoutRef.addSibling(this, offsetLayout, true); return; } // Else, add an empty base EmptyLayoutRef child1 = EmptyLayoutRef(); HorizontalLayoutRef newChild = HorizontalLayoutRef(child1, offsetLayout); - m_layoutRef.addSibling(this, newChild, false); - m_layoutRef = child1; - m_position = LayoutCursor::Position::Right; + m_layoutRef.addSibling(this, newChild, true); } void LayoutCursor::addXNTCharLayout() { diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 8c2349cb5..614d6c4e7 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -86,7 +86,8 @@ void LayoutNode::moveCursorDownInDescendants(LayoutCursor * cursor, bool * shoul } LayoutCursor LayoutNode::equivalentCursor(LayoutCursor * cursor) { - // Only HorizontalLayout may have no parent, and it overloads this method + /* Only HorizontalLayout or AllocationFailedLayout may have no parent, and + * they overload this method */ assert(parent()); return (cursor->layoutReference().node() == this) ? parent()->equivalentCursor(cursor) : LayoutCursor(); } From 4eb5b4355ae82ac4d8ddb7beee5e24aaa66a72f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 10:43:39 +0200 Subject: [PATCH 140/156] [poincare] LayoutCursor::addEmptyPowerLayout --- poincare/include/poincare/layout_cursor.h | 4 ++- poincare/src/layout_cursor.cpp | 33 +++++++++++++++-------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index fc35d6610..761649306 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -8,6 +8,7 @@ namespace Poincare { class HorizontalLayoutNode; +class VerticalOffsetLayoutRef; class LayoutCursor { template @@ -108,7 +109,7 @@ public: /* Layout modification */ void addEmptyExponentialLayout() {} //TODO void addEmptyMatrixLayout() {} //TODO - void addEmptyPowerLayout() {} //TODO + void addEmptyPowerLayout(); void addEmptySquareRootLayout() {} //TODO void addEmptySquarePowerLayout(); void addEmptyTenPowerLayout() {} //TODO @@ -137,6 +138,7 @@ public: private: constexpr static KDCoordinate k_cursorHeight = 18; KDCoordinate layoutHeight(); + void privateAddEmptyPowerLayout(VerticalOffsetLayoutRef v); bool baseForNewPowerLayout(); bool privateShowHideEmptyLayoutIfNeeded(bool show); LayoutRef m_layoutRef; diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 1d1deff58..abbf723d0 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -65,18 +65,17 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { /* Layout modification */ -void LayoutCursor::addEmptySquarePowerLayout() { - CharLayoutRef indiceLayout = CharLayoutRef('2'); - VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(indiceLayout, VerticalOffsetLayoutNode::Type::Superscript); - // If there is already a base - if (baseForNewPowerLayout()) { - m_layoutRef.addSibling(this, offsetLayout, true); - return; +void LayoutCursor::addEmptyPowerLayout() { + VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(EmptyLayoutRef(), VerticalOffsetLayoutNode::Type::Superscript); + privateAddEmptyPowerLayout(offsetLayout); + if (offsetLayout.parent().isDefined() && offsetLayout.numberOfChildren() == 1 && !offsetLayout.childAtIndex(0).isAllocationFailure()) { + m_layoutRef = offsetLayout.childAtIndex(0); } - // Else, add an empty base - EmptyLayoutRef child1 = EmptyLayoutRef(); - HorizontalLayoutRef newChild = HorizontalLayoutRef(child1, offsetLayout); - m_layoutRef.addSibling(this, newChild, true); +} + +void LayoutCursor::addEmptySquarePowerLayout() { + VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(CharLayoutRef('2'), VerticalOffsetLayoutNode::Type::Superscript); + privateAddEmptyPowerLayout(offsetLayout); } void LayoutCursor::addXNTCharLayout() { @@ -170,6 +169,18 @@ KDCoordinate LayoutCursor::layoutHeight() { } +void LayoutCursor::privateAddEmptyPowerLayout(VerticalOffsetLayoutRef v) { + // If there is already a base + if (baseForNewPowerLayout()) { + m_layoutRef.addSibling(this, v, true); + return; + } + // Else, add an empty base + EmptyLayoutRef e = EmptyLayoutRef(); + HorizontalLayoutRef newChild = HorizontalLayoutRef(e, v); + m_layoutRef.addSibling(this, newChild, true); +} + bool LayoutCursor::baseForNewPowerLayout() { /* Returns true if the layout on the left of the pointed layout is suitable to * be the base of a new power layout: the base layout should be anything but From 2bb5c3d83132a711e91f033aabe80fdba7ef8f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 10:53:18 +0200 Subject: [PATCH 141/156] [poincare] LayoutCursor::addEmptyExponentialLayout --- poincare/include/poincare/layout_cursor.h | 2 +- poincare/include/poincare/tree_reference.h | 4 ++++ poincare/src/layout_cursor.cpp | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 761649306..8bb911329 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -107,7 +107,7 @@ public: } /* Layout modification */ - void addEmptyExponentialLayout() {} //TODO + void addEmptyExponentialLayout(); void addEmptyMatrixLayout() {} //TODO void addEmptyPowerLayout(); void addEmptySquareRootLayout() {} //TODO diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index d4e0d4bdc..096dab0ae 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -91,6 +91,10 @@ public: assert(isDefined()); return node()->hasSibling(t.node()); } + bool hasAncestor(TreeReference t, bool includeSelf) const { + assert(isDefined()); + return node()->hasAncestor(t.node(), includeSelf); + } int numberOfChildren() const { assert(isDefined()); return node()->numberOfChildren(); diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index abbf723d0..7957eb7f5 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -65,6 +65,18 @@ void LayoutCursor::moveUnder(bool * shouldRecomputeLayout) { /* Layout modification */ +void LayoutCursor::addEmptyExponentialLayout() { + EmptyLayoutRef emptyLayout; + HorizontalLayoutRef sibling = HorizontalLayoutRef( + CharLayoutRef(Ion::Charset::Exponential), + VerticalOffsetLayoutRef(emptyLayout, VerticalOffsetLayoutNode::Type::Superscript)); + LayoutRef rootRef = m_layoutRef.root(); + m_layoutRef.addSibling(this, sibling, false); + if (emptyLayout.hasAncestor(rootRef, false) && !emptyLayout.isAllocationFailure()) { + m_layoutRef = emptyLayout; + } +} + void LayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(EmptyLayoutRef(), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); From 9b7987c0bbeaeedded423dd7f5108e87adaa3077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 11:13:35 +0200 Subject: [PATCH 142/156] [poincare] LayoutCursor::addEmptyTenPowerLayout --- .../include/poincare/horizontal_layout_node.h | 7 +++++++ poincare/include/poincare/layout_cursor.h | 2 +- poincare/src/layout_cursor.cpp | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 1e4824ebd..9e49465e4 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -75,6 +75,13 @@ public: addChildTreeAtIndex(l2, 1); } + HorizontalLayoutRef(LayoutRef l1, LayoutRef l2, LayoutRef l3, LayoutRef l4) : LayoutReference() { + addChildTreeAtIndex(l1, 0); + addChildTreeAtIndex(l2, 1); + addChildTreeAtIndex(l3, 2); + addChildTreeAtIndex(l4, 3); + } + void addOrMergeChildAtIndex(LayoutRef l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); void mergeChildrenAtIndex(HorizontalLayoutRef h, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); private: diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index 8bb911329..efb3d75d2 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -112,7 +112,7 @@ public: void addEmptyPowerLayout(); void addEmptySquareRootLayout() {} //TODO void addEmptySquarePowerLayout(); - void addEmptyTenPowerLayout() {} //TODO + void addEmptyTenPowerLayout(); void addFractionLayoutAndCollapseSiblings() {} //TODO void addXNTCharLayout(); void insertText(const char * text); diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 7957eb7f5..9343797d3 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -90,6 +90,22 @@ void LayoutCursor::addEmptySquarePowerLayout() { privateAddEmptyPowerLayout(offsetLayout); } +void LayoutCursor::addEmptyTenPowerLayout() { + EmptyLayoutRef emptyLayout; + HorizontalLayoutRef sibling = HorizontalLayoutRef( + CharLayoutRef(Ion::Charset::MiddleDot), + CharLayoutRef('1'), + CharLayoutRef('0'), + VerticalOffsetLayoutRef( + emptyLayout, + VerticalOffsetLayoutNode::Type::Superscript)); + LayoutRef rootRef = m_layoutRef.root(); + m_layoutRef.addSibling(this, sibling, false); + if (emptyLayout.hasAncestor(rootRef, false) && !emptyLayout.isAllocationFailure()) { + m_layoutRef = emptyLayout; + } +} + void LayoutCursor::addXNTCharLayout() { m_layoutRef.addSibling(this, CharLayoutRef(m_layoutRef.XNTChar()), true); } From 4eac4507875b10cf63360c465071edf2827c1ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 11:40:55 +0200 Subject: [PATCH 143/156] [poincare] Put layouts on expressions --- poincare/include/poincare/arc_cosine.h | 4 +- poincare/include/poincare/arc_sine.h | 4 +- poincare/include/poincare/arc_tangent.h | 4 +- poincare/include/poincare/complex.h | 4 +- poincare/include/poincare/complex_argument.h | 4 +- .../include/poincare/confidence_interval.h | 4 +- poincare/include/poincare/cosine.h | 4 +- poincare/include/poincare/derivative.h | 4 +- poincare/include/poincare/determinant.h | 4 +- poincare/include/poincare/division_quotient.h | 7 ++- .../include/poincare/division_remainder.h | 4 +- poincare/include/poincare/factor.h | 4 +- poincare/include/poincare/frac_part.h | 4 +- .../include/poincare/great_common_divisor.h | 4 +- .../include/poincare/hyperbolic_arc_cosine.h | 4 +- .../include/poincare/hyperbolic_arc_sine.h | 4 +- .../include/poincare/hyperbolic_arc_tangent.h | 4 +- poincare/include/poincare/hyperbolic_cosine.h | 4 +- poincare/include/poincare/hyperbolic_sine.h | 4 +- .../include/poincare/hyperbolic_tangent.h | 4 +- poincare/include/poincare/imaginary_part.h | 4 +- poincare/include/poincare/layout_engine.h | 2 +- .../include/poincare/least_common_multiple.h | 4 +- poincare/include/poincare/matrix_dimension.h | 4 +- poincare/include/poincare/matrix_inverse.h | 4 +- poincare/include/poincare/matrix_trace.h | 4 +- poincare/include/poincare/matrix_transpose.h | 4 +- .../include/poincare/naperian_logarithm.h | 4 +- .../include/poincare/permute_coefficient.h | 4 +- .../include/poincare/prediction_interval.h | 5 +- poincare/include/poincare/randint.h | 5 +- poincare/include/poincare/random.h | 4 +- poincare/include/poincare/real_part.h | 4 +- poincare/include/poincare/round.h | 4 +- .../include/poincare/simplification_root.h | 2 +- poincare/include/poincare/sine.h | 4 +- poincare/include/poincare/subtraction.h | 4 +- poincare/include/poincare/tangent.h | 4 +- poincare/src/complex.cpp | 27 +++++----- poincare/src/decimal.cpp | 8 +-- poincare/src/empty_expression.cpp | 9 +--- poincare/src/equal.cpp | 17 +++--- poincare/src/factorial.cpp | 15 +++--- poincare/src/layout_engine.cpp | 16 +++--- poincare/src/logarithm.cpp | 7 +-- poincare/src/matrix.cpp | 3 ++ poincare/src/multiplication.cpp | 3 -- poincare/src/opposite.cpp | 16 +++--- poincare/src/parenthesis.cpp | 6 +-- poincare/src/power.cpp | 21 ++++---- poincare/src/store.cpp | 17 +++--- poincare/src/symbol.cpp | 54 ++++++++----------- poincare/src/undefined.cpp | 6 +-- 53 files changed, 132 insertions(+), 246 deletions(-) diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index e3731a648..6e0da4bdf 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 0ec4295da..0c7b7e354 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index dd0c197a4..fe99497c6 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 44b47aaf2..6b5721d7b 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -54,8 +54,8 @@ private: /* convertComplexToText and convertFloatToTextPrivate return the string length * of the buffer (does not count the 0 last char)*/ int convertComplexToText(char * buffer, int bufferSize, int numberOfSignificantDigits, PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat, char multiplicationSign) const; - //ExpressionLayout * createPolarLayout(PrintFloat::Mode floatDisplayMode) const; - //ExpressionLayout * createCartesianLayout(PrintFloat::Mode floatDisplayMode) const; + LayoutRef createPolarLayout(PrintFloat::Mode floatDisplayMode) const; + LayoutRef createCartesianLayout(PrintFloat::Mode floatDisplayMode) const; T m_a; T m_b; }; diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 02352b066..9388513c8 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 4acaf340a..8f31e3408 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -3,7 +3,6 @@ #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 8f059c4d0..1536c5574 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -6,7 +6,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -21,8 +20,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 9cc0d0f29..c8a3cf5b2 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -17,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 9cff27f3b..252962381 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 6747d284a..498fd6da2 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -4,7 +4,7 @@ #include #include #include -#include //TODO remove +#include namespace Poincare { @@ -16,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); @@ -28,7 +27,7 @@ private: /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } Expression * privateApproximate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } - template Complex * templatedApproximate(Context& context, AngleUnit angleUnit) const; + template Complex * templatedApproximate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index dce48e7c2..28f0a0b84 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 8de7892b9..75e6f516b 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -7,7 +7,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -19,8 +18,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index a55d70db6..0dac5fe25 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 0540535b4..93fba41a5 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 4ae9ec6e2..4b8d00668 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 2596b6b1d..04c0f148b 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 8cd59453f..7e664e062 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index aa21b03b8..210872a84 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -17,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index f85dedca0..1626ea1e9 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -17,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index e18ae5700..d8ad73595 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -17,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 064c395a4..bc0078878 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index b9ee87f3e..27af73b53 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -16,7 +16,7 @@ public: /* Create special layouts */ static LayoutRef createParenthesedLayout(LayoutRef layout, bool cloneLayout); static LayoutRef createStringLayout(const char * buffer, int bufferSize, KDText::FontSize fontSize = KDText::FontSize::Large); - static ExpressionLayout * createLogLayout(ExpressionLayout * argument, ExpressionLayout * index); + static LayoutRef createLogLayout(LayoutRef argument, LayoutRef index); /* Expression to Text */ static int writeInfixExpressionTextInBuffer( diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 8da3cef98..1c0a73acd 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 71655e449..a67f91d94 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO -// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 675b56875..5bf9fcf69 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Evaluation */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO -// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 710d3ce6a..d7797d9df 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index c0b3e09db..15066ec5e 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 244041555..9a770337d 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 9ed509d0e..21837adc8 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { @@ -17,8 +16,7 @@ private: constexpr static int k_maxNValue = 100; /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO -// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 2f3fc7adb..aa8f3b739 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -3,8 +3,6 @@ #include #include -#include -#include //TODO remove namespace Poincare { @@ -17,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/randint.h b/poincare/include/poincare/randint.h index 8eb650f8c..87f31f5ac 100644 --- a/poincare/include/poincare/randint.h +++ b/poincare/include/poincare/randint.h @@ -3,8 +3,6 @@ #include #include -#include -#include //TODO remove namespace Poincare { @@ -16,8 +14,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO -// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/random.h b/poincare/include/poincare/random.h index 1b61d1e0c..37bc0effe 100644 --- a/poincare/include/poincare/random.h +++ b/poincare/include/poincare/random.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -19,8 +18,7 @@ private: Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - /*return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());*/ + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index d4fe41f81..f2e8edc95 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index cb26f2c48..fc60f99d4 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -16,8 +15,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index 049224c6c..868a70577 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -21,7 +21,7 @@ public: int polynomialDegree(char symbolName) const override { return -1; } Type type() const override { return Expression::Type::SimplificationRoot; } LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutRef(nullptr); //TODO + return LayoutRef(nullptr); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return 0; } Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index da9e2debe..ea3f8b899 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -5,7 +5,6 @@ #include #include #include -#include namespace Poincare { @@ -20,8 +19,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO -// return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 223962455..752c3dabc 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -19,8 +18,7 @@ private: /* Layout */ bool needParenthesisWithParent(const Expression * e) const override; LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - return CharLayoutRef('a'); //TODO - // return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 6606029b7..2acd44ef6 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -17,8 +16,7 @@ public: private: /* Layout */ LayoutRef privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const override { - //return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); - return CharLayoutRef('a'); //TODO + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 0f02dc3d6..f8dbdceb3 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -6,8 +6,8 @@ #include #include #include -#include "layout/horizontal_layout.h" -#include "layout/vertical_offset_layout.h" +#include +#include #include #include @@ -20,8 +20,6 @@ extern "C" { #include } -#include - namespace Poincare { template @@ -216,13 +214,12 @@ Complex::Complex(T a, T b) : template LayoutRef Complex::privateCreateLayout(PrintFloat::Mode floatDisplayMode, Expression::ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); if (complexFormat == Expression::ComplexFormat::Polar) { return createPolarLayout(floatDisplayMode); } return createCartesianLayout(floatDisplayMode); -*/} +} template Expression * Complex::CreateDecimal(T f) { @@ -309,8 +306,8 @@ int Complex::convertComplexToText(char * buffer, int bufferSize, int numberOf return numberOfChars; } -/*template -ExpressionLayout * Complex::createPolarLayout(PrintFloat::Mode floatDisplayMode) const { +template +LayoutRef Complex::createPolarLayout(PrintFloat::Mode floatDisplayMode) const { char bufferBase[PrintFloat::k_maxFloatBufferLength+2]; int numberOfCharInBase = 0; char bufferSuperscript[PrintFloat::k_maxFloatBufferLength+2]; @@ -340,19 +337,19 @@ ExpressionLayout * Complex::createPolarLayout(PrintFloat::Mode floatDisplayMo if (numberOfCharInSuperscript == 0) { return LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); } - ExpressionLayout * result = LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); - ExpressionLayout * exponentLayout = LayoutEngine::createStringLayout(bufferSuperscript, numberOfCharInSuperscript); - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(exponentLayout, VerticalOffsetLayout::Type::Superscript, false); - (static_cast(result))->addChildAtIndex(offsetLayout, result->numberOfChildren()); + LayoutRef result = LayoutEngine::createStringLayout(bufferBase, numberOfCharInBase); + LayoutRef exponentLayout = LayoutEngine::createStringLayout(bufferSuperscript, numberOfCharInSuperscript); + VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(exponentLayout, VerticalOffsetLayoutNode::Type::Superscript); + result.addChildAtIndex(offsetLayout, result.numberOfChildren(), nullptr); return result; } template -ExpressionLayout * Complex::createCartesianLayout(PrintFloat::Mode floatDisplayMode) const { +LayoutRef Complex::createCartesianLayout(PrintFloat::Mode floatDisplayMode) const { char buffer[PrintFloat::k_maxComplexBufferLength]; int numberOfChars = convertComplexToText(buffer, PrintFloat::k_maxComplexBufferLength, Preferences::sharedPreferences()->numberOfSignificantDigits(), floatDisplayMode, Expression::ComplexFormat::Cartesian, Ion::Charset::MiddleDot); return LayoutEngine::createStringLayout(buffer, numberOfChars); -}*/ +} template class Complex; template class Complex; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 478a858b8..75fdc0475 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -6,10 +6,7 @@ #include #include #include -extern "C" { #include -} -#include namespace Poincare { @@ -219,10 +216,9 @@ bool Decimal::needParenthesisWithParent(const Expression * e) const { } LayoutRef Decimal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*char buffer[k_maxBufferSize]; + char buffer[k_maxBufferSize]; int numberOfChars = convertToText(buffer, k_maxBufferSize, floatDisplayMode, PrintFloat::k_numberOfStoredSignificantDigits); - return LayoutEngine::createStringLayout(buffer, numberOfChars);*/ + return LayoutEngine::createStringLayout(buffer, numberOfChars); } Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/empty_expression.cpp b/poincare/src/empty_expression.cpp index 13d22f174..7a1b63257 100644 --- a/poincare/src/empty_expression.cpp +++ b/poincare/src/empty_expression.cpp @@ -1,12 +1,8 @@ #include +#include #include -#include #include -#include - -extern "C" { #include -} namespace Poincare { @@ -19,8 +15,7 @@ int EmptyExpression::writeTextInBuffer(char * buffer, int bufferSize, int number } LayoutRef EmptyExpression::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - // return new EmptyLayout(); + return EmptyLayoutRef(); } template Complex * EmptyExpression::templatedApproximate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/equal.cpp b/poincare/src/equal.cpp index ee9e35a3d..8b278ac43 100644 --- a/poincare/src/equal.cpp +++ b/poincare/src/equal.cpp @@ -16,8 +16,8 @@ extern "C" { #include #include #include -#include "layout/char_layout.h" -#include "layout/horizontal_layout.h" +#include +#include namespace Poincare { @@ -51,14 +51,13 @@ Expression * Equal::shallowReduce(Context& context, AngleUnit angleUnit) { } LayoutRef Equal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); - result->addChildAtIndex(new CharLayout('='), result->numberOfChildren()); - result->addOrMergeChildAtIndex(operand(1)->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), false); - return result;*/ + HorizontalLayoutRef result; + result.addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); + result.addChildAtIndex(CharLayoutRef('='), result.numberOfChildren(), nullptr); + result.addOrMergeChildAtIndex(operand(1)->createLayout(floatDisplayMode, complexFormat), result.numberOfChildren(), false); + return result; } template diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 983c4f6bc..1fdde4484 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -1,6 +1,6 @@ #include -#include "layout/char_layout.h" -#include "layout/horizontal_layout.h" +#include +#include #include #include #include @@ -11,7 +11,6 @@ extern "C" { #include } #include -#include namespace Poincare { @@ -94,14 +93,12 @@ Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) } LayoutRef Factorial::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); - result->addChildAtIndex(new CharLayout('!'), result->numberOfChildren()); + HorizontalLayoutRef result; + result.addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 0, false); + result.addChildAtIndex(CharLayoutRef('!'), result.numberOfChildren(), nullptr); return result; -*/ } int Factorial::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 00816d3d0..2e3fcd1e7 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -4,8 +4,9 @@ #include "layout/left_parenthesis_layout.h" #include "layout/right_parenthesis_layout.h" #include "layout/vertical_offset_layout.h" -#include #include +#include +#include extern "C" { #include @@ -97,13 +98,12 @@ LayoutRef LayoutEngine::createStringLayout(const char * buffer, int bufferSize, return resultLayout; } -ExpressionLayout * LayoutEngine::createLogLayout(ExpressionLayout * argument, ExpressionLayout * index) { - return nullptr; //TODO - /*HorizontalLayout * resultLayout = static_cast(createStringLayout("log", 3)); - VerticalOffsetLayout * offsetLayout = new VerticalOffsetLayout(index, VerticalOffsetLayout::Type::Subscript, false); - resultLayout->addChildAtIndex(offsetLayout, resultLayout->numberOfChildren()); - resultLayout->addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout->numberOfChildren(), true); - return resultLayout;*/ +LayoutRef LayoutEngine::createLogLayout(LayoutRef argument, LayoutRef index) { + HorizontalLayoutRef resultLayout = HorizontalLayoutRef(createStringLayout("log", 3)); + VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(index, VerticalOffsetLayoutNode::Type::Subscript); + resultLayout.addChildAtIndex(offsetLayout, resultLayout.numberOfChildren(), nullptr); + resultLayout.addOrMergeChildAtIndex(createParenthesedLayout(argument, false), resultLayout.numberOfChildren(), true); + return resultLayout; } int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, int numberOfDigits, const char * operatorName) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index d7ddc1f53..4972e562d 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,6 +1,4 @@ #include -#include "layout/horizontal_layout.h" -#include "layout/vertical_offset_layout.h" #include #include #include @@ -229,13 +227,12 @@ Expression * Logarithm::templatedApproximate(Context& context, AngleUnit angleUn } LayoutRef Logarithm::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); if (numberOfOperands() == 1) { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } - return LayoutEngine::createLogLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat));*/ + return LayoutEngine::createLogLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); } } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index e567f0e66..0c6a9135d 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -16,6 +16,9 @@ extern "C" { #include #include +#include //TODO + + namespace Poincare { Matrix::Matrix(MatrixData * matrixData) : diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 532af5ad8..ab863f36c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -86,11 +86,8 @@ bool Multiplication::needParenthesisWithParent(const Expression * e) const { } LayoutRef Multiplication::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO -/* const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, middleDotString); -*/ } int Multiplication::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index dedce8527..7f55cb561 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,6 +1,6 @@ #include -#include "layout/char_layout.h" -#include "layout/horizontal_layout.h" +#include +#include #include #include #include @@ -12,8 +12,6 @@ extern "C" { #include } -#include - namespace Poincare { Expression::Type Opposite::type() const { @@ -69,17 +67,15 @@ Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { } LayoutRef Opposite::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO -/* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - HorizontalLayout * result = new HorizontalLayout(new CharLayout('-'), false); + HorizontalLayoutRef result = HorizontalLayoutRef(CharLayoutRef('-')); if (operand(0)->type() == Type::Opposite) { - result->addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1, false); + result.addOrMergeChildAtIndex(LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false), 1, false); } else { - result->addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); + result.addOrMergeChildAtIndex(operand(0)->createLayout(floatDisplayMode, complexFormat), 1, false); } return result; -*/ } int Opposite::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index e990da75d..382f0876e 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -1,6 +1,4 @@ #include -#include - extern "C" { #include #include @@ -23,11 +21,9 @@ int Parenthesis::polynomialDegree(char symbolName) const { } LayoutRef Parenthesis::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('('); //TODO -/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false);*/ + return LayoutEngine::createParenthesedLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); } Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 28dcdcb34..101e949d9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -17,8 +17,8 @@ #include #include -#include "layout/horizontal_layout.h" -#include "layout/vertical_offset_layout.h" +#include +#include #include #include @@ -176,22 +176,21 @@ bool Power::needParenthesisWithParent(const Expression * e) const { } LayoutRef Power::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); const Expression * indiceOperand = m_operands[1]; // Delete eventual parentheses of the indice in the pretty print if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = m_operands[1]->operand(0); } - HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(m_operands[0]->createLayout(floatDisplayMode, complexFormat), 0, false); - result->addChildAtIndex(new VerticalOffsetLayout( + HorizontalLayoutRef result = HorizontalLayoutRef(); + result.addOrMergeChildAtIndex(m_operands[0]->createLayout(floatDisplayMode, complexFormat), 0, false); + result.addChildAtIndex(VerticalOffsetLayoutRef( indiceOperand->createLayout(floatDisplayMode, complexFormat), - VerticalOffsetLayout::Type::Superscript, - false), - result->numberOfChildren()); - return result;*/ + VerticalOffsetLayoutNode::Type::Superscript), + result.numberOfChildren(), + nullptr); + return result; } int Power::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 098b69a3d..6a95b197e 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -7,9 +7,9 @@ extern "C" { #include #include #include -#include "layout/char_layout.h" -#include "layout/horizontal_layout.h" #include +#include + namespace Poincare { @@ -36,14 +36,13 @@ Expression * Store::shallowReduce(Context& context, AngleUnit angleUnit) { } LayoutRef Store::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - HorizontalLayout * result = new HorizontalLayout(); - result->addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0, false); - result->addChildAtIndex(new CharLayout(Ion::Charset::Sto), result->numberOfChildren()); - result->addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result->numberOfChildren(), false); - return result;*/ + HorizontalLayoutRef result = HorizontalLayoutRef(); + result.addOrMergeChildAtIndex(value()->createLayout(floatDisplayMode, complexFormat), 0, false); + result.addChildAtIndex(CharLayoutRef(Ion::Charset::Sto), result.numberOfChildren(), nullptr); + result.addOrMergeChildAtIndex(symbol()->createLayout(floatDisplayMode, complexFormat), result.numberOfChildren(), false); + return result; } template diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 9730df9df..1b4cfd014 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -8,11 +8,9 @@ #include #include -#include "layout/char_layout.h" -#include "layout/horizontal_layout.h" -#include "layout/vertical_offset_layout.h" - #include +#include +#include #include #include @@ -247,53 +245,43 @@ char Symbol::name() const { } LayoutRef Symbol::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO -/* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); if (m_name == SpecialSymbols::Ans) { return LayoutEngine::createStringLayout("ans", 3); } if (m_name == SpecialSymbols::un) { - return new HorizontalLayout( - new CharLayout('u'), - new VerticalOffsetLayout( - new CharLayout('n', KDText::FontSize::Small), - VerticalOffsetLayout::Type::Subscript, - false), - false); + return HorizontalLayoutRef( + CharLayoutRef('u'), + VerticalOffsetLayoutRef( + CharLayoutRef('n', KDText::FontSize::Small), + VerticalOffsetLayoutNode::Type::Subscript)); } if (m_name == SpecialSymbols::un1) { - return new HorizontalLayout( - new CharLayout('u'), - new VerticalOffsetLayout( + return HorizontalLayoutRef( + CharLayoutRef('u'), + VerticalOffsetLayoutRef( LayoutEngine::createStringLayout("n+1", 3, KDText::FontSize::Small), - VerticalOffsetLayout::Type::Subscript, - false), - false); + VerticalOffsetLayoutNode::Type::Subscript)); } if (m_name == SpecialSymbols::vn) { - return new HorizontalLayout( - new CharLayout('v'), - new VerticalOffsetLayout( - new CharLayout('n', KDText::FontSize::Small), - VerticalOffsetLayout::Type::Subscript, - false), - false); + return HorizontalLayoutRef( + CharLayoutRef('v'), + VerticalOffsetLayoutRef( + CharLayoutRef('n', KDText::FontSize::Small), + VerticalOffsetLayoutNode::Type::Subscript)); } if (m_name == SpecialSymbols::vn1) { - return new HorizontalLayout( - new CharLayout('v'), - new VerticalOffsetLayout( + return HorizontalLayoutRef( + CharLayoutRef('v'), + VerticalOffsetLayoutRef( LayoutEngine::createStringLayout("n+1", 3, KDText::FontSize::Small), - VerticalOffsetLayout::Type::Subscript, - false), - false); + VerticalOffsetLayoutNode::Type::Subscript)); } if (isMatrixSymbol() || isSeriesSymbol(m_name) || isRegressionSymbol(m_name)) { return LayoutEngine::createStringLayout(textForSpecialSymbols(m_name), 2); } - return LayoutEngine::createStringLayout(&m_name, 1);*/ + return LayoutEngine::createStringLayout(&m_name, 1); } int Symbol::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 678854151..dd16eba42 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -1,6 +1,5 @@ #include #include -#include extern "C" { #include @@ -26,10 +25,9 @@ template Complex * Undefined::templatedApproximate(Context& conte } LayoutRef Undefined::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - /*char buffer[16]; + char buffer[16]; int numberOfChars = PrintFloat::convertFloatToText(NAN, buffer, 16, 1, floatDisplayMode); - return LayoutEngine::createStringLayout(buffer, numberOfChars);*/ - return CharLayoutRef('a'); //TODO + return LayoutEngine::createStringLayout(buffer, numberOfChars); } int Undefined::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { From a08b00aa5ff64910fe0ab4fb4a2c7041f5af9d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 14:30:20 +0200 Subject: [PATCH 144/156] [poincare] Sequence and Sum layouts --- poincare/Makefile | 2 + poincare/include/poincare.h | 1 + poincare/include/poincare/char_layout_node.h | 8 + .../include/poincare/horizontal_layout_node.h | 6 +- poincare/include/poincare/layout_reference.h | 5 + poincare/include/poincare/product.h | 2 +- poincare/include/poincare/sequence.h | 2 +- .../include/poincare/sequence_layout_node.h | 70 +++++ poincare/include/poincare/sum.h | 2 +- poincare/include/poincare/sum_layout_node.h | 29 +++ poincare/include/poincare/tree_reference.h | 2 +- poincare/src/layout_node.cpp | 5 +- poincare/src/product.cpp | 8 +- poincare/src/sequence.cpp | 7 +- poincare/src/sequence_layout_node.cpp | 245 ++++++++++++++++++ poincare/src/sum.cpp | 7 +- poincare/src/sum_layout_node.cpp | 46 ++++ 17 files changed, 428 insertions(+), 19 deletions(-) create mode 100644 poincare/include/poincare/sequence_layout_node.h create mode 100644 poincare/include/poincare/sum_layout_node.h create mode 100644 poincare/src/sequence_layout_node.cpp create mode 100644 poincare/src/sum_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 9ecd76948..8c2a18e69 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -14,6 +14,8 @@ objs += $(addprefix poincare/src/,\ layout_cursor.o\ layout_node.o\ layout_reference.o\ + sequence_layout_node.o\ + sum_layout_node.o\ vertical_offset_layout_node.o\ ) diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index d5d9c49a3..4fe451774 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/char_layout_node.h b/poincare/include/poincare/char_layout_node.h index 74820f3ae..c346cfbd1 100644 --- a/poincare/include/poincare/char_layout_node.h +++ b/poincare/include/poincare/char_layout_node.h @@ -17,6 +17,7 @@ public: // CharLayout void setChar(char c) { m_char = c; } + KDText::FontSize fontSize() const { return m_fontSize; } void setFontSize(KDText::FontSize fontSize) { m_fontSize = fontSize; } // LayoutNode @@ -63,6 +64,13 @@ public: } CharLayoutRef(TreeNode * t) : LayoutReference(t) {} + KDText::FontSize fontSize() const { + if (!(this->node()->isAllocationFailure())) { + return this->typedNode()->fontSize(); + } + return KDText::FontSize::Large; + } + }; } diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 9e49465e4..67a826e50 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -74,7 +74,11 @@ public: addChildTreeAtIndex(l1, 0); addChildTreeAtIndex(l2, 1); } - + HorizontalLayoutRef(LayoutRef l1, LayoutRef l2, LayoutRef l3) : LayoutReference() { + addChildTreeAtIndex(l1, 0); + addChildTreeAtIndex(l2, 1); + addChildTreeAtIndex(l3, 2); + } HorizontalLayoutRef(LayoutRef l1, LayoutRef l2, LayoutRef l3, LayoutRef l4) : LayoutReference() { addChildTreeAtIndex(l1, 0); addChildTreeAtIndex(l2, 1); diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 3249ab209..d65981e6f 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -14,6 +14,10 @@ class LayoutReference : public SerializableReference { public: using SerializableReference::SerializableReference; + LayoutReference clone() const { + return LayoutReference(this->treeClone().node()); + } + // Operators // Allow every LayoutReference to be transformed into a LayoutRef @@ -40,6 +44,7 @@ public: void invalidAllSizesPositionsAndBaselines() { return this->typedNode()->invalidAllSizesPositionsAndBaselines(); } // Layout properties + KDPoint positionOfChild(LayoutReference child) { return this->typedNode()->positionOfChild(child.typedNode()); } bool mustHaveLeftSibling() const { return this->typedNode()->mustHaveLeftSibling(); } bool isEmpty() const { return this->typedNode()->isEmpty(); } bool isHorizontal() const { return this->typedNode()->isHorizontal(); } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 954a1aa20..ff9282fc8 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -13,7 +13,7 @@ public: private: const char * name() const override; int emptySequenceValue() const override; - ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const override; + LayoutRef createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const override; Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { return templatedApproximateWithNextTerm(a, b); } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 88f1a0064..59750768d 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -14,7 +14,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, numberOfSignificantDigits, name()); } - virtual ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const = 0; + virtual LayoutRef createSequenceLayout(LayoutRef subscriptLayout, LayoutRef superscriptLayout, LayoutRef argumentLayout) const = 0; virtual const char * name() const = 0; /* Evaluation */ Expression * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedApproximate(context, angleUnit); } diff --git a/poincare/include/poincare/sequence_layout_node.h b/poincare/include/poincare/sequence_layout_node.h new file mode 100644 index 000000000..53edf6d8d --- /dev/null +++ b/poincare/include/poincare/sequence_layout_node.h @@ -0,0 +1,70 @@ +#ifndef POINCARE_SEQUENCE_LAYOUT_NODE_H +#define POINCARE_SEQUENCE_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class SequenceLayoutNode : public LayoutNode { +public: + constexpr static KDCoordinate k_symbolHeight = 15; + constexpr static KDCoordinate k_symbolWidth = 9; + + using LayoutNode::LayoutNode; + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void deleteBeforeCursor(LayoutCursor * cursor) override; + LayoutNode * layoutToPointWhenInserting() override { + assert(lowerBoundLayout() != nullptr); + return lowerBoundLayout(); + } + char XNTChar() const override { return 'n'; } + + // TreeNode + size_t size() const override { return sizeof(SequenceLayoutNode); } + int numberOfChildren() const override { return 3; } +#if TREE_LOG + const char * description() const override { + return "Sequence Layout"; + } +#endif + +protected: + constexpr static KDCoordinate k_boundHeightMargin = 2; + constexpr static KDCoordinate k_argumentWidthMargin = 2; + + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override; + + int writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const; + LayoutNode * argumentLayout() { return childAtIndex(0); } + LayoutNode * lowerBoundLayout() { return childAtIndex(1); } + LayoutNode * upperBoundLayout() { return childAtIndex(2); } + + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +/*class SequenceLayoutRef : public LayoutReference { +public: + VerticalOffsetLayoutRef(LayoutRef l, VerticalOffsetLayoutNode::Type type) : + LayoutReference() + { + if (!(this->node()->isAllocationFailure())) { + this->typedNode()->setType(type); + } + addChildTreeAtIndex(l, 0); + } + VerticalOffsetLayoutRef(TreeNode * t) : LayoutReference(t) {} +};*/ + +} + +#endif diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 1aae88773..369e5b7a5 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -13,7 +13,7 @@ public: private: const char * name() const override; int emptySequenceValue() const override; - ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const override; + LayoutRef createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const override; Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { return templatedApproximateWithNextTerm(a, b); } diff --git a/poincare/include/poincare/sum_layout_node.h b/poincare/include/poincare/sum_layout_node.h new file mode 100644 index 000000000..f28047fae --- /dev/null +++ b/poincare/include/poincare/sum_layout_node.h @@ -0,0 +1,29 @@ +#ifndef POINCARE_SUM_LAYOUT_NODE_H +#define POINCARE_SUM_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class SumLayoutNode : public SequenceLayoutNode { +public: + using SequenceLayoutNode::SequenceLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; +private: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +class SumLayoutRef : public LayoutReference { +public: + SumLayoutRef(TreeNode * n) : LayoutReference(n) {} + SumLayoutRef(LayoutRef argument, LayoutRef lowerB, LayoutRef upperB) : LayoutReference() { + addChildTreeAtIndex(argument, 0); + addChildTreeAtIndex(lowerB, 1); + addChildTreeAtIndex(upperB, 2); + } +}; + +} + +#endif diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 096dab0ae..65d891b70 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -31,7 +31,7 @@ public: inline bool operator==(TreeReference t) { return m_identifier == t.identifier(); } - TreeReference clone() const { + TreeReference treeClone() const { if (!isDefined()){ return TreeReference(nullptr); } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 614d6c4e7..509b404aa 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -239,9 +239,8 @@ void LayoutNode::scoreCursorInDescendantsVertically ( } } if (layoutIsUnderOrAbove || layoutContains) { - int childIndex = 0; - while (childAtIndex(childIndex++)) { - childAtIndex(childIndex-1)->scoreCursorInDescendantsVertically(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); + for (LayoutNode * c : children()) { + c->scoreCursorInDescendantsVertically(direction, cursor, shouldRecomputeLayout, childResult, castedResultPosition, resultScore); } } } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index ab07fbc0d..8b7b0e022 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -1,6 +1,7 @@ #include #include -#include "layout/product_layout.h" +#include //TODO remove +//#include extern "C" { #include #include @@ -26,8 +27,9 @@ int Product::emptySequenceValue() const { return 1; } -ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const { - return new ProductLayout(argumentLayout, subscriptLayout, superscriptLayout, false); +LayoutRef Product::createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const { + return SumLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); + // TODO return ProductLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); } template diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index d0dcef341..8d5b5ac1a 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -3,7 +3,6 @@ #include #include #include -#include extern "C" { #include #include @@ -13,11 +12,9 @@ extern "C" { namespace Poincare { LayoutRef Sequence::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO -/* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return createSequenceLayoutWithArgumentLayouts(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat)); -*/ + return createSequenceLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat)); } template diff --git a/poincare/src/sequence_layout_node.cpp b/poincare/src/sequence_layout_node.cpp new file mode 100644 index 000000000..0abbb0ade --- /dev/null +++ b/poincare/src/sequence_layout_node.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +/*#include "left_parenthesis_layout.h" +#include "right_parenthesis_layout.h" TODO*/ +#include + +namespace Poincare { + +void SequenceLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (cursor->position() == LayoutCursor::Position::Left + && ((lowerBoundLayout() && cursor->layoutReference() == lowerBoundLayout()) + || (upperBoundLayout() && cursor->layoutReference() == upperBoundLayout()))) + { + // Case: Left of the bounds. Go Left of the sequence. + cursor->setLayoutNode(this); + return; + } + if (cursor->position() == LayoutCursor::Position::Left + && argumentLayout() + && cursor->layoutReference() == argumentLayout()) + { + // Case: Left of the argument. Go Right of the lower bound. + assert(lowerBoundLayout() != nullptr); + cursor->setLayoutNode(lowerBoundLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + assert(cursor->layoutReference() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Go to the argument and move Left. + assert(argumentLayout() != nullptr); + cursor->setLayoutNode(argumentLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left. Ask the parent. + LayoutNode * parentLayout = parent(); + if (parentLayout) { + parentLayout->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void SequenceLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (cursor->position() == LayoutCursor::Position::Right + && ((lowerBoundLayout() && cursor->layoutReference() == lowerBoundLayout()) + || (upperBoundLayout() && cursor->layoutReference() == upperBoundLayout()))) + { + // Case: Right of the bounds. Go Left of the argument. + assert(argumentLayout() != nullptr); + cursor->setLayoutNode(argumentLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + if (cursor->position() == LayoutCursor::Position::Right + && argumentLayout() + && cursor->layoutReference() == argumentLayout()) + { + // Case: Right of the argument. Go Right. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutReference() == this); + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Go to the upper bound + assert(upperBoundLayout() != nullptr); + cursor->setLayoutNode(upperBoundLayout()); + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // Case: Right. Ask the parent + LayoutNode * parentLayout = parent(); + if (parentLayout) { + return parentLayout->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +void SequenceLayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (lowerBoundLayout() && cursor->layoutNode()->hasAncestor(lowerBoundLayout(), true)) { + // If the cursor is inside the lower bound, move it to the upper bound + assert(upperBoundLayout() != nullptr); + upperBoundLayout()->moveCursorUpInDescendants(cursor, shouldRecomputeLayout); + return; + } + if (argumentLayout() + && cursor->isEquivalentTo(LayoutCursor(argumentLayout(), LayoutCursor::Position::Left))) + { + // If the cursor is Left of the argument, move it to the upper bound + assert(upperBoundLayout() != nullptr); + upperBoundLayout()->moveCursorUpInDescendants(cursor, shouldRecomputeLayout); + return; + } + LayoutNode::moveCursorUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void SequenceLayoutNode::moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (upperBoundLayout() && cursor->layoutNode()->hasAncestor(upperBoundLayout(), true)) { + // If the cursor is inside the upper bound, move it to the lower bound + assert(lowerBoundLayout() != nullptr); + lowerBoundLayout()->moveCursorDownInDescendants(cursor, shouldRecomputeLayout); + return; + } + // If the cursor is Left of the argument, move it to the lower bound + if (argumentLayout() + && cursor->isEquivalentTo(LayoutCursor(argumentLayout(), LayoutCursor::Position::Left))) + { + assert(lowerBoundLayout() != nullptr); + lowerBoundLayout()->moveCursorDownInDescendants(cursor, shouldRecomputeLayout); + return; + } + LayoutNode::moveCursorDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void SequenceLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + if (cursor->isEquivalentTo(LayoutCursor(argumentLayout(), LayoutCursor::Position::Left))) { + // Case: Left of the argument. Delete the layout, keep the argument. + LayoutRef(this).replaceWith(LayoutRef(argumentLayout()), cursor); + // WARNING: do not use "this" afterwards + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + + +// Protected + +void SequenceLayoutNode::computeSize() { + KDSize lowerBoundSizeWithNEquals = HorizontalLayoutRef(CharLayoutRef('n'), CharLayoutRef('='), LayoutRef(lowerBoundLayout()).clone()).layoutSize(); + + + //TODO LeftParenthesisLayoutRef dummyLeftParenthesis; + //RightParenthesisLayoutRef dummyRightParenthesis; + //HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis); + HorizontalLayoutRef dummyLayout2(LayoutRef(argumentLayout()).clone()); + + + KDSize dummyLayoutSize = dummyLayout2.layoutSize(); + KDSize upperBoundSize = upperBoundLayout()->layoutSize(); + KDSize result = KDSize( + max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+dummyLayoutSize.width(), + baseline() + max(k_symbolHeight/2+k_boundHeightMargin+lowerBoundSizeWithNEquals.height(), dummyLayoutSize.height() - argumentLayout()->baseline()) + ); + m_frame.setSize(result); + m_sized = true; +} + +void SequenceLayoutNode::computeBaseline() { + m_baseline = max(upperBoundLayout()->layoutSize().height()+k_boundHeightMargin+(k_symbolHeight+1)/2, argumentLayout()->baseline()); + m_baselined = true; +} + + +KDPoint SequenceLayoutNode::positionOfChild(LayoutNode * l) { + LayoutRef lowerBoundClone = LayoutRef(lowerBoundLayout()).clone(); + HorizontalLayoutRef dummyLayout1(CharLayoutRef('n'), CharLayoutRef('='), lowerBoundClone); + KDSize lowerBoundSizeWithNEquals = dummyLayout1.layoutSize(); + KDSize upperBoundSize = upperBoundLayout()->layoutSize(); + + + /* TODO LeftParenthesisLayoutRef dummyLeftParenthesis; + HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone());*/ + HorizontalLayoutRef dummyLayout2(LayoutRef(argumentLayout()).clone()); + + + + KDCoordinate x = 0; + KDCoordinate y = 0; + if (l == lowerBoundLayout()) { + x = dummyLayout1.positionOfChild(lowerBoundClone).x() + +max(max(0, (k_symbolWidth-lowerBoundSizeWithNEquals.width())/2), + (upperBoundSize.width()-lowerBoundSizeWithNEquals.width())/2); + y = baseline() + k_symbolHeight/2 + k_boundHeightMargin; + } else if (l == upperBoundLayout()) { + x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSizeWithNEquals.width()-upperBoundSize.width())/2); + y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); + } else if (l == argumentLayout()) { + x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin;// TODO+dummyLeftParenthesis.layoutSize().width(); + y = baseline() - argumentLayout()->baseline(); + } else { + assert(false); + } + return KDPoint(x,y); +} + +int SequenceLayoutNode::writeDerivedClassInBuffer(const char * operatorName, char * buffer, int bufferSize, int numberOfSignificantDigits) const { + assert(operatorName != nullptr); + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + + // Write the operator name + int numberOfChar = strlcpy(buffer, operatorName, bufferSize); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the opening parenthesis + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the argument + numberOfChar += const_cast(this)->argumentLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the comma + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the lower bound + numberOfChar += const_cast(this)->lowerBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the comma + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the upper bound + numberOfChar += const_cast(this)->upperBoundLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the closing parenthesis + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void SequenceLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Render the "n=" + CharLayoutRef dummyN = CharLayoutRef('n'); + LayoutRef lowerBoundClone = LayoutRef(lowerBoundLayout()).clone(); + HorizontalLayoutRef dummyLayout(dummyN, CharLayoutRef('='), lowerBoundClone); + KDPoint nEqualsPosition = positionOfChild(lowerBoundLayout()).translatedBy((dummyLayout.positionOfChild(lowerBoundClone)).opposite()).translatedBy(dummyLayout.positionOfChild(dummyN)); + ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN.fontSize(), expressionColor, backgroundColor); + + // Render the parentheses + /* TODO LeftParenthesisLayoutRef dummyLeftParenthesis; + RightParenthesisLayoutRef dummyRightParenthesis; + HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis, false); + KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); + KDPoint rightParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); + dummyLeftParenthesis.render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); + dummyRightParenthesis.render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor);*/ +} + +} diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index fe973047a..eb9ff6046 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -1,6 +1,7 @@ #include #include -#include "layout/sum_layout.h" +#include + extern "C" { #include #include @@ -26,8 +27,8 @@ int Sum::emptySequenceValue() const { return 0; } -ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * argumentLayout, ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout) const { - return new SumLayout(argumentLayout, subscriptLayout, superscriptLayout, false); +LayoutRef Sum::createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const { + return SumLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); } template diff --git a/poincare/src/sum_layout_node.cpp b/poincare/src/sum_layout_node.cpp new file mode 100644 index 000000000..c8f7d3d59 --- /dev/null +++ b/poincare/src/sum_layout_node.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +namespace Poincare { + +const uint8_t symbolPixel[SumLayoutNode::k_symbolHeight][SumLayoutNode::k_symbolWidth] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, +}; + + +int SumLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return SequenceLayoutNode::writeDerivedClassInBuffer("sum", buffer, bufferSize, numberOfSignificantDigits); +} + +void SumLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Computes sizes. + KDSize upperBoundSize = upperBoundLayout()->layoutSize(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayoutRef(CharLayoutRef('n'), CharLayoutRef('='), LayoutRef(lowerBoundLayout()).clone()).layoutSize(); + + // Render the Sum symbol. + KDColor workingBuffer[k_symbolWidth*k_symbolHeight]; + KDRect symbolFrame(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + k_symbolWidth, k_symbolHeight); + ctx->blendRectWithMask(symbolFrame, expressionColor, (const uint8_t *)symbolPixel, (KDColor *)workingBuffer); + + // Render the "n=" and the parentheses. + SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); +} + +} From 1057b3ba2e1253329d4ff1221f2e1f783bed8356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 14:38:54 +0200 Subject: [PATCH 145/156] [poincare] Fix EmptyLayoutNode::moveCursorVertically --- poincare/src/empty_layout_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/empty_layout_node.cpp b/poincare/src/empty_layout_node.cpp index 6956b87d1..6f7bf4494 100644 --- a/poincare/src/empty_layout_node.cpp +++ b/poincare/src/empty_layout_node.cpp @@ -60,7 +60,7 @@ void EmptyLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCu * should be checked. */ assert(cursor->layoutReference() == this); LayoutCursor cursorResult = cursor->clone(); - moveCursorVertically(direction, &cursorResult, shouldRecomputeLayout, equivalentPositionVisited); + LayoutNode::moveCursorVertically(direction, &cursorResult, shouldRecomputeLayout, equivalentPositionVisited); if (cursorResult.isDefined()) { cursor->setTo(&cursorResult); return; From cfe3e7aa919f80708df45b085c9f2adb2bda6596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 14:39:29 +0200 Subject: [PATCH 146/156] [poincare] ProductLayoutNode --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + .../include/poincare/product_layout_node.h | 31 +++++++++++++++++++ poincare/src/product.cpp | 6 ++-- poincare/src/product_layout_node.cpp | 31 +++++++++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 poincare/include/poincare/product_layout_node.h create mode 100644 poincare/src/product_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 8c2a18e69..b46e58a1e 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -14,6 +14,7 @@ objs += $(addprefix poincare/src/,\ layout_cursor.o\ layout_node.o\ layout_reference.o\ + product_layout_node.o\ sequence_layout_node.o\ sum_layout_node.o\ vertical_offset_layout_node.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 4fe451774..1b714e32a 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/product_layout_node.h b/poincare/include/poincare/product_layout_node.h new file mode 100644 index 000000000..310d5450e --- /dev/null +++ b/poincare/include/poincare/product_layout_node.h @@ -0,0 +1,31 @@ +#ifndef POINCARE_PRODUCT_LAYOUT_NODE_H +#define POINCARE_PRODUCT_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class ProductLayoutNode : public SequenceLayoutNode { +public: + using SequenceLayoutNode::SequenceLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +private: + constexpr static KDCoordinate k_lineThickness = 1; +}; + +class ProductLayoutRef : public LayoutReference { +public: + ProductLayoutRef(TreeNode * n) : LayoutReference(n) {} + ProductLayoutRef(LayoutRef argument, LayoutRef lowerB, LayoutRef upperB) : LayoutReference() { + addChildTreeAtIndex(argument, 0); + addChildTreeAtIndex(lowerB, 1); + addChildTreeAtIndex(upperB, 2); + } +}; + +} + +#endif diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 8b7b0e022..9e0b48265 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -1,7 +1,6 @@ #include #include -#include //TODO remove -//#include +#include extern "C" { #include #include @@ -28,8 +27,7 @@ int Product::emptySequenceValue() const { } LayoutRef Product::createSequenceLayout(LayoutRef argumentLayout, LayoutRef subscriptLayout, LayoutRef superscriptLayout) const { - return SumLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); - // TODO return ProductLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); + return ProductLayoutRef(argumentLayout, subscriptLayout, superscriptLayout); } template diff --git a/poincare/src/product_layout_node.cpp b/poincare/src/product_layout_node.cpp new file mode 100644 index 000000000..3b9bb2208 --- /dev/null +++ b/poincare/src/product_layout_node.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +namespace Poincare { + +int ProductLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return SequenceLayoutNode::writeDerivedClassInBuffer("product", buffer, bufferSize, numberOfSignificantDigits); +} + +void ProductLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + // Compute sizes. + KDSize upperBoundSize = upperBoundLayout()->layoutSize(); + KDSize lowerBoundSizeWithNEquals = HorizontalLayoutRef(CharLayoutRef('n'), CharLayoutRef('='), LayoutRef(lowerBoundLayout()).clone()).layoutSize(); + + // Render the Product symbol. + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + k_lineThickness, k_symbolHeight), expressionColor); + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + k_symbolWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSizeWithNEquals.width()-k_symbolWidth)/2)+k_symbolWidth, + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, argumentLayout()->baseline()-(k_symbolHeight+1)/2), + k_lineThickness, k_symbolHeight), expressionColor); + + // Render the "n=" and the parentheses. + SequenceLayoutNode::render(ctx, p, expressionColor, backgroundColor); +} + +} From f6c164080064c1c338b2ab61ad0cd5d44f73de7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 15:31:38 +0200 Subject: [PATCH 147/156] [poincare] Left and right parenthesis --- poincare/Makefile | 3 + poincare/include/poincare.h | 2 + .../include/poincare/bracket_layout_node.h | 41 +++++ .../poincare/left_parenthesis_layout_node.h | 37 ++++ .../poincare/parenthesis_layout_node.h | 36 ++++ .../poincare/right_parenthesis_layout_node.h | 37 ++++ poincare/src/bracket_layout_node.cpp | 161 ++++++++++++++++++ poincare/src/left_parenthesis_layout_node.cpp | 57 +++++++ .../src/right_parenthesis_layout_node.cpp | 64 +++++++ poincare/src/vertical_offset_layout_node.cpp | 19 ++- 10 files changed, 449 insertions(+), 8 deletions(-) create mode 100644 poincare/include/poincare/bracket_layout_node.h create mode 100644 poincare/include/poincare/left_parenthesis_layout_node.h create mode 100644 poincare/include/poincare/parenthesis_layout_node.h create mode 100644 poincare/include/poincare/right_parenthesis_layout_node.h create mode 100644 poincare/src/bracket_layout_node.cpp create mode 100644 poincare/src/left_parenthesis_layout_node.cpp create mode 100644 poincare/src/right_parenthesis_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index b46e58a1e..efd604b53 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -8,13 +8,16 @@ objs += $(addprefix poincare/src/,\ ) objs += $(addprefix poincare/src/,\ + bracket_layout_node.o\ char_layout_node.o\ empty_layout_node.o\ horizontal_layout_node.o\ layout_cursor.o\ layout_node.o\ layout_reference.o\ + left_parenthesis_layout_node.o\ product_layout_node.o\ + right_parenthesis_layout_node.o\ sequence_layout_node.o\ sum_layout_node.o\ vertical_offset_layout_node.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 1b714e32a..3808623b4 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/bracket_layout_node.h b/poincare/include/poincare/bracket_layout_node.h new file mode 100644 index 000000000..3b3272524 --- /dev/null +++ b/poincare/include/poincare/bracket_layout_node.h @@ -0,0 +1,41 @@ +#ifndef POINCARE_BRACKET_LAYOUT_NODE_H +#define POINCARE_BRACKET_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class BracketLayoutNode : public LayoutNode { +public: + BracketLayoutNode() : + LayoutNode(), + m_childHeightComputed(false), + m_childHeight(0) + {} + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void invalidAllSizesPositionsAndBaselines() override; + + // TreeNode + size_t size() const override { return sizeof(BracketLayoutNode); } + int numberOfChildren() const override { return 0; } +#if TREE_LOG + const char * description() const override { return "BracketLayout"; } +#endif + +protected: + // LayoutNode + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override; + KDCoordinate childHeight(); + void computeChildHeight(); + bool m_childHeightComputed; + uint16_t m_childHeight; +}; +} + +#endif diff --git a/poincare/include/poincare/left_parenthesis_layout_node.h b/poincare/include/poincare/left_parenthesis_layout_node.h new file mode 100644 index 000000000..e1154b748 --- /dev/null +++ b/poincare/include/poincare/left_parenthesis_layout_node.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_LEFT_PARENTHESIS_LAYOUT_NODE_H +#define POINCARE_LEFT_PARENTHESIS_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class LeftParenthesisLayoutNode : public ParenthesisLayoutNode { +//TODO friend class BinomialCoefficientLayout; + friend class SequenceLayoutNode; +public: + using ParenthesisLayoutNode::ParenthesisLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '('); + } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; + bool isLeftParenthesis() const override { return true; } + // TreeNode + size_t size() const override { return sizeof(LeftParenthesisLayoutNode); } +#if TREE_LOG + const char * description() const override { return "Left parenthesis"; } +#endif + +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +class LeftParenthesisLayoutRef : public LayoutReference { +public: + LeftParenthesisLayoutRef(TreeNode * n) : LayoutReference(n) {} + LeftParenthesisLayoutRef() : LayoutReference() {} +}; + +} + +#endif diff --git a/poincare/include/poincare/parenthesis_layout_node.h b/poincare/include/poincare/parenthesis_layout_node.h new file mode 100644 index 000000000..8ef390bc1 --- /dev/null +++ b/poincare/include/poincare/parenthesis_layout_node.h @@ -0,0 +1,36 @@ +#ifndef POINCARE_PARENTHESIS_LAYOUT_NODE_H +#define POINCARE_PARENTHESIS_LAYOUT_NODE_H + +#include + +namespace Poincare { + +class ParenthesisLayoutNode : public BracketLayoutNode { +public: + using BracketLayoutNode::BracketLayoutNode; + constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; } + constexpr static KDCoordinate k_parenthesisCurveWidth = 5; + constexpr static KDCoordinate k_parenthesisCurveHeight = 7; + constexpr static KDCoordinate k_externWidthMargin = 1; + constexpr static KDCoordinate k_externHeightMargin = 2; + constexpr static KDCoordinate k_widthMargin = 5; + constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_verticalMargin = 4; + + // TreeNode + size_t size() const override { return sizeof(ParenthesisLayoutNode); } +#if TREE_LOG + const char * description() const override { return "ParenthesisLayout"; } +#endif + +protected: + KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; + void computeSize() override { + m_frame.setSize(KDSize(parenthesisWidth(), childHeight() + k_verticalMargin)); + m_sized = true; + } +}; + +} + +#endif diff --git a/poincare/include/poincare/right_parenthesis_layout_node.h b/poincare/include/poincare/right_parenthesis_layout_node.h new file mode 100644 index 000000000..7b63425ee --- /dev/null +++ b/poincare/include/poincare/right_parenthesis_layout_node.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_RIGHT_PARENTHESIS_LAYOUT_NODE_H +#define POINCARE_RIGHT_PARENTHESIS_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class RightParenthesisLayoutNode : public ParenthesisLayoutNode { +//TODO friend class BinomialCoefficientLayout; + friend class SequenceLayoutNode; +public: + using ParenthesisLayoutNode::ParenthesisLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ')'); + } + bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override; + bool isRightParenthesis() const override { return true; } + // TreeNode + size_t size() const override { return sizeof(RightParenthesisLayoutNode); } +#if TREE_LOG + const char * description() const override { return "Right parenthesis"; } +#endif + +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +class RightParenthesisLayoutRef : public LayoutReference { +public: + RightParenthesisLayoutRef(TreeNode * n) : LayoutReference(n) {} + RightParenthesisLayoutRef() : LayoutReference() {} +}; + +} + +#endif diff --git a/poincare/src/bracket_layout_node.cpp b/poincare/src/bracket_layout_node.cpp new file mode 100644 index 000000000..6dc57306d --- /dev/null +++ b/poincare/src/bracket_layout_node.cpp @@ -0,0 +1,161 @@ +#include +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +static inline KDCoordinate max(KDCoordinate x, KDCoordinate y) { return (x>y ? x : y); } + +void BracketLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->layoutReference() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Go Left. + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left. Ask the parent. + LayoutNode * parentLayout = parent(); + if (parentLayout) { + parentLayout->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void BracketLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + assert(cursor->layoutReference() == this); + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Go Right. + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // Case: Right. Ask the parent. + LayoutNode * parentLayout = parent(); + if (parentLayout) { + parentLayout->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +void BracketLayoutNode::invalidAllSizesPositionsAndBaselines() { + m_childHeightComputed = false; + LayoutNode::invalidAllSizesPositionsAndBaselines(); +} + +void BracketLayoutNode::computeBaseline() { + LayoutNode * parentLayout = parent(); + assert(parentLayout != nullptr); + int idxInParent = parentLayout->indexOfChild(this); + int numberOfSiblings = parentLayout->numberOfChildren(); + if (((isLeftParenthesis() || isLeftBracket()) && idxInParent == numberOfSiblings - 1) + || ((isRightParenthesis() || isRightBracket()) && idxInParent == 0) + || ((isLeftParenthesis() || isLeftBracket()) && idxInParent < numberOfSiblings - 1 && parentLayout->childAtIndex(idxInParent + 1)->isVerticalOffset())) + { + /* The bracket does not have siblings on its open direction, or it is a left + * bracket that is base of a superscript layout. In the latter case, it + * should have a default baseline, else it creates an infinite loop as the + * bracket needs the superscript baseline, which needs the bracket baseline.*/ + m_baseline = layoutSize().height()/2; + m_baselined = true; + return; + } + + int currentNumberOfOpenBrackets = 1; + m_baseline = 0; + int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1; + for (int i = idxInParent + increment; i >= 0 && i < numberOfSiblings; i+=increment) { + LayoutNode * sibling = parentLayout->childAtIndex(i); + if ((isLeftParenthesis() && sibling->isRightParenthesis()) + || (isLeftBracket() && sibling->isRightBracket()) + || (isRightParenthesis() && sibling->isLeftParenthesis()) + || (isRightBracket() && sibling->isLeftBracket())) + { + if (i == idxInParent + increment) { + /* If the bracket is immediately closed, we set the baseline to half the + * bracket height. */ + m_baseline = layoutSize().height()/2; + m_baselined = true; + return; + } + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isLeftParenthesis() && sibling->isLeftParenthesis()) + || (isLeftBracket() && sibling->isLeftBracket()) + || (isRightParenthesis() && sibling->isRightParenthesis()) + || (isRightBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets++; + } + m_baseline = max(m_baseline, sibling->baseline()); + } + m_baseline += (layoutSize().height() - childHeight()) / 2; + m_baselined = true; +} + +KDCoordinate BracketLayoutNode::childHeight() { + if (!m_childHeightComputed) { + computeChildHeight(); + } + return m_childHeight; +} + +void BracketLayoutNode::computeChildHeight() { + LayoutNode * parentLayout = parent(); + assert(parentLayout != nullptr); + m_childHeight = Metric::MinimalBracketAndParenthesisHeight; + int idxInParent = parentLayout->indexOfChild(this); + int numberOfSiblings = parentLayout->numberOfChildren(); + if ((isLeftParenthesis() || isLeftBracket()) + && idxInParent < numberOfSiblings - 1 + && parentLayout->childAtIndex(idxInParent + 1)->isVerticalOffset()) + { + /* If a left bracket is the base of a superscript layout, it should have a + * a default height, else it creates an infinite loop because the bracket + * needs the superscript height, which needs the bracket height. */ + m_childHeightComputed = true; + return; + } + + KDCoordinate maxUnderBaseline = 0; + KDCoordinate maxAboveBaseline = 0; + + int currentNumberOfOpenBrackets = 1; + int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1; + for (int i = idxInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) { + LayoutNode * sibling = parentLayout->childAtIndex(i); + if ((isLeftParenthesis() && sibling->isRightParenthesis()) + || (isLeftBracket() && sibling->isRightBracket()) + || (isRightParenthesis() && sibling->isLeftParenthesis()) + || (isRightBracket() && sibling->isLeftBracket())) + { + currentNumberOfOpenBrackets--; + if (currentNumberOfOpenBrackets == 0) { + break; + } + } else if ((isLeftParenthesis() && sibling->isLeftParenthesis()) + || (isLeftBracket() && sibling->isLeftBracket()) + || (isRightParenthesis() && sibling->isRightParenthesis()) + || (isRightBracket() && sibling->isRightBracket())) + { + currentNumberOfOpenBrackets++; + } + KDCoordinate siblingHeight = sibling->layoutSize().height(); + KDCoordinate siblingBaseline = sibling->baseline(); + maxUnderBaseline = max(maxUnderBaseline, siblingHeight - siblingBaseline); + maxAboveBaseline = max(maxAboveBaseline, siblingBaseline); + } + m_childHeight = max(m_childHeight, maxUnderBaseline + maxAboveBaseline); + m_childHeightComputed = true; + +} + +KDPoint BracketLayoutNode::positionOfChild(LayoutNode * child) { + assert(false); + return KDPointZero; +} + +} diff --git a/poincare/src/left_parenthesis_layout_node.cpp b/poincare/src/left_parenthesis_layout_node.cpp new file mode 100644 index 000000000..d3b666e9c --- /dev/null +++ b/poincare/src/left_parenthesis_layout_node.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +namespace Poincare { + +const uint8_t topLeftCurve[ParenthesisLayoutNode::k_parenthesisCurveHeight][ParenthesisLayoutNode::k_parenthesisCurveWidth] = { + {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, + {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, + {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, + {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, + {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, + {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, + {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, +}; + +const uint8_t bottomLeftCurve[ParenthesisLayoutNode::k_parenthesisCurveHeight][ParenthesisLayoutNode::k_parenthesisCurveWidth] = { + {0x11, 0xEE, 0xFF, 0xFF, 0xFF}, + {0x45, 0xBE, 0xFF, 0xFF, 0xFF}, + {0xA9, 0x5A, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x49, 0xB6, 0xFF, 0xFF}, + {0xFF, 0xF2, 0x40, 0xBF, 0xFF}, + {0xFF, 0xFF, 0xEB, 0x40, 0x9A}, + {0xFF, 0xFF, 0xFF, 0xF9, 0x66}, +}; + +bool LeftParenthesisLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis == 0 && goingLeft) { + return false; + } + *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis - 1 : *numberOfOpenParenthesis + 1; + return true; +} + +void LeftParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + KDRect frame(p.x()+ParenthesisLayoutNode::k_externWidthMargin, + p.y()+ParenthesisLayoutNode::k_externHeightMargin, + ParenthesisLayoutNode::k_parenthesisCurveWidth, + ParenthesisLayoutNode::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLayoutNode::s_parenthesisWorkingBuffer)); + + frame = KDRect(p.x()+ParenthesisLayoutNode::k_externWidthMargin, + p.y() + layoutSize().height() - ParenthesisLayoutNode::k_parenthesisCurveHeight - ParenthesisLayoutNode::k_externHeightMargin, + ParenthesisLayoutNode::k_parenthesisCurveWidth, + ParenthesisLayoutNode::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomLeftCurve, (KDColor *)(ParenthesisLayoutNode::s_parenthesisWorkingBuffer)); + + ctx->fillRect(KDRect(p.x()+ParenthesisLayoutNode::k_externWidthMargin, + p.y()+ParenthesisLayoutNode::k_parenthesisCurveHeight+ParenthesisLayoutNode::k_externHeightMargin, + ParenthesisLayoutNode::k_lineThickness, + layoutSize().height() - 2*(ParenthesisLayoutNode::k_parenthesisCurveHeight+ParenthesisLayoutNode::k_externHeightMargin)), + expressionColor); +} + +} diff --git a/poincare/src/right_parenthesis_layout_node.cpp b/poincare/src/right_parenthesis_layout_node.cpp new file mode 100644 index 000000000..6ec3661a4 --- /dev/null +++ b/poincare/src/right_parenthesis_layout_node.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +namespace Poincare { + +const uint8_t topRightCurve[ParenthesisLayoutNode::k_parenthesisCurveHeight][ParenthesisLayoutNode::k_parenthesisCurveWidth] = { + {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, + {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, + {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, + {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, + {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, + {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, +}; + +const uint8_t bottomRightCurve[ParenthesisLayoutNode::k_parenthesisCurveHeight][ParenthesisLayoutNode::k_parenthesisCurveWidth] = { + {0xFF, 0xFF, 0xFF, 0xEE, 0x11}, + {0xFF, 0xFF, 0xFF, 0xBE, 0x45}, + {0xFF, 0xFF, 0xFF, 0x5A, 0xA9}, + {0xFF, 0xFF, 0xB6, 0x49, 0xFF}, + {0xFF, 0xBF, 0x40, 0xF2, 0xFF}, + {0x9A, 0x40, 0xEB, 0xFF, 0xFF}, + {0x66, 0xF9, 0xFF, 0xFF, 0xFF}, +}; + +bool RightParenthesisLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { + if (*numberOfOpenParenthesis == 0 && !goingLeft) { + return false; + } + *numberOfOpenParenthesis = goingLeft ? *numberOfOpenParenthesis + 1 : *numberOfOpenParenthesis - 1; + return true; +} + +void RightParenthesisLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + KDRect frame = KDRect(p.x() + ParenthesisLayoutNode::k_widthMargin + ParenthesisLayoutNode::k_lineThickness - ParenthesisLayoutNode::k_parenthesisCurveWidth, + p.y() + ParenthesisLayoutNode::k_externHeightMargin, + ParenthesisLayoutNode::k_parenthesisCurveWidth, + ParenthesisLayoutNode::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLayoutNode::s_parenthesisWorkingBuffer)); + + frame = KDRect(p.x() + ParenthesisLayoutNode::k_widthMargin + ParenthesisLayoutNode::k_lineThickness - ParenthesisLayoutNode::k_parenthesisCurveWidth, + p.y() + layoutSize().height() - ParenthesisLayoutNode::k_parenthesisCurveHeight - ParenthesisLayoutNode::k_externHeightMargin, + ParenthesisLayoutNode::k_parenthesisCurveWidth, + ParenthesisLayoutNode::k_parenthesisCurveHeight); + + ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)bottomRightCurve, (KDColor *)(ParenthesisLayoutNode::s_parenthesisWorkingBuffer)); + + ctx->fillRect(KDRect(p.x()+ParenthesisLayoutNode::k_widthMargin, + p.y()+ParenthesisLayoutNode::k_parenthesisCurveHeight+2, + ParenthesisLayoutNode::k_lineThickness, + layoutSize().height() - 2*(ParenthesisLayoutNode::k_parenthesisCurveHeight+ParenthesisLayoutNode::k_externHeightMargin)), + expressionColor); +} + +} + + + + + + + diff --git a/poincare/src/vertical_offset_layout_node.cpp b/poincare/src/vertical_offset_layout_node.cpp index fcbf20014..2a866308a 100644 --- a/poincare/src/vertical_offset_layout_node.cpp +++ b/poincare/src/vertical_offset_layout_node.cpp @@ -1,8 +1,8 @@ #include #include #include -//TODO #include "left_parenthesis_layout.h" -//TODO #include "right_parenthesis_layout.h" +#include +#include #include #include #include @@ -242,29 +242,32 @@ bool VerticalOffsetLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode VerticalOffsetLayoutNode * verticalOffsetSibling = static_cast(sibling); if (verticalOffsetSibling->type() == Type::Superscript) { LayoutNode * parentNode = parent(); + LayoutRef parentRef = LayoutRef(parentNode); assert(parentNode->isHorizontal()); // Add the Left parenthesis int idxInParent = parentNode->indexOfChild(this); int leftParenthesisIndex = idxInParent; - //TODO LeftParenthesisLayout * leftParenthesis = new LeftParenthesisLayout(); + LeftParenthesisLayoutRef leftParenthesis = LeftParenthesisLayoutRef(); int numberOfOpenParenthesis = 0; while (leftParenthesisIndex > 0 && parentNode->childAtIndex(leftParenthesisIndex-1)->isCollapsable(&numberOfOpenParenthesis, true)) { leftParenthesisIndex--; } - //TODO parentNode->addChildAtIndex(leftParenthesis, leftParenthesisIndex); + parentRef.addChildAtIndex(leftParenthesis, leftParenthesisIndex, nullptr); idxInParent++; // Add the Right parenthesis - //TODO RightParenthesisLayout * rightParenthesis = new RightParenthesisLayout(); + RightParenthesisLayoutRef rightParenthesis = RightParenthesisLayoutRef(); if (cursor->position() == LayoutCursor::Position::Right) { - //TODO parentNode->addChildAtIndex(rightParenthesis, idxInParent + 1); + parentRef.addChildAtIndex(rightParenthesis, idxInParent + 1, nullptr); } else { assert(cursor->position() == LayoutCursor::Position::Left); - //TODO parentNode->addChildAtIndex(rightParenthesis, idxInParent); + parentRef.addChildAtIndex(rightParenthesis, idxInParent, nullptr); + } + if (rightParenthesis.parent().isDefined()) { + cursor->setLayoutReference(rightParenthesis); } - //TODOcursor->setLayoutNode(rightParenthesis); } } return true; From d7a8ca4093299f169eecf7bbe8b14243ca555232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 16:36:45 +0200 Subject: [PATCH 148/156] [poincare] Fix layout cloning (invalidate memoized data) --- poincare/include/poincare/layout_reference.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index d65981e6f..5b467dc35 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -15,7 +15,9 @@ public: using SerializableReference::SerializableReference; LayoutReference clone() const { - return LayoutReference(this->treeClone().node()); + LayoutReference result = LayoutReference(this->treeClone().node()); + result.invalidAllSizesPositionsAndBaselines(); + return result; } // Operators From 21c832b558d17812e443d8fb126ec08b1284c507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 16:37:54 +0200 Subject: [PATCH 149/156] [poincare] Use parenthesis in SequenceLayoutNode --- poincare/src/sequence_layout_node.cpp | 42 +++++++++++---------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/poincare/src/sequence_layout_node.cpp b/poincare/src/sequence_layout_node.cpp index 0abbb0ade..d5d01d53c 100644 --- a/poincare/src/sequence_layout_node.cpp +++ b/poincare/src/sequence_layout_node.cpp @@ -1,8 +1,8 @@ #include #include #include -/*#include "left_parenthesis_layout.h" -#include "right_parenthesis_layout.h" TODO*/ +#include +#include #include namespace Poincare { @@ -127,14 +127,9 @@ void SequenceLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { void SequenceLayoutNode::computeSize() { KDSize lowerBoundSizeWithNEquals = HorizontalLayoutRef(CharLayoutRef('n'), CharLayoutRef('='), LayoutRef(lowerBoundLayout()).clone()).layoutSize(); - - - //TODO LeftParenthesisLayoutRef dummyLeftParenthesis; - //RightParenthesisLayoutRef dummyRightParenthesis; - //HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis); - HorizontalLayoutRef dummyLayout2(LayoutRef(argumentLayout()).clone()); - - + LeftParenthesisLayoutRef dummyLeftParenthesis; + RightParenthesisLayoutRef dummyRightParenthesis; + HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis); KDSize dummyLayoutSize = dummyLayout2.layoutSize(); KDSize upperBoundSize = upperBoundLayout()->layoutSize(); KDSize result = KDSize( @@ -156,14 +151,8 @@ KDPoint SequenceLayoutNode::positionOfChild(LayoutNode * l) { HorizontalLayoutRef dummyLayout1(CharLayoutRef('n'), CharLayoutRef('='), lowerBoundClone); KDSize lowerBoundSizeWithNEquals = dummyLayout1.layoutSize(); KDSize upperBoundSize = upperBoundLayout()->layoutSize(); - - - /* TODO LeftParenthesisLayoutRef dummyLeftParenthesis; - HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone());*/ - HorizontalLayoutRef dummyLayout2(LayoutRef(argumentLayout()).clone()); - - - + LeftParenthesisLayoutRef dummyLeftParenthesis; + HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone()); KDCoordinate x = 0; KDCoordinate y = 0; if (l == lowerBoundLayout()) { @@ -175,7 +164,7 @@ KDPoint SequenceLayoutNode::positionOfChild(LayoutNode * l) { x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSizeWithNEquals.width()-upperBoundSize.width())/2); y = baseline() - (k_symbolHeight+1)/2- k_boundHeightMargin-upperBoundSize.height(); } else if (l == argumentLayout()) { - x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin;// TODO+dummyLeftParenthesis.layoutSize().width(); + x = max(max(k_symbolWidth, lowerBoundSizeWithNEquals.width()), upperBoundSize.width())+k_argumentWidthMargin+dummyLeftParenthesis.layoutSize().width(); y = baseline() - argumentLayout()->baseline(); } else { assert(false); @@ -233,13 +222,16 @@ void SequenceLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionCo ctx->drawString("n=", p.translatedBy(nEqualsPosition), dummyN.fontSize(), expressionColor, backgroundColor); // Render the parentheses - /* TODO LeftParenthesisLayoutRef dummyLeftParenthesis; + LeftParenthesisLayoutRef dummyLeftParenthesis; RightParenthesisLayoutRef dummyRightParenthesis; - HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis, false); - KDPoint leftParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); - KDPoint rightParenthesisPoint = positionOfChild(argumentLayout()).translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)).translatedBy(dummyLayout2.positionOfChild(dummyLayout2.editableChild(1)).opposite()); - dummyLeftParenthesis.render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); - dummyRightParenthesis.render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor);*/ + HorizontalLayoutRef dummyLayout2(dummyLeftParenthesis, LayoutRef(argumentLayout()).clone(), dummyRightParenthesis); + KDPoint positionOfArg = positionOfChild(argumentLayout()); + KDPoint oppositeDummyPositionOfArg = dummyLayout2.positionOfChild(dummyLayout2.childAtIndex(1)).opposite(); + KDPoint startOfParenthesis = positionOfArg.translatedBy(oppositeDummyPositionOfArg); + KDPoint leftParenthesisPoint = startOfParenthesis.translatedBy(dummyLayout2.positionOfChild(dummyLeftParenthesis)); + KDPoint rightParenthesisPoint = startOfParenthesis.translatedBy(dummyLayout2.positionOfChild(dummyRightParenthesis)); + dummyLeftParenthesis.typedNode()->render(ctx, p.translatedBy(leftParenthesisPoint), expressionColor, backgroundColor); + dummyRightParenthesis.typedNode()->render(ctx, p.translatedBy(rightParenthesisPoint), expressionColor, backgroundColor); } } From 1b3ebedc18c71a468de97ad2622814aeaa9d57c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Jul 2018 18:06:31 +0200 Subject: [PATCH 150/156] [poincare] Add bracket layout and its derivates --- poincare/Makefile | 3 + poincare/include/poincare.h | 7 + .../poincare/absolute_value_layout_node.h | 37 +++++ .../poincare/bracket_pair_layout_node.h | 52 +++++++ .../include/poincare/ceiling_layout_node.h | 32 +++++ poincare/include/poincare/floor_layout_node.h | 33 +++++ .../include/poincare/horizontal_layout_node.h | 2 +- poincare/include/poincare/layout_node.h | 8 +- poincare/include/poincare/layout_reference.h | 12 +- .../left_square_bracket_layout_node.h | 33 +++++ .../right_square_bracket_layout_node.h | 34 +++++ .../poincare/square_bracket_layout_node.h | 23 +++ poincare/include/poincare/tree_node.h | 1 + poincare/include/poincare/tree_pool.h | 2 +- poincare/src/absolute_value.cpp | 4 +- poincare/src/bracket_pair_layout_node.cpp | 134 ++++++++++++++++++ poincare/src/floor_layout.cpp | 10 ++ poincare/src/horizontal_layout_node.cpp | 16 ++- poincare/src/layout_reference.cpp | 22 +++ .../src/left_square_bracket_layout_node.cpp | 11 ++ .../src/right_square_bracket_layout_node.cpp | 11 ++ 21 files changed, 467 insertions(+), 20 deletions(-) create mode 100644 poincare/include/poincare/absolute_value_layout_node.h create mode 100644 poincare/include/poincare/bracket_pair_layout_node.h create mode 100644 poincare/include/poincare/ceiling_layout_node.h create mode 100644 poincare/include/poincare/floor_layout_node.h create mode 100644 poincare/include/poincare/left_square_bracket_layout_node.h create mode 100644 poincare/include/poincare/right_square_bracket_layout_node.h create mode 100644 poincare/include/poincare/square_bracket_layout_node.h create mode 100644 poincare/src/bracket_pair_layout_node.cpp create mode 100644 poincare/src/floor_layout.cpp create mode 100644 poincare/src/left_square_bracket_layout_node.cpp create mode 100644 poincare/src/right_square_bracket_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index efd604b53..e787bc2f4 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -9,6 +9,7 @@ objs += $(addprefix poincare/src/,\ objs += $(addprefix poincare/src/,\ bracket_layout_node.o\ + bracket_pair_layout_node.o\ char_layout_node.o\ empty_layout_node.o\ horizontal_layout_node.o\ @@ -16,8 +17,10 @@ objs += $(addprefix poincare/src/,\ layout_node.o\ layout_reference.o\ left_parenthesis_layout_node.o\ + left_square_bracket_layout_node.o\ product_layout_node.o\ right_parenthesis_layout_node.o\ + right_square_bracket_layout_node.o\ sequence_layout_node.o\ sum_layout_node.o\ vertical_offset_layout_node.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 3808623b4..2816e89df 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -4,14 +4,17 @@ #define MATRICES_ARE_DEFINED 1 #include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -35,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -74,11 +79,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/absolute_value_layout_node.h b/poincare/include/poincare/absolute_value_layout_node.h new file mode 100644 index 000000000..798ae8106 --- /dev/null +++ b/poincare/include/poincare/absolute_value_layout_node.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_ABSOLUTE_VALUE_LAYOUT_NODE_H +#define POINCARE_ABSOLUTE_VALUE_LAYOUT_NODE_H + +#include + +namespace Poincare { + +class AbsoluteValueLayoutNode : public BracketPairLayoutNode { +public: + using BracketPairLayoutNode::BracketPairLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "abs"); + } + // TreeNode + size_t size() const override { return sizeof(AbsoluteValueLayoutNode); } +#if TREE_LOG + const char * description() const override { return "AbsoluteValueLayout"; } +#endif + +private: + KDCoordinate widthMargin() const override { return 2; } + virtual KDCoordinate verticalExternMargin() const override { return 1; } + bool renderTopBar() const override { return false; } + bool renderBottomBar() const override { return false; } +}; + +class AbsoluteValueLayoutRef : public LayoutReference { +public: + AbsoluteValueLayoutRef(TreeNode * n) : LayoutReference(n) {} + AbsoluteValueLayoutRef(LayoutRef l) : LayoutReference() { + addChildTreeAtIndex(l, 0); + } +}; + +} + +#endif diff --git a/poincare/include/poincare/bracket_pair_layout_node.h b/poincare/include/poincare/bracket_pair_layout_node.h new file mode 100644 index 000000000..04eb41121 --- /dev/null +++ b/poincare/include/poincare/bracket_pair_layout_node.h @@ -0,0 +1,52 @@ +#ifndef POINCARE_BRACKET_PAIR_LAYOUT_NODE_H +#define POINCARE_BRACKET_PAIR_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class BracketPairLayoutNode : public LayoutNode { + //TODO friend class MatrixLayout; +public: + using LayoutNode::LayoutNode; + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void deleteBeforeCursor(LayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool shouldCollapseSiblingsOnRight() const override{ return true; } + void didCollapseSiblings(LayoutCursor * cursor) override; + + // TreeNode + size_t size() const override { return sizeof(BracketPairLayoutNode); } + int numberOfChildren() const override { return 1; } +#if TREE_LOG + const char * description() const override { return "BracketPairLayout"; } +#endif + +protected: + // LayoutNode + void computeBaseline() override; + void computeSize() override; + KDPoint positionOfChild(LayoutNode * child) override; + LayoutNode * childLayout() { return childAtIndex(0); } + +private: + KDCoordinate externWidthMargin() const { return 2; } + virtual KDCoordinate widthMargin() const { return 5; } + virtual KDCoordinate verticalExternMargin() const { return 0; } + constexpr static KDCoordinate k_bracketWidth = 5; + constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_verticalMargin = 1; + virtual bool renderTopBar() const { return true; } + virtual bool renderBottomBar() const { return true; } + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +} + +#endif + diff --git a/poincare/include/poincare/ceiling_layout_node.h b/poincare/include/poincare/ceiling_layout_node.h new file mode 100644 index 000000000..3f7f648a3 --- /dev/null +++ b/poincare/include/poincare/ceiling_layout_node.h @@ -0,0 +1,32 @@ +#ifndef POINCARE_CEILING_LAYOUT_NODE_H +#define POINCARE_CEILING_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class CeilingLayoutNode : public BracketPairLayoutNode { +public: + using BracketPairLayoutNode::BracketPairLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "ceil"); + } + // TreeNode + size_t size() const override { return sizeof(CeilingLayoutNode); } +#if TREE_LOG + const char * description() const override { return "CeilingLayout"; } +#endif + +protected: + bool renderBottomBar() const override { return false; } +}; + +class CeilingLayoutRef : public LayoutReference { +public: + using LayoutReference::LayoutReference; +}; + +} + +#endif diff --git a/poincare/include/poincare/floor_layout_node.h b/poincare/include/poincare/floor_layout_node.h new file mode 100644 index 000000000..f9499617d --- /dev/null +++ b/poincare/include/poincare/floor_layout_node.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_FLOOR_LAYOUT_NODE_H +#define POINCARE_FLOOR_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class FloorLayoutNode : public BracketPairLayoutNode { +public: + using BracketPairLayoutNode::BracketPairLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "floor"); + } + + // TreeNode + size_t size() const override { return sizeof(FloorLayoutNode); } +#if TREE_LOG + const char * description() const override { return "FloorLayout"; } +#endif + +protected: + bool renderTopBar() const override { return false; } +}; + +class FloorLayoutRef : public LayoutReference { +public: + using LayoutReference::LayoutReference; +}; + +} + +#endif diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 67a826e50..923f63061 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -89,7 +89,7 @@ public: void addOrMergeChildAtIndex(LayoutRef l, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); void mergeChildrenAtIndex(HorizontalLayoutRef h, int index, bool removeEmptyChildren, LayoutCursor * cursor = nullptr); private: - int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft); + int removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft, LayoutCursor * cursor = nullptr); }; } diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index c853cab93..c2d28d0fe 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -58,8 +58,12 @@ public: // Tree modification // Collapse - virtual bool shouldCollapseSiblingsOnLeft() { return false; } - virtual bool shouldCollapseSiblingsOnRight() { return false; } + virtual bool shouldCollapseSiblingsOnLeft() const { return false; } + virtual bool shouldCollapseSiblingsOnRight() const { return false; } + virtual int leftCollapsingAbsorbingChildIndex() const { return 0; } + virtual int rightCollapsingAbsorbingChildIndex() const { return 0; } + virtual void didCollapseSiblings(LayoutCursor * cursor) {} + // User input virtual void deleteBeforeCursor(LayoutCursor * cursor); diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 5b467dc35..2975b3d8d 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -53,6 +53,8 @@ public: bool isVerticalOffset() const { return this->typedNode()->isVerticalOffset(); } bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); } bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return this->typedNode()->isCollapsable(numberOfOpenParenthesis, goingLeft); } + int leftCollapsingAbsorbingChildIndex() const { return this->typedNode()->leftCollapsingAbsorbingChildIndex(); } + int rightCollapsingAbsorbingChildIndex() const { return this->typedNode()->rightCollapsingAbsorbingChildIndex(); } bool hasText() { return this->typedNode()->hasText(); } char XNTChar() const { return this->typedNode()->XNTChar(); } @@ -95,15 +97,7 @@ public: return removeChild(childAtIndex(index), cursor, force); } // Collapse - void collapseSiblings(LayoutCursor * cursor) { - int absorbingChildIndex = 0; //TODO - if (this->typedNode()->shouldCollapseSiblingsOnRight()) { - collapseOnDirection(HorizontalDirection::Right, absorbingChildIndex); - } - if (this->typedNode()->shouldCollapseSiblingsOnLeft()) { - collapseOnDirection(HorizontalDirection::Left, absorbingChildIndex); - } - } + void collapseSiblings(LayoutCursor * cursor); // Allocation failure static TreeNode * FailedAllocationStaticNode(); diff --git a/poincare/include/poincare/left_square_bracket_layout_node.h b/poincare/include/poincare/left_square_bracket_layout_node.h new file mode 100644 index 000000000..0f5921b20 --- /dev/null +++ b/poincare/include/poincare/left_square_bracket_layout_node.h @@ -0,0 +1,33 @@ +#ifndef POINCARE_LEFT_SQUARE_BRACKET_LAYOUT_NODE_H +#define POINCARE_LEFT_SQUARE_BRACKET_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class LeftSquareBracketLayoutNode : public SquareBracketLayoutNode { +public: + using SquareBracketLayoutNode::SquareBracketLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, '['); + } + bool isLeftBracket() const override { return true; } + + // TreeNode + size_t size() const override { return sizeof(LeftSquareBracketLayoutNode); } +#if TREE_LOG + const char * description() const override { return "LeftSquareBracketLayout"; } +#endif +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +class LeftSquareBracketLayoutRef : public LayoutReference { +public: + using LayoutReference::LayoutReference; +}; + +} + +#endif diff --git a/poincare/include/poincare/right_square_bracket_layout_node.h b/poincare/include/poincare/right_square_bracket_layout_node.h new file mode 100644 index 000000000..e764a364a --- /dev/null +++ b/poincare/include/poincare/right_square_bracket_layout_node.h @@ -0,0 +1,34 @@ +#ifndef POINCARE_RIGHT_SQUARE_BRACKET_LAYOUT_NODE_H +#define POINCARE_RIGHT_SQUARE_BRACKET_LAYOUT_NODE_H + +#include +#include + +namespace Poincare { + +class RightSquareBracketLayoutNode : public SquareBracketLayoutNode { +public: + using SquareBracketLayoutNode::SquareBracketLayoutNode; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override { + return LayoutEngine::writeOneCharInBuffer(buffer, bufferSize, ']'); + } + bool isRightBracket() const override { return true; } + + // TreeNode + size_t size() const override { return sizeof(RightSquareBracketLayoutNode); } +#if TREE_LOG + const char * description() const override { return "RightSquareBracketLayout"; } +#endif + +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; +}; + +class RightSquareBracketLayoutRef : public LayoutReference { +public: + using LayoutReference::LayoutReference; +}; + +} + +#endif diff --git a/poincare/include/poincare/square_bracket_layout_node.h b/poincare/include/poincare/square_bracket_layout_node.h new file mode 100644 index 000000000..86400ae14 --- /dev/null +++ b/poincare/include/poincare/square_bracket_layout_node.h @@ -0,0 +1,23 @@ +#ifndef POINCARE_SQUARE_BRACKET_LAYOUT_NODE_H +#define POINCARE_SQUARE_BRACKET_LAYOUT_NODE_H + +#include "bracket_layout_node.h" + +namespace Poincare { + +class SquareBracketLayoutNode : public BracketLayoutNode { +public: + using BracketLayoutNode::BracketLayoutNode; +protected: + constexpr static KDCoordinate k_bracketWidth = 5; + constexpr static KDCoordinate k_lineThickness = 1; + constexpr static KDCoordinate k_widthMargin = 5; + constexpr static KDCoordinate k_externWidthMargin = 2; + void computeSize() override { + m_frame.setSize(KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, childHeight() + k_lineThickness)); + m_sized = true; + } +}; +} + +#endif diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 379bd0a5a..bfec1b9a9 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -12,6 +12,7 @@ * - an identifier * - a reference counter */ +#define TREE_LOG 1 namespace Poincare { diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 0d32deafc..974dbb18f 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -76,7 +76,7 @@ public: } private: - constexpr static int BufferSize = 256; + constexpr static int BufferSize = 1024;//2048; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); constexpr static int MaxNumberOfStaticNodes = 2; diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 773eac040..143fccea3 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include extern "C" { #include @@ -27,7 +27,7 @@ Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUn LayoutRef AbsoluteValue::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return CharLayoutRef('a'); //TODO + return AbsoluteValueLayoutRef(operand(0)->createLayout(floatDisplayMode, complexFormat)); } Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) { diff --git a/poincare/src/bracket_pair_layout_node.cpp b/poincare/src/bracket_pair_layout_node.cpp new file mode 100644 index 000000000..6e7c84198 --- /dev/null +++ b/poincare/src/bracket_pair_layout_node.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +void BracketPairLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (childLayout() + && cursor->layoutNode() == childLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the operand. Go Left of the brackets. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right of the brackets. Go Right of the operand. + assert(childLayout() != nullptr); + cursor->setLayoutNode(childLayout()); + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left of the brackets. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void BracketPairLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (childLayout() + && cursor->layoutNode() == childLayout() + && cursor->position() == LayoutCursor::Position::Right) + { + // Case: Right of the operand. Go Right of the brackets. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left of the brackets. Go Left of the operand. + assert(childLayout() != nullptr); + cursor->setLayoutNode(childLayout()); + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // Case: Right of the brackets. Ask the parent. + cursor->setLayoutNode(this); //TODO Remove? + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +void BracketPairLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + if (cursor->isEquivalentTo(LayoutCursor(childLayout(), LayoutCursor::Position::Left))) { + // Case: Left of the operand. Delete the layout, keep the operand. + LayoutRef(this).replaceWith(childLayout(), cursor); + // WARNING: do not call "this" afterwards + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + +void BracketPairLayoutNode::didCollapseSiblings(LayoutCursor * cursor) { + cursor->setLayoutNode(childLayout()); + cursor->setPosition(LayoutCursor::Position::Left); +} + +int BracketPairLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + + // Write the opening bracket + int numberOfChar = 0; + buffer[numberOfChar++] = '['; + if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + + // Write the argument + numberOfChar += const_cast(this)->childLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + // Write the closing bracket + buffer[numberOfChar++] = ']'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void BracketPairLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + const KDCoordinate k_widthMargin = widthMargin(); + const KDCoordinate k_externWidthMargin = externWidthMargin(); + KDSize childSize = childLayout()->layoutSize(); + KDCoordinate verticalBarHeight = childLayout()->layoutSize().height() + 2*k_verticalMargin; + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+childSize.width()+2*k_widthMargin+k_lineThickness, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); + if (renderTopBar()) { + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+childSize.width()+2*k_widthMargin-k_bracketWidth, p.y() + verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); + } + if (renderBottomBar()) { + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+childSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + } +} + +void BracketPairLayoutNode::computeSize() { + const KDCoordinate k_widthMargin = widthMargin(); + const KDCoordinate k_externWidthMargin = externWidthMargin(); + KDSize childSize = childLayout()->layoutSize(); + KDSize result = KDSize(childSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, childSize.height() + 2 * k_verticalMargin + 2*verticalExternMargin()); + m_frame.setSize(result); + m_sized = true; +} + +void BracketPairLayoutNode::computeBaseline() { + m_baseline = childLayout()->baseline() + k_verticalMargin + verticalExternMargin(); + m_baselined = true; +} + +KDPoint BracketPairLayoutNode::positionOfChild(LayoutNode * child) { + assert(child == childLayout()); + const KDCoordinate k_widthMargin = widthMargin(); //TODO ? + const KDCoordinate k_externWidthMargin = externWidthMargin(); + return KDPoint(k_widthMargin + k_externWidthMargin + k_lineThickness, k_verticalMargin + verticalExternMargin()); +} + +} diff --git a/poincare/src/floor_layout.cpp b/poincare/src/floor_layout.cpp new file mode 100644 index 000000000..598cfea39 --- /dev/null +++ b/poincare/src/floor_layout.cpp @@ -0,0 +1,10 @@ +#include "floor_layout.h" + +namespace Poincare { + +ExpressionLayout * FloorLayout::clone() const { + FloorLayout * layout = new FloorLayout(const_cast(this)->operandLayout(), true); + return layout; +} + +} diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 531a39b96..2a4b7c6f3 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -218,14 +218,20 @@ KDPoint HorizontalLayoutNode::positionOfChild(LayoutNode * l) { bool HorizontalLayoutNode::willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { if (m_numberOfChildren > 0) { - *index = HorizontalLayoutRef(this).removeEmptyChildBeforeInsertionAtIndex(*index, !childAtIndex(0)->mustHaveLeftSibling()); + *index = HorizontalLayoutRef(this).removeEmptyChildBeforeInsertionAtIndex(*index, !childAtIndex(0)->mustHaveLeftSibling(), cursor); + } return true; } bool HorizontalLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { - int childrenCount = numberOfChildren(); HorizontalLayoutRef thisRef(this); + int newChildIndex = cursor->position() == LayoutCursor::Position::Left ? 0 : numberOfChildren(); + thisRef.addChildAtIndex(sibling, newChildIndex, cursor); + return false; + + + int childrenCount = numberOfChildren(); // Add the "sibling" as a child. if (cursor->position() == LayoutCursor::Position::Left) { int indexForInsertion = 0; @@ -420,7 +426,7 @@ void HorizontalLayoutRef::mergeChildrenAtIndex(HorizontalLayoutRef h, int index, } } -int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft) { +int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool shouldRemoveOnLeft, LayoutCursor * cursor) { int currentNumberOfChildren = numberOfChildren(); assert(index >= 0 && index <= currentNumberOfChildren); int newIndex = index; @@ -429,7 +435,7 @@ int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool if (newIndex < currentNumberOfChildren) { LayoutRef c = childAtIndex(newIndex); if (c.isEmpty()) { - removeChild(c, nullptr); + removeChild(c, cursor); currentNumberOfChildren--; } } @@ -438,7 +444,7 @@ int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool if (shouldRemoveOnLeft && newIndex - 1 >= 0 && newIndex - 1 <= currentNumberOfChildren -1) { LayoutRef c = childAtIndex(newIndex - 1); if (c.isEmpty()) { - removeChild(c, nullptr, true); + removeChild(c, cursor, true); newIndex = index - 1; } } diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 18237e7be..06c5b49f8 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -217,6 +217,28 @@ void LayoutRef::collapseOnDirection(HorizontalDirection direction, int absorbing } } +/* Layout specialization, at the end of the .cpp as they must be defined after + * the definition of the methods they calls */ +template<> +void LayoutRef::collapseSiblings(LayoutCursor * cursor) { + if (this->typedNode()->shouldCollapseSiblingsOnRight()) { + LayoutReference absorbingChild = childAtIndex(rightCollapsingAbsorbingChildIndex()); + if (!absorbingChild.isHorizontal()) { + replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor); + } + collapseOnDirection(HorizontalDirection::Right, rightCollapsingAbsorbingChildIndex()); + } + if (this->typedNode()->shouldCollapseSiblingsOnLeft()) { + LayoutReference absorbingChild = childAtIndex(leftCollapsingAbsorbingChildIndex()); + if (!absorbingChild.isHorizontal()) { + replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor); + } + collapseOnDirection(HorizontalDirection::Left, leftCollapsingAbsorbingChildIndex()); + } + this->typedNode()->didCollapseSiblings(cursor); +} + + template LayoutCursor LayoutReference::cursor() const; template LayoutCursor LayoutReference::cursor() const; template void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force); diff --git a/poincare/src/left_square_bracket_layout_node.cpp b/poincare/src/left_square_bracket_layout_node.cpp new file mode 100644 index 000000000..95839baa1 --- /dev/null +++ b/poincare/src/left_square_bracket_layout_node.cpp @@ -0,0 +1,11 @@ +#include + +namespace Poincare { + +void LeftSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_lineThickness, childHeight()), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); +} + +} diff --git a/poincare/src/right_square_bracket_layout_node.cpp b/poincare/src/right_square_bracket_layout_node.cpp new file mode 100644 index 000000000..2e97b598d --- /dev/null +++ b/poincare/src/right_square_bracket_layout_node.cpp @@ -0,0 +1,11 @@ +#include + +namespace Poincare { + +void RightSquareBracketLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + ctx->fillRect(KDRect(p.x()+k_widthMargin, p.y(), k_lineThickness, childHeight()), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x()+k_widthMargin-k_bracketWidth+1, p.y() + childHeight(), k_bracketWidth, k_lineThickness), expressionColor); +} + +} From 74e8091594b7966eb5ca4c5f82ea6c8707c25d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Jul 2018 11:07:02 +0200 Subject: [PATCH 151/156] [poincare] Fix layout insertion in empty horizontal layouts --- .../poincare/allocation_failed_layout_node.h | 2 +- .../include/poincare/horizontal_layout_node.h | 2 +- poincare/include/poincare/layout_node.h | 2 +- poincare/src/horizontal_layout_node.cpp | 53 ++----------------- poincare/src/layout_node.cpp | 2 +- poincare/src/layout_reference.cpp | 2 +- 6 files changed, 9 insertions(+), 54 deletions(-) diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 75ddeaeb0..36c2fb329 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -37,7 +37,7 @@ protected: private: bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; } bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override { return false; } - bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override { return false; } + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} }; diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 923f63061..69b99e88c 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -54,7 +54,7 @@ protected: private: bool willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) override; bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; - bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor) override; + bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override; void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) override; bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index c2d28d0fe..fa585631d 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -107,7 +107,7 @@ public: virtual bool willAddChildAtIndex(LayoutNode * l, int * index, LayoutCursor * cursor) { return true; } virtual bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { return true; } virtual bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); - virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor); + virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force); virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} protected: // Tree navigation diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index 2a4b7c6f3..f5cab42b1 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -227,57 +227,12 @@ bool HorizontalLayoutNode::willAddChildAtIndex(LayoutNode * l, int * index, Layo bool HorizontalLayoutNode::willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) { HorizontalLayoutRef thisRef(this); int newChildIndex = cursor->position() == LayoutCursor::Position::Left ? 0 : numberOfChildren(); - thisRef.addChildAtIndex(sibling, newChildIndex, cursor); - return false; - - - int childrenCount = numberOfChildren(); - // Add the "sibling" as a child. - if (cursor->position() == LayoutCursor::Position::Left) { - int indexForInsertion = 0; - /* If the first child is empty, remove it before adding the layout, unless - * the new sibling needs the empty layout as a base. */ - if (childrenCount > 0 && childAtIndex(0)->isEmpty()) { - if (sibling->mustHaveLeftSibling()) { - indexForInsertion = 1; - } else { - /* We force the removal of the child even followed by a neighbourg - * requiring a left sibling as we are about to add a sibling in first - * position anyway. */ - thisRef.removeChildAtIndex(0, cursor, true); - // WARNING: do not call "this" afterwards - } - } - if (moveCursor) { - if (childrenCount > indexForInsertion) { - cursor->setLayoutReference(thisRef.childAtIndex(indexForInsertion)); - } else { - cursor->setLayoutReference(thisRef); - cursor->setPosition(LayoutCursor::Position::Right); - } - } - thisRef.addOrMergeChildAtIndex(sibling, indexForInsertion, false); - // WARNING: do not call "this" afterwards - } else { - assert(cursor->position() == LayoutCursor::Position::Right); - // If the last child is empty, remove it before adding the layout. - if (childrenCount > 0 && childAtIndex(childrenCount - 1)->isEmpty() && !sibling->mustHaveLeftSibling()) { - /* Force remove the last child. */ - thisRef.removeChildAtIndex(childrenCount - 1, cursor, true); - // WARNING: do not call "this" afterwards - childrenCount--; - } - thisRef.addOrMergeChildAtIndex(sibling, childrenCount, false); - // WARNING: do not call "this" afterwards - if (moveCursor) { - cursor->setLayoutReference(thisRef); - } - } + thisRef.addOrMergeChildAtIndex(sibling, newChildIndex, cursor); return false; } -bool HorizontalLayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { - if (numberOfChildren() == 1) { +bool HorizontalLayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) { + if (!force && numberOfChildren() == 1) { assert(childAtIndex(0) == l); LayoutNode * p = parent(); if (p != nullptr) { @@ -435,7 +390,7 @@ int HorizontalLayoutRef::removeEmptyChildBeforeInsertionAtIndex(int index, bool if (newIndex < currentNumberOfChildren) { LayoutRef c = childAtIndex(newIndex); if (c.isEmpty()) { - removeChild(c, cursor); + removeChild(c, cursor, true); currentNumberOfChildren--; } } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 509b404aa..9c86450ed 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -129,7 +129,7 @@ bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, return true; } -bool LayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor) { +bool LayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) { LayoutRef(this).replaceChildWithEmpty(l, cursor); return false; } diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index 06c5b49f8..b22669c6b 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -141,7 +141,7 @@ void LayoutRef::addSibling(LayoutCursor * cursor, LayoutReference si template void LayoutReference::removeChild(LayoutRef l, LayoutCursor * cursor, bool force) { - if (!this->typedNode()->willRemoveChild(l.typedNode(), cursor)) { + if (!this->typedNode()->willRemoveChild(l.typedNode(), cursor, force)) { return; } assert(this->hasChild(l)); From 8cffc647b7cac17edd07d0c28dd6bd2682b34505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Jul 2018 11:11:44 +0200 Subject: [PATCH 152/156] [poincare] Use Floor and Ceiling layouts --- poincare/include/poincare/ceiling_layout_node.h | 5 ++++- poincare/include/poincare/floor.h | 1 - poincare/include/poincare/floor_layout_node.h | 5 ++++- poincare/src/ceiling.cpp | 10 ++++------ poincare/src/floor.cpp | 7 +++---- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/ceiling_layout_node.h b/poincare/include/poincare/ceiling_layout_node.h index 3f7f648a3..af0ef98e2 100644 --- a/poincare/include/poincare/ceiling_layout_node.h +++ b/poincare/include/poincare/ceiling_layout_node.h @@ -24,7 +24,10 @@ protected: class CeilingLayoutRef : public LayoutReference { public: - using LayoutReference::LayoutReference; + CeilingLayoutRef(TreeNode * n) : LayoutReference(n) {} + CeilingLayoutRef(LayoutRef l) : LayoutReference() { + addChildTreeAtIndex(l, 0); + } }; } diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index c64bd8612..6df68fe9b 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -4,7 +4,6 @@ #include #include #include -#include //TODO remove namespace Poincare { diff --git a/poincare/include/poincare/floor_layout_node.h b/poincare/include/poincare/floor_layout_node.h index f9499617d..827f4ed2e 100644 --- a/poincare/include/poincare/floor_layout_node.h +++ b/poincare/include/poincare/floor_layout_node.h @@ -25,7 +25,10 @@ protected: class FloorLayoutRef : public LayoutReference { public: - using LayoutReference::LayoutReference; + FloorLayoutRef(TreeNode * n) : LayoutReference(n) {} + FloorLayoutRef(LayoutRef l) : LayoutReference() { + addChildTreeAtIndex(l, 0); + } }; } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index a3feb6b03..a7cf2176f 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -1,5 +1,5 @@ #include -#include "layout/ceiling_layout.h" +#include #include #include #include @@ -8,7 +8,6 @@ extern "C" { #include } -#include namespace Poincare { @@ -61,10 +60,9 @@ Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { } LayoutRef Ceiling::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new CeilingLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false); -*/} + return CeilingLayoutRef(m_operands[0]->createLayout(floatDisplayMode, complexFormat)); +} } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index a8302a05b..281123d2d 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -1,5 +1,5 @@ #include -#include "layout/floor_layout.h" +#include #include #include #include @@ -57,10 +57,9 @@ Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { } LayoutRef Floor::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO -/* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new FloorLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), false);*/ + return FloorLayoutRef(m_operands[0]->createLayout(floatDisplayMode, complexFormat)); } } From e273c6e863f6d0cb0e4d23a820931997fb6994da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Jul 2018 14:07:58 +0200 Subject: [PATCH 153/156] [poincare] Move FailedAllocationStaticNode implementation from Reference to Node and factorize part of code --- poincare/include/poincare/layout_reference.h | 2 -- poincare/include/poincare/tree_pool.h | 2 ++ poincare/src/layout_node.cpp | 4 +++- poincare/src/layout_reference.cpp | 11 ----------- poincare/src/tree_pool.cpp | 7 +++++++ 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index 2975b3d8d..cd9c3bc9a 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -99,8 +99,6 @@ public: // Collapse void collapseSiblings(LayoutCursor * cursor); - // Allocation failure - static TreeNode * FailedAllocationStaticNode(); private: // Tree modification enum class HorizontalDirection { diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 974dbb18f..77d97035e 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -51,6 +51,8 @@ public: return copy; } + void registerStaticNodeIfRequired(TreeNode * node); + int registerStaticNode(TreeNode * node) { int nodeID = 0; while (m_staticNodes[nodeID] != nullptr && nodeID < MaxNumberOfStaticNodes) { diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 9c86450ed..1f9a64635 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -65,7 +65,9 @@ void LayoutNode::invalidAllSizesPositionsAndBaselines() { // TreeNode TreeNode * LayoutNode::FailedAllocationStaticNode() { - return LayoutRef::FailedAllocationStaticNode(); + static AllocationFailedLayoutNode FailureNode; + TreePool::sharedPool()->registerStaticNodeIfRequired(&FailureNode); + return &FailureNode; } // Tree navigation diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index b22669c6b..ae65094bd 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -9,16 +8,6 @@ namespace Poincare { -template<> -TreeNode * LayoutRef::FailedAllocationStaticNode() { - static AllocationFailedLayoutNode FailureNode; - if (FailureNode.identifier() >= -1) { - int newIdentifier = TreePool::sharedPool()->registerStaticNode(&FailureNode); - FailureNode.rename(newIdentifier); - } - return &FailureNode; -} - // Cursor template LayoutCursor LayoutReference::cursor() const { diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 815bf05f5..ca589dd6b 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -49,6 +49,13 @@ void TreePool::logNodeForIdentifierArray() { #endif } +void TreePool::registerStaticNodeIfRequired(TreeNode * node) { + if (node->identifier() == -1) { + int newIdentifier = registerStaticNode(node); + node->rename(newIdentifier); + } +} + void TreePool::move(TreeNode * destination, TreeNode * source) { size_t moveSize = source->deepSize(); moveNodes(destination, source, moveSize); From 9112feba6cfa97418d011fbb42af15f50cb74ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Jul 2018 15:04:05 +0200 Subject: [PATCH 154/156] [poincare] NthRootLayoutNode --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/layout_cursor.h | 2 +- .../include/poincare/nth_root_layout_node.h | 85 ++++++ poincare/src/layout_cursor.cpp | 11 +- poincare/src/nth_root.cpp | 7 +- poincare/src/nth_root_layout_node.cpp | 274 ++++++++++++++++++ poincare/src/square_root.cpp | 9 +- 8 files changed, 377 insertions(+), 13 deletions(-) create mode 100644 poincare/include/poincare/nth_root_layout_node.h create mode 100644 poincare/src/nth_root_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index e787bc2f4..ca8eea061 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -18,6 +18,7 @@ objs += $(addprefix poincare/src/,\ layout_reference.o\ left_parenthesis_layout_node.o\ left_square_bracket_layout_node.o\ + nth_root_layout_node.o\ product_layout_node.o\ right_parenthesis_layout_node.o\ right_square_bracket_layout_node.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 2816e89df..8543b210b 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/layout_cursor.h b/poincare/include/poincare/layout_cursor.h index efb3d75d2..f012d640b 100644 --- a/poincare/include/poincare/layout_cursor.h +++ b/poincare/include/poincare/layout_cursor.h @@ -110,7 +110,7 @@ public: void addEmptyExponentialLayout(); void addEmptyMatrixLayout() {} //TODO void addEmptyPowerLayout(); - void addEmptySquareRootLayout() {} //TODO + void addEmptySquareRootLayout(); void addEmptySquarePowerLayout(); void addEmptyTenPowerLayout(); void addFractionLayoutAndCollapseSiblings() {} //TODO diff --git a/poincare/include/poincare/nth_root_layout_node.h b/poincare/include/poincare/nth_root_layout_node.h new file mode 100644 index 000000000..ba3406709 --- /dev/null +++ b/poincare/include/poincare/nth_root_layout_node.h @@ -0,0 +1,85 @@ +#ifndef POINCARE_NTH_ROOT_LAYOUT_NODE_H +#define POINCARE_NTH_ROOT_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class NthRootLayoutNode : public LayoutNode { +public: + constexpr static KDCoordinate k_leftRadixHeight = 8; + constexpr static KDCoordinate k_leftRadixWidth = 5; + + NthRootLayoutNode() : + LayoutNode(), + m_numberOfChildren(0) + {} + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited = false) override; + void deleteBeforeCursor(LayoutCursor * cursor) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool shouldCollapseSiblingsOnRight() const override { return true; } + bool hasUpperLeftIndex() const override { return numberOfChildren() > 1; } + + // TreeNode + void incrementNumberOfChildren(int increment = 1) override { + assert(increment == 1); + m_numberOfChildren+= increment; + } + void decrementNumberOfChildren(int decrement = 1) override { + assert(m_numberOfChildren >= decrement); + m_numberOfChildren-= decrement; + } + size_t size() const override { return sizeof(NthRootLayoutNode); } + int numberOfChildren() const override { return m_numberOfChildren; } +#if TREE_LOG + const char * description() const override { + return "NthRootLayout"; + } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override; +private: + constexpr static KDCoordinate k_rightRadixHeight = 2; + constexpr static KDCoordinate k_radixHorizontalOverflow = 2; + constexpr static KDCoordinate k_indexHeight = 4; + constexpr static KDCoordinate k_heightMargin = 2; + constexpr static KDCoordinate k_widthMargin = 2; + constexpr static KDCoordinate k_radixLineThickness = 1; + KDSize adjustedIndexSize(); + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + LayoutNode * radicandLayout() { return childAtIndex(0);} + LayoutNode * indexLayout() { return numberOfChildren() > 1 ? childAtIndex(1) : nullptr; } + int m_numberOfChildren; +}; + +class NthRootLayoutRef : public LayoutReference { +public: + NthRootLayoutRef(LayoutRef radicand) : + LayoutReference() + { + addChildTreeAtIndex(radicand, 0); + } + NthRootLayoutRef(LayoutRef radicand, LayoutRef index) : + LayoutReference() + { + addChildTreeAtIndex(radicand, 0); + addChildTreeAtIndex(index, 1); + } + + NthRootLayoutRef(TreeNode * t) : LayoutReference(t) {} +}; + +} + +#endif diff --git a/poincare/src/layout_cursor.cpp b/poincare/src/layout_cursor.cpp index 9343797d3..600220cb8 100644 --- a/poincare/src/layout_cursor.cpp +++ b/poincare/src/layout_cursor.cpp @@ -2,8 +2,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -77,6 +78,14 @@ void LayoutCursor::addEmptyExponentialLayout() { } } +void LayoutCursor::addEmptySquareRootLayout() { + HorizontalLayoutRef child1 = HorizontalLayoutRef(EmptyLayoutRef()); + NthRootLayoutRef newChild = NthRootLayoutRef(child1); + m_layoutRef.addSibling(this, newChild, false); + m_layoutRef = newChild.childAtIndex(0); + ((LayoutRef *)&newChild)->collapseSiblings(this); +} + void LayoutCursor::addEmptyPowerLayout() { VerticalOffsetLayoutRef offsetLayout = VerticalOffsetLayoutRef(EmptyLayoutRef(), VerticalOffsetLayoutNode::Type::Superscript); privateAddEmptyPowerLayout(offsetLayout); diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 3a32a88c6..3d7192972 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "layout/nth_root_layout.h" +#include extern "C" { #include @@ -39,12 +39,9 @@ Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { } LayoutRef NthRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /* assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat), false); -*/ + return NthRootLayoutRef(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); } template diff --git a/poincare/src/nth_root_layout_node.cpp b/poincare/src/nth_root_layout_node.cpp new file mode 100644 index 000000000..0c15f56a3 --- /dev/null +++ b/poincare/src/nth_root_layout_node.cpp @@ -0,0 +1,274 @@ +#include +#include +#include +#include + +namespace Poincare { + +static inline uint16_t max(uint16_t x, uint16_t y) { return (x>y ? x : y); } + +const uint8_t radixPixel[NthRootLayoutNode::k_leftRadixHeight][NthRootLayoutNode::k_leftRadixWidth] = { + {0x00, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0x00}, +}; + +void NthRootLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (radicandLayout() + && cursor->layoutNode() == radicandLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the radicand. Go the index if any, ir go Left of the root. + if (indexLayout()) { + cursor->setLayoutNode(indexLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + } else { + cursor->setLayoutNode(this); + } + return; + } + if (indexLayout() + && cursor->layoutNode() == indexLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the index. Go Left of the root. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Go Right of the radicand. + assert(radicandLayout() != nullptr); + cursor->setLayoutNode(radicandLayout()); + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode != nullptr) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void NthRootLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (radicandLayout() + && cursor->layoutNode() == radicandLayout() + && cursor->position() == LayoutCursor::Position::Right) + { + // Case: Right of the radicand. Go the Right of the root. + cursor->setLayoutNode(this); + return; + } + if (indexLayout() + && cursor->layoutNode() == indexLayout() + && cursor->position() == LayoutCursor::Position::Right) + { + // Case: Right of the index. Go Left of the integrand. + assert(radicandLayout() != nullptr); + cursor->setLayoutNode(radicandLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Left) { + // Case: Left. Go to the index if there is one, else go to the radicand. + if (indexLayout()) { + cursor->setLayoutNode(indexLayout()); + } else { + assert(radicandLayout() != nullptr); + cursor->setLayoutNode(radicandLayout()); + } + return; + } + assert(cursor->position() == LayoutCursor::Position::Right); + // Case: Right. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +void NthRootLayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (indexLayout() + && radicandLayout() + && cursor->isEquivalentTo(LayoutCursor(radicandLayout(), LayoutCursor::Position::Left))) + { + // If the cursor is Left of the radicand, move it to the index. + cursor->setLayoutNode(indexLayout()); + cursor->setPosition(LayoutCursor::Position::Right); + return; + } + if (indexLayout() + && cursor->layoutNode() == this + && cursor->position() == LayoutCursor::Position::Left) + { + // If the cursor is Left, move it to the index. + cursor->setLayoutNode(indexLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + LayoutNode::moveCursorUp(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void NthRootLayoutNode::moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { + if (indexLayout() && cursor->layoutNode()->hasAncestor(indexLayout(), true)) { + if (cursor->isEquivalentTo(LayoutCursor(indexLayout(), LayoutCursor::Position::Right))) { + // If the cursor is Right of the index, move it to the radicand. + assert(radicandLayout() != nullptr); + cursor->setLayoutNode(radicandLayout()); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + // If the cursor is Left of the index, move it Left . + if (cursor->isEquivalentTo(LayoutCursor(indexLayout(), LayoutCursor::Position::Left))) { + cursor->setLayoutNode(this); + cursor->setPosition(LayoutCursor::Position::Left); + return; + } + } + LayoutNode::moveCursorDown(cursor, shouldRecomputeLayout, equivalentPositionVisited); +} + +void NthRootLayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { + if (cursor->layoutNode() == radicandLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the radicand. Delete the layout, keep the radicand. + NthRootLayoutRef(this).replaceWith(LayoutRef(radicandLayout()), cursor); + // WARNING: Do not call "this" afterwards + return; + } + LayoutNode::deleteBeforeCursor(cursor); +} + +static_assert('\x91' == Ion::Charset::Root, "Unicode error"); +int NthRootLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + // Case: root(x,n) + if (numberOfChildren() == 2 + && (const_cast(this))->indexLayout() + && !(const_cast(this))->indexLayout()->isEmpty()) + { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "root"); + } + // Case: squareRoot(x) + if (numberOfChildren() == 1) { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "\x91"); + } + // Case: root(x,empty) + // Write "'SquareRootSymbol'('radicandLayout')". + assert((const_cast(this))->indexLayout() && (const_cast(this))->indexLayout()->isEmpty()); + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + + buffer[numberOfChar++] = '\x91'; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { + return bufferSize-1; + } + + numberOfChar += (const_cast(this))->radicandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar, numberOfSignificantDigits); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + +void NthRootLayoutNode::computeSize() { + KDSize radicandSize = radicandLayout()->layoutSize(); + KDSize indexSize = adjustedIndexSize(); + KDSize newSize = KDSize( + indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width() + k_radixHorizontalOverflow, + baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin + ); + m_frame.setSize(newSize); + m_sized = true; +} + +void NthRootLayoutNode::computeBaseline() { + if (indexLayout() != nullptr) { + m_baseline = max(radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin, + indexLayout()->layoutSize().height() + k_indexHeight); + } else { + m_baseline = radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin; + } + m_baselined = true; +} + +KDPoint NthRootLayoutNode::positionOfChild(LayoutNode * child) { + KDCoordinate x = 0; + KDCoordinate y = 0; + KDSize indexSize = adjustedIndexSize(); + if (child == radicandLayout()) { + x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; + y = baseline() - radicandLayout()->baseline(); + } else if (indexLayout() && child == indexLayout()) { + x = 0; + y = baseline() - indexSize.height() - k_indexHeight; + } else { + assert(false); + } + return KDPoint(x,y); +} + +KDSize NthRootLayoutNode::adjustedIndexSize() { + return indexLayout() != nullptr ? + KDSize(max(k_leftRadixWidth, indexLayout()->layoutSize().width()), indexLayout()->layoutSize().height()) : + KDSize(k_leftRadixWidth, 0); +} + +void NthRootLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + KDSize radicandSize = radicandLayout()->layoutSize(); + KDSize indexSize = adjustedIndexSize(); + KDColor workingBuffer[k_leftRadixWidth*k_leftRadixHeight]; + KDRect leftRadixFrame(p.x() + indexSize.width() + k_widthMargin - k_leftRadixWidth, + p.y() + baseline() + radicandSize.height() - radicandLayout()->baseline() + k_heightMargin - k_leftRadixHeight, + k_leftRadixWidth, k_leftRadixHeight); + ctx->blendRectWithMask(leftRadixFrame, expressionColor, (const uint8_t *)radixPixel, (KDColor *)workingBuffer); + // If the indice is higher than the root. + if (indexSize.height() + k_indexHeight > radicandLayout()->baseline() + k_radixLineThickness + k_heightMargin) { + // Vertical radix bar + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, + k_radixLineThickness, + radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); + // Horizontal radix bar + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, + k_radixLineThickness), expressionColor); + // Right radix bar + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, + p.y() + indexSize.height() + k_indexHeight - radicandLayout()->baseline() - k_radixLineThickness - k_heightMargin, + k_radixLineThickness, + k_rightRadixHeight + k_radixLineThickness), expressionColor); + } else { + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y(), + k_radixLineThickness, + radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y(), + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin + k_radixHorizontalOverflow, + p.y(), + k_radixLineThickness, + k_rightRadixHeight + k_radixLineThickness), expressionColor); + } + +} + +} diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 683137a27..a312efc94 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -2,13 +2,12 @@ #include #include #include -#include "layout/nth_root_layout.h" +#include extern "C" { #include } #include #include -#include namespace Poincare { @@ -51,11 +50,9 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { } LayoutRef SquareRoot::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /* assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); -*/ + return NthRootLayoutRef(operand(0)->createLayout(floatDisplayMode, complexFormat)); } } From 1137a167502ff198c71390f76c8a6b2f191e9a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Jul 2018 16:08:07 +0200 Subject: [PATCH 155/156] [poincare] ConjugateLayoutNode --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + .../poincare/allocation_failed_layout_node.h | 2 +- .../include/poincare/conjugate_layout_node.h | 54 +++++++++ .../include/poincare/horizontal_layout_node.h | 2 +- poincare/include/poincare/layout_node.h | 2 +- poincare/include/poincare/layout_reference.h | 2 +- poincare/src/conjugate.cpp | 13 +-- poincare/src/conjugate_layout_node.cpp | 105 ++++++++++++++++++ poincare/src/horizontal_layout_node.cpp | 5 +- poincare/src/layout_node.cpp | 9 +- poincare/src/layout_reference.cpp | 8 +- 12 files changed, 183 insertions(+), 21 deletions(-) create mode 100644 poincare/include/poincare/conjugate_layout_node.h create mode 100644 poincare/src/conjugate_layout_node.cpp diff --git a/poincare/Makefile b/poincare/Makefile index ca8eea061..377cf0977 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -11,6 +11,7 @@ objs += $(addprefix poincare/src/,\ bracket_layout_node.o\ bracket_pair_layout_node.o\ char_layout_node.o\ + conjugate_layout_node.o\ empty_layout_node.o\ horizontal_layout_node.o\ layout_cursor.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 8543b210b..a34d96e5c 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/allocation_failed_layout_node.h b/poincare/include/poincare/allocation_failed_layout_node.h index 36c2fb329..a0d2db301 100644 --- a/poincare/include/poincare/allocation_failed_layout_node.h +++ b/poincare/include/poincare/allocation_failed_layout_node.h @@ -36,7 +36,7 @@ protected: private: bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; } - bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override { return false; } + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override { return false; } bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} diff --git a/poincare/include/poincare/conjugate_layout_node.h b/poincare/include/poincare/conjugate_layout_node.h new file mode 100644 index 000000000..d22efe5d8 --- /dev/null +++ b/poincare/include/poincare/conjugate_layout_node.h @@ -0,0 +1,54 @@ +#ifndef POINCARE_CONJUGATE_LAYOUT_NODE_H +#define POINCARE_CONJUGATE_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class ConjugateLayoutNode : public LayoutNode { +public: + using LayoutNode::LayoutNode; + + // LayoutNode + void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override; + int writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const override; + bool shouldCollapseSiblingsOnRight() const override{ return true; } + + // TreeNode + size_t size() const override { return sizeof(ConjugateLayoutNode); } + int numberOfChildren() const override { return 1; } +#if TREE_LOG + const char * description() const override { + return "ConjugateLayout"; + } +#endif + +protected: + // LayoutNode + void computeSize() override; + void computeBaseline() override; + KDPoint positionOfChild(LayoutNode * child) override; +private: + constexpr static KDCoordinate k_overlineWidth = 1; + constexpr static KDCoordinate k_overlineVerticalMargin = 1; + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override; + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + LayoutNode * childLayout() { return childAtIndex(0); } +}; + +class ConjugateLayoutRef : public LayoutReference { +public: + ConjugateLayoutRef(LayoutRef l) : + LayoutReference() + { + addChildTreeAtIndex(l, 0); + } + ConjugateLayoutRef(TreeNode * n) : LayoutReference(n) {} +}; + +} + +#endif diff --git a/poincare/include/poincare/horizontal_layout_node.h b/poincare/include/poincare/horizontal_layout_node.h index 69b99e88c..c83eca6ab 100644 --- a/poincare/include/poincare/horizontal_layout_node.h +++ b/poincare/include/poincare/horizontal_layout_node.h @@ -56,7 +56,7 @@ private: bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override; bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override; void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) override; - bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) override; + bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override; void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {} int m_numberOfChildren; }; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index fa585631d..4bd63535c 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -106,7 +106,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 bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor); + virtual bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force); virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force); virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} protected: diff --git a/poincare/include/poincare/layout_reference.h b/poincare/include/poincare/layout_reference.h index cd9c3bc9a..9e8b3194d 100644 --- a/poincare/include/poincare/layout_reference.h +++ b/poincare/include/poincare/layout_reference.h @@ -83,7 +83,7 @@ public: void addSibling(LayoutCursor * cursor, LayoutReference sibling, bool moveCursor); // Replace void replaceChildAtIndex(int oldChildIndex, LayoutReference newChild) { TreeReference::replaceChildAtIndex(oldChildIndex, newChild); } - void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr); + void replaceChild(LayoutReference oldChild, LayoutReference newChild, LayoutCursor * cursor = nullptr, bool force = false); void replaceChildWithEmpty(LayoutReference oldChild, LayoutCursor * cursor = nullptr); void replaceWith(LayoutReference newChild, LayoutCursor * cursor) { LayoutReference p = parent(); diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index d27f96ac6..65db01522 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -1,12 +1,8 @@ #include #include #include -#include "layout/conjugate_layout.h" -#include - -extern "C" { +#include #include -} #include namespace Poincare { @@ -21,11 +17,10 @@ Expression * Conjugate::clone() const { } LayoutRef Conjugate::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const { - return CharLayoutRef('a'); //TODO - /*assert(floatDisplayMode != PrintFloat::Mode::Default); + assert(floatDisplayMode != PrintFloat::Mode::Default); assert(complexFormat != ComplexFormat::Default); - return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), false); -*/} + return ConjugateLayoutRef(operand(0)->createLayout(floatDisplayMode, complexFormat)); +} Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { Expression * e = Expression::shallowReduce(context, angleUnit); diff --git a/poincare/src/conjugate_layout_node.cpp b/poincare/src/conjugate_layout_node.cpp new file mode 100644 index 000000000..2d4072593 --- /dev/null +++ b/poincare/src/conjugate_layout_node.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +namespace Poincare { + +void ConjugateLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + if (childLayout() + && cursor->layoutNode() == childLayout() + && cursor->position() == LayoutCursor::Position::Left) + { + // Case: Left of the operand. Move Left. + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + if (cursor->position() == LayoutCursor::Position::Right) { + // Case: Right. Go to the operand. + assert(childLayout() != nullptr); + cursor->setLayoutNode(childLayout()); + return; + } + assert(cursor->position() == LayoutCursor::Position::Left); + // Case: Left. Ask the parent. + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorLeft(cursor, shouldRecomputeLayout); + } +} + +void ConjugateLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) { + // Case: Right of the operand. Move Right. + if (childLayout() + && cursor->layoutNode() == childLayout() + && cursor->position() == LayoutCursor::Position::Right) + { + cursor->setLayoutNode(this); + return; + } + assert(cursor->layoutNode() == this); + // Case: Left. Go to the operand. + if (cursor->position() == LayoutCursor::Position::Left) { + assert(childLayout() != nullptr); + cursor->setLayoutNode(childLayout()); + return; + } + // Case: Right. Ask the parent. + assert(cursor->position() == LayoutCursor::Position::Right); + LayoutNode * parentNode = parent(); + if (parentNode) { + parentNode->moveCursorRight(cursor, shouldRecomputeLayout); + } +} + +int ConjugateLayoutNode::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const { + return LayoutEngine::writePrefixSerializableRefTextInBuffer(SerializableRef(const_cast(this)), buffer, bufferSize, numberOfSignificantDigits, "conj"); +} + +void ConjugateLayoutNode::computeSize() { + KDSize childSize = childLayout()->layoutSize(); + KDCoordinate newWidth = + Metric::FractionAndConjugateHorizontalMargin + + Metric::FractionAndConjugateHorizontalOverflow + + childSize.width() + + Metric::FractionAndConjugateHorizontalOverflow + + Metric::FractionAndConjugateHorizontalMargin; + KDCoordinate newHeight = + childSize.height() + + k_overlineWidth + + k_overlineVerticalMargin; + m_frame.setSize(KDSize(newWidth, newHeight)); + m_sized = true; +} + +void ConjugateLayoutNode::computeBaseline() { + m_baseline = childLayout()->baseline()+k_overlineWidth+k_overlineVerticalMargin; + m_baselined = true; +} + +KDPoint ConjugateLayoutNode::positionOfChild(LayoutNode * child) { + assert(child == childLayout()); + return KDPoint( + Metric::FractionAndConjugateHorizontalMargin + Metric::FractionAndConjugateHorizontalOverflow, + k_overlineWidth + k_overlineVerticalMargin); +} + +void ConjugateLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + ctx->fillRect(KDRect(p.x()+Metric::FractionAndConjugateHorizontalMargin, p.y(), childLayout()->layoutSize().width()+2*Metric::FractionAndConjugateHorizontalOverflow, k_overlineWidth), expressionColor); +} + +bool ConjugateLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) { + if (oldChild == newChild) { + return false; + } + assert(oldChild == childLayout()); + if (!force && newChild->isEmpty()) { + ConjugateLayoutRef(this).replaceWith(LayoutRef(newChild), cursor); + // WARNING: do not call "this" afterwards + return false; + } + return true; +} + +} diff --git a/poincare/src/horizontal_layout_node.cpp b/poincare/src/horizontal_layout_node.cpp index f5cab42b1..8531225c7 100644 --- a/poincare/src/horizontal_layout_node.cpp +++ b/poincare/src/horizontal_layout_node.cpp @@ -253,10 +253,13 @@ void HorizontalLayoutNode::didRemoveChildAtIndex(int index, LayoutCursor * curso } } -bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { +bool HorizontalLayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) { if (oldChild == newChild) { return false; } + if (force) { + return true; + } HorizontalLayoutRef thisRef(this); int oldChildIndex = indexOfChild(oldChild); if (newChild->isEmpty()) { diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 1f9a64635..cefd77e0a 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -123,7 +123,7 @@ void LayoutNode::deleteBeforeCursor(LayoutCursor * cursor) { //WARNING: Do no use "this" afterwards } -bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor) { +bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) { assert(hasChild(oldChild)); if (!newChild->hasAncestor(oldChild, false)) { cursor->setPosition(LayoutCursor::Position::Right); @@ -132,8 +132,11 @@ bool LayoutNode::willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, } bool LayoutNode::willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) { - LayoutRef(this).replaceChildWithEmpty(l, cursor); - return false; + if (!force) { + LayoutRef(this).replaceChildWithEmpty(l, cursor); + return false; + } + return true; } // Other diff --git a/poincare/src/layout_reference.cpp b/poincare/src/layout_reference.cpp index ae65094bd..351887069 100644 --- a/poincare/src/layout_reference.cpp +++ b/poincare/src/layout_reference.cpp @@ -22,8 +22,8 @@ LayoutCursor LayoutRef::equivalentCursor(LayoutCursor * cursor) { // Tree modification template<> -void LayoutRef::replaceChild(LayoutRef oldChild, LayoutRef newChild, LayoutCursor * cursor) { - if (!typedNode()->willReplaceChild(oldChild.typedNode(), newChild.typedNode(), cursor)) { +void LayoutRef::replaceChild(LayoutRef oldChild, LayoutRef newChild, LayoutCursor * cursor, bool force) { + if (!typedNode()->willReplaceChild(oldChild.typedNode(), newChild.typedNode(), cursor, force)) { return; } replaceTreeChild(oldChild, newChild); @@ -213,14 +213,14 @@ void LayoutRef::collapseSiblings(LayoutCursor * cursor) { if (this->typedNode()->shouldCollapseSiblingsOnRight()) { LayoutReference absorbingChild = childAtIndex(rightCollapsingAbsorbingChildIndex()); if (!absorbingChild.isHorizontal()) { - replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor); + replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor, true); } collapseOnDirection(HorizontalDirection::Right, rightCollapsingAbsorbingChildIndex()); } if (this->typedNode()->shouldCollapseSiblingsOnLeft()) { LayoutReference absorbingChild = childAtIndex(leftCollapsingAbsorbingChildIndex()); if (!absorbingChild.isHorizontal()) { - replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor); + replaceChild(absorbingChild, HorizontalLayoutRef(absorbingChild.clone()), cursor, true); } collapseOnDirection(HorizontalDirection::Left, leftCollapsingAbsorbingChildIndex()); } From 3c44a5540c409bda9715cf55da589f7e3ad5b4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Jul 2018 17:37:11 +0200 Subject: [PATCH 156/156] [poincare] Tree: enable to create node of variable size given in parameters --- poincare/include/poincare/tree_pool.h | 6 +++--- poincare/include/poincare/tree_reference.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index 77d97035e..74062cb36 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -19,13 +19,13 @@ public: TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } template - TreeNode * createTreeNode() { + TreeNode * createTreeNode(size_t size) { int nodeIdentifier = generateIdentifier(); if (nodeIdentifier == -1) { T::FailedAllocationStaticNode()->retain(); return T::FailedAllocationStaticNode(); } - void * ptr = alloc(sizeof(T)); + void * ptr = alloc(size); if (ptr == nullptr) { T::FailedAllocationStaticNode()->retain(); return T::FailedAllocationStaticNode(); @@ -80,7 +80,7 @@ public: private: constexpr static int BufferSize = 1024;//2048; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); - constexpr static int MaxNumberOfStaticNodes = 2; + constexpr static int MaxNumberOfStaticNodes = 2; // ExpressionNode, LayoutNode // TreeNode void discardTreeNode(TreeNode * node) { diff --git a/poincare/include/poincare/tree_reference.h b/poincare/include/poincare/tree_reference.h index 65d891b70..e024fb220 100644 --- a/poincare/include/poincare/tree_reference.h +++ b/poincare/include/poincare/tree_reference.h @@ -272,8 +272,8 @@ public: } protected: - TreeReference() { - TreeNode * node = TreePool::sharedPool()->createTreeNode(); + TreeReference(size_t size = sizeof(T)) { + TreeNode * node = TreePool::sharedPool()->createTreeNode(size); m_identifier = node->identifier(); }