You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1017 lines
37KB

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