Wt examples  4.10.0
Loading...
Searching...
No Matches
DemoTreeList.C
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7#include <Wt/WApplication.h>
8#include <Wt/WText.h>
9#include <Wt/WImage.h>
10#include <Wt/WPushButton.h>
11
12#include "DemoTreeList.h"
13#include "TreeNode.h"
14#include "IconPair.h"
15
16using namespace Wt;
17using std::rand;
18
20 : WContainerWidget(),
21 testCount_(0)
22{
23 addWidget
24 (std::make_unique<WText>("<h2>Wt Tree List example</h2>"
25 "<p>This is a simple demo of a treelist, implemented using"
26 " <a href='http://witty.sourceforge.net/'>Wt</a>.</p>"
27 "<p>The leafs of the tree contain the source code of the "
28 "tree-list in the classes <b>TreeNode</b> and "
29 "<b>IconPair</b>, as well as the implementation of this "
30 "demo itself in the class <b>DemoTreeList</b>.</p>"));
31
32 auto tree = makeTreeFolder("Examples");
33 tree_ = addWidget(std::move(tree));
34
35 TreeNode *treelist = makeTreeFolder("Tree List", tree_);
36 TreeNode *wstateicon = makeTreeFolder("class IconPair", treelist);
37 makeTreeFile("<a href=\"IconPair.h\">IconPair.h</a>", wstateicon);
38 makeTreeFile("<a href=\"IconPair.C\">IconPair.C</a>", wstateicon);
39 TreeNode *wtreenode = makeTreeFolder("class TreeNode", treelist);
40 makeTreeFile("<a href=\"TreeNode.h\">TreeNode.h</a>", wtreenode);
41 makeTreeFile("<a href=\"TreeNode.C\">TreeNode.C</a>", wtreenode);
42 TreeNode *demotreelist = makeTreeFolder("class DemoTreeList", treelist);
43 makeTreeFile("<a href=\"DemoTreeList.h\">DemoTreeList.h</a>", demotreelist);
44 makeTreeFile("<a href=\"DemoTreeList.C\">DemoTreeList.C</a>", demotreelist);
45
46 testFolder_ = makeTreeFolder("Test folder", tree_);
47
48 /*
49 * Buttons to dynamically demonstrate changing the tree contents.
50 */
51 addWidget
52 (std::make_unique<WText>("<p>Use the following buttons to change the tree "
53 "contents:</p>"));
54
56 = this->addWidget(std::make_unique<WPushButton>("Add folder"));
57 addFolderButton_->clicked().connect(this, &DemoTreeList::addFolder);
58
60 = this->addWidget(std::make_unique<WPushButton>("Remove folder"));
61 removeFolderButton_->clicked().connect(this, &DemoTreeList::removeFolder);
62 removeFolderButton_->disable();
63
64 addWidget
65 (std::make_unique<WText>("<p>Remarks:"
66 "<ul>"
67 "<li><p>This is not the instantiation of a pre-defined "
68 "tree list component, but the full implementation of such "
69 "a component, in about 350 lines of C++ code !</p> "
70 "<p>In comparison, the <a href='http://myfaces.apache.org'> "
71 "Apache MyFaces</a> JSF implementation of tree2, with similar "
72 "functionality, uses about 2400 lines of Java, and 140 lines "
73 "of JavaScript code.</p></li>"
74 "<li><p>Once loaded, the tree list does not require any "
75 "interaction with the server for handling the click events on "
76 "the <img src='icons/nav-plus-line-middle.gif' /> and "
77 "<img src='icons/nav-minus-line-middle.gif' /> icons, "
78 "because these events have been connected to slots using "
79 "STATIC connections. Such connections are converted to the "
80 "appropriate JavaScript code that is inserted into the page. "
81 "Still, the events are signaled to the server to update the "
82 "application state.</p></li>"
83 "<li><p>In contrast, the buttons for manipulating the tree "
84 "contents use DYNAMIC connections, and thus the update "
85 "is computed at server-side, and communicated back to the "
86 "browser (by default using AJAX).</p></li>"
87 "<li><p>When loading a page, only visible widgets (that are not "
88 "<b>setHidden(true)</b>) are transmitted. "
89 "The remaining widgets are loaded in the background after "
90 "rendering the page. "
91 "As a result the application is loaded as fast as possible.</p>"
92 "</li>"
93 "<li><p>The browser reload button is supported and behaves as "
94 "expected: the page is reloaded from the server. Again, "
95 "only visible widgets are transmitted immediately.</p> "
96 "<p>(For the curious, this is the way to see the actual "
97 "HTML/JavaScript code !)</p></li>"
98 "</ul></p>"));
99}
100
102{
103 TreeNode *node
104 = makeTreeFolder("Folder " + std::to_string(++testCount_), testFolder_);
105 makeTreeFile("File " + std::to_string(testCount_), node);
106
107 removeFolderButton_->enable();
108}
109
111{
112 int numFolders = testFolder_->childNodes().size();
113
114 if (numFolders > 0) {
115 int c = rand() % numFolders;
116
117 TreeNode *child = testFolder_->childNodes()[c];
118 testFolder_->removeChildNode(child, c);
119
120 if (numFolders == 1)
121 removeFolderButton_->disable();
122 }
123}
124
125TreeNode *DemoTreeList::makeTreeFolder(const std::string name, TreeNode *parent)
126{
127 auto labelIcon = std::make_unique<IconPair>(
128 "icons/yellow-folder-closed.png",
129 "icons/yellow-folder-open.png",
130 false);
131
132 auto node =
133 std::make_unique<TreeNode>(name, TextFormat::Plain, std::move(labelIcon));
134 auto node_ = node.get();
135 parent->addChildNode(std::move(node));
136
137 return node_;
138}
139
140std::unique_ptr<TreeNode> DemoTreeList::makeTreeFolder(const std::string name)
141{
142 auto labelIcon = std::make_unique<IconPair>(
143 "icons/yellow-folder-closed.png",
144 "icons/yellow-folder-open.png",
145 false);
146 auto node =
147 std::make_unique<TreeNode>(name, TextFormat::Plain, std::move(labelIcon));
148
149 return node;
150}
151
152TreeNode *DemoTreeList::makeTreeFile(const std::string name,
153 TreeNode *parent)
154{
155 auto labelIcon
156 = std::make_unique<IconPair>("icons/document.png", "icons/yellow-folder-open.png",
157 false);
158
159 auto node = std::make_unique<TreeNode>(name, TextFormat::XHTML, std::move(labelIcon));
160 auto node_ = node.get();
161 if (parent)
162 parent->addChildNode(std::move(node));
163
164 return node_;
165}
166
167std::unique_ptr<TreeNode> DemoTreeList::makeTreeFile(const std::string name)
168{
169 auto labelIcon
170 = std::make_unique<IconPair>("icons/document.png", "icons/yellow-folder-open.png",
171 false);
172 auto node =
173 std::make_unique<TreeNode>(name, TextFormat::XHTML, std::move(labelIcon));
174
175 return node;
176}
177
178std::unique_ptr<WApplication> createApplication(const WEnvironment& env)
179{
180 auto app
181 = std::make_unique<WApplication>(env);
182 app->root()->addWidget(std::make_unique<DemoTreeList>());
183
184 /*
185 * The look & feel of the tree node is configured using a CSS style sheet.
186 * If you are not familiar with CSS, you can use the WCssDecorationStyle
187 * class ...
188 */
189 WCssDecorationStyle treeNodeLabelStyle;
190 treeNodeLabelStyle.font().setFamily(FontFamily::Serif, "Helvetica");
191 app->styleSheet().addRule(".treenodelabel", treeNodeLabelStyle);
192
193 /*
194 * ... or if you speak CSS fluently, you can add verbatim rules.
195 */
196 app->styleSheet().addRule(".treenodechildcount",
197 "color:blue; font-family:Helvetica,serif;");
198
199 return app;
200}
201
202int main(int argc, char **argv)
203{
204 return WRun(argc, argv, &createApplication);
205}
206
int main(int argc, char **argv)
std::unique_ptr< WApplication > createApplication(const WEnvironment &env)
TreeNode * testFolder_
TreeNode * tree_
void removeFolder()
Remove a folder.
void addFolder()
Add a folder.
DemoTreeList()
Create a DemoTreeList.
TreeNode * makeTreeFolder(const std::string name, TreeNode *parent)
Create a "folder" node, and insert in the given parent.
WPushButton * removeFolderButton_
TreeNode * makeTreeFile(const std::string name, TreeNode *parent)
Create a "file" node, and insert in the given parent.
WPushButton * addFolderButton_
Example implementation of a single tree list node.
Definition TreeNode.h:58
void removeChildNode(TreeNode *node, int index)
Removes a child node.
Definition TreeNode.C:91
const std::vector< TreeNode * > & childNodes() const
Returns the list of children.
Definition TreeNode.h:84
void addChildNode(std::unique_ptr< TreeNode > node)
Adds a child node.
Definition TreeNode.C:81