cwidget  0.5.17
subtree.h
1 // subtree.h (this is -*-c++-*-)
2 //
3 // Copyright 1999-2003, 2005 Daniel Burrows
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; see the file COPYING. If not, write to
17 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 // Boston, MA 02111-1307, USA.
19 //
20 // Subtrees for trees.
21 
22 #ifndef SUBTREE_H
23 #define SUBTREE_H
24 
25 #include <list>
26 #include "treeitem.h"
27 #include "tree.h"
28 
30 
31 namespace cwidget
32 {
33  namespace widgets
34  {
35  template<class childtype, class default_sorter=tag_sort_policy>
36  class subtree:virtual public treeitem
37  // A tree-item which can contain other tree items. Still abstract -- the
38  // display routines have to be filled in, and you may want to add more behavior
39  // on keypresses -- but we're getting there :)
40  {
41  protected:
42 
43  typedef std::list<childtype *> child_list;
44  typedef typename std::list<childtype *>::iterator child_iterator;
45 
46  class levelref:public tree_levelref
47  {
48  child_iterator realitem;
49 
50  child_list *parent_list;
51  public:
52  levelref(const levelref &x)
53  :tree_levelref(x), realitem(x.realitem), parent_list(x.parent_list) {}
54  levelref(const child_iterator &_realitem, child_list *_parent_list)
55  :realitem(_realitem), parent_list(_parent_list)
56  {
57  }
58 
59  treeitem *get_item() {eassert(realitem!=parent_list->end()); return *realitem;}
60  virtual void advance_next() {++realitem;}
61  virtual void return_prev() {--realitem;}
62  bool is_begin() {return realitem==parent_list->begin();}
63  bool is_end() {return realitem==parent_list->end();}
64  levelref *clone() const {return new levelref(*this);}
65  };
66 
67  private:
68  bool expanded;
69 
70  child_list children;
71 
72  protected:
73  child_iterator get_children_begin() {return children.begin();}
74  child_iterator get_children_end() {return children.end();}
75 
76  public:
77  typedef treeiterator iterator;
78  typedef default_sorter default_sort;
79 
80  subtree(bool _expanded):treeitem(),expanded(_expanded) {}
81 
82  bool get_expanded() {return expanded;}
83 
84  void expand() {expanded=true;}
85 
86  void expand_all()
87  {
88  expanded=true;
89  for(child_iterator i=children.begin(); i!=children.end(); i++)
90  (*i)->expand_all();
91  }
92 
93  void collapse_all()
94  {
95  expanded=false;
96  for(child_iterator i=children.begin(); i!=children.end(); i++)
97  (*i)->collapse_all();
98  }
99 
100  void paint(tree *win, int y, bool hierarchical,
101  const std::wstring &str, int depth_shift=2)
102  {
103  int width, height;
104  int basex=hierarchical?depth_shift*get_depth():0;
105  win->getmaxyx(height,width);
106 
107  win->move(y,0);
108 
109  int x=0;
110  while(x<basex && x<width)
111  {
112  win->add_wch(L' ');
113  x+=wcwidth(L' ');
114  }
115 
116  if(basex>width)
117  return;
118 
119  const wchar_t *ws;
120  if(hierarchical)
121  ws=get_expanded()?L"--\\ ":L"--- ";
122  else
123  ws=L"-> ";
124 
125  while(*ws!=0 && x<width)
126  {
127  win->add_wch(*ws);
128  x+=wcwidth(*ws);
129  ++ws;
130  }
131 
132  if(x>=width)
133  return;
134 
135  size_t i=0;
136  while(i<str.size() && x<width)
137  {
138  wchar_t ch=str[i];
139 
140  win->add_wch(ch);
141  x+=wcwidth(ch);
142  ++i;
143  }
144 
145  while(x<width)
146  {
147  win->add_wch(L' ');
148  x+=wcwidth(L' ');
149  }
150  }
151 
152  void set_depth(int _depth)
153  {
154  for(child_iterator i=children.begin(); i!=children.end(); i++)
155  (*i)->set_depth(_depth+1);
156 
157  treeitem::set_depth(_depth);
158  }
159 
160  void add_child(childtype *newchild)
161  {
162  newchild->set_depth(get_depth()+1);
163 
164  children.push_back(newchild);
165  }
166 
167  // Adds a new child item at an unspecified location -- you should call sort()
168  // after adding children or the tree will have an undetermined order. (yes,
169  // you can deduce the real order. Don't.)
170  void sort(sortpolicy &sort_method)
171  {
172  for(child_iterator i=children.begin(); i!=children.end(); i++)
173  (*i)->sort(sort_method);
174 
175  children.sort(sortpolicy_wrapper(sort_method));
176  }
177 
178  void sort()
179  {
180  default_sort sorter;
181  sort(sorter);
182  }
183 
184  virtual bool dispatch_key(const config::key &k, tree *owner)
185  {
186  if(tree::bindings->key_matches(k, "ToggleExpanded"))
187  {
188  expanded=!expanded;
189  return true;
190  }
191  else if(tree::bindings->key_matches(k, "ExpandTree"))
192  {
193  if(!expanded)
194  {
195  expanded=true;
196  return true;
197  }
198  else
199  return false;
200  }
201  else if(tree::bindings->key_matches(k, "CollapseTree"))
202  {
203  if(expanded)
204  {
205  expanded=false;
206  return true;
207  } else
208  return false;
209  }
210  else if(tree::bindings->key_matches(k, "ExpandAll"))
211  {
212  expand_all();
213  return true;
214  }
215  else if(tree::bindings->key_matches(k, "CollapseAll"))
216  {
217  collapse_all();
218  return true;
219  }
220  return false;
221  }
222  // The default action is to expand or shrink the tree when Enter is pressed.
223  // FIXME: should I use '+' and '-' here? That would appear to conflict with
224  // the other keybindings I need. Hm.
225 
226  virtual void dispatch_mouse(short id, int x, mmask_t bstate, tree *owner)
227  {
228  if(bstate & (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED |
229  BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED |
230  BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED |
231  BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED))
232  expanded=!expanded;
233  }
234 
235  virtual levelref *begin() {return new levelref(children.begin(), &children);}
236  virtual levelref *end() {return new levelref(children.end(), &children);}
237 
238  bool has_visible_children() {return expanded && children.size()>0;}
239  bool has_children() {return children.size()>0;}
240 
241  virtual ~subtree()
242  {
243  child_iterator i,j;
244  for(i=children.begin(); i!=children.end(); i=j)
245  {
246  j=i;
247  j++;
248  delete *i;
249  }
250  }
251  };
252 
253  class subtree_generic:public subtree<treeitem>
254  {
255  public:
256  subtree_generic(int _expanded):subtree<treeitem>(_expanded) {}
257  };
258  }
259 }
260 
261 #endif
Definition: subtree.h:36
Definition: treeitem.h:372
Definition: subtree.h:253
The namespace containing everything defined by cwidget.
Definition: columnify.cc:26
Definition: subtree.h:46
Definition: treeitem.h:101
Represents a keystroke as seen by curses.
Definition: keybindings.h:42
Support for defining and remapping keybindings.
Definition: treeitem.h:45
Definition: treeitem.h:208
Definition: tree.h:57
Definition: treeitem.h:399