blob: cce11e729cc7635b6b2a76a0a2c79d2038f5237e [file] [log] [blame]
DRC2ff39b82011-07-28 08:38:59 +00001//
2// "$Id: Fl_Tree.H 8632 2011-05-04 02:59:50Z greg.ercolano $"
3//
4
5#ifndef FL_TREE_H
6#define FL_TREE_H
7
8#include <FL/Fl.H>
9#include <FL/Fl_Group.H>
10#include <FL/Fl_Scrollbar.H>
11#include <FL/fl_draw.H>
12
13#include <FL/Fl_Tree_Item.H>
14#include <FL/Fl_Tree_Prefs.H>
15
16//////////////////////
17// FL/Fl_Tree.H
18//////////////////////
19//
20// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
21// Copyright (C) 2009-2010 by Greg Ercolano.
22//
23// This library is free software; you can redistribute it and/or
24// modify it under the terms of the GNU Library General Public
25// License as published by the Free Software Foundation; either
26// version 2 of the License, or (at your option) any later version.
27//
28// This library is distributed in the hope that it will be useful,
29// but WITHOUT ANY WARRANTY; without even the implied warranty of
30// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31// Library General Public License for more details.
32//
33// You should have received a copy of the GNU Library General Public
34// License along with this library; if not, write to the Free Software
35// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
36// USA.
37//
38
39///
40/// \file
41/// \brief This file contains the definitions of the Fl_Tree class
42///
43
44/// \class Fl_Tree
45///
46/// \brief Tree widget.
47///
48/// \image html tree-simple.png "Fl_Tree example program"
49/// \image latex tree-simple.png "Fl_Tree example program" width=4cm
50///
51/// \code
52/// Fl_Tree // Top level widget
53/// |--- Fl_Tree_Item // Items in the tree
54/// |--- Fl_Tree_Prefs // Preferences for the tree
55/// |--- Fl_Tree_Connector (enum) // Connection modes
56/// |--- Fl_Tree_Select (enum) // Selection modes
57/// |--- Fl_Tree_Sort (enum) // Sort behavior
58/// \endcode
59///
60/// Similar to Fl_Browser, Fl_Tree is a browser of Fl_Tree_Item's, which is arranged
61/// in a parented hierarchy, or 'tree'. Subtrees can be expanded or closed. Items can be
62/// added, deleted, inserted, sorted and re-ordered.
63///
64/// The tree items may also contain other FLTK widgets, like buttons, input fields,
65/// or even "custom" widgets.
66///
67/// The callback() is invoked depending on the value of when():
68///
69/// - FL_WHEN_RELEASE -- callback invoked when left mouse button is released on an item
70/// - FL_WHEN_CHANGED -- callback invoked when left mouse changes selection state
71///
72/// The simple way to define a tree:
73/// \code
74/// #include <FL/Fl_Tree.H>
75/// [..]
76/// Fl_Tree tree(X,Y,W,H);
77/// tree.begin();
78/// tree.add("Flintstones/Fred");
79/// tree.add("Flintstones/Wilma");
80/// tree.add("Flintstones/Pebbles");
81/// tree.add("Simpsons/Homer");
82/// tree.add("Simpsons/Marge");
83/// tree.add("Simpsons/Bart");
84/// tree.add("Simpsons/Lisa");
85/// tree.end();
86/// \endcode
87///
88/// Items can be added with add(),
89/// removed with remove(),
90/// completely cleared with clear(),
91/// inserted with insert() and insert_above(),
92/// selected/deselected with select() and deselect(),
93/// open/closed with open() and closed().
94/// Children of an item can be swapped around with Fl_Tree_Item::swap_children(),
95/// sorting can be controlled when items are add()ed via sortorder().
96/// You can walk the entire tree with first() and next().
97/// You can walk selected items with first_selected_item() and
98/// next_selected_item().
99/// Items can be found by their pathname using find_item(const char*),
100/// and an item's pathname can be found with item_pathname().
101/// The selected items' colors are controlled by selection_color() (inherited from Fl_Widget).
102///
103/// The tree can have different selection behaviors controlled by selectmode().
104///
105/// FLTK widgets (including custom widgets) can be assigned to tree items via
106/// Fl_Tree_Item::widget().
107///
108/// Icons for individual items can be changed with
109/// Fl_Tree_Item::openicon(),
110/// Fl_Tree_Item::closeicon(),
111/// Fl_Tree_Item::usericon().
112///
113/// Various default preferences can be globally manipulated via Fl_Tree_Prefs,
114/// including colors, margins, icons, connection lines.
115///
116/// The tree's callback() will be invoked when items change state or are open/closed.
117/// when() controls when mouse/keyboard events invoke the callback.
118/// callback_item() and callback_reason() can be used to determine the cause of the callback. eg:
119///
120/// \code
121/// void MyTreeCallback(Fl_Widget *w, void *data) {
122/// Fl_Tree *tree = (Fl_Tree*)w;
123/// Fl_Tree_Item *item = (Fl_Tree_Item*)tree->callback_item(); // get selected item
124/// switch ( tree->callback_reason() ) {
125/// case FL_TREE_REASON_SELECTED: [..]
126/// case FL_TREE_REASON_DESELECTED: [..]
127/// case FL_TREE_REASON_OPENED: [..]
128/// case FL_TREE_REASON_CLOSED: [..]
129/// }
130/// \endcode
131///
132/// To get the item's full menu pathname, you can use Fl_Tree_Item::item_pathname(), eg:
133///
134/// \code
135/// char pathname[256] = "???";
136/// tree->item_pathname(pathname, sizeof(pathname), item); // eg. "Parent/Child/Item"
137/// \endcode
138///
139/// To walk all the items of the tree from top to bottom:
140/// \code
141/// // Walk all the items in the tree, and print their labels
142/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) {
143/// printf("Item: %s\n", item->label());
144/// }
145/// \endcode
146///
147/// To recursively walk all the children of a particular item,
148/// define a function that uses recursion:
149/// \code
150/// // Find all of the item's children and print an indented report of their labels
151/// void my_print_all_children(Fl_Tree_Item *item, int indent=0) {
152/// for ( int t=0; t<item->children(); t++ ) {
153/// printf("%*s Item: %s\n", indent, "", item->child(t)->label());
154/// my_print_all_children(item->child(t), indent+4); // recurse
155/// }
156/// }
157/// \endcode
158///
159/// To change the default label font and color for creating new items:
160/// \code
161/// tree = new Fl_Tree(..);
162/// tree->item_labelfont(FL_COURIER); // Use Courier font for all new items
163/// tree->item_labelfgcolor(FL_RED); // Use red color for labels of all new items
164/// [..]
165/// // Now create the items in the tree using the above defaults.
166/// tree->add("Aaa");
167/// tree->add("Bbb");
168/// [..]
169/// \endcode
170///
171/// To change the font and color of all items in the tree:
172/// \code
173/// // Change the font and color of all items currently in the tree
174/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) {
175/// item->labelfont(FL_COURIER);
176/// item->labelcolor(FL_RED);
177/// }
178/// \endcode
179///
180/// The following image shows the tree's various visual elements
181/// and the methods that control them:
182///
183/// \image html tree-elements.png
184/// \image latex tree-elements.png "Fl_Tree dimensions" width=6cm
185///
186
187/// \enum Fl_Tree_Reason
188/// The reason the callback was invoked.
189///
190enum Fl_Tree_Reason {
191 FL_TREE_REASON_NONE=0, ///< unknown reason
192 FL_TREE_REASON_SELECTED, ///< an item was selected
193 FL_TREE_REASON_DESELECTED, ///< an item was de-selected
194 FL_TREE_REASON_OPENED, ///< an item was opened
195 FL_TREE_REASON_CLOSED ///< an item was closed
196};
197
198
199class FL_EXPORT Fl_Tree : public Fl_Group {
200 Fl_Tree_Item *_root; // can be null!
201 Fl_Tree_Item *_item_focus; // item that has focus box
202 Fl_Tree_Item *_callback_item; // item invoked during callback (can be NULL)
203 Fl_Tree_Reason _callback_reason; // reason for the callback
204 Fl_Tree_Prefs _prefs; // all the tree's settings
205 int _scrollbar_size; // size of scrollbar trough
206
207protected:
208 /// Vertical scrollbar
209 Fl_Scrollbar *_vscroll;
210
211protected:
212 void item_clicked(Fl_Tree_Item* val);
213 /// Do the callback for the item, setting the item and reason
214 void do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) {
215 callback_reason(reason);
216 callback_item(item);
217 do_callback((Fl_Widget*)this, user_data());
218 }
219 Fl_Tree_Item *next_visible_item(Fl_Tree_Item *start, int dir);
220
221public:
222 Fl_Tree(int X, int Y, int W, int H, const char *L=0);
223 ~Fl_Tree();
224 int handle(int e);
225 void draw();
226
227 ///////////////////////
228 // root methods
229 ///////////////////////
230
231 /// Set the label for the root item.
232 ///
233 /// Makes an internally managed copy of 'new_label'.
234 ///
235 void root_label(const char *new_label) {
236 if ( ! _root ) return;
237 _root->label(new_label);
238 }
239 /// Returns the root item.
240 Fl_Tree_Item* root() {
241 return(_root);
242 }
243
244 ////////////////////////////////
245 // Item creation/removal methods
246 ////////////////////////////////
247 Fl_Tree_Item *add(const char *path);
248 Fl_Tree_Item* add(Fl_Tree_Item *item, const char *name);
249 Fl_Tree_Item *insert_above(Fl_Tree_Item *above, const char *name);
250 Fl_Tree_Item* insert(Fl_Tree_Item *item, const char *name, int pos);
251
252 /// Remove the specified \p item from the tree.
253 /// \p item may not be NULL.
254 /// If it has children, all those are removed too.
255 /// \returns 0 if done, -1 if 'item' not found.
256 ///
257 int remove(Fl_Tree_Item *item) {
258 if ( item == _root ) {
259 clear();
260 } else {
261 Fl_Tree_Item *parent = item->parent(); // find item's parent
262 if ( ! parent ) return(-1);
263 parent->remove_child(item); // remove child + children
264 }
265 return(0);
266 }
267 /// Clear all children from the tree.
268 /// The tree will be left completely empty.
269 ///
270 void clear() {
271 if ( ! _root ) return;
272 _root->clear_children();
273 delete _root; _root = 0;
274 }
275 /// Clear all the children of a particular node in the tree specified by \p item.
276 /// Item may not be NULL.
277 ///
278 void clear_children(Fl_Tree_Item *item) {
279 if ( item->has_children() ) {
280 item->clear_children();
281 redraw(); // redraw only if there were children to clear
282 }
283 }
284
285 ////////////////////////
286 // Item lookup methods
287 ////////////////////////
288 Fl_Tree_Item *find_item(const char *path);
289 const Fl_Tree_Item *find_item(const char *path) const;
290 int item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item *item) const;
291
292 const Fl_Tree_Item *find_clicked() const;
293
294 /// Return the item that was last clicked.
295 ///
296 /// Valid only from within the callback().
297 ///
298 /// Deprecated: use callback_item() instead.
299 ///
300 /// \returns the item clicked, or 0 if none.
301 /// 0 may also be used to indicate several items were clicked/changed.
302 ///
303 Fl_Tree_Item *item_clicked() {
304 return(_callback_item);
305 }
306 Fl_Tree_Item *first();
307 Fl_Tree_Item *next(Fl_Tree_Item *item=0);
308 Fl_Tree_Item *prev(Fl_Tree_Item *item=0);
309 Fl_Tree_Item *last();
310 Fl_Tree_Item *first_selected_item();
311 Fl_Tree_Item *next_selected_item(Fl_Tree_Item *item=0);
312
313 //////////////////////////
314 // Item open/close methods
315 //////////////////////////
316
317 /// Open the specified 'item'.
318 /// This causes the item's children (if any) to be shown.
319 /// Handles redrawing if anything was actually changed.
320 /// Invokes the callback depending on the value of optional parameter \p docallback.
321 ///
322 /// The callback can use callback_item() and callback_reason() respectively to determine
323 /// the item changed and the reason the callback was called.
324 ///
325 /// \param[in] item -- the item to be opened. Must not be NULL.
326 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
327 /// - 0 - callback() is not invoked
328 /// - 1 - callback() is invoked if item changed,
329 /// callback_reason() will be FL_TREE_REASON_OPENED
330 /// \returns
331 /// - 1 -- item was opened
332 /// - 0 -- item was already open, no change
333 ///
334 /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason()
335 ///
336 int open(Fl_Tree_Item *item, int docallback=1) {
337 if ( item->is_open() ) return(0);
338 item->open();
339 redraw();
340 if ( docallback ) {
341 do_callback_for_item(item, FL_TREE_REASON_OPENED);
342 }
343 return(1);
344 }
345 /// Opens the item specified by \p path (eg: "Parent/child/item").
346 /// This causes the item's children (if any) to be shown.
347 /// Handles redrawing if anything was actually changed.
348 /// Invokes the callback depending on the value of optional parameter \p docallback.
349 ///
350 /// Items or submenus that themselves contain slashes ('/' or '\')
351 /// should be escaped, e.g. open("Holidays/12\\/25\//2010").
352 ///
353 /// The callback can use callback_item() and callback_reason() respectively to determine
354 /// the item changed and the reason the callback was called.
355 ///
356 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
357 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
358 /// - 0 - callback() is not invoked
359 /// - 1 - callback() is invoked if item changed,
360 /// callback_reason() will be FL_TREE_REASON_OPENED
361 /// \returns
362 /// - 1 -- OK: item opened
363 /// - 0 -- OK: item was already open, no change
364 /// - -1 -- ERROR: item was not found
365 ///
366 /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason()
367 ///
368 int open(const char *path, int docallback=1) {
369 Fl_Tree_Item *item = find_item(path);
370 if ( ! item ) return(-1);
371 return(open(item, docallback));
372 }
373 /// Toggle the open state of \p item.
374 /// Handles redrawing if anything was actually changed.
375 /// Invokes the callback depending on the value of optional parameter \p docallback.
376 ///
377 /// The callback can use callback_item() and callback_reason() respectively to determine
378 /// the item changed and the reason the callback was called.
379 ///
380 /// \param[in] item -- the item whose open state is to be toggled. Must not be NULL.
381 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
382 /// - 0 - callback() is not invoked
383 /// - 1 - callback() is invoked, callback_reason() will be either
384 /// FL_TREE_REASON_OPENED or FL_TREE_REASON_CLOSED
385 ///
386 /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason()
387 ///
388 void open_toggle(Fl_Tree_Item *item, int docallback=1) {
389 if ( item->is_open() ) {
390 close(item, docallback);
391 } else {
392 open(item, docallback);
393 }
394 }
395 /// Closes the specified \p item.
396 /// Handles redrawing if anything was actually changed.
397 /// Invokes the callback depending on the value of optional parameter \p docallback.
398 ///
399 /// The callback can use callback_item() and callback_reason() respectively to determine
400 /// the item changed and the reason the callback was called.
401 ///
402 /// \param[in] item -- the item to be closed. Must not be NULL.
403 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
404 /// - 0 - callback() is not invoked
405 /// - 1 - callback() is invoked if item changed,
406 /// callback_reason() will be FL_TREE_REASON_CLOSED
407 /// \returns
408 /// - 1 -- item was closed
409 /// - 0 -- item was already closed, no change
410 ///
411 /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason()
412 ///
413 int close(Fl_Tree_Item *item, int docallback=1) {
414 if ( item->is_close() ) return(0);
415 item->close();
416 redraw();
417 if ( docallback ) {
418 do_callback_for_item(item, FL_TREE_REASON_CLOSED);
419 }
420 return(1);
421 }
422 /// Closes the item specified by \p path, eg: "Parent/child/item".
423 /// Handles redrawing if anything was actually changed.
424 /// Invokes the callback depending on the value of optional parameter \p docallback.
425 ///
426 /// Items or submenus that themselves contain slashes ('/' or '\')
427 /// should be escaped, e.g. close("Holidays/12\\/25\//2010").
428 ///
429 /// The callback can use callback_item() and callback_reason() respectively to determine
430 /// the item changed and the reason the callback was called.
431 ///
432 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
433 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
434 /// - 0 - callback() is not invoked
435 /// - 1 - callback() is invoked if item changed,
436 /// callback_reason() will be FL_TREE_REASON_CLOSED
437 /// \returns
438 /// - 1 -- OK: item closed
439 /// - 0 -- OK: item was already closed, no change
440 /// - -1 -- ERROR: item was not found
441 ///
442 /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason()
443 ///
444 int close(const char *path, int docallback=1) {
445 Fl_Tree_Item *item = find_item(path);
446 if ( ! item ) return(-1);
447 return(close(item, docallback));
448 }
449 /// See if \p item is open.
450 ///
451 /// Items that are 'open' are themselves not necessarily visible;
452 /// one of the item's parents might be closed.
453 ///
454 /// \param[in] item -- the item to be tested. Must not be NULL.
455 /// \returns
456 /// - 1 : item is open
457 /// - 0 : item is closed
458 ///
459 int is_open(Fl_Tree_Item *item) const {
460 return(item->is_open()?1:0);
461 }
462 /// See if item specified by \p path (eg: "Parent/child/item") is open.
463 ///
464 /// Items or submenus that themselves contain slashes ('/' or '\')
465 /// should be escaped, e.g. is_open("Holidays/12\\/25\//2010").
466 ///
467 /// Items that are 'open' are themselves not necessarily visible;
468 /// one of the item's parents might be closed.
469 ///
470 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
471 /// \returns
472 /// - 1 - OK: item is open
473 /// - 0 - OK: item is closed
474 /// - -1 - ERROR: item was not found
475 ///
476 int is_open(const char *path) const {
477 const Fl_Tree_Item *item = find_item(path);
478 if ( ! item ) return(-1);
479 return(item->is_open()?1:0);
480 }
481 /// See if the specified \p item is closed.
482 ///
483 /// \param[in] item -- the item to be tested. Must not be NULL.
484 /// \returns
485 /// - 1 : item is open
486 /// - 0 : item is closed
487 ///
488 int is_close(Fl_Tree_Item *item) const {
489 return(item->is_close());
490 }
491 /// See if item specified by \p path (eg: "Parent/child/item") is closed.
492 ///
493 /// Items or submenus that themselves contain slashes ('/' or '\')
494 /// should be escaped, e.g. is_close("Holidays/12\\/25\//2010").
495 ///
496 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
497 /// \returns
498 /// - 1 - OK: item is closed
499 /// - 0 - OK: item is open
500 /// - -1 - ERROR: item was not found
501 ///
502 int is_close(const char *path) const {
503 const Fl_Tree_Item *item = find_item(path);
504 if ( ! item ) return(-1);
505 return(item->is_close()?1:0);
506 }
507
508 /// Select the specified \p item. Use 'deselect()' to de-select it.
509 /// Handles redrawing if anything was actually changed.
510 /// Invokes the callback depending on the value of optional parameter \p docallback.
511 ///
512 /// The callback can use callback_item() and callback_reason() respectively to determine
513 /// the item changed and the reason the callback was called.
514 ///
515 /// \param[in] item -- the item to be selected. Must not be NULL.
516 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
517 /// - 0 - the callback() is not invoked
518 /// - 1 - the callback() is invoked if item changed state,
519 /// callback_reason() will be FL_TREE_REASON_SELECTED
520 /// \returns
521 /// - 1 - item's state was changed
522 /// - 0 - item was already selected, no change was made
523 ///
524 int select(Fl_Tree_Item *item, int docallback=1) {
525 if ( ! item->is_selected() ) {
526 item->select();
527 set_changed();
528 if ( docallback ) {
529 do_callback_for_item(item, FL_TREE_REASON_SELECTED);
530 }
531 redraw();
532 return(1);
533 }
534 return(0);
535 }
536 /// Select the item specified by \p path (eg: "Parent/child/item").
537 /// Handles redrawing if anything was actually changed.
538 /// Invokes the callback depending on the value of optional parameter \p docallback.
539 ///
540 /// Items or submenus that themselves contain slashes ('/' or '\')
541 /// should be escaped, e.g. select("Holidays/12\\/25\//2010").
542 ///
543 /// The callback can use callback_item() and callback_reason() respectively to determine
544 /// the item changed and the reason the callback was called.
545 ///
546 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
547 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
548 /// - 0 - the callback() is not invoked
549 /// - 1 - the callback() is invoked if item changed state,
550 /// callback_reason() will be FL_TREE_REASON_SELECTED
551 /// \returns
552 /// - 1 : OK: item's state was changed
553 /// - 0 : OK: item was already selected, no change was made
554 /// - -1 : ERROR: item was not found
555 ///
556 int select(const char *path, int docallback=1) {
557 Fl_Tree_Item *item = find_item(path);
558 if ( ! item ) return(-1);
559 return(select(item, docallback));
560 }
561 /// Toggle the select state of the specified \p item.
562 /// Handles redrawing if anything was actually changed.
563 /// Invokes the callback depending on the value of optional parameter \p docallback.
564 ///
565 /// The callback can use callback_item() and callback_reason() respectively to determine
566 /// the item changed and the reason the callback was called.
567 ///
568 /// \param[in] item -- the item to be selected. Must not be NULL.
569 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
570 /// - 0 - the callback() is not invoked
571 /// - 1 - the callback() is invoked, callback_reason() will be
572 /// either FL_TREE_REASON_SELECTED or FL_TREE_REASON_DESELECTED
573 ///
574 void select_toggle(Fl_Tree_Item *item, int docallback=1) {
575 item->select_toggle();
576 set_changed();
577 if ( docallback ) {
578 do_callback_for_item(item, item->is_selected() ? FL_TREE_REASON_SELECTED
579 : FL_TREE_REASON_DESELECTED);
580 }
581 redraw();
582 }
583 /// De-select the specified \p item.
584 /// Handles redrawing if anything was actually changed.
585 /// Invokes the callback depending on the value of optional parameter \p docallback.
586 ///
587 /// The callback can use callback_item() and callback_reason() respectively to determine
588 /// the item changed and the reason the callback was called.
589 ///
590 /// \param[in] item -- the item to be selected. Must not be NULL.
591 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
592 /// - 0 - the callback() is not invoked
593 /// - 1 - the callback() is invoked if item changed state,
594 /// callback_reason() will be FL_TREE_REASON_DESELECTED
595 /// \returns
596 /// - 0 - item was already deselected, no change was made
597 /// - 1 - item's state was changed
598 ///
599 int deselect(Fl_Tree_Item *item, int docallback=1) {
600 if ( item->is_selected() ) {
601 item->deselect();
602 set_changed();
603 if ( docallback ) {
604 do_callback_for_item(item, FL_TREE_REASON_DESELECTED);
605 }
606 redraw();
607 return(1);
608 }
609 return(0);
610 }
611 /// Deselect an item specified by \p path (eg: "Parent/child/item").
612 /// Handles redrawing if anything was actually changed.
613 /// Invokes the callback depending on the value of optional parameter \p docallback.
614 ///
615 /// Items or submenus that themselves contain slashes ('/' or '\')
616 /// should be escaped, e.g. deselect("Holidays/12\\/25\//2010").
617 ///
618 /// The callback can use callback_item() and callback_reason() respectively to determine
619 /// the item changed and the reason the callback was called.
620 ///
621 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
622 /// \param[in] docallback -- A flag that determines if the callback() is invoked or not:
623 /// - 0 - the callback() is not invoked
624 /// - 1 - the callback() is invoked if item changed state,
625 /// callback_reason() will be FL_TREE_REASON_DESELECTED
626 /// \returns
627 /// - 1 - OK: item's state was changed
628 /// - 0 - OK: item was already deselected, no change was made
629 /// - -1 - ERROR: item was not found
630 ///
631 int deselect(const char *path, int docallback=1) {
632 Fl_Tree_Item *item = find_item(path);
633 if ( ! item ) return(-1);
634 return(deselect(item, docallback));
635 }
636
637 int deselect_all(Fl_Tree_Item *item=0, int docallback=1);
638 int select_only(Fl_Tree_Item *selitem, int docallback=1);
639 int select_all(Fl_Tree_Item *item=0, int docallback=1);
640 void set_item_focus(Fl_Tree_Item *o);
641
642 /// See if the specified \p item is selected.
643 ///
644 /// \param[in] item -- the item to be tested. Must not be NULL.
645 ///
646 /// \return
647 /// - 1 : item selected
648 /// - 0 : item deselected
649 ///
650 int is_selected(Fl_Tree_Item *item) const {
651 return(item->is_selected()?1:0);
652 }
653 /// See if item specified by \p path (eg: "Parent/child/item") is selected.
654 ///
655 /// Items or submenus that themselves contain slashes ('/' or '\')
656 /// should be escaped, e.g. is_selected("Holidays/12\\/25\//2010").
657 ///
658 /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred")
659 /// \returns
660 /// - 1 : item selected
661 /// - 0 : item deselected
662 /// - -1 : item was not found
663 ///
664 int is_selected(const char *path) {
665 Fl_Tree_Item *item = find_item(path);
666 if ( ! item ) return(-1);
667 return(is_selected(item));
668 }
669 /// Print the tree as 'ascii art' to stdout.
670 /// Used mainly for debugging.
671 ///
672 void show_self() {
673 if ( ! _root ) return;
674 _root->show_self();
675 }
676
677 /////////////////////////////////
678 // Item attribute related methods
679 /////////////////////////////////
680
681 /// Get the default label fontsize used for creating new items.
682 Fl_Fontsize item_labelsize() const {
683 return(_prefs.labelsize());
684 }
685 /// Set the default label font size used for creating new items.
686 /// To change the font size on a per-item basis, use Fl_Tree_Item::labelsize(Fl_Fontsize)
687 ///
688 void item_labelsize(Fl_Fontsize val) {
689 _prefs.labelsize(val);
690 }
691 /// Get the default font face used for creating new items.
692 Fl_Font item_labelfont() const {
693 return(_prefs.labelfont());
694 }
695 /// Set the default font face used for creating new items.
696 /// To change the font face on a per-item basis, use Fl_Tree_Item::labelfont(Fl_Font)
697 ///
698 void item_labelfont(Fl_Font val) {
699 _prefs.labelfont(val);
700 }
701 /// Get the default label foreground color used for creating new items.
702 Fl_Color item_labelfgcolor(void) const {
703 return(_prefs.labelfgcolor());
704 }
705 /// Set the default label foreground color used for creating new items.
706 /// To change the foreground color on a per-item basis, use Fl_Tree_Item::labelfgcolor(Fl_Color)
707 ///
708 void item_labelfgcolor(Fl_Color val) {
709 _prefs.labelfgcolor(val);
710 }
711 /// Get the default label background color used for creating new items.
712 Fl_Color item_labelbgcolor(void) const {
713 return(_prefs.labelbgcolor());
714 }
715 /// Set the default label background color used for creating new items.
716 /// To change the background color on a per-item basis, use Fl_Tree_Item::labelbgcolor(Fl_Color)
717 ///
718 void item_labelbgcolor(Fl_Color val) {
719 _prefs.labelbgcolor(val);
720 }
721 /// Get the connector color used for tree connection lines.
722 Fl_Color connectorcolor() const {
723 return(_prefs.connectorcolor());
724 }
725 /// Set the connector color used for tree connection lines.
726 void connectorcolor(Fl_Color val) {
727 _prefs.connectorcolor(val);
728 }
729 /// Get the amount of white space (in pixels) that should appear
730 /// between the widget's left border and the tree's contents.
731 ///
732 int marginleft() const {
733 return(_prefs.marginleft());
734 }
735 /// Set the amount of white space (in pixels) that should appear
736 /// between the widget's left border and the left side of the tree's contents.
737 ///
738 void marginleft(int val) {
739 _prefs.marginleft(val);
740 redraw();
741 }
742 /// Get the amount of white space (in pixels) that should appear
743 /// between the widget's top border and the top of the tree's contents.
744 ///
745 int margintop() const {
746 return(_prefs.margintop());
747 }
748 /// Sets the amount of white space (in pixels) that should appear
749 /// between the widget's top border and the top of the tree's contents.
750 ///
751 void margintop(int val) {
752 _prefs.margintop(val);
753 redraw();
754 }
755 /// Get the amount of white space (in pixels) that should appear
756 /// below an open child tree's contents.
757 ///
758 int openchild_marginbottom() const {
759 return(_prefs.openchild_marginbottom());
760 }
761 /// Set the amount of white space (in pixels) that should appear
762 /// below an open child tree's contents.
763 ///
764 void openchild_marginbottom(int val) {
765 _prefs.openchild_marginbottom(val);
766 redraw();
767 }
768 /// Gets the width of the horizontal connection lines (in pixels)
769 /// that appear to the left of each tree item's label.
770 ///
771 int connectorwidth() const {
772 return(_prefs.connectorwidth());
773 }
774 /// Sets the width of the horizontal connection lines (in pixels)
775 /// that appear to the left of each tree item's label.
776 ///
777 void connectorwidth(int val) {
778 _prefs.connectorwidth(val);
779 redraw();
780 }
781 /// Returns the Fl_Image being used as the default user icon for all
782 /// newly created items.
783 /// Returns zero if no icon has been set, which is the default.
784 ///
785 Fl_Image *usericon() const {
786 return(_prefs.usericon());
787 }
788 /// Sets the Fl_Image to be used as the default user icon for all
789 /// newly created items.
790 ///
791 /// If you want to specify user icons on a per-item basis,
792 /// use Fl_Tree_Item::usericon() instead.
793 ///
794 /// \param[in] val -- The new image to be used, or
795 /// zero to disable user icons.
796 ///
797 void usericon(Fl_Image *val) {
798 _prefs.usericon(val);
799 redraw();
800 }
801 /// Returns the icon to be used as the 'open' icon.
802 /// If none was set, the internal default is returned,
803 /// a simple '[+]' icon.
804 ///
805 Fl_Image *openicon() const {
806 return(_prefs.openicon());
807 }
808 /// Sets the icon to be used as the 'open' icon.
809 /// This overrides the built in default '[+]' icon.
810 ///
811 /// \param[in] val -- The new image, or zero to use the default [+] icon.
812 ///
813 void openicon(Fl_Image *val) {
814 _prefs.openicon(val);
815 redraw();
816 }
817 /// Returns the icon to be used as the 'close' icon.
818 /// If none was set, the internal default is returned,
819 /// a simple '[-]' icon.
820 ///
821 Fl_Image *closeicon() const {
822 return(_prefs.closeicon());
823 }
824 /// Sets the icon to be used as the 'close' icon.
825 /// This overrides the built in default '[-]' icon.
826 ///
827 /// \param[in] val -- The new image, or zero to use the default [-] icon.
828 ///
829 void closeicon(Fl_Image *val) {
830 _prefs.closeicon(val);
831 redraw();
832 }
833 /// Returns 1 if the collapse icon is enabled, 0 if not.
834 int showcollapse() const {
835 return(_prefs.showcollapse());
836 }
837 /// Set if we should show the collapse icon or not.
838 /// If collapse icons are disabled, the user will not be able
839 /// to interactively collapse items in the tree, unless the application
840 /// provides some other means via open() and close().
841 ///
842 /// \param[in] val 1: shows collapse icons (default),\n
843 /// 0: hides collapse icons.
844 ///
845 void showcollapse(int val) {
846 _prefs.showcollapse(val);
847 redraw();
848 }
849 /// Returns 1 if the root item is to be shown, or 0 if not.
850 int showroot() const {
851 return(_prefs.showroot());
852 }
853 /// Set if the root item should be shown or not.
854 /// \param[in] val 1 -- show the root item (default)\n
855 /// 0 -- hide the root item.
856 ///
857 void showroot(int val) {
858 _prefs.showroot(val);
859 redraw();
860 }
861 /// Returns the line drawing style for inter-connecting items.
862 Fl_Tree_Connector connectorstyle() const {
863 return(_prefs.connectorstyle());
864 }
865 /// Sets the line drawing style for inter-connecting items.
866 void connectorstyle(Fl_Tree_Connector val) {
867 _prefs.connectorstyle(val);
868 redraw();
869 }
870 /// Set the default sort order used when items are added to the tree.
871 /// See Fl_Tree_Sort for possible values.
872 ///
873 Fl_Tree_Sort sortorder() const {
874 return(_prefs.sortorder());
875 }
876 /// Gets the sort order used to add items to the tree.
877 void sortorder(Fl_Tree_Sort val) {
878 _prefs.sortorder(val);
879 // no redraw().. only affects new add()itions
880 }
881 /// Sets the style of box used to draw selected items.
882 /// This is an fltk Fl_Boxtype.
883 /// The default is influenced by FLTK's current Fl::scheme()
884 ///
885 Fl_Boxtype selectbox() const {
886 return(_prefs.selectbox());
887 }
888 /// Gets the style of box used to draw selected items.
889 /// This is an fltk Fl_Boxtype.
890 /// The default is influenced by FLTK's current Fl::scheme()
891 ///
892 void selectbox(Fl_Boxtype val) {
893 _prefs.selectbox(val);
894 redraw();
895 }
896 /// Gets the tree's current selection mode.
897 Fl_Tree_Select selectmode() const {
898 return(_prefs.selectmode());
899 }
900 /// Sets the tree's selection mode.
901 void selectmode(Fl_Tree_Select val) {
902 _prefs.selectmode(val);
903 }
904 int displayed(Fl_Tree_Item *item);
905 void show_item(Fl_Tree_Item *item, int yoff);
906 void show_item(Fl_Tree_Item *item);
907 void show_item_bottom(Fl_Tree_Item *item);
908 void show_item_middle(Fl_Tree_Item *item);
909 void show_item_top(Fl_Tree_Item *item);
910 void display(Fl_Tree_Item *item);
911 int vposition() const;
912 void vposition(int ypos);
913
914 /// See if widget \p w is one of the Fl_Tree widget's scrollbars.
915 /// Use this to skip over the scrollbars when walking the child() array. Example:
916 /// \code
917 /// for ( int i=0; i<tree->children(); i++ ) { // walk children
918 /// Fl_Widget *w= tree->child(i);
919 /// if ( brow->is_scrollbar(w) ) continue; // skip scrollbars
920 /// ..do work here..
921 /// }
922 /// \endcode
923 /// \param[in] w Widget to test
924 /// \returns 1 if \p w is a scrollbar, 0 if not.
925 ///
926 int is_scrollbar(Fl_Widget *w) {
927 return( ( w == _vscroll ) ? 1 : 0 );
928 }
929 /// Gets the current size of the scrollbars' troughs, in pixels.
930 ///
931 /// If this value is zero (default), this widget will use the global
932 /// Fl::scrollbar_size() value as the scrollbar's width.
933 ///
934 /// \returns Scrollbar size in pixels, or 0 if the global Fl::scrollsize() is being used.
935 /// \see Fl::scrollbar_size(int)
936 ///
937 int scrollbar_size() const {
938 return(_scrollbar_size);
939 }
940 /// Sets the pixel size of the scrollbars' troughs to the \p size, in pixels.
941 ///
942 /// Normally you should not need this method, and should use the global
943 /// Fl::scrollbar_size(int) instead to manage the size of ALL
944 /// your widgets' scrollbars. This ensures your application
945 /// has a consistent UI, is the default behavior, and is normally
946 /// what you want.
947 ///
948 /// Only use THIS method if you really need to override the global
949 /// scrollbar size. The need for this should be rare.
950 ///
951 /// Setting \p size to the special value of 0 causes the widget to
952 /// track the global Fl::scrollbar_size(), which is the default.
953 ///
954 /// \param[in] size Sets the scrollbar size in pixels.\n
955 /// If 0 (default), scrollbar size tracks the global Fl::scrollbar_size()
956 /// \see Fl::scrollbar_size()
957 ///
958 void scrollbar_size(int size) {
959 _scrollbar_size = size;
960 int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size();
961 if ( _vscroll->w() != scrollsize ) {
962 _vscroll->resize(x()+w()-scrollsize, h(), scrollsize, _vscroll->h());
963 }
964 }
965
966 ///////////////////////
967 // callback related
968 ///////////////////////
969
970 /// Sets the item that was changed for this callback.
971 /// Used internally to pass the item that invoked the callback.
972 ///
973 void callback_item(Fl_Tree_Item* item) {
974 _callback_item = item;
975 }
976 /// Gets the item that caused the callback.
977 /// The callback() can use this value to see which item changed.
978 ///
979 Fl_Tree_Item* callback_item() {
980 return(_callback_item);
981 }
982 /// Sets the reason for this callback.
983 /// Used internally to pass the reason the callback was invoked.
984 ///
985 void callback_reason(Fl_Tree_Reason reason) {
986 _callback_reason = reason;
987 }
988 /// Gets the reason for this callback.
989 ///
990 /// The callback() can use this value to see why it was called. Example:
991 /// \code
992 /// void MyTreeCallback(Fl_Widget *w, void *userdata) {
993 /// Fl_Tree *tree = (Fl_Tree*)w;
994 /// Fl_Tree_Item *item = tree->callback_item(); // the item changed (can be NULL if more than one item was changed!)
995 /// switch ( tree->callback_reason() ) { // reason callback was invoked
996 /// case FL_TREE_REASON_OPENED: ..item was opened..
997 /// case FL_TREE_REASON_CLOSED: ..item was closed..
998 /// case FL_TREE_REASON_SELECTED: ..item was selected..
999 /// case FL_TREE_REASON_DESELECTED: ..item was deselected..
1000 /// }
1001 /// }
1002 /// \endcode
1003 ///
1004 Fl_Tree_Reason callback_reason() const {
1005 return(_callback_reason);
1006 }
1007
1008 /// Load FLTK preferences
1009 void load(class Fl_Preferences&);
1010};
1011
1012#endif /*FL_TREE_H*/
1013
1014//
1015// End of "$Id: Fl_Tree.H 8632 2011-05-04 02:59:50Z greg.ercolano $".
1016//