subtree.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef SUBTREE_H
00023 #define SUBTREE_H
00024
00025 #include <list>
00026 #include "treeitem.h"
00027 #include "tree.h"
00028
00029 #include <cwidget/config/keybindings.h>
00030
00031 namespace cwidget
00032 {
00033 namespace widgets
00034 {
00035 template<class childtype, class default_sorter=tag_sort_policy>
00036 class subtree:virtual public treeitem
00037
00038
00039
00040 {
00041 protected:
00042
00043 typedef std::list<childtype *> child_list;
00044 typedef typename std::list<childtype *>::iterator child_iterator;
00045
00046 class levelref:public tree_levelref
00047 {
00048 child_iterator realitem;
00049
00050 child_list *parent_list;
00051 public:
00052 levelref(const levelref &x)
00053 :tree_levelref(x), realitem(x.realitem), parent_list(x.parent_list) {}
00054 levelref(const child_iterator &_realitem, child_list *_parent_list)
00055 :realitem(_realitem), parent_list(_parent_list)
00056 {
00057 }
00058
00059 treeitem *get_item() {eassert(realitem!=parent_list->end()); return *realitem;}
00060 virtual void advance_next() {++realitem;}
00061 virtual void return_prev() {--realitem;}
00062 bool is_begin() {return realitem==parent_list->begin();}
00063 bool is_end() {return realitem==parent_list->end();}
00064 levelref *clone() const {return new levelref(*this);}
00065 };
00066
00067 private:
00068 bool expanded;
00069
00070 child_list children;
00071
00072 protected:
00073 child_iterator get_children_begin() {return children.begin();}
00074 child_iterator get_children_end() {return children.end();}
00075
00076 public:
00077 typedef treeiterator iterator;
00078 typedef default_sorter default_sort;
00079
00080 subtree(bool _expanded):treeitem(),expanded(_expanded) {}
00081
00082 bool get_expanded() {return expanded;}
00083
00084 void expand() {expanded=true;}
00085
00086 void expand_all()
00087 {
00088 expanded=true;
00089 for(child_iterator i=children.begin(); i!=children.end(); i++)
00090 (*i)->expand_all();
00091 }
00092
00093 void collapse_all()
00094 {
00095 expanded=false;
00096 for(child_iterator i=children.begin(); i!=children.end(); i++)
00097 (*i)->collapse_all();
00098 }
00099
00100 void paint(tree *win, int y, bool hierarchical,
00101 const std::wstring &str, int depth_shift=2)
00102 {
00103 int width, height;
00104 int basex=hierarchical?depth_shift*get_depth():0;
00105 win->getmaxyx(height,width);
00106
00107 win->move(y,0);
00108
00109 int x=0;
00110 while(x<basex && x<width)
00111 {
00112 win->add_wch(L' ');
00113 x+=wcwidth(L' ');
00114 }
00115
00116 if(basex>width)
00117 return;
00118
00119 const wchar_t *ws;
00120 if(hierarchical)
00121 ws=get_expanded()?L"--\\ ":L"--- ";
00122 else
00123 ws=L"-> ";
00124
00125 while(*ws!=0 && x<width)
00126 {
00127 win->add_wch(*ws);
00128 x+=wcwidth(*ws);
00129 ++ws;
00130 }
00131
00132 if(x>=width)
00133 return;
00134
00135 size_t i=0;
00136 while(i<str.size() && x<width)
00137 {
00138 wchar_t ch=str[i];
00139
00140 win->add_wch(ch);
00141 x+=wcwidth(ch);
00142 ++i;
00143 }
00144
00145 while(x<width)
00146 {
00147 win->add_wch(L' ');
00148 x+=wcwidth(L' ');
00149 }
00150 }
00151
00152 void set_depth(int _depth)
00153 {
00154 for(child_iterator i=children.begin(); i!=children.end(); i++)
00155 (*i)->set_depth(_depth+1);
00156
00157 treeitem::set_depth(_depth);
00158 }
00159
00160 void add_child(childtype *newchild)
00161 {
00162 newchild->set_depth(get_depth()+1);
00163
00164 children.push_back(newchild);
00165 }
00166
00167
00168
00169
00170 void sort(sortpolicy &sort_method)
00171 {
00172 for(child_iterator i=children.begin(); i!=children.end(); i++)
00173 (*i)->sort(sort_method);
00174
00175 children.sort(sortpolicy_wrapper(sort_method));
00176 }
00177
00178 void sort()
00179 {
00180 default_sort sorter;
00181 sort(sorter);
00182 }
00183
00184 virtual bool dispatch_key(const config::key &k, tree *owner)
00185 {
00186 if(tree::bindings->key_matches(k, "ToggleExpanded"))
00187 {
00188 expanded=!expanded;
00189 return true;
00190 }
00191 else if(tree::bindings->key_matches(k, "ExpandTree"))
00192 {
00193 if(!expanded)
00194 {
00195 expanded=true;
00196 return true;
00197 }
00198 else
00199 return false;
00200 }
00201 else if(tree::bindings->key_matches(k, "CollapseTree"))
00202 {
00203 if(expanded)
00204 {
00205 expanded=false;
00206 return true;
00207 } else
00208 return false;
00209 }
00210 else if(tree::bindings->key_matches(k, "ExpandAll"))
00211 {
00212 expand_all();
00213 return true;
00214 }
00215 else if(tree::bindings->key_matches(k, "CollapseAll"))
00216 {
00217 collapse_all();
00218 return true;
00219 }
00220 return false;
00221 }
00222
00223
00224
00225
00226 virtual void dispatch_mouse(short id, int x, mmask_t bstate, tree *owner)
00227 {
00228 if(bstate & (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED |
00229 BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED |
00230 BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED |
00231 BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED))
00232 expanded=!expanded;
00233 }
00234
00235 virtual levelref *begin() {return new levelref(children.begin(), &children);}
00236 virtual levelref *end() {return new levelref(children.end(), &children);}
00237
00238 bool has_visible_children() {return expanded && children.size()>0;}
00239 bool has_children() {return children.size()>0;}
00240
00241 virtual ~subtree()
00242 {
00243 child_iterator i,j;
00244 for(i=children.begin(); i!=children.end(); i=j)
00245 {
00246 j=i;
00247 j++;
00248 delete *i;
00249 }
00250 }
00251 };
00252
00253 class subtree_generic:public subtree<treeitem>
00254 {
00255 public:
00256 subtree_generic(int _expanded):subtree<treeitem>(_expanded) {}
00257 };
00258 }
00259 }
00260
00261 #endif