00001
00002
00003
00004
00005
00006 #include <boost/lexical_cast.hpp>
00007 #include <Wt/WTable>
00008 #include <Wt/WTableCell>
00009 #include <Wt/WImage>
00010 #include <Wt/WText>
00011 #include <Wt/WCssDecorationStyle>
00012
00013 #include "TreeNode.h"
00014 #include "IconPair.h"
00015
00016 using std::find;
00017
00018 std::string TreeNode::imageLine_[] = { "icons/line-middle.gif",
00019 "icons/line-last.gif" };
00020 std::string TreeNode::imagePlus_[] = { "icons/nav-plus-line-middle.gif",
00021 "icons/nav-plus-line-last.gif" };
00022 std::string TreeNode::imageMin_[] = { "icons/nav-minus-line-middle.gif",
00023 "icons/nav-minus-line-last.gif" };
00024
00025 TreeNode::TreeNode(const std::string labelText,
00026 Wt::TextFormat labelFormat,
00027 IconPair *labelIcon,
00028 Wt::WContainerWidget *parent)
00029 : Wt::WCompositeWidget(parent),
00030 parentNode_(0),
00031 labelIcon_(labelIcon)
00032 {
00033
00034 implementStateless(&TreeNode::expand, &TreeNode::undoExpand);
00035 implementStateless(&TreeNode::collapse, &TreeNode::undoCollapse);
00036
00037
00038
00039
00040
00041
00042 setImplementation(layout_ = new Wt::WTable());
00043
00044 expandIcon_ = new IconPair(imagePlus_[Last], imageMin_[Last]);
00045 expandIcon_->hide();
00046 noExpandIcon_ = new Wt::WImage(imageLine_[Last]);
00047
00048 expandedContent_ = new Wt::WContainerWidget();
00049 expandedContent_->hide();
00050
00051 labelText_ = new Wt::WText(labelText);
00052 labelText_->setTextFormat(labelFormat);
00053 labelText_->setStyleClass("treenodelabel");
00054 childCountLabel_ = new Wt::WText();
00055 childCountLabel_->setMargin(7, Wt::Left);
00056 childCountLabel_->setStyleClass("treenodechildcount");
00057
00058 layout_->elementAt(0, 0)->addWidget(expandIcon_);
00059 layout_->elementAt(0, 0)->addWidget(noExpandIcon_);
00060
00061 if (labelIcon_) {
00062 layout_->elementAt(0, 1)->addWidget(labelIcon_);
00063 labelIcon_->setVerticalAlignment(Wt::AlignMiddle);
00064 }
00065 layout_->elementAt(0, 1)->addWidget(labelText_);
00066 layout_->elementAt(0, 1)->addWidget(childCountLabel_);
00067
00068 layout_->elementAt(1, 1)->addWidget(expandedContent_);
00069
00070 layout_->elementAt(0, 0)->setContentAlignment(Wt::AlignTop);
00071 layout_->elementAt(0, 1)->setContentAlignment(Wt::AlignMiddle);
00072
00073 expandIcon_->icon1Clicked.connect(SLOT(this, TreeNode::expand));
00074 expandIcon_->icon2Clicked.connect(SLOT(this, TreeNode::collapse));
00075 }
00076
00077 bool TreeNode::isLastChildNode() const
00078 {
00079 if (parentNode_) {
00080 return parentNode_->childNodes_.back() == this;
00081 } else
00082 return true;
00083 }
00084
00085 void TreeNode::addChildNode(TreeNode *node)
00086 {
00087 childNodes_.push_back(node);
00088 node->parentNode_ = this;
00089
00090 expandedContent_->addWidget(node);
00091
00092 childNodesChanged();
00093 }
00094
00095 void TreeNode::removeChildNode(TreeNode *node)
00096 {
00097 childNodes_.erase(find(childNodes_.begin(), childNodes_.end(), node));
00098
00099 node->parentNode_ = 0;
00100
00101 expandedContent_->removeWidget(node);
00102
00103 childNodesChanged();
00104 }
00105
00106 void TreeNode::childNodesChanged()
00107 {
00108 for (unsigned i = 0; i < childNodes_.size(); ++i)
00109 childNodes_[i]->adjustExpandIcon();
00110
00111 adjustExpandIcon();
00112
00113 if (childNodes_.size())
00114 childCountLabel_
00115 ->setText("(" + boost::lexical_cast<std::string>(childNodes_.size())
00116 + ")");
00117 else
00118 childCountLabel_->setText("");
00119
00120 resetLearnedSlots();
00121 }
00122
00123 void TreeNode::collapse()
00124 {
00125 wasCollapsed_ = expandedContent_->isHidden();
00126
00127 expandIcon_->setState(0);
00128 expandedContent_->hide();
00129 if (labelIcon_)
00130 labelIcon_->setState(0);
00131 }
00132
00133 void TreeNode::expand()
00134 {
00135 wasCollapsed_ = expandedContent_->isHidden();
00136
00137 expandIcon_->setState(1);
00138 expandedContent_->show();
00139 if (labelIcon_)
00140 labelIcon_->setState(1);
00141
00142
00143
00144
00145 for (unsigned i = 0; i < childNodes_.size(); ++i)
00146 childNodes_[i]->collapse();
00147 }
00148
00149 void TreeNode::undoCollapse()
00150 {
00151 if (!wasCollapsed_) {
00152
00153 expandIcon_->setState(1);
00154 expandedContent_->show();
00155 if (labelIcon_)
00156 labelIcon_->setState(1);
00157 }
00158 }
00159
00160 void TreeNode::undoExpand()
00161 {
00162 if (wasCollapsed_) {
00163
00164 expandIcon_->setState(0);
00165 expandedContent_->hide();
00166 if (labelIcon_)
00167 labelIcon_->setState(0);
00168 }
00169
00170
00171
00172
00173 for (unsigned i = 0; i < childNodes_.size(); ++i)
00174 childNodes_[i]->undoCollapse();
00175 }
00176
00177 void TreeNode::adjustExpandIcon()
00178 {
00179 ImageIndex index = isLastChildNode() ? Last : Middle;
00180
00181 if (expandIcon_->icon1()->imageRef() != imagePlus_[index])
00182 expandIcon_->icon1()->setImageRef(imagePlus_[index]);
00183 if (expandIcon_->icon2()->imageRef() != imageMin_[index])
00184 expandIcon_->icon2()->setImageRef(imageMin_[index]);
00185 if (noExpandIcon_->imageRef() != imageLine_[index])
00186 noExpandIcon_->setImageRef(imageLine_[index]);
00187
00188 if (index == Last) {
00189 layout_->elementAt(0, 0)
00190 ->decorationStyle().setBackgroundImage("");
00191 layout_->elementAt(1, 0)
00192 ->decorationStyle().setBackgroundImage("");
00193 } else {
00194 layout_->elementAt(0, 0)
00195 ->decorationStyle().setBackgroundImage("icons/line-trunk.gif",
00196 Wt::WCssDecorationStyle::RepeatY);
00197 layout_->elementAt(1, 0)
00198 ->decorationStyle().setBackgroundImage("icons/line-trunk.gif",
00199 Wt::WCssDecorationStyle::RepeatY);
00200 }
00201
00202 if (childNodes_.empty()) {
00203 if (noExpandIcon_->isHidden()) {
00204 noExpandIcon_->show();
00205 expandIcon_->hide();
00206 }
00207 } else {
00208 if (expandIcon_->isHidden()) {
00209 noExpandIcon_->hide();
00210 expandIcon_->show();
00211 }
00212 }
00213 }