TreeNode.C 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
  3. *
  4. * See the LICENSE file for terms of use.
  5. */
  6. #include <boost/lexical_cast.hpp>
  7. #include <Wt/WTable>
  8. #include <Wt/WTableCell>
  9. #include <Wt/WImage>
  10. #include <Wt/WText>
  11. #include <Wt/WCssDecorationStyle>
  12. #include "TreeNode.h"
  13. #include "IconPair.h"
  14. using std::find;
  15. std::string TreeNode::imageLine_[] = { "icons/line-middle.gif",
  16. "icons/line-last.gif" };
  17. std::string TreeNode::imagePlus_[] = { "icons/nav-plus-line-middle.gif",
  18. "icons/nav-plus-line-last.gif" };
  19. std::string TreeNode::imageMin_[] = { "icons/nav-minus-line-middle.gif",
  20. "icons/nav-minus-line-last.gif" };
  21. TreeNode::TreeNode(const std::string labelText,
  22. Wt::TextFormat labelFormat,
  23. IconPair *labelIcon,
  24. Wt::WContainerWidget *parent)
  25. : Wt::WCompositeWidget(parent),
  26. parentNode_(0),
  27. labelIcon_(labelIcon)
  28. {
  29. // pre-learned stateless implementations ...
  30. implementStateless(&TreeNode::expand, &TreeNode::undoExpand);
  31. implementStateless(&TreeNode::collapse, &TreeNode::undoCollapse);
  32. // ... or auto-learned stateless implementations
  33. // which do not need undo functions
  34. //implementStateless(&TreeNode::expand);
  35. //implementStateless(&TreeNode::collapse);
  36. setImplementation(layout_ = new Wt::WTable());
  37. expandIcon_ = new IconPair(imagePlus_[Last], imageMin_[Last]);
  38. expandIcon_->hide();
  39. noExpandIcon_ = new Wt::WImage(imageLine_[Last]);
  40. expandedContent_ = new Wt::WContainerWidget();
  41. expandedContent_->hide();
  42. labelText_ = new Wt::WText(labelText);
  43. labelText_->setTextFormat(labelFormat);
  44. labelText_->setStyleClass("treenodelabel");
  45. childCountLabel_ = new Wt::WText();
  46. childCountLabel_->setMargin(7, Wt::Left);
  47. childCountLabel_->setStyleClass("treenodechildcount");
  48. layout_->elementAt(0, 0)->addWidget(expandIcon_);
  49. layout_->elementAt(0, 0)->addWidget(noExpandIcon_);
  50. if (labelIcon_) {
  51. layout_->elementAt(0, 1)->addWidget(labelIcon_);
  52. labelIcon_->setVerticalAlignment(Wt::AlignMiddle);
  53. }
  54. layout_->elementAt(0, 1)->addWidget(labelText_);
  55. layout_->elementAt(0, 1)->addWidget(childCountLabel_);
  56. layout_->elementAt(1, 1)->addWidget(expandedContent_);
  57. layout_->elementAt(0, 0)->setContentAlignment(Wt::AlignTop);
  58. layout_->elementAt(0, 1)->setContentAlignment(Wt::AlignMiddle);
  59. expandIcon_->icon1Clicked.connect(this, &TreeNode::expand);
  60. expandIcon_->icon2Clicked.connect(this, &TreeNode::collapse);
  61. } //
  62. bool TreeNode::isLastChildNode() const
  63. {
  64. if (parentNode_) {
  65. return parentNode_->childNodes_.back() == this;
  66. } else
  67. return true;
  68. }
  69. void TreeNode::addChildNode(TreeNode *node)
  70. {
  71. childNodes_.push_back(node);
  72. node->parentNode_ = this;
  73. expandedContent_->addWidget(node);
  74. childNodesChanged();
  75. }
  76. void TreeNode::removeChildNode(TreeNode *node)
  77. {
  78. childNodes_.erase(std::find(childNodes_.begin(), childNodes_.end(), node));
  79. node->parentNode_ = 0;
  80. expandedContent_->removeWidget(node);
  81. childNodesChanged();
  82. } //
  83. void TreeNode::childNodesChanged()
  84. {
  85. for (unsigned i = 0; i < childNodes_.size(); ++i)
  86. childNodes_[i]->adjustExpandIcon();
  87. adjustExpandIcon();
  88. if (childNodes_.size())
  89. childCountLabel_
  90. ->setText("(" + boost::lexical_cast<std::string>(childNodes_.size())
  91. + ")");
  92. else
  93. childCountLabel_->setText("");
  94. resetLearnedSlots();
  95. } //
  96. void TreeNode::collapse()
  97. {
  98. wasCollapsed_ = expandedContent_->isHidden();
  99. expandIcon_->setState(0);
  100. expandedContent_->hide();
  101. if (labelIcon_)
  102. labelIcon_->setState(0);
  103. } //
  104. void TreeNode::expand()
  105. {
  106. wasCollapsed_ = expandedContent_->isHidden();
  107. expandIcon_->setState(1);
  108. expandedContent_->show();
  109. if (labelIcon_)
  110. labelIcon_->setState(1);
  111. /*
  112. * collapse all children
  113. */
  114. for (unsigned i = 0; i < childNodes_.size(); ++i)
  115. childNodes_[i]->collapse();
  116. } //
  117. void TreeNode::undoCollapse()
  118. {
  119. if (!wasCollapsed_) {
  120. // re-expand
  121. expandIcon_->setState(1);
  122. expandedContent_->show();
  123. if (labelIcon_)
  124. labelIcon_->setState(1);
  125. }
  126. }
  127. void TreeNode::undoExpand()
  128. {
  129. if (wasCollapsed_) {
  130. // re-collapse
  131. expandIcon_->setState(0);
  132. expandedContent_->hide();
  133. if (labelIcon_)
  134. labelIcon_->setState(0);
  135. }
  136. /*
  137. * undo collapse of children
  138. */
  139. for (unsigned i = 0; i < childNodes_.size(); ++i)
  140. childNodes_[i]->undoCollapse();
  141. } //
  142. void TreeNode::adjustExpandIcon()
  143. {
  144. ImageIndex index = isLastChildNode() ? Last : Middle;
  145. if (expandIcon_->icon1()->imageLink().url() != imagePlus_[index])
  146. expandIcon_->icon1()->setImageLink(imagePlus_[index]);
  147. if (expandIcon_->icon2()->imageLink().url() != imageMin_[index])
  148. expandIcon_->icon2()->setImageLink(imageMin_[index]);
  149. if (noExpandIcon_->imageLink().url() != imageLine_[index])
  150. noExpandIcon_->setImageLink(imageLine_[index]);
  151. if (index == Last) {
  152. layout_->elementAt(0, 0)
  153. ->decorationStyle().setBackgroundImage("");
  154. layout_->elementAt(1, 0)
  155. ->decorationStyle().setBackgroundImage("");
  156. } else {
  157. layout_->elementAt(0, 0)
  158. ->decorationStyle().setBackgroundImage("icons/line-trunk.gif",
  159. Wt::WCssDecorationStyle::RepeatY);
  160. layout_->elementAt(1, 0)
  161. ->decorationStyle().setBackgroundImage("icons/line-trunk.gif",
  162. Wt::WCssDecorationStyle::RepeatY);
  163. } //
  164. if (childNodes_.empty()) {
  165. if (noExpandIcon_->isHidden()) {
  166. noExpandIcon_->show();
  167. expandIcon_->hide();
  168. }
  169. } else {
  170. if (expandIcon_->isHidden()) {
  171. noExpandIcon_->hide();
  172. expandIcon_->show();
  173. }
  174. }
  175. } //