Fl_Tree_Item.H 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. //
  2. // "$Id: Fl_Tree_Item.H 12036 2016-10-17 12:51:05Z AlbrechtS $"
  3. //
  4. #ifndef FL_TREE_ITEM_H
  5. #define FL_TREE_ITEM_H
  6. #include <FL/Fl.H>
  7. #include <FL/Fl_Widget.H>
  8. #include <FL/Fl_Image.H>
  9. #include <FL/fl_draw.H>
  10. #include <FL/Fl_Tree_Item_Array.H>
  11. #include <FL/Fl_Tree_Prefs.H>
  12. //////////////////////
  13. // FL/Fl_Tree_Item.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. Distribution and use rights are outlined in
  20. // the file "COPYING" which should have been included with this file. If this
  21. // file is missing or damaged, see the license at:
  22. //
  23. // http://www.fltk.org/COPYING.php
  24. //
  25. // Please report all bugs and problems on the following page:
  26. //
  27. // http://www.fltk.org/str.php
  28. //
  29. ///
  30. /// \file
  31. /// \brief This file contains the definitions for Fl_Tree_Item
  32. ///
  33. /// \class Fl_Tree_Item
  34. /// \brief Tree widget item.
  35. ///
  36. /// This class is a single tree item, and manages all of the item's attributes.
  37. /// Fl_Tree_Item is used by Fl_Tree, which is comprised of many instances of Fl_Tree_Item.
  38. ///
  39. /// Fl_Tree_Item is hierarchical; it dynamically manages an Fl_Tree_Item_Array of children
  40. /// that are themselves instances of Fl_Tree_Item. Each item can have zero or more children.
  41. /// When an item has children, close() and open() can be used to hide or show them.
  42. ///
  43. /// Items have their own attributes; font size, face, color.
  44. /// Items maintain their own hierarchy of children.
  45. ///
  46. /// When you make changes to items, you'll need to tell the tree to redraw()
  47. /// for the changes to show up.
  48. ///
  49. /// New 1.3.3 ABI feature:
  50. /// You can define custom items by either adding a custom widget to the item
  51. /// with Fl_Tree_Item::widget(), or override the draw_item_content() method
  52. /// if you want to just redefine how the label is drawn.
  53. ///
  54. /// The following shows the Fl_Tree_Item's dimensions, useful when overriding
  55. /// the draw_item_content() method:
  56. ///
  57. /// \image html Fl_Tree_Item-dimensions.png "Fl_Tree_Item's internal dimensions." width=6cm
  58. /// \image latex Fl_Tree_Item-dimensions.png "Fl_Tree_Item's internal dimensions." width=6cm
  59. ///
  60. class Fl_Tree;
  61. class FL_EXPORT Fl_Tree_Item {
  62. Fl_Tree *_tree; // parent tree
  63. const char *_label; // label (memory managed)
  64. Fl_Font _labelfont; // label's font face
  65. Fl_Fontsize _labelsize; // label's font size
  66. Fl_Color _labelfgcolor; // label's fg color
  67. Fl_Color _labelbgcolor; // label's bg color (0xffffffff is 'transparent')
  68. /// \enum Fl_Tree_Item_Flags
  69. enum Fl_Tree_Item_Flags {
  70. OPEN = 1<<0, ///> item is open
  71. VISIBLE = 1<<1, ///> item is visible
  72. ACTIVE = 1<<2, ///> item is active
  73. SELECTED = 1<<3 ///> item is selected
  74. };
  75. unsigned short _flags; // misc flags
  76. int _xywh[4]; // xywh of this widget (if visible)
  77. int _collapse_xywh[4]; // xywh of collapse icon (if visible)
  78. int _label_xywh[4]; // xywh of label
  79. Fl_Widget *_widget; // item's label widget (optional)
  80. Fl_Image *_usericon; // item's user-specific icon (optional)
  81. Fl_Image *_userdeicon; // deactivated usericon
  82. Fl_Tree_Item_Array _children; // array of child items
  83. Fl_Tree_Item *_parent; // parent item (=0 if root)
  84. void *_userdata; // user data that can be associated with an item
  85. Fl_Tree_Item *_prev_sibling; // previous sibling (same level)
  86. Fl_Tree_Item *_next_sibling; // next sibling (same level)
  87. // Protected methods
  88. protected:
  89. void _Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree);
  90. void show_widgets();
  91. void hide_widgets();
  92. void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs);
  93. void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs);
  94. void recalc_tree();
  95. int calc_item_height(const Fl_Tree_Prefs &prefs) const;
  96. Fl_Color drawfgcolor() const;
  97. Fl_Color drawbgcolor() const;
  98. public:
  99. Fl_Tree_Item(const Fl_Tree_Prefs &prefs); // CTOR -- backwards compatible
  100. Fl_Tree_Item(Fl_Tree *tree); // CTOR -- ABI 1.3.3+
  101. virtual ~Fl_Tree_Item(); // DTOR -- ABI 1.3.3+
  102. Fl_Tree_Item(const Fl_Tree_Item *o); // COPY CTOR
  103. /// The item's x position relative to the window
  104. int x() const { return(_xywh[0]); }
  105. /// The item's y position relative to the window
  106. int y() const { return(_xywh[1]); }
  107. /// The entire item's width to right edge of Fl_Tree's inner width
  108. /// within scrollbars.
  109. int w() const { return(_xywh[2]); }
  110. /// The item's height
  111. int h() const { return(_xywh[3]); }
  112. /// The item's label x position relative to the window
  113. /// \version 1.3.3
  114. int label_x() const { return(_label_xywh[0]); }
  115. /// The item's label y position relative to the window
  116. /// \version 1.3.3
  117. int label_y() const { return(_label_xywh[1]); }
  118. /// The item's maximum label width to right edge of Fl_Tree's inner width
  119. /// within scrollbars.
  120. /// \version 1.3.3
  121. int label_w() const { return(_label_xywh[2]); }
  122. /// The item's label height
  123. /// \version 1.3.3
  124. int label_h() const { return(_label_xywh[3]); }
  125. virtual int draw_item_content(int render);
  126. void draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus,
  127. int &tree_item_xmax, int lastchild=1, int render=1);
  128. void show_self(const char *indent = "") const;
  129. void label(const char *val);
  130. const char *label() const;
  131. /// Set a user-data value for the item.
  132. inline void user_data( void* data ) { _userdata = data; }
  133. /// Retrieve the user-data value that has been assigned to the item.
  134. inline void* user_data() const { return _userdata; }
  135. /// Set item's label font face.
  136. void labelfont(Fl_Font val) {
  137. _labelfont = val;
  138. recalc_tree(); // may change tree geometry
  139. }
  140. /// Get item's label font face.
  141. Fl_Font labelfont() const {
  142. return(_labelfont);
  143. }
  144. /// Set item's label font size.
  145. void labelsize(Fl_Fontsize val) {
  146. _labelsize = val;
  147. recalc_tree(); // may change tree geometry
  148. }
  149. /// Get item's label font size.
  150. Fl_Fontsize labelsize() const {
  151. return(_labelsize);
  152. }
  153. /// Set item's label foreground text color.
  154. void labelfgcolor(Fl_Color val) {
  155. _labelfgcolor = val;
  156. }
  157. /// Return item's label foreground text color.
  158. Fl_Color labelfgcolor() const {
  159. return(_labelfgcolor);
  160. }
  161. /// Set item's label text color. Alias for labelfgcolor(Fl_Color)).
  162. void labelcolor(Fl_Color val) {
  163. labelfgcolor(val);
  164. }
  165. /// Return item's label text color. Alias for labelfgcolor() const).
  166. Fl_Color labelcolor() const {
  167. return labelfgcolor();
  168. }
  169. /// Set item's label background color.
  170. /// A special case is made for color 0xffffffff which uses the parent tree's bg color.
  171. void labelbgcolor(Fl_Color val) {
  172. _labelbgcolor = val;
  173. }
  174. /// Return item's label background text color.
  175. /// If the color is 0xffffffff, the default behavior is the parent tree's
  176. /// bg color will be used. (An overloaded draw_item_content() can override
  177. /// this behavior.)
  178. Fl_Color labelbgcolor() const {
  179. return(_labelbgcolor);
  180. }
  181. /// Assign an FLTK widget to this item.
  182. void widget(Fl_Widget *val) {
  183. _widget = val;
  184. recalc_tree(); // may change tree geometry
  185. }
  186. /// Return FLTK widget assigned to this item.
  187. Fl_Widget *widget() const {
  188. return(_widget);
  189. }
  190. /// Return the number of children this item has.
  191. int children() const {
  192. return(_children.total());
  193. }
  194. /// Return the child item for the given 'index'.
  195. Fl_Tree_Item *child(int index) {
  196. return(_children[index]);
  197. }
  198. /// Return the const child item for the given 'index'.
  199. const Fl_Tree_Item *child(int t) const;
  200. /// See if this item has children.
  201. int has_children() const {
  202. return(children());
  203. }
  204. int find_child(const char *name);
  205. int find_child(Fl_Tree_Item *item);
  206. int remove_child(Fl_Tree_Item *item);
  207. int remove_child(const char *new_label);
  208. void clear_children();
  209. void swap_children(int ax, int bx);
  210. int swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b);
  211. const Fl_Tree_Item *find_child_item(const char *name) const;
  212. Fl_Tree_Item *find_child_item(const char *name);
  213. const Fl_Tree_Item *find_child_item(char **arr) const;
  214. Fl_Tree_Item *find_child_item(char **arr);
  215. const Fl_Tree_Item *find_item(char **arr) const;
  216. Fl_Tree_Item *find_item(char **arr);
  217. //////////////////
  218. // Adding items
  219. //////////////////
  220. Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs,
  221. const char *new_label,
  222. Fl_Tree_Item *newitem);
  223. Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs,
  224. const char *new_label);
  225. Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs,
  226. char **arr,
  227. Fl_Tree_Item *newitem);
  228. Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs,
  229. char **arr);
  230. Fl_Tree_Item *replace(Fl_Tree_Item *new_item);
  231. Fl_Tree_Item *replace_child(Fl_Tree_Item *olditem, Fl_Tree_Item *newitem);
  232. Fl_Tree_Item *insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos=0);
  233. Fl_Tree_Item *insert_above(const Fl_Tree_Prefs &prefs, const char *new_label);
  234. Fl_Tree_Item* deparent(int index);
  235. int reparent(Fl_Tree_Item *newchild, int index);
  236. int move(int to, int from);
  237. int move(Fl_Tree_Item *item, int op=0, int pos=0);
  238. int move_above(Fl_Tree_Item *item);
  239. int move_below(Fl_Tree_Item *item);
  240. int move_into(Fl_Tree_Item *item, int pos=0);
  241. int depth() const;
  242. Fl_Tree_Item *prev();
  243. Fl_Tree_Item *next();
  244. Fl_Tree_Item *next_sibling();
  245. Fl_Tree_Item *prev_sibling();
  246. void update_prev_next(int index);
  247. Fl_Tree_Item *next_displayed(Fl_Tree_Prefs &prefs); // deprecated
  248. Fl_Tree_Item *prev_displayed(Fl_Tree_Prefs &prefs); // deprecated
  249. Fl_Tree_Item *next_visible(Fl_Tree_Prefs &prefs);
  250. Fl_Tree_Item *prev_visible(Fl_Tree_Prefs &prefs);
  251. /// Return the parent for this item. Returns NULL if we are the root.
  252. Fl_Tree_Item *parent() {
  253. return(_parent);
  254. }
  255. /// Return the const parent for this item. Returns NULL if we are the root.
  256. const Fl_Tree_Item *parent() const {
  257. return(_parent);
  258. }
  259. /// Set the parent for this item.
  260. /// Should only be used by Fl_Tree's internals.
  261. ///
  262. void parent(Fl_Tree_Item *val) {
  263. _parent = val;
  264. }
  265. const Fl_Tree_Prefs& prefs() const;
  266. /// Return the tree for this item.
  267. /// \version 1.3.3
  268. const Fl_Tree *tree() const {
  269. return(_tree);
  270. }
  271. /// Return the tree for this item.
  272. /// \version 1.3.4
  273. Fl_Tree *tree() {
  274. return(_tree);
  275. }
  276. //////////////////
  277. // State
  278. //////////////////
  279. void open();
  280. void close();
  281. /// See if the item is 'open'.
  282. int is_open() const {
  283. return(is_flag(OPEN));
  284. }
  285. /// See if the item is 'closed'.
  286. int is_close() const {
  287. return(is_flag(OPEN)?0:1);
  288. }
  289. /// Toggle the item's open/closed state.
  290. void open_toggle() {
  291. is_open()?close():open(); // handles calling recalc_tree()
  292. }
  293. /// Change the item's selection state to the optionally specified 'val'.
  294. /// If 'val' is not specified, the item will be selected.
  295. ///
  296. void select(int val=1) {
  297. set_flag(SELECTED, val);
  298. }
  299. /// Toggle the item's selection state.
  300. void select_toggle() {
  301. if ( is_selected() ) {
  302. deselect(); // deselect if selected
  303. } else {
  304. select(); // select if deselected
  305. }
  306. }
  307. /// Select item and all its children.
  308. /// Returns count of how many items were in the 'deselected' state,
  309. /// ie. how many items were "changed".
  310. ///
  311. int select_all() {
  312. int count = 0;
  313. if ( ! is_selected() ) {
  314. select();
  315. ++count;
  316. }
  317. for ( int t=0; t<children(); t++ ) {
  318. count += child(t)->select_all();
  319. }
  320. return(count);
  321. }
  322. /// Disable the item's selection state.
  323. void deselect() {
  324. set_flag(SELECTED, 0);
  325. }
  326. /// Deselect item and all its children.
  327. /// Returns count of how many items were in the 'selected' state,
  328. /// ie. how many items were "changed".
  329. ///
  330. int deselect_all() {
  331. int count = 0;
  332. if ( is_selected() ) {
  333. deselect();
  334. ++count;
  335. }
  336. for ( int t=0; t<children(); t++ ) {
  337. count += child(t)->deselect_all();
  338. }
  339. return(count);
  340. }
  341. /// See if the item is selected.
  342. char is_selected() const {
  343. return(is_flag(SELECTED));
  344. }
  345. /// Change the item's activation state to the optionally specified 'val'.
  346. ///
  347. /// When deactivated, the item will be 'grayed out'; the callback()
  348. /// won't be invoked if the user clicks on the label. If a widget()
  349. /// is associated with the item, its activation state will be changed as well.
  350. ///
  351. /// If 'val' is not specified, the item will be activated.
  352. ///
  353. void activate(int val=1) {
  354. set_flag(ACTIVE,val);
  355. if ( _widget && val != (int)_widget->active() ) {
  356. if ( val ) {
  357. _widget->activate();
  358. } else {
  359. _widget->deactivate();
  360. }
  361. _widget->redraw();
  362. }
  363. }
  364. /// Deactivate the item; the callback() won't be invoked when clicked.
  365. /// Same as activate(0)
  366. ///
  367. void deactivate() {
  368. activate(0);
  369. }
  370. /// See if the item is activated.
  371. char is_activated() const {
  372. return(is_flag(ACTIVE));
  373. }
  374. /// See if the item is activated. Alias for is_activated().
  375. char is_active() const {
  376. return(is_activated());
  377. }
  378. /// See if the item is visible. Alias for is_visible().
  379. int visible() const {
  380. return(is_visible());
  381. }
  382. /// See if the item is visible.
  383. int is_visible() const {
  384. return(is_flag(VISIBLE));
  385. }
  386. int visible_r() const;
  387. /// Set the item's user icon to an Fl_Image. Use '0' to disable.
  388. /// No internal copy is made, caller must manage icon's memory.
  389. ///
  390. /// Note, if you expect your items to be deactivated(),
  391. /// use userdeicon(Fl_Image*) to set up a 'grayed out' version of your icon
  392. /// to be used for display.
  393. ///
  394. /// \see userdeicon(Fl_Image*)
  395. ///
  396. void usericon(Fl_Image *val) {
  397. _usericon = val;
  398. recalc_tree(); // may change tree geometry
  399. }
  400. /// Get the item's user icon as an Fl_Image. Returns '0' if disabled.
  401. Fl_Image *usericon() const {
  402. return(_usericon);
  403. }
  404. /// Set the usericon to draw when the item is deactivated. Use '0' to disable.
  405. /// No internal copy is made; caller must manage icon's memory.
  406. ///
  407. /// To create a typical 'grayed out' version of your usericon image,
  408. /// you can do the following:
  409. ///
  410. /// \code
  411. /// // Create tree + usericon for items
  412. /// Fl_Tree *tree = new Fl_Tree(..);
  413. /// Fl_Image *usr_icon = new Fl_Pixmap(..); // your usericon
  414. /// Fl_Image *de_icon = usr_icon->copy(); // make a copy, and..
  415. /// de_icon->inactive(); // make it 'grayed out'
  416. /// ...
  417. /// for ( .. ) { // item loop..
  418. /// item = tree->add("..."); // create new item
  419. /// item->usericon(usr_icon); // assign usericon to items
  420. /// item->userdeicon(de_icon); // assign userdeicon to items
  421. /// ..
  422. /// }
  423. /// \endcode
  424. ///
  425. /// In the above example, the app should 'delete' the two icons
  426. /// when they're no longer needed (e.g. after the tree is destroyed)
  427. ///
  428. /// \version 1.3.4
  429. ///
  430. void userdeicon(Fl_Image* val) {
  431. _userdeicon = val;
  432. }
  433. /// Return the deactivated version of the user icon, if any.
  434. /// Returns 0 if none.
  435. Fl_Image* userdeicon() const {
  436. return _userdeicon;
  437. }
  438. //////////////////
  439. // Events
  440. //////////////////
  441. const Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0) const;
  442. Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0);
  443. int event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const;
  444. int event_on_label(const Fl_Tree_Prefs &prefs) const;
  445. /// Is this item the root of the tree?
  446. int is_root() const {
  447. return(_parent==0?1:0);
  448. }
  449. // Protected methods
  450. // TODO: move these to top 'protected:' section
  451. protected:
  452. /// Set a flag to an on or off value. val is 0 or 1.
  453. inline void set_flag(unsigned short flag,int val) {
  454. if ( flag==OPEN || flag==VISIBLE ) {
  455. recalc_tree(); // may change tree geometry
  456. }
  457. if ( val ) _flags |= flag; else _flags &= ~flag;
  458. }
  459. /// See if flag set. Returns 0 or 1.
  460. inline int is_flag(unsigned short val) const {
  461. return(_flags & val ? 1 : 0);
  462. }
  463. };
  464. #endif /*FL_TREE_ITEM_H*/
  465. //
  466. // End of "$Id: Fl_Tree_Item.H 12036 2016-10-17 12:51:05Z AlbrechtS $".
  467. //