cwidget 0.5.18
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
31namespace 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
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:47
Definition: subtree.h:254
Definition: subtree.h:40
Definition: treeitem.h:48
Definition: treeitem.h:105
Definition: treeitem.h:209
Support for defining and remapping keybindings.
The namespace containing everything defined by cwidget.
Definition: columnify.cc:28