cwidget  0.5.17
treeitem.h
1 // treeitem.h (this is -*-c++-*-)
2 //
3 // Copyright 1999-2001, 2004-2005, 2007 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 // The basic tree item declaration (moved here to reduce the size of
21 // tree.h)
22 //
23 // I think this is *TOO* general. A simplified version will probably be
24 // introduced at some point -- but the API should be fairly stable and nothing
25 // outside this file is likely to change significantly. Yeah, right.
26 
27 #ifndef TREEITEM_H
28 #define TREEITEM_H
29 
30 #include <stdlib.h>
31 
32 #include <cwidget/curses++.h>
33 #include <cwidget/style.h>
34 
35 #include "minibuf_win.h"
36 
37 namespace cwidget
38 {
39  namespace widgets
40  {
41  class tree;
42  class treeitem;
43  class sortpolicy;
44 
46  // A generic way to iterate over a *single level* of a tree. Not really an
47  // "iterator" since it doesn't do the operators and so on.
48  {
49  tree_levelref *parent;
50  public:
51  tree_levelref():parent(NULL) {}
53  :parent(x.parent?x.parent->clone():NULL) {}
54  virtual ~tree_levelref() {}
55 
56  virtual treeitem *get_item()=0;
57  virtual void advance_next()=0;
58  virtual void return_prev()=0;
59  // Like ++ and --, sort of..
60 
61  virtual bool is_begin()=0;
62  // Should return true if this iterator is at the front of a list (so going
63  // back will do Really Bad Things) -- many STL containers need this..
64  virtual bool is_end()=0;
65  // Should return true if this iterator no longer refers to something valid.
66 
67  virtual tree_levelref *clone() const=0;
68 
69  friend class treeiterator;
70  };
71 
73  // A dummy iterator for use on parent-less trees (all other iterators
74  // assume that they have a valid parent -- er?)
75  {
76  treeitem *val;
77  treeitem *prevval;
78 
79  treeitem *get_item() {return val;}
80  public:
81  tree_root_iterator(treeitem *_val):val(_val), prevval(NULL) {}
82  tree_root_iterator(const tree_root_iterator &x):tree_levelref(x), val(x.val), prevval(x.prevval) {}
83 
84  void advance_next() {if(val) { prevval=val; val=NULL;} }
85  void return_prev() {if(prevval) {val=prevval; prevval=NULL;} }
86 
87  tree_root_iterator *clone() const {return new tree_root_iterator(*this);}
88 
89  bool is_end() {return !val;}
90  bool is_begin() {return prevval==NULL;}
91 
92  // Returns an "end iterator" for this tree
93  tree_root_iterator *end()
94  {
95  tree_root_iterator *rval=new tree_root_iterator(*this);
96  rval->advance_next();
97  return rval;
98  }
99  };
100 
101  class treeitem
102  // An abstracted item (could be a leaf node or a subtree) -- this isn't really
103  // meant to be that useful in general, derive from the specialized children
104  // instead.
105  {
106  int depth;
107  bool selectable;
108  protected:
109  virtual void set_depth(int _depth) {depth=_depth;}
110  virtual void set_selectable(bool _selectable) {selectable=_selectable;}
111  public:
112  treeitem(bool _selectable=true):depth(0),selectable(_selectable) {}
113 
126  virtual void paint(tree *win, int y, bool hierarchical,
127  const style &st)=0;
128 
138  void paint(tree *win, int y, bool hierarchical,
139  const std::wstring &str, int depth_shift=2);
140 
141  virtual const wchar_t *tag()=0;
142  // The tag that this item should be sorted by [for the trivial version of
143  // the subtree object]
144  virtual const wchar_t *label()=0;
145  // The label to display when this item is "active" in non-hierarchical mode.
146 
147  int get_depth() {return depth;}
148  bool get_selectable() {return selectable;}
149 
150  virtual style get_normal_style() {return style();}
151  virtual style get_highlight_style() {return get_normal_style()+style_attrs_flip(A_REVERSE);}
152 
153  virtual void sort(sortpolicy &sort_method) {}
154  // Sorts an item's subtree using the given method.
155 
156  virtual void sort() {}
157  // Sorts an item's subtree (NOP for most items) -- provided to make it easy
158  // to recursively sort the list.
159 
169 
171  sigc::signal1<void, bool> highlighted_changed;
172 
174 
175  virtual bool dispatch_key(const config::key &k, tree *owner) {return false;}
176  // Called when a key is pressed while the item is highlighted. The return
177  // value indicates whether a redraw of the screen is needed.
178  // (not any more; now it indicates whether the item consumed the keystroke
179  // -- this also triggers a screen repainting, but is a more useful semantic)
180  virtual void dispatch_mouse(short id, int x, mmask_t bstate, tree *owner)
181  {
182  }
183  // Called when a mouse event occurs at the y location assigned to this
184  // item.
185 
186  virtual tree_levelref *begin() {return NULL;}
187  virtual tree_levelref *end() {return NULL;}
188  // These can act like containers; these routines return a NEWLY ALLOCATED
189  // POINTER, though.
190 
191  virtual bool has_visible_children() {return false;}
192  virtual bool has_children() {return false;}
193 
194  virtual bool matches(const std::wstring &s) const {return false;}
195  // Returns true if this item matches the given string.
196 
197  // More hackery: do what's needed to expand the children of this item.
198  virtual void expand() {}
199  virtual void expand_all() {}
200  virtual void collapse_all() {}
201 
202  template<class childtype, class sorter>
203  friend class subtree;
204 
205  virtual ~treeitem() {}
206  };
207 
209  {
210  tree_levelref *curr;
211  bool ignore_collapsed;
212 
213  public:
214  treeiterator(tree_levelref *_curr, bool _ignore_collapsed=false):curr(_curr),ignore_collapsed(_ignore_collapsed) {}
215  treeiterator(const treeiterator &x):curr(x.curr?x.curr->clone():NULL),ignore_collapsed(x.ignore_collapsed) {}
216  treeiterator(const treeiterator &x, bool _ignore_collapsed):curr(x.curr?x.curr->clone():NULL),ignore_collapsed(_ignore_collapsed) {}
217 
218  bool is_root() {return curr->parent==NULL;}
219  // Ugh, a really nasty hack.
220  treeiterator get_up()
221  {
222  return treeiterator(curr->parent->clone());
223  }
224 
225  void expand()
226  {
227  if(curr && curr->get_item())
228  curr->get_item()->expand();
229  }
230 
231  treeitem &operator*() {return *curr->get_item();}
232  const treeitem &operator*() const {return *curr->get_item();}
233  treeitem *operator->() {return curr->get_item();}
234  const treeitem *operator->() const {return curr->get_item();}
235 
236  bool operator==(const treeiterator &x)
237  {
238  if(!curr)
239  return !x.curr;
240  else if(!x.curr)
241  return false;
242  else if(curr->is_end())
243  return x.curr->is_end() && curr->parent == x.curr->parent;
244  else if(x.curr->is_end())
245  return false;
246  else
247  return curr->get_item()==x.curr->get_item();
248  }
249  bool operator!=(const treeiterator &x)
250  {return !(*this==x);}
251 
252  treeiterator &operator=(const treeiterator &x)
253  {
254  while(curr)
255  {
256  tree_levelref *old=curr;
257  curr=curr->parent;
258  delete old;
259  }
260 
261  curr=x.curr?x.curr->clone():NULL;
262 
263  return *this;
264  }
265 
266  treeiterator &operator++()
267  {
268  if(curr->get_item() &&
269  (ignore_collapsed?curr->get_item()->has_children():curr->get_item()->has_visible_children()))
270  {
271  tree_levelref *newref=curr->get_item()->begin();
272  newref->parent=curr;
273  curr=newref;
274  }
275  else
276  {
277  curr->advance_next();
278 
279  while(curr->is_end() && curr->parent)
280  {
281  tree_levelref *old=curr;
282  curr=curr->parent;
283  curr->advance_next();
284  delete old;
285  }
286  }
287 
288  return *this;
289  }
290  treeiterator operator++(int)
291  {
292  treeiterator oldval(curr?curr->clone():NULL);
293 
294  ++*this;
295 
296  return oldval;
297  }
298 
299  treeiterator &operator--()
300  {
301  if(curr->is_begin())
302  {
303  if(curr->parent)
304  {
305  tree_levelref *old=curr;
306  curr=curr->parent;
307  delete old;
308  }
309  }
310  else
311  {
312  curr->return_prev();
313  while(curr->get_item() &&
314  (ignore_collapsed?curr->get_item()->has_children():curr->get_item()->has_visible_children()))
315  {
316  tree_levelref *newref=curr->get_item()->end();
317 
318  newref->parent=curr;
319  newref->return_prev();
320  curr=newref;
321  }
322  }
323  return *this;
324  }
325 
326  treeiterator operator--(int)
327  {
328  treeiterator oldval(curr?curr->clone():NULL);
329 
330  --*this;
331 
332  return oldval;
333  }
334 
335  void move_forward_level()
336  {
337  if(!curr->is_end())
338  {
339  tree_levelref *old=curr->clone();
340  curr->advance_next();
341 
342  if(curr->is_end())
343  {
344  delete curr;
345  curr=old;
346  }
347  else
348  delete old;
349  }
350  }
351 
352  void move_backward_level()
353  {
354  if(!curr->is_begin())
355  curr->return_prev();
356  }
357 
358  ~treeiterator()
359  {
360  while(curr)
361  {
362  tree_levelref *old=curr;
363  curr=curr->parent;
364  delete old;
365  }
366  }
367  };
368 
369  // A generic sorter.
370  //
371  // Making operator() virtual is a bit icky.
373  {
374  public:
375  sortpolicy() {}
376 
377  virtual bool operator()(treeitem *item1,
378  treeitem *item2)=0;
379 
380  virtual ~sortpolicy() {}
381  };
382 
383  // ack! How dare this be templated?
384  //template<class childtype>
386  {
387  public:
388  bool operator()(treeitem *item1, treeitem *item2)
389  {
390  return (wcscmp(item1->tag(), item2->tag())<0);
391  }
392  };
393 
394  // Hack? hmm..
395  //
396  // Here's the situation: STL sort passes the sort method by value, probably
397  // to keep people from being horrendously inefficient like I'm about to. But
398  // we can get around that with an inline wrapper:
400  {
401  sortpolicy &real_policy;
402  public:
403  sortpolicy_wrapper(sortpolicy &_real_policy):real_policy(_real_policy)
404  {
405  }
406 
407  inline bool operator()(treeitem *item1,
408  treeitem *item2) const
409  {
410  return real_policy(item1, item2);
411  }
412  };
413  }
414 }
415 
416 #endif
A "style" is a setting to be applied to a display element (widget, text, etc).
Definition: style.h:51
style style_attrs_flip(attr_t attrs)
Definition: style.h:235
Definition: subtree.h:36
Definition: treeitem.h:372
The namespace containing everything defined by cwidget.
Definition: columnify.cc:26
label widgets display some (possibly formatted) text statically.
Definition: label.h:24
Definition: treeitem.h:385
Definition: treeitem.h:101
Represents a keystroke as seen by curses.
Definition: keybindings.h:42
sigc::signal1< void, bool > highlighted_changed
A signal emitted when the tree-item is highlighted or unhighlighted.
Definition: treeitem.h:171
Definition: treeitem.h:45
Definition: treeitem.h:208
Definition: tree.h:57
Definition: treeitem.h:72
Definition: treeitem.h:399