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