diff --git a/bazaar/Tree/Tree.cpp b/bazaar/Tree/Tree.cpp new file mode 100644 index 000000000..1372092b4 --- /dev/null +++ b/bazaar/Tree/Tree.cpp @@ -0,0 +1,2 @@ +#include "Tree.h" + diff --git a/bazaar/Tree/Tree.h b/bazaar/Tree/Tree.h new file mode 100644 index 000000000..e87739ce7 --- /dev/null +++ b/bazaar/Tree/Tree.h @@ -0,0 +1,107 @@ +#ifndef _Tree_Tree_h +#define _Tree_Tree_h + +#include +using namespace Upp; + +template +class Tree + : protected Array +{ +protected: + typedef Array B; + T * parent; + T * root; + + inline void Link(T & t) { t.root = root; t.parent = (T *)this; } + inline void Unlink(T & t) { t.root = NULL; t.parent = NULL; } + + void Relink() { for(int i = 0; i < B::GetCount(); i++) { T & t = B::operator[](i); Link(t); t.Relink();} } + +public: + T *GetPtr() { return (T *) this; } + const T *GetPtr() const { return (const T *) this; } + T *GetParent() { return parent; } + const T *GetParent() const { return parent; } + T *GetRoot() { return root; } + const T *GetRoot() const { return root; } + void SetAsRoot() { ASSERT(parent == NULL); root = (T *)this; Relink(); } + +// Array interface + + T& Add() { T & t = B::Add(); Link(t); return t; } + void Add(const T& x) { T & t = B::Add(DeepCopyNew(x)); Link(t); }// return t; } + void AddPick(pick_ T& x) { T & t = B::Add(new T(x)); Link(t); }// return t; } + T& Add(T *newt) { ASSERT(newt->parent == NULL); T & t = B::Add(newt); Link(t); return t; } + + using B::operator[]; + using B::GetCount; + using B::IsEmpty; + + using B::Trim; + void SetCount(int n) { B::SetCount(n); for(int i = 0; i < B::GetCount(); i++) Link(B::operator[](i)); } + void SetCountR(int n) { B::SetCountR(n); for(int i = 0; i < B::GetCount(); i++) Link(B::operator[](i)); } + using B::Clear; + + using B::Remove; + T& Insert(int i) { T & t = B::Insert(i); Link(t); return t; } + void InsertPick(int i, pick_ T& x) { Link(x); B::InsertPick(i, x); } + + using B::GetIndex; + using B::Swap; + using B::Move; + + T *Detach(int i) { T *t = B::Detach(i); Unlink(t); } + T& Set(int i, T *newt) { ASSERT(newt->parent == NULL); T & t = B::Set(i, newt); Link(t); return t; } + void Insert(int i, T *newt) { ASSERT(newt->parent == NULL); B::Insert(i, newt); Link(*newt); } + + using B::Drop; + using B::Top; + + T *PopDetach() { T * t = B::PopDetach(); Unlink(*t); return t; } + + void Swap(Tree& b) { B::Swap(b); for(int i = 0; i < B::GetCount(); i++) Link(B::operator[](i)); for(int i = 0; i < b.GetCount(); i++) b.Link(b[i]); } + + Tree& operator<<(const T& x) { Add(x); return *this; } + Tree& operator<<(T *newt) { Add(newt); return *this; } + Tree& operator|(pick_ T& x) { AddPick(x); return *this; } + +// Array Interface end + + Tree() + : parent(NULL) + , root(NULL) + {} + +private: + Tree(const Tree&); + void operator=(const Tree&); + +public: +#ifdef _DEBUG + void Dump() { + for(int i = 0; i < GetCount(); i++) + LOG((*this)[i]); + LOG("-------------------------------------"); + } +#endif +}; + +//Tree Node helper class + +template +class Node + : public Tree > +{ +public: + typedef Node CLASSNAME; + T leaf; +}; + +template +class Leaf + : public Tree > + , public B + {}; + +#endif diff --git a/bazaar/Tree/Tree.upp b/bazaar/Tree/Tree.upp new file mode 100644 index 000000000..8168e45d7 --- /dev/null +++ b/bazaar/Tree/Tree.upp @@ -0,0 +1,11 @@ +uses + Core; + +file + Tree.h, + Tree.cpp, + src.tpp; + +mainconfig + "" = ""; + diff --git a/bazaar/Tree/init b/bazaar/Tree/init new file mode 100644 index 000000000..e384952ef --- /dev/null +++ b/bazaar/Tree/init @@ -0,0 +1,4 @@ +#ifndef _Tree_icpp_init_stub +#define _Tree_icpp_init_stub +#include "Core/init" +#endif diff --git a/bazaar/Tree/src.tpp/Leaf$en-us.tpp b/bazaar/Tree/src.tpp/Leaf$en-us.tpp new file mode 100644 index 000000000..e91f43e0f --- /dev/null +++ b/bazaar/Tree/src.tpp/Leaf$en-us.tpp @@ -0,0 +1,14 @@ +topic "template "; +[ $$0,0#00000000000000000000000000000000:Default] +[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem] +[l288;2 $$2,0#27521748481378242620020725143825:desc] +[0 $$3,0#96390100711032703541132217272105:end] +[{_} +[s1;:noref: [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T], [@(0.0.255) class]_[*@3 B]_`=_Em +ptyClass>&] +[s1;:Leaf`:`:class: [@(0.0.255) class]_[* Leaf]_:_[@(0.0.255) public]_[*@3 Tree]<[* Leaf]<[*@4 T], + [*@3 B]>_>_, [@(0.0.255) public]_[*@3 B]&] +[s2;%% another Node implementation, showing how to chain inheritance +with Tree, this one is usefull if te leaf itself is the tree&] +[s3; &] +[s0; ] \ No newline at end of file diff --git a/bazaar/Tree/src.tpp/Node$en-us.tpp b/bazaar/Tree/src.tpp/Node$en-us.tpp new file mode 100644 index 000000000..ea84e9a58 --- /dev/null +++ b/bazaar/Tree/src.tpp/Node$en-us.tpp @@ -0,0 +1,13 @@ +topic "template "; +[ $$0,0#00000000000000000000000000000000:Default] +[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem] +[l288;2 $$2,0#27521748481378242620020725143825:desc] +[0 $$3,0#96390100711032703541132217272105:end] +[{_} +[s1;:noref: [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]>&] +[s1;:Node`:`:class: [@(0.0.255) class]_[* Node]_:_[@(0.0.255) public]_[*@3 Tree]<[* Node]<[*@4 T]> +_>_&] +[s2;%% an example implementation of a Tree Node, usefull for almost +all cases, since leaf type T can be specified what ever type.&] +[s3; &] +[s0;%% ] \ No newline at end of file diff --git a/bazaar/Tree/src.tpp/Tree$en-us.tpp b/bazaar/Tree/src.tpp/Tree$en-us.tpp new file mode 100644 index 000000000..8715c0b95 --- /dev/null +++ b/bazaar/Tree/src.tpp/Tree$en-us.tpp @@ -0,0 +1,47 @@ +topic "template "; +[ $$0,0#00000000000000000000000000000000:Default] +[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem] +[l288;2 $$2,0#27521748481378242620020725143825:desc] +[0 $$3,0#96390100711032703541132217272105:end] +[H6;0 $$4,0#05600065144404261032431302351956:begin] +[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem] +[{_} +[s1;:noref: [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]>&] +[s1;:Tree`:`:class: [@(0.0.255) class]_[* Tree]_:_[@(0.0.255) protected]_[*@3 Array]<[*@4 T]>_&] +[s2;%% a template class that can be used in the same manner as Link, +to see how to use it, check out the manual&] +[s3; &] +[s4; &] +[s5;:Tree`:`:GetPtr`(`): [*@4 T]_`*[* GetPtr]()&] +[s2;%% returns a pointer to self. caution on using it on Tree +elements only, which are not T themselves.&] +[s3; &] +[s4; &] +[s5;:Tree`:`:GetParent`(`): [*@4 T]_`*[* GetParent]()&] +[s2;%% GetParent reference if any&] +[s3; &] +[s4; &] +[s5;:Tree`:`:GetRoot`(`): [*@4 T]_`*[* GetRoot]()&] +[s2;%% GetRoot reference, if NULL, element is root itself&] +[s3; &] +[s4; &] +[s5;:Tree`:`:SetAsRoot`(`): [@(0.0.255) void]_[* SetAsRoot]()&] +[s2;%% a VERY important function. To be called for the root element +to set up the root reference which is forwarded to each child +later. call only once on root element only.&] +[s3; &] +[s4; &] +[s5;:Tree`:`:Link`(T`&`): [@(0.0.255) void]_[* Link]([*@4 T]_`&_[*@3 t])&] +[s2;%% provides a shallow linking of [%-*@3 t].only, this means that +it does `*NOT`* change pertenance of object, but simply links +the root and parent reference.&] +[s3;%% &] +[s4; &] +[s5;:Tree`:`:Unlink`(T`&`): [@(0.0.255) void]_[* Unlink]([*@4 T]_`&_[*@3 t])&] +[s2;%% does the opposite of Link to object [%-*@3 t].&] +[s3;%% &] +[s4; &] +[s5;:Tree`:`:Relink`(`): [@(0.0.255) void]_[* Relink]()&] +[s2;%% `'repairs`' linkage of a tree recursively&] +[s3; &] +[s0; ] \ No newline at end of file diff --git a/bazaar/Tree/src.tpp/about$en-us.tpp b/bazaar/Tree/src.tpp/about$en-us.tpp new file mode 100644 index 000000000..613c2e4e7 --- /dev/null +++ b/bazaar/Tree/src.tpp/about$en-us.tpp @@ -0,0 +1,88 @@ +topic "Tree"; +[ $$0,0#00000000000000000000000000000000:Default] +[{_}%EN-US +[s0; [+150 Tree]&] +[s0; &] +[s0; A Tree is a very effective way of bringing in some level of +logical organisation in a bunch of data which the NTL containers +can`'t provide inherently. They make access to a variety of `*[* equal +/ similar]`* data easy but it is all lineary organised. Every +item is equaly important. It is hard and errorprone to say `'The +first ten elements are special, the others are reserved`'. In +some cases one can use linked lists (U`+`+ Link) to reflect +such things, defining maybe sth like `'everything after LinkOwner +is free, everything before is used. But what if grouped hierarchy +comes into play? Handling with sorts of paths etc. Here, a Tree +can help provide means not merly to store elements, but bring +in a model based hierarchy.&] +[s0; &] +[s0; One could use constructs like this:&] +[s0; &] +[s0;i160; [C2 struct MyTree]&] +[s0;i160; [C2 `{]&] +[s0;i160; [C2 -|Array tree;]&] +[s0;i160; [C2 `};]&] +[s0;i160; &] +[s0; but one might end up needing Parent references, or even Root +references. and who is going to take care of them when moving +the elements around?&] +[s0; &] +[s0; Here comes a solution, which is not the only one in this world, +but serves 95 % of cases.&] +[s0; &] +[s0; The Tree is actually a partially hidden Array of the same +type elements, This making usage of well known and tested NTL +containers. It has a parent pointer and a root pointer. some +methods from Array are free to access, some are overblended. +the protected inheritance ensures that the overblended base methods +are inaccessible in any case. some methods are not critical though +and can be exposed (using using), in some, the correct parent +ref is to be ensured. this thing can be thought in Vector and +the Map flavours as well, making handling more difficult though. +Array was chosen because of its Attach/Detach ability, which +comes in really handy when dealing with Trees (attaching detaching +or moving trees somewhere)&] +[s0; &] +[s0; Maybe in near future, one might provide an extended templated +version where to specify which container to use...&] +[s0; &] +[s0; Example of usage:&] +[s0; &] +[s0; HINT: using One as T instead of T directly gives you the ability +of handling true leafs, which are attachable / detachable independantly +from the tree structure. This a tree can remain intact, while +you detach the leafs..&] +[s0; &] +[s0;i160; [C2 class Element]&] +[s0;i160; [C2 `{]&] +[s0;i160; [C2 public:]&] +[s0;i160; [C2 -|String name;]&] +[s0;i160; [C2 -|Value value;]&] +[s0;i160; [C2 `};]&] +[s0;i160;C2 &] +[s0;i160; [C2 Node > root;]&] +[s0;i160; [C2 Node roota;]&] +[s0;i160;C2 &] +[s0;i160; [C2 //Tree >]&] +[s0;i128;C2 &] +[s0;i128; [C2 root.SetAsRoot();]&] +[s0;i128; [C2 root.leaf.Create();]&] +[s0;i128; [C2 root.leaf`->name `= `"/`";]&] +[s0;i128; [C2 root.SetCount(3);]&] +[s0;i128; [C2 Node > `& child `= root`[2`];]&] +[s0;i128; [C2 child.leaf.Create();]&] +[s0;i128; [C2 child.leaf`->name `= `"Hallo`";]&] +[s0;i128; [C2 String `& s `= child.GetParent()`->leaf`->name;]&] +[s0;i128; [C2 s `= `"root`";]&] +[s0;i128; [C2 String `& ss `= root.leaf`->name;]&] +[s0;i128;C2 &] +[s0;i128; [C2 //Node]&] +[s0;i128; [C2 roota.SetAsRoot();]&] +[s0;i128; [C2 roota.leaf.name `= `"/`";]&] +[s0;i128; [C2 roota.SetCount(3);]&] +[s0;i128; [C2 Node `& childa `= roota`[2`];]&] +[s0;i128; [C2 childa.leaf.name `= `"Hallo`";]&] +[s0;i128; [C2 String `& sa `= childa.GetParent()`->leaf.name;]&] +[s0;i128; [C2 sa `= `"root`";]&] +[s0;i128; [C2 String `& ssa `= roota.leaf.name;]&] +[s0;i128;C2 ] \ No newline at end of file diff --git a/bazaar/TreeTest/TreeTest.h b/bazaar/TreeTest/TreeTest.h new file mode 100644 index 000000000..132f6f05c --- /dev/null +++ b/bazaar/TreeTest/TreeTest.h @@ -0,0 +1,33 @@ +#ifndef _TreeTest_TreeTest_h +#define _TreeTest_TreeTest_h + +#include + +using namespace Upp; + +#define LAYOUTFILE +#include + +#include + +class Element +{ +public: + typedef Element CLASSNAME; + String name; + Value value; +}; + +/// + +class TreeTest : public WithLayout { +public: + typedef TreeTest CLASSNAME; + TreeTest(); + + Node > root; + Node roota; +}; + +#endif + diff --git a/bazaar/TreeTest/TreeTest.lay b/bazaar/TreeTest/TreeTest.lay new file mode 100644 index 000000000..668a4f4f9 --- /dev/null +++ b/bazaar/TreeTest/TreeTest.lay @@ -0,0 +1,5 @@ + +LAYOUT(Layout, 200, 100) + +END_LAYOUT + diff --git a/bazaar/TreeTest/TreeTest.upp b/bazaar/TreeTest/TreeTest.upp new file mode 100644 index 000000000..87c0ae28c --- /dev/null +++ b/bazaar/TreeTest/TreeTest.upp @@ -0,0 +1,12 @@ +uses + CtrlLib, + Tree; + +file + TreeTest.h, + main.cpp, + TreeTest.lay; + +mainconfig + "" = "GUI"; + diff --git a/bazaar/TreeTest/init b/bazaar/TreeTest/init new file mode 100644 index 000000000..048c5ff27 --- /dev/null +++ b/bazaar/TreeTest/init @@ -0,0 +1,5 @@ +#ifndef _TreeTest_icpp_init_stub +#define _TreeTest_icpp_init_stub +#include "CtrlLib/init" +#include "Tree/init" +#endif diff --git a/bazaar/TreeTest/main.cpp b/bazaar/TreeTest/main.cpp new file mode 100644 index 000000000..04c513489 --- /dev/null +++ b/bazaar/TreeTest/main.cpp @@ -0,0 +1,44 @@ +#include "TreeTest.h" + +TreeTest::TreeTest() +{ + CtrlLayout(*this, "Window title"); + + //Tree > + + root.SetAsRoot(); + root.leaf.Create(); + root.leaf->name = "/"; + root.SetCount(3); + Node > & child = root[2]; + ASSERT(child.GetParent() == &root); + ASSERT(child.GetRoot() == &root); + child.leaf.Create(); + child.leaf->name = "Hallo"; + String & s = child.GetParent()->leaf->name; + s = "root"; + String & ss = root.leaf->name; + ASSERT(ss.IsEqual(s)); + + //Node + + roota.SetAsRoot(); + roota.leaf.name = "/"; + roota.SetCount(3); + Node & childa = roota[2]; + childa.leaf.name = "Hallo"; + ASSERT(childa.GetParent() == &roota); + ASSERT(childa.GetRoot() == &roota); + String & sa = childa.GetParent()->leaf.name; + sa = "root"; + String & ssa = roota.leaf.name; + ASSERT(ssa.IsEqual(sa)); + + int x = 123; +} + +GUI_APP_MAIN +{ + TreeTest().Run(); +} +