00001
00002
00003
00004
00005
00006 #include <boost/lexical_cast.hpp>
00007
00008 #include <Wt/WApplication>
00009 #include <Wt/WText>
00010 #include <Wt/WImage>
00011 #include <Wt/WPushButton>
00012
00013 #include "DemoTreeList.h"
00014 #include "TreeNode.h"
00015 #include "IconPair.h"
00016
00017 using namespace Wt;
00018 using std::rand;
00019
00020 DemoTreeList::DemoTreeList(WContainerWidget *parent)
00021 : WContainerWidget(parent),
00022 testCount_(0)
00023 {
00024 addWidget
00025 (new WText(L"<h2>Wt Tree List example</h2>"
00026 L"<p>This is a simple demo of a treelist, implemented using"
00027 L" <a href='http://witty.sourceforge.net/'>Wt</a>.</p>"
00028 L"<p>The leafs of the tree contain the source code of the "
00029 L"tree-list in the classes <b>TreeNode</b> and "
00030 L"<b>IconPair</b>, as well as the implementation of this "
00031 L"demo itself in the class <b>DemoTreeList</b>.</p>"));
00032
00033 tree_ = makeTreeMap(L"Examples", 0);
00034 addWidget(tree_);
00035
00036 TreeNode *treelist = makeTreeMap(L"Tree List", tree_);
00037 TreeNode *wstateicon = makeTreeMap(L"class IconPair", treelist);
00038 makeTreeFile(L"<a href=\"IconPair.h\">IconPair.h</a>", wstateicon);
00039 makeTreeFile(L"<a href=\"IconPair.C\">IconPair.C</a>", wstateicon);
00040 TreeNode *wtreenode = makeTreeMap(L"class TreeNode", treelist);
00041 makeTreeFile(L"<a href=\"TreeNode.h\">TreeNode.h</a>", wtreenode);
00042 makeTreeFile(L"<a href=\"TreeNode.C\">TreeNode.C</a>", wtreenode);
00043 TreeNode *demotreelist = makeTreeMap(L"class DemoTreeList", treelist);
00044 makeTreeFile(L"<a href=\"DemoTreeList.h\">DemoTreeList.h</a>", demotreelist);
00045 makeTreeFile(L"<a href=\"DemoTreeList.C\">DemoTreeList.C</a>", demotreelist);
00046
00047 testMap_ = makeTreeMap(L"Test map", tree_);
00048
00049
00050
00051
00052 addWidget
00053 (new WText(L"<p>Use the following buttons to change the tree "
00054 L"contents:</p>"));
00055
00056 addMapButton_
00057 = new WPushButton(L"Add map", this);
00058 addMapButton_->clicked.connect(SLOT(this, DemoTreeList::addMap));
00059
00060 removeMapButton_
00061 = new WPushButton(L"Remove map", this);
00062 removeMapButton_->clicked.connect(SLOT(this, DemoTreeList::removeMap));
00063 removeMapButton_->disable();
00064
00065 addWidget
00066 (new WText(L"<p>Remarks:"
00067 L"<ul>"
00068 L"<li><p>This is not the instantiation of a pre-defined "
00069 L"tree list component, but the full implementation of such "
00070 L"a component, in about 350 lines of C++ code !</p> "
00071 L"<p>In comparison, the <a href='http://myfaces.apache.org'> "
00072 L"Apache MyFaces</a> JSF implementation of tree2, with similar "
00073 L"functionality, uses about 2400 lines of Java, and 140 lines "
00074 L"of JavaScript code.</p></li>"
00075 L"<li><p>Once loaded, the tree list does not require any "
00076 L"interaction with the server for handling the click events on "
00077 L"the <img src='icons/nav-plus-line-middle.gif' /> and "
00078 L"<img src='icons/nav-minus-line-middle.gif' /> icons, "
00079 L"because these events have been connected to slots using "
00080 L"STATIC connections. Such connections are converted to the "
00081 L"appropriate JavaScript code that is inserted into the page. "
00082 L"Still, the events are signaled to the server to update the "
00083 L"application state.</p></li>"
00084 L"<li><p>In contrast, the buttons for manipulating the tree "
00085 L"contents use DYNAMIC connections, and thus the update "
00086 L"is computed at server-side, and communicated back to the "
00087 L"browser (by default using AJAX).</p></li>"
00088 L"<li><p>When loading a page, only visible widgets (that are not "
00089 L"<b>setHidden(true)</b>) are transmitted. "
00090 L"The remaining widgets are loaded in the background after "
00091 L"rendering the page. "
00092 L"As a result the application is loaded as fast as possible.</p>"
00093 L"</li>"
00094 L"<li><p>The browser reload button is supported and behaves as "
00095 L"expected: the page is reloaded from the server. Again, "
00096 L"only visible widgets are transmitted immediately.</p> "
00097 L"<p>(For the curious, this is the way to see the actual "
00098 L"HTML/JavaScript code !)</p></li>"
00099 L"</ul></p>"));
00100 }
00101
00102 void DemoTreeList::addMap()
00103 {
00104 TreeNode *node
00105 = makeTreeMap(L"Map " + boost::lexical_cast<std::wstring>(++testCount_),
00106 testMap_);
00107 makeTreeFile(L"File " + boost::lexical_cast<std::wstring>(testCount_),
00108 node);
00109
00110 removeMapButton_->enable();
00111 }
00112
00113 void DemoTreeList::removeMap()
00114 {
00115 int numMaps = testMap_->childNodes().size();
00116
00117 if (numMaps > 0) {
00118 int c = rand() % numMaps;
00119
00120 TreeNode *child = testMap_->childNodes()[c];
00121 testMap_->removeChildNode(child);
00122 delete child;
00123
00124 if (numMaps == 1)
00125 removeMapButton_->disable();
00126 }
00127 }
00128
00129 TreeNode *DemoTreeList::makeTreeMap(const std::wstring name, TreeNode *parent)
00130 {
00131 IconPair *labelIcon
00132 = new IconPair("icons/yellow-folder-closed.png",
00133 "icons/yellow-folder-open.png",
00134 false);
00135
00136 TreeNode *node = new TreeNode(name, WText::PlainFormatting, labelIcon, 0);
00137 if (parent)
00138 parent->addChildNode(node);
00139
00140 return node;
00141 }
00142
00143 TreeNode *DemoTreeList::makeTreeFile(const std::wstring name,
00144 TreeNode *parent)
00145 {
00146 IconPair *labelIcon
00147 = new IconPair("icons/document.png", "icons/yellow-folder-open.png",
00148 false);
00149
00150 TreeNode *node = new TreeNode(name, WText::XHTMLFormatting, labelIcon, 0);
00151 if (parent)
00152 parent->addChildNode(node);
00153
00154 return node;
00155 }
00156
00157 WApplication *createApplication(const WEnvironment& env)
00158 {
00159 WApplication *app = new WApplication(env);
00160 new DemoTreeList(app->root());
00161
00162
00163
00164
00165
00166
00167 WCssDecorationStyle treeNodeLabelStyle;
00168 treeNodeLabelStyle.font().setFamily(WFont::Serif, L"Helvetica");
00169 app->styleSheet().addRule(".treenodelabel", treeNodeLabelStyle);
00170
00171
00172
00173
00174 app->styleSheet().addRule(".treenodechildcount",
00175 L"color:blue; font-family:Helvetica,serif;");
00176
00177 return app;
00178 }
00179
00180 int main(int argc, char **argv)
00181 {
00182 return WRun(argc, argv, &createApplication);
00183 }
00184