Modified lines:  473, 474, 494, 503, 511, 512, 1034, 1037, 1039, 1051, 1054, 1056
Added line:  39, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 90, 91, 92, 93, 94, 95, 96, 97, 98, 112, 113, 114, 179, 195, 308, 309, 310, 312, 313, 360, 372, 373, 374, 376, 380, 408, 423, 518, 519, 520, 521, 522, 523, 528, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 631, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 1068, 1119, 1129, 1301, 1319, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368
Removed line:  475, 476, 477, 478, 479, 480, 481, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529
Generated by diff2html
© Yves Bailly, MandrakeSoft S.A. 2001
diff2html is licensed under the GNU GPL.

  ../fltk-1.3.x-svn-current/src/Fl_Tree_Item.cxx     src/Fl_Tree_Item.cxx
  1093 lines
36072 bytes
Last modified : Thu Dec 12 14:27:14 2013

    1371 lines
47005 bytes
Last modified : Thu Dec 12 06:31:46 2013

1 //   1 //
2 // "$Id: Fl_Tree_Item.cxx 10018 2013-11-10 04:33:44Z greg.ercolano $"   2 // "$Id: Fl_Tree_Item.cxx 10018 2013-11-10 04:33:44Z greg.ercolano $"
3 //   3 //
4   4
5 #include <stdio.h>   5 #include <stdio.h>
6 #include <stdlib.h>   6 #include <stdlib.h>
7 #include <string.h>   7 #include <string.h>
8 #include <FL/Fl_Widget.H>   8 #include <FL/Fl_Widget.H>
9 #include <FL/Fl_Tree_Item.H>   9 #include <FL/Fl_Tree_Item.H>
10 #include <FL/Fl_Tree_Prefs.H>   10 #include <FL/Fl_Tree_Prefs.H>
11 #include <FL/Fl_Tree.H>   11 #include <FL/Fl_Tree.H>
12   12
13 //////////////////////   13 //////////////////////
14 // Fl_Tree_Item.cxx   14 // Fl_Tree_Item.cxx
15 //////////////////////   15 //////////////////////
16 //   16 //
17 // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK   17 // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
18 // Copyright (C) 2009-2010 by Greg Ercolano.   18 // Copyright (C) 2009-2010 by Greg Ercolano.
19 //   19 //
20 // This library is free software. Distribution and use rights are outlined in   20 // This library is free software. Distribution and use rights are outlined in
21 // the file "COPYING" which should have been included with this file. If this   21 // the file "COPYING" which should have been included with this file. If this
22 // file is missing or damaged, see the license at:   22 // file is missing or damaged, see the license at:
23 //   23 //
24 // http://www.fltk.org/COPYING.php   24 // http://www.fltk.org/COPYING.php
25 //   25 //
26 // Please report all bugs and problems on the following page:   26 // Please report all bugs and problems on the following page:
27 //   27 //
28 // http://www.fltk.org/str.php   28 // http://www.fltk.org/str.php
29 //   29 //
30 /////////////////////////////////////////////////////////////////////////// 80 /   30 /////////////////////////////////////////////////////////////////////////// 80 /
31   31
32 // Was the last event inside the specified xywh?   32 // Was the last event inside the specified xywh?
33 static int event_inside(const int xywh[4]) {   33 static int event_inside(const int xywh[4]) {
34   return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3]));   34   return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3]));
35 }   35 }
36   36
37 /// Constructor.   37 /// Constructor.
38 /// Makes a new instance of Fl_Tree_Item using defaults from 'prefs'.   38 /// Makes a new instance of Fl_Tree_Item using defaults from 'prefs'.
      39 /// \note Deprecated in 1.3.3 ABI -- use Fl_Tree_Item(Fl_Tree*) instead.
39 ///   40 ///
40 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) {   41 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) {
      42   _Init(prefs, 0);
      43 }
      44
      45 // Initialize the tree item
      46 // Used by constructors
      47 //
      48 void Fl_Tree_Item::_Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree) {
      49 #if FLTK_ABI_VERSION >= 10303
      50   _tree = tree;
      51 #endif
41   _label = 0;   52   _label = 0;
42   _labelfont = prefs.labelfont();   53   _labelfont = prefs.labelfont();
43   _labelsize = prefs.labelsize();   54   _labelsize = prefs.labelsize();
44   _labelfgcolor = prefs.labelfgcolor();   55   _labelfgcolor = prefs.labelfgcolor();
45   _labelbgcolor = prefs.labelbgcolor();   56   _labelbgcolor = prefs.labelbgcolor();
46   _widget = 0;   57   _widget = 0;
47 #if FLTK_ABI_VERSION >= 10301   58 #if FLTK_ABI_VERSION >= 10301
48   _flags = OPEN|VISIBLE|ACTIVE;   59   _flags = OPEN|VISIBLE|ACTIVE;
49 #else /*FLTK_ABI_VERSION*/   60 #else /*FLTK_ABI_VERSION*/
50   _open = 1;   61   _open = 1;
51   _visible = 1;   62   _visible = 1;
52   _active = 1;   63   _active = 1;
53   _selected = 0;   64   _selected = 0;
54 #endif /*FLTK_ABI_VERSION*/   65 #endif /*FLTK_ABI_VERSION*/
55   _xywh[0] = 0;   66   _xywh[0] = 0;
56   _xywh[1] = 0;   67   _xywh[1] = 0;
57   _xywh[2] = 0;   68   _xywh[2] = 0;
58   _xywh[3] = 0;   69   _xywh[3] = 0;
59   _collapse_xywh[0] = 0;   70   _collapse_xywh[0] = 0;
60   _collapse_xywh[1] = 0;   71   _collapse_xywh[1] = 0;
61   _collapse_xywh[2] = 0;   72   _collapse_xywh[2] = 0;
62   _collapse_xywh[3] = 0;   73   _collapse_xywh[3] = 0;
63   _label_xywh[0] = 0;   74   _label_xywh[0] = 0;
64   _label_xywh[1] = 0;   75   _label_xywh[1] = 0;
65   _label_xywh[2] = 0;   76   _label_xywh[2] = 0;
66   _label_xywh[3] = 0;   77   _label_xywh[3] = 0;
67   _usericon = 0;   78   _usericon = 0;
68   _userdata = 0;   79   _userdata = 0;
69   _parent = 0;   80   _parent = 0;
70 #if FLTK_ABI_VERSION >= 10303   81 #if FLTK_ABI_VERSION >= 10303
71   _children.manage_item_destroy(1); // let array's dtor manage destroying Fl_Tree_Items   82   _children.manage_item_destroy(1); // let array's dtor manage destroying Fl_Tree_Items
72 #endif   83 #endif
73 #if FLTK_ABI_VERSION >= 10301   84 #if FLTK_ABI_VERSION >= 10301
74   _prev_sibling = 0;   85   _prev_sibling = 0;
75   _next_sibling = 0;   86   _next_sibling = 0;
76 #endif /*FLTK_ABI_VERSION*/   87 #endif /*FLTK_ABI_VERSION*/
77 }   88 }
78   89
      90 #if FLTK_ABI_VERSION >= 10303
      91 /// Constructor.
      92 /// Makes a new instance of Fl_Tree_Item for 'tree'.
      93 ///
      94 Fl_Tree_Item::Fl_Tree_Item(Fl_Tree *tree) {
      95   _Init(tree->_prefs, tree);
      96 }
      97 #endif
      98
79 // DTOR   99 // DTOR
80 Fl_Tree_Item::~Fl_Tree_Item() {   100 Fl_Tree_Item::~Fl_Tree_Item() {
81   if ( _label ) {   101   if ( _label ) {
82     free((void*)_label);   102     free((void*)_label);
83     _label = 0;   103     _label = 0;
84   }   104   }
85   _widget = 0; // Fl_Group will handle destruction   105   _widget = 0; // Fl_Group will handle destruction
86   _usericon = 0; // user handled allocation   106   _usericon = 0; // user handled allocation
87   //_children.clear(); // array's destructor handles itself   107   //_children.clear(); // array's destructor handles itself
88 }   108 }
89   109
90 /// Copy constructor.   110 /// Copy constructor.
91 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {   111 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {
      112 #if FLTK_ABI_VERSION >= 10303
      113   _tree = o->_tree;
      114 #endif
92   _label = o->label() ? strdup(o->label()) : 0;   115   _label = o->label() ? strdup(o->label()) : 0;
93   _labelfont = o->labelfont();   116   _labelfont = o->labelfont();
94   _labelsize = o->labelsize();   117   _labelsize = o->labelsize();
95   _labelfgcolor = o->labelfgcolor();   118   _labelfgcolor = o->labelfgcolor();
96   _labelbgcolor = o->labelbgcolor();   119   _labelbgcolor = o->labelbgcolor();
97   _widget = o->widget();   120   _widget = o->widget();
98 #if FLTK_ABI_VERSION >= 10301   121 #if FLTK_ABI_VERSION >= 10301
99   _flags = o->_flags;   122   _flags = o->_flags;
100 #else /*FLTK_ABI_VERSION*/   123 #else /*FLTK_ABI_VERSION*/
101   _open = o->_open;   124   _open = o->_open;
102   _visible = o->_visible;   125   _visible = o->_visible;
103   _active = o->_active;   126   _active = o->_active;
104   _selected = o->_selected;   127   _selected = o->_selected;
105 #endif /*FLTK_ABI_VERSION*/   128 #endif /*FLTK_ABI_VERSION*/
106   _xywh[0] = o->_xywh[0];   129   _xywh[0] = o->_xywh[0];
107   _xywh[1] = o->_xywh[1];   130   _xywh[1] = o->_xywh[1];
108   _xywh[2] = o->_xywh[2];   131   _xywh[2] = o->_xywh[2];
109   _xywh[3] = o->_xywh[3];   132   _xywh[3] = o->_xywh[3];
110   _collapse_xywh[0] = o->_collapse_xywh[0];   133   _collapse_xywh[0] = o->_collapse_xywh[0];
111   _collapse_xywh[1] = o->_collapse_xywh[1];   134   _collapse_xywh[1] = o->_collapse_xywh[1];
112   _collapse_xywh[2] = o->_collapse_xywh[2];   135   _collapse_xywh[2] = o->_collapse_xywh[2];
113   _collapse_xywh[3] = o->_collapse_xywh[3];   136   _collapse_xywh[3] = o->_collapse_xywh[3];
114   _label_xywh[0] = o->_label_xywh[0];   137   _label_xywh[0] = o->_label_xywh[0];
115   _label_xywh[1] = o->_label_xywh[1];   138   _label_xywh[1] = o->_label_xywh[1];
116   _label_xywh[2] = o->_label_xywh[2];   139   _label_xywh[2] = o->_label_xywh[2];
117   _label_xywh[3] = o->_label_xywh[3];   140   _label_xywh[3] = o->_label_xywh[3];
118   _usericon = o->usericon();   141   _usericon = o->usericon();
119   _userdata = o->user_data();   142   _userdata = o->user_data();
120   _parent = o->_parent;   143   _parent = o->_parent;
121 #if FLTK_ABI_VERSION >= 10301   144 #if FLTK_ABI_VERSION >= 10301
122   _prev_sibling = 0; // do not copy ptrs! use update_prev_next()   145   _prev_sibling = 0; // do not copy ptrs! use update_prev_next()
123   _next_sibling = 0; // do not copy ptrs! use update_prev_next()   146   _next_sibling = 0; // do not copy ptrs! use update_prev_next()
124 #endif /*FLTK_ABI_VERSION*/   147 #endif /*FLTK_ABI_VERSION*/
125 }   148 }
126   149
127 /// Print the tree as 'ascii art' to stdout.   150 /// Print the tree as 'ascii art' to stdout.
128 /// Used mainly for debugging.   151 /// Used mainly for debugging.
129 ///   152 ///
130 void Fl_Tree_Item::show_self(const char *indent) const {   153 void Fl_Tree_Item::show_self(const char *indent) const {
131   if ( label() ) {   154   if ( label() ) {
132 #if FLTK_ABI_VERSION >= 10301   155 #if FLTK_ABI_VERSION >= 10301
133     printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n",   156     printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n",
134            indent,label(),children(),(void*)this, (void*)_parent,   157            indent,label(),children(),(void*)this, (void*)_parent,
135 _prev_sibling, _next_sibling, depth());   158 _prev_sibling, _next_sibling, depth());
136 #else /*FLTK_ABI_VERSION*/   159 #else /*FLTK_ABI_VERSION*/
137     printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n",   160     printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n",
138            indent,label(),children(),(void*)this, (void*)_parent, depth());   161            indent,label(),children(),(void*)this, (void*)_parent, depth());
139 #endif /*FLTK_ABI_VERSION*/   162 #endif /*FLTK_ABI_VERSION*/
140   }   163   }
141   if ( children() ) {   164   if ( children() ) {
142     char *i2 = (char*)malloc(strlen(indent) + 2);   165     char *i2 = (char*)malloc(strlen(indent) + 2);
143     strcpy(i2, indent);   166     strcpy(i2, indent);
144     strcat(i2, " |");   167     strcat(i2, " |");
145     for ( int t=0; t<children(); t++ ) {   168     for ( int t=0; t<children(); t++ ) {
146       child(t)->show_self(i2);   169       child(t)->show_self(i2);
147     }   170     }
148   }   171   }
149   fflush(stdout);   172   fflush(stdout);
150 }   173 }
151   174
152 /// Set the label. Makes a copy of the name.   175 /// Set the label. Makes a copy of the name.
153 void Fl_Tree_Item::label(const char *name) {   176 void Fl_Tree_Item::label(const char *name) {
154   if ( _label ) { free((void*)_label); _label = 0; }   177   if ( _label ) { free((void*)_label); _label = 0; }
155   _label = name ? strdup(name) : 0;   178   _label = name ? strdup(name) : 0;
      179   recalc_tree(); // may change label geometry
156 }   180 }
157   181
158 /// Return the label.   182 /// Return the label.
159 const char *Fl_Tree_Item::label() const {   183 const char *Fl_Tree_Item::label() const {
160   return(_label);   184   return(_label);
161 }   185 }
162   186
163 /// Return child item for the specified 'index'.   187 /// Return child item for the specified 'index'.
164 const Fl_Tree_Item *Fl_Tree_Item::child(int index) const {   188 const Fl_Tree_Item *Fl_Tree_Item::child(int index) const {
165   return(_children[index]);   189   return(_children[index]);
166 }   190 }
167   191
168 /// Clear all the children for this item.   192 /// Clear all the children for this item.
169 void Fl_Tree_Item::clear_children() {   193 void Fl_Tree_Item::clear_children() {
170   _children.clear();   194   _children.clear();
      195   recalc_tree(); // may change tree geometry
171 }   196 }
172   197
173 /// Return the index of the immediate child of this item that has the label 'name'.   198 /// Return the index of the immediate child of this item that has the label 'name'.
174 ///   199 ///
175 /// \returns index of found item, or -1 if not found.   200 /// \returns index of found item, or -1 if not found.
176 ///   201 ///
177 int Fl_Tree_Item::find_child(const char *name) {   202 int Fl_Tree_Item::find_child(const char *name) {
178   if ( name ) {   203   if ( name ) {
179     for ( int t=0; t<children(); t++ ) {   204     for ( int t=0; t<children(); t++ ) {
180       if ( child(t)->label() ) {   205       if ( child(t)->label() ) {
181         if ( strcmp(child(t)->label(), name) == 0 ) {   206         if ( strcmp(child(t)->label(), name) == 0 ) {
182           return(t);   207           return(t);
183         }   208         }
184       }   209       }
185     }   210     }
186   }   211   }
187   return(-1);   212   return(-1);
188 }   213 }
189   214
190 /// Find child item by descending array of names. Does not include self in search.   215 /// Find child item by descending array of names. Does not include self in search.
191 /// Only Fl_Tree should need this method.   216 /// Only Fl_Tree should need this method.
192 ///   217 ///
193 /// \returns item, or 0 if not found   218 /// \returns item, or 0 if not found
194 ///   219 ///
195 const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const {   220 const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const {
196   for ( int t=0; t<children(); t++ ) {   221   for ( int t=0; t<children(); t++ ) {
197     if ( child(t)->label() ) {   222     if ( child(t)->label() ) {
198       if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?   223       if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?
199         if ( *(arr+1) ) { // more in arr? descend   224         if ( *(arr+1) ) { // more in arr? descend
200           return(_children[t]->find_item(arr+1));   225           return(_children[t]->find_item(arr+1));
201         } else { // end of arr? done   226         } else { // end of arr? done
202           return(_children[t]);   227           return(_children[t]);
203         }   228         }
204       }   229       }
205     }   230     }
206   }   231   }
207   return(0);   232   return(0);
208 }   233 }
209   234
210 /// Find child item by descending array of names. Does not include self in search.   235 /// Find child item by descending array of names. Does not include self in search.
211 /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead.   236 /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead.
212 ///   237 ///
213 /// \returns item, or 0 if not found   238 /// \returns item, or 0 if not found
214 ///   239 ///
215 Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) {   240 Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) {
216   for ( int t=0; t<children(); t++ ) {   241   for ( int t=0; t<children(); t++ ) {
217     if ( child(t)->label() ) {   242     if ( child(t)->label() ) {
218       if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?   243       if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?
219         if ( *(arr+1) ) { // more in arr? descend   244         if ( *(arr+1) ) { // more in arr? descend
220           return(_children[t]->find_item(arr+1));   245           return(_children[t]->find_item(arr+1));
221         } else { // end of arr? done   246         } else { // end of arr? done
222           return(_children[t]);   247           return(_children[t]);
223         }   248         }
224       }   249       }
225     }   250     }
226   }   251   }
227   return(0);   252   return(0);
228 }   253 }
229   254
230 /// Find item by descending array of \p names. Includes self in search.   255 /// Find item by descending array of \p names. Includes self in search.
231 /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead.   256 /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead.
232 ///   257 ///
233 /// \returns item, or 0 if not found   258 /// \returns item, or 0 if not found
234 ///   259 ///
235 const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const {   260 const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const {
236   if ( label() && strcmp(label(), *names) == 0 ) { // match self?   261   if ( label() && strcmp(label(), *names) == 0 ) { // match self?
237     if ( *(names+1) == 0 ) { // end of names,   262     if ( *(names+1) == 0 ) { // end of names,
238       return(this); // found ourself.   263       return(this); // found ourself.
239     }   264     }
240   }   265   }
241   if ( children() ) { // check children..   266   if ( children() ) { // check children..
242     return(find_child_item(names));   267     return(find_child_item(names));
243   }   268   }
244   return(0);   269   return(0);
245 }   270 }
246   271
247 /// Find item by descending array of \p names. Includes self in search.   272 /// Find item by descending array of \p names. Includes self in search.
248 /// Only Fl_Tree should need this method.   273 /// Only Fl_Tree should need this method.
249 ///   274 ///
250 /// \returns item, or 0 if not found   275 /// \returns item, or 0 if not found
251 ///   276 ///
252 Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) {   277 Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) {
253   if ( label() && strcmp(label(), *names) == 0 ) { // match self?   278   if ( label() && strcmp(label(), *names) == 0 ) { // match self?
254     if ( *(names+1) == 0 ) { // end of names,   279     if ( *(names+1) == 0 ) { // end of names,
255       return(this); // found ourself.   280       return(this); // found ourself.
256     }   281     }
257   }   282   }
258   if ( children() ) { // check children..   283   if ( children() ) { // check children..
259     return(find_child_item(names));   284     return(find_child_item(names));
260   }   285   }
261   return(0);   286   return(0);
262 }   287 }
263   288
264 /// Find the index number for the specified 'item'   289 /// Find the index number for the specified 'item'
265 /// in the current item's list of children.   290 /// in the current item's list of children.
266 ///   291 ///
267 /// \returns the index, or -1 if not found.   292 /// \returns the index, or -1 if not found.
268 ///   293 ///
269 int Fl_Tree_Item::find_child(Fl_Tree_Item *item) {   294 int Fl_Tree_Item::find_child(Fl_Tree_Item *item) {
270   for ( int t=0; t<children(); t++ ) {   295   for ( int t=0; t<children(); t++ ) {
271     if ( item == child(t) ) {   296     if ( item == child(t) ) {
272       return(t);   297       return(t);
273     }   298     }
274   }   299   }
275   return(-1);   300   return(-1);
276 }   301 }
277   302
278 /// Add a new child to this item with the name 'new_label', with defaults from 'prefs'.   303 /// Add a new child to this item with the name 'new_label', with defaults from 'prefs'.
279 /// An internally managed copy is made of the label string.   304 /// An internally managed copy is made of the label string.
280 /// Adds the item based on the value of prefs.sortorder().   305 /// Adds the item based on the value of prefs.sortorder().
281 ///   306 ///
282 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) {   307 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) {
      308 #if FLTK_ABI_VERSION >= 10303
      309   Fl_Tree_Item *item = new Fl_Tree_Item(_tree);
      310 #else
283   Fl_Tree_Item *item = new Fl_Tree_Item(prefs);   311   Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
      312 #endif
      313   recalc_tree(); // may change tree geometry
284   item->label(new_label);   314   item->label(new_label);
285   item->_parent = this;   315   item->_parent = this;
286   switch ( prefs.sortorder() ) {   316   switch ( prefs.sortorder() ) {
287     case FL_TREE_SORT_NONE: {   317     case FL_TREE_SORT_NONE: {
288       _children.add(item);   318       _children.add(item);
289       return(item);   319       return(item);
290     }   320     }
291     case FL_TREE_SORT_ASCENDING: {   321     case FL_TREE_SORT_ASCENDING: {
292       for ( int t=0; t<_children.total(); t++ ) {   322       for ( int t=0; t<_children.total(); t++ ) {
293         Fl_Tree_Item *c = _children[t];   323         Fl_Tree_Item *c = _children[t];
294         if ( c->label() && strcmp(c->label(), new_label) > 0 ) {   324         if ( c->label() && strcmp(c->label(), new_label) > 0 ) {
295           _children.insert(t, item);   325           _children.insert(t, item);
296           return(item);   326           return(item);
297         }   327         }
298       }   328       }
299       _children.add(item);   329       _children.add(item);
300       return(item);   330       return(item);
301     }   331     }
302     case FL_TREE_SORT_DESCENDING: {   332     case FL_TREE_SORT_DESCENDING: {
303       for ( int t=0; t<_children.total(); t++ ) {   333       for ( int t=0; t<_children.total(); t++ ) {
304         Fl_Tree_Item *c = _children[t];   334         Fl_Tree_Item *c = _children[t];
305         if ( c->label() && strcmp(c->label(), new_label) < 0 ) {   335         if ( c->label() && strcmp(c->label(), new_label) < 0 ) {
306           _children.insert(t, item);   336           _children.insert(t, item);
307           return(item);   337           return(item);
308         }   338         }
309       }   339       }
310       _children.add(item);   340       _children.add(item);
311       return(item);   341       return(item);
312     }   342     }
313   }   343   }
314   return(item);   344   return(item);
315 }   345 }
316   346
317 /// Descend into the path specified by \p arr, and add a new child there.   347 /// Descend into the path specified by \p arr, and add a new child there.
318 /// Should be used only by Fl_Tree's internals.   348 /// Should be used only by Fl_Tree's internals.
319 /// Adds the item based on the value of prefs.sortorder().   349 /// Adds the item based on the value of prefs.sortorder().
320 /// \returns the item added.   350 /// \returns the item added.
321 ///   351 ///
322 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {   352 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {
323   int t = (*arr && *(arr+1)) ? find_child(*arr) : -1;   353   int t = (*arr && *(arr+1)) ? find_child(*arr) : -1;
324   Fl_Tree_Item *item = 0;   354   Fl_Tree_Item *item = 0;
325   if ( t == -1 ) {   355   if ( t == -1 ) {
326     item = (Fl_Tree_Item*)add(prefs, *arr);   356     item = (Fl_Tree_Item*)add(prefs, *arr);
327   } else {   357   } else {
328     item = (Fl_Tree_Item*)child(t);   358     item = (Fl_Tree_Item*)child(t);
329   }   359   }
      360   recalc_tree(); // may change tree geometry
330   if ( *(arr+1) ) { // descend?   361   if ( *(arr+1) ) { // descend?
331     return(item->add(prefs, arr+1));   362     return(item->add(prefs, arr+1));
332   } else {   363   } else {
333     return(item); // end? done   364     return(item); // end? done
334   }   365   }
335 }   366 }
336   367
337 /// Insert a new item into current item's children at a specified position.   368 /// Insert a new item into current item's children at a specified position.
338 /// \returns the new item inserted.   369 /// \returns the new item inserted.
339 ///   370 ///
340 Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) {   371 Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) {
      372 #if FLTK_ABI_VERSION >= 10303
      373   Fl_Tree_Item *item = new Fl_Tree_Item(_tree);
      374 #else
341   Fl_Tree_Item *item = new Fl_Tree_Item(prefs);   375   Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
      376 #endif
342   item->label(new_label);   377   item->label(new_label);
343   item->_parent = this;   378   item->_parent = this;
344   _children.insert(pos, item);   379   _children.insert(pos, item);
      380   recalc_tree(); // may change tree geometry
345   return(item);   381   return(item);
346 }   382 }
347   383
348 /// Insert a new item above this item.   384 /// Insert a new item above this item.
349 /// \returns the new item inserted, or 0 if an error occurred.   385 /// \returns the new item inserted, or 0 if an error occurred.
350 ///   386 ///
351 Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) {   387 Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) {
352   Fl_Tree_Item *p = _parent;   388   Fl_Tree_Item *p = _parent;
353   if ( ! p ) return(0);   389   if ( ! p ) return(0);
354   // Walk our parent's children to find ourself   390   // Walk our parent's children to find ourself
355   for ( int t=0; t<p->children(); t++ ) {   391   for ( int t=0; t<p->children(); t++ ) {
356     Fl_Tree_Item *c = p->child(t);   392     Fl_Tree_Item *c = p->child(t);
357     if ( this == c ) {   393     if ( this == c ) {
358       return(p->insert(prefs, new_label, t));   394       return(p->insert(prefs, new_label, t));
359     }   395     }
360   }   396   }
361   return(0);   397   return(0);
362 }   398 }
363   399
364 /// Remove child by item.   400 /// Remove child by item.
365 /// \returns 0 if removed, -1 if item not an immediate child.   401 /// \returns 0 if removed, -1 if item not an immediate child.
366 ///   402 ///
367 int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) {   403 int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) {
368   for ( int t=0; t<children(); t++ ) {   404   for ( int t=0; t<children(); t++ ) {
369     if ( child(t) == item ) {   405     if ( child(t) == item ) {
370       item->clear_children();   406       item->clear_children();
371       _children.remove(t);   407       _children.remove(t);
      408       recalc_tree(); // may change tree geometry
372       return(0);   409       return(0);
373     }   410     }
374   }   411   }
375   return(-1);   412   return(-1);
376 }   413 }
377   414
378 /// Remove immediate child (and its children) by its label 'name'.   415 /// Remove immediate child (and its children) by its label 'name'.
379 /// \returns 0 if removed, -1 if not found.   416 /// \returns 0 if removed, -1 if not found.
380 ///   417 ///
381 int Fl_Tree_Item::remove_child(const char *name) {   418 int Fl_Tree_Item::remove_child(const char *name) {
382   for ( int t=0; t<children(); t++ ) {   419   for ( int t=0; t<children(); t++ ) {
383     if ( child(t)->label() ) {   420     if ( child(t)->label() ) {
384       if ( strcmp(child(t)->label(), name) == 0 ) {   421       if ( strcmp(child(t)->label(), name) == 0 ) {
385         _children.remove(t);   422         _children.remove(t);
      423 recalc_tree(); // may change tree geometry
386         return(0);   424         return(0);
387       }   425       }
388     }   426     }
389   }   427   }
390   return(-1);   428   return(-1);
391 }   429 }
392   430
393 /// Swap two of our children, given two child index values.   431 /// Swap two of our children, given two child index values.
394 /// Use this eg. for sorting.   432 /// Use this eg. for sorting.
395 ///   433 ///
396 /// This method is FAST, and does not involve lookups.   434 /// This method is FAST, and does not involve lookups.
397 ///   435 ///
398 /// No range checking is done on either index value.   436 /// No range checking is done on either index value.
399 ///   437 ///
400 /// \returns   438 /// \returns
401 /// - 0 : OK   439 /// - 0 : OK
402 /// - -1 : failed: 'a' or 'b' is not our immediate child   440 /// - -1 : failed: 'a' or 'b' is not our immediate child
403 ///   441 ///
404 void Fl_Tree_Item::swap_children(int ax, int bx) {   442 void Fl_Tree_Item::swap_children(int ax, int bx) {
405   _children.swap(ax, bx);   443   _children.swap(ax, bx);
406 }   444 }
407   445
408 /// Swap two of our children, given item pointers.   446 /// Swap two of our children, given item pointers.
409 /// Use this eg. for sorting.   447 /// Use this eg. for sorting.
410 ///   448 ///
411 /// This method is SLOW because it involves linear lookups.   449 /// This method is SLOW because it involves linear lookups.
412 /// For speed, use swap_children(int,int) instead.   450 /// For speed, use swap_children(int,int) instead.
413 ///   451 ///
414 /// \returns   452 /// \returns
415 /// - 0 : OK   453 /// - 0 : OK
416 /// - -1 : failed: 'a' or 'b' is not our immediate child   454 /// - -1 : failed: 'a' or 'b' is not our immediate child
417 ///   455 ///
418 int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) {   456 int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) {
419   int ax = -1, bx = -1;   457   int ax = -1, bx = -1;
420   for ( int t=0; t<children(); t++ ) { // find index for a and b   458   for ( int t=0; t<children(); t++ ) { // find index for a and b
421     if ( _children[t] == a ) { ax = t; if ( bx != -1 ) break; else continue; }   459     if ( _children[t] == a ) { ax = t; if ( bx != -1 ) break; else continue; }
422     if ( _children[t] == b ) { bx = t; if ( ax != -1 ) break; else continue; }   460     if ( _children[t] == b ) { bx = t; if ( ax != -1 ) break; else continue; }
423   }   461   }
424   if ( ax == -1 || bx == -1 ) return(-1); // not found? fail   462   if ( ax == -1 || bx == -1 ) return(-1); // not found? fail
425   swap_children(ax,bx);   463   swap_children(ax,bx);
426   return(0);   464   return(0);
427 }   465 }
428   466
429 /// Internal: Horizontal connector line based on preference settings.   467 /// Internal: Horizontal connector line based on preference settings.
430 void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) {   468 void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) {
431   fl_color(prefs.connectorcolor());   469   fl_color(prefs.connectorcolor());
432   switch ( prefs.connectorstyle() ) {   470   switch ( prefs.connectorstyle() ) {
433     case FL_TREE_CONNECTOR_SOLID:   471     case FL_TREE_CONNECTOR_SOLID:
434       y |= 1; // force alignment w/dot pattern   472       y |= 1; // force alignment w/dot pattern
435       fl_line(x1,y,x2,y);   473       fl_line(x1,y,x2,y);
436       return;   474       return;
437     case FL_TREE_CONNECTOR_DOTTED:   475     case FL_TREE_CONNECTOR_DOTTED:
438         {   476         {
439             y |= 1; // force alignment w/dot pattern   477             y |= 1; // force alignment w/dot pattern
440             for ( int xx=x1; xx<=x2; xx++ ) {   478             for ( int xx=x1; xx<=x2; xx++ ) {
441                 if ( !(xx & 1) ) fl_point(xx, y);   479                 if ( !(xx & 1) ) fl_point(xx, y);
442             }   480             }
443         }   481         }
444       return;   482       return;
445     case FL_TREE_CONNECTOR_NONE:   483     case FL_TREE_CONNECTOR_NONE:
446       return;   484       return;
447   }   485   }
448 }   486 }
449   487
450 /// Internal: Vertical connector line based on preference settings.   488 /// Internal: Vertical connector line based on preference settings.
451 void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) {   489 void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) {
452   fl_color(prefs.connectorcolor());   490   fl_color(prefs.connectorcolor());
453   switch ( prefs.connectorstyle() ) {   491   switch ( prefs.connectorstyle() ) {
454     case FL_TREE_CONNECTOR_SOLID:   492     case FL_TREE_CONNECTOR_SOLID:
455       y1 |= 1; // force alignment w/dot pattern   493       y1 |= 1; // force alignment w/dot pattern
456       y2 |= 1; // force alignment w/dot pattern   494       y2 |= 1; // force alignment w/dot pattern
457       fl_line(x,y1,x,y2);   495       fl_line(x,y1,x,y2);
458       return;   496       return;
459     case FL_TREE_CONNECTOR_DOTTED:   497     case FL_TREE_CONNECTOR_DOTTED:
460         {   498         {
461             y1 |= 1; // force alignment w/dot pattern   499             y1 |= 1; // force alignment w/dot pattern
462             y2 |= 1; // force alignment w/dot pattern   500             y2 |= 1; // force alignment w/dot pattern
463             for ( int yy=y1; yy<=y2; yy++ ) {   501             for ( int yy=y1; yy<=y2; yy++ ) {
464                 if ( yy & 1 ) fl_point(x, yy);   502                 if ( yy & 1 ) fl_point(x, yy);
465             }   503             }
466         }   504         }
467         return;   505         return;
468     case FL_TREE_CONNECTOR_NONE:   506     case FL_TREE_CONNECTOR_NONE:
469       return;   507       return;
470   }   508   }
471 }   509 }
472   510
473 /// Find the item that the last event was over.   511 // Internal
474 ///   512 const Fl_Tree_Item *Fl_Tree_Item::find_clicked_(const Fl_Tree_Prefs &prefs, int yonly) const {
475 /// Returns the item if it is visible, and mouse is over it.      
476 /// Works even if widget deactivated.      
477 /// Use event_on_collapse_icon() to determine if collapse button was pressed.      
478 ///      
479 /// \returns const visible item under the event if found, or 0 if none.      
480 ///      
481 const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const {      
482   if ( ! is_visible() ) return(0);   513   if ( ! is_visible() ) return(0);
483   if ( is_root() && !prefs.showroot() ) {   514   if ( is_root() && !prefs.showroot() ) {
484     // skip event check if we're root but root not being shown   515     // skip event check if we're root but root not being shown
485   } else {   516   } else {
486     // See if event is over us   517     // See if event is over us
      518     if ( yonly ) {
      519       if ( Fl::event_y() >= _xywh[1] &&
      520            Fl::event_y() <= (_xywh[1]+_xywh[3]) ) {
      521         return(this);
      522       }
      523     } else {
487     if ( event_inside(_xywh) ) { // event within this item?   524       if ( event_inside(_xywh) ) { // event within this item?
488       return(this); // found   525         return(this); // found
489     }   526       }
490   }   527     }
      528   }
491   if ( is_open() ) { // open? check children of this item   529   if ( is_open() ) { // open? check children of this item
492     for ( int t=0; t<children(); t++ ) {   530     for ( int t=0; t<children(); t++ ) {
493       const Fl_Tree_Item *item;   531       const Fl_Tree_Item *item;
494       if ( ( item = _children[t]->find_clicked(prefs) ) != NULL) { // check child and its descendents   532       if ( (item = _children[t]->find_clicked(prefs, yonly)) != NULL) { // check child and its descendents
495         return(item); // found?   533         return(item); // found?
496       }   534       }
497     }   535     }
498   }   536   }
499   return(0);   537   return(0);
500 }   538 }
501   539
      540 /// Find the item that last event was over.
      541 ///
      542 /// Returns the item if it is visible, and mouse is over it.
      543 /// Works even if widget deactivated.
      544 /// Use event_on_collapse_icon() to determine if collapse button was pressed.
      545 ///
      546 /// If \a yonly is set, only the mouse Y position is checked.
      547 ///
      548 /// \returns const visible item under the event if found, or 0 if none.
      549 ///
      550 const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) const {
      551   return(find_clicked_(prefs, yonly));
      552 }
      553
502 /// Non-const version of the above.   554 /// Non-const version of the above.
503 /// Find the item that the last event was over.   555 /// Find the item that last event was over.
504 ///   556 ///
505 /// Returns the item if it is visible, and mouse is over it.   557 /// Returns the item if it is visible, and mouse is over it.
506 /// Works even if widget deactivated.   558 /// Works even if widget deactivated.
507 /// Use event_on_collapse_icon() to determine if collapse button was pressed.   559 /// Use event_on_collapse_icon() to determine if collapse button was pressed.
508 ///   560 ///
509 /// \returns the visible item under the event if found, or 0 if none.   561 /// \returns the visible item under the event if found, or 0 if none.
510 ///   562 ///
511 Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) {   563 Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) {
512   if ( ! is_visible() ) return(0);   564   return((Fl_Tree_Item*)find_clicked_(prefs, yonly));
513   if ( is_root() && !prefs.showroot() ) {      
514     // skip event check if we're root but root not being shown      
515   } else {      
516     // See if event is over us      
517     if ( event_inside(_xywh) ) { // event within this item?      
518       return(this); // found      
519     }      
520   }      
521   if ( is_open() ) { // open? check children of this item      
522     for ( int t=0; t<children(); t++ ) {      
523       Fl_Tree_Item *item;      
524       if ( ( item = _children[t]->find_clicked(prefs) ) != NULL ) { // check child and its descendents      
525         return(item); // found?      
526       }      
527     }      
528   }      
529   return(0);      
530 }   565 }
531   566
532 static void draw_item_focus(Fl_Boxtype B, Fl_Color fg, Fl_Color bg, int X, int Y, int W, int H) {   567 static void draw_item_focus(Fl_Boxtype B, Fl_Color fg, Fl_Color bg, int X, int Y, int W, int H) {
533   if (!Fl::visible_focus()) return;   568   if (!Fl::visible_focus()) return;
534   switch (B) {   569   switch (B) {
535     case FL_DOWN_BOX:   570     case FL_DOWN_BOX:
536     case FL_DOWN_FRAME:   571     case FL_DOWN_FRAME:
537     case FL_THIN_DOWN_BOX:   572     case FL_THIN_DOWN_BOX:
538     case FL_THIN_DOWN_FRAME:   573     case FL_THIN_DOWN_FRAME:
539       X ++;   574       X ++;
540       Y ++;   575       Y ++;
541     default:   576     default:
542       break;   577       break;
543   }   578   }
544   fl_color(fl_contrast(fg, bg));   579   fl_color(fl_contrast(fg, bg));
545   580
546 #if defined(USE_X11) || defined(__APPLE_QUARTZ__)   581 #if defined(USE_X11) || defined(__APPLE_QUARTZ__)
547   fl_line_style(FL_DOT);   582   fl_line_style(FL_DOT);
548   fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B),   583   fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B),
549           W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1);   584           W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1);
550   fl_line_style(FL_SOLID);   585   fl_line_style(FL_SOLID);
551 #else   586 #else
552   // Some platforms don't implement dotted line style, so draw   587   // Some platforms don't implement dotted line style, so draw
553   // every other pixel around the focus area...   588   // every other pixel around the focus area...
554   //   589   //
555   // Also, QuickDraw (MacOS) does not support line styles specifically,   590   // Also, QuickDraw (MacOS) does not support line styles specifically,
556   // and the hack we use in fl_line_style() will not draw horizontal lines   591   // and the hack we use in fl_line_style() will not draw horizontal lines
557   // on odd-numbered rows...   592   // on odd-numbered rows...
558   int i, xx, yy;   593   int i, xx, yy;
559   594
560   X += Fl::box_dx(B);   595   X += Fl::box_dx(B);
561   Y += Fl::box_dy(B);   596   Y += Fl::box_dy(B);
562   W -= Fl::box_dw(B) + 2;   597   W -= Fl::box_dw(B) + 2;
563   H -= Fl::box_dh(B) + 2;   598   H -= Fl::box_dh(B) + 2;
564   599
565   for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y);   600   for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y);
566   for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy);   601   for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy);
567   for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H);   602   for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H);
568   for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy);   603   for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy);
569 #endif   604 #endif
570 }   605 }
571   606
572 /// Return the item's 'visible' height.   607 /// Return the item's 'visible' height.
573 /// Doesn't include linespacing(); prevents affecting eg. height of widget().   608 /// Doesn't include linespacing(); prevents affecting eg. height of widget().
574 ///   609 ///
575 int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const {   610 int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const {
576   if ( ! is_visible() ) return(0);   611   if ( ! is_visible() ) return(0);
577   int H = 0;   612   int H = 0;
578   if ( _label ) {   613   if ( _label ) {
579     fl_font(_labelfont, _labelsize); // fl_descent() needs this :/   614     fl_font(_labelfont, _labelsize); // fl_descent() needs this :/
580     H = _labelsize + fl_descent() + 1; // at least one pixel space below descender   615     H = _labelsize + fl_descent() + 1; // at least one pixel space below descender
581   }   616   }
582 #if FLTK_ABI_VERSION >= 10301   617 #if FLTK_ABI_VERSION >= 10301
583   if ( widget() &&   618   if ( widget() &&
584        (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) &&   619        (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) &&
585        H < widget()->h()) {   620        H < widget()->h()) {
586     H = widget()->h();   621     H = widget()->h();
587   }   622   }
588 #endif /*FLTK_ABI_VERSION*/   623 #endif /*FLTK_ABI_VERSION*/
589   if ( has_children() && prefs.openicon() && H<prefs.openicon()->h() )   624   if ( has_children() && prefs.openicon() && H<prefs.openicon()->h() )
590     H = prefs.openicon()->h();   625     H = prefs.openicon()->h();
591   if ( usericon() && H<usericon()->h() )   626   if ( usericon() && H<usericon()->h() )
592     H = usericon()->h();   627     H = usericon()->h();
593   return(H);   628   return(H);
594 }   629 }
595   630
      631 #if FLTK_ABI_VERSION >= 10303
596 /// Draw this item and its children.   632 /// Draw this item and its children.
      633 ///
      634 /// \param[in] X Horizontal position for item being drawn
      635 /// \param[in,out] Y Vertical position for item being drawn, returns new position for next item
      636 /// \param[in] W Recommended width of item
      637 /// \param[in] itemfocus The tree's current focus item (if any)
      638 /// \param[in,out] tree_item_xmax The tree's running xmax (right-most edge so far).
      639 /// Mainly used by parent tree when render==0 to calculate tree's max width.
      640 /// \param[in] lastchild Is this item the last child in a subtree?
      641 /// \param[in] render Whether or not to render the item:
      642 /// - 0 -- no rendering, just calculate size.
      643 /// (used to calculate size of tree without doing drawing)
      644 /// - 1 -- render the item as well as doing size calculations
      645 ///
      646 void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus,
      647 int &tree_item_xmax, int lastchild, int render) {
      648   Fl_Tree_Prefs &prefs = _tree->_prefs;
      649   if ( !is_visible() ) return;
      650   int tree_top = _tree->_tiy;
      651   int tree_bot = tree_top + _tree->_tih;
      652   int H = calc_item_height(prefs); // height of item
      653   int H2 = H + prefs.linespacing(); // height of item with line spacing
      654
      655   // Update the xywh of this item
      656   _xywh[0] = X;
      657   _xywh[1] = Y;
      658   _xywh[2] = W;
      659   _xywh[3] = H;
      660
      661   // Determine collapse icon's xywh
      662   // Note: calculate collapse icon's xywh for possible mouse click detection.
      663   // We don't care about items clipped off the viewport; they won't get mouse events.
      664   //
      665   int item_y_center = Y+(H/2);
      666   _collapse_xywh[2] = prefs.openicon()->w();
      667   int &icon_w = _collapse_xywh[2];
      668   _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3;
      669   int &icon_x = _collapse_xywh[0];
      670   _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2);
      671   int &icon_y = _collapse_xywh[1];
      672   _collapse_xywh[3] = prefs.openicon()->h();
      673
      674   // Horizontal connector values
      675   // Must calculate these even if(clipped) because 'draw children' code (below)
      676   // needs hconn_x_center value. (Otherwise, these calculations could be 'clipped')
      677   //
      678   int hconn_x = X+icon_w/2-1;
      679   int hconn_x2 = hconn_x + prefs.connectorwidth();
      680   int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2);
      681   int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();
      682   int conn_w = cw1>cw2 ? cw1 : cw2;
      683
      684   // Background xywh
      685   int &bg_x = _label_xywh[0] = X+(icon_w/2-1+conn_w);
      686   int &bg_y = _label_xywh[1] = Y;
      687   int &bg_w = _label_xywh[2] = _tree->_tix + _tree->_tiw - bg_x;
      688   int &bg_h = _label_xywh[3] = H;
      689
      690   // Usericon position
      691   int uicon_x = bg_x + ( (usericon() || prefs.usericon()) ? prefs.usericonmarginleft() : 0);
      692   int uicon_w = usericon() ? usericon()->w() : prefs.usericon() ? prefs.usericon()->w() : 0;
      693
      694   // Label position
      695   int label_x = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0);
      696
      697   // Begin calc of this item's max width..
      698   // It might not even be visible, so start at zero.
      699   //
      700   int ixmax = 0;
      701
      702   // Recalc widget position
      703   // Do this whether clipped or not, so that when scrolled,
      704   // the widgets move to appropriate 'offscreen' positions
      705   // (so that they don't get mouse events, etc)
      706   //
      707   if ( widget() ) {
      708     int wx = label_x;
      709     int wy = bg_y;
      710     int ww = widget()->w(); // use widget's width
      711     int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET)
      712              ? widget()->h() : H;
      713     if ( _label &&
      714          (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) {
      715       fl_font(_labelfont, _labelsize); // fldescent() needs this
      716       int lw=0, lh=0;
      717       fl_measure(_label,lw,lh); // get box around text (including white space)
      718       wx += (lw + prefs.widgetmarginleft());
      719     }
      720     if ( widget()->x() != wx || widget()->y() != wy ||
      721 widget()->w() != ww || widget()->h() != wh ) {
      722       widget()->resize(wx,wy,ww,wh); // we'll handle redraw below
      723     }
      724   }
      725   char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;
      726   if (!render) clipped = 0; // NOT rendering? Then don't clip, so we calc unclipped items
      727   char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
      728   if ( !clipped ) {
      729     Fl_Color fg = is_selected() ? fl_contrast(_labelfgcolor, _tree->selection_color())
      730 : is_active() ? _labelfgcolor
      731 : fl_inactive(_labelfgcolor);
      732     Fl_Color bg = is_selected() ? is_active() ? _tree->selection_color()
      733 : fl_inactive(_tree->selection_color())
      734 : _labelbgcolor == 0xffffffff ? _tree->color() // transparent bg?
      735 : _labelbgcolor;
      736     // See if we should draw this item
      737     // If this item is root, and showroot() is disabled, don't draw.
      738     // 'clipped' is an optimization to prevent drawing anything offscreen.
      739     //
      740     if ( drawthis ) { // draw this item at all?
      741       if ( (_tree->damage() & ~FL_DAMAGE_CHILD) || !render ) { // non-child damage?
      742 // Draw connectors
      743 if ( render && prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
      744 // Horiz connector between center of icon and text
      745 // if this is root, the connector should not dangle in thin air on the left
      746 if (is_root()) draw_horizontal_connector(hconn_x_center, hconn_x2, item_y_center, prefs);
      747 else draw_horizontal_connector(hconn_x, hconn_x2, item_y_center, prefs);
      748 // Small vertical line down to children
      749 if ( has_children() && is_open() )
      750 draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs);
      751 // Connectors for last child
      752 if ( !is_root() ) {
      753 if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs);
      754 else draw_vertical_connector(hconn_x, Y, Y+H2, prefs);
      755 }
      756 }
      757 // Draw collapse icon
      758 if ( render && has_children() && prefs.showcollapse() ) {
      759 // Draw icon image
      760 if ( is_open() ) {
      761 prefs.closeicon()->draw(icon_x,icon_y);
      762 } else {
      763 prefs.openicon()->draw(icon_x,icon_y);
      764 }
      765 }
      766 // Background for this item
      767 // Draw bg only if different from tree's bg
      768 if ( render && (bg != _tree->color() || is_selected()) ) {
      769 if ( is_selected() ) { // Selected? Use selectbox() style
      770 fl_draw_box(prefs.selectbox(),bg_x,bg_y,bg_w,bg_h,bg);
      771 } else { // Not Selected? use plain filled rectangle
      772 fl_color(bg);
      773 fl_rectf(bg_x,bg_y,bg_w,bg_h);
      774 }
      775 if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it
      776 }
      777 // Draw user icon (if any)
      778 if ( render && usericon() ) {
      779 // Item has user icon? Use it
      780 int uicon_y = item_y_center - (usericon()->h() >> 1);
      781 usericon()->draw(uicon_x,uicon_y);
      782 } else if ( render && prefs.usericon() ) {
      783 // Prefs has user icon? Use it
      784 int uicon_y = item_y_center - (prefs.usericon()->h() >> 1);
      785 prefs.usericon()->draw(uicon_x,uicon_y);
      786 }
      787 // Draw label
      788         if ( _label &&
      789 ( !widget() ||
      790 (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) {
      791 if ( render ) {
      792 fl_color(fg);
      793 fl_font(_labelfont, _labelsize);
      794           }
      795 int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2;
      796
      797 int lw=0, lh=0;
      798 fl_measure(_label, lw, lh); // get box around text (including white space)
      799 if ( render ) fl_draw(_label, label_x, label_y);
      800 ixmax = label_x + lw; // update max width of drawn item
      801 }
      802       } // end non-child damage
      803       // Draw child FLTK widget?
      804       if ( widget() ) {
      805         if (render)
      806 _tree->draw_child(*widget()); // let group handle drawing child
      807 if ( widget()->label() && render )
      808 _tree->draw_outside_label(*widget()); // label too
      809         ixmax = widget()->x() + widget()->w(); // update max width of widget
      810       }
      811       // Draw focus box around item's bg last
      812       if ( render &&
      813            this == itemfocus &&
      814            Fl::visible_focus() &&
      815 Fl::focus() == _tree &&
      816 prefs.selectmode() != FL_TREE_SELECT_NONE ) {
      817 draw_item_focus(FL_NO_BOX,fg,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1);
      818       }
      819     } // end drawthis
      820   } // end clipped
      821   if ( drawthis ) Y += H2; // adjust Y (even if clipped)
      822   // Manage tree_item_xmax
      823   if ( ixmax > tree_item_xmax )
      824     tree_item_xmax = ixmax;
      825   // Draw child items (if any)
      826   if ( has_children() && is_open() ) {
      827     int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset children to right,
      828                            : X; // unless didn't drawthis
      829     int child_w = W - (child_x-X);
      830     int child_y_start = Y;
      831     for ( int t=0; t<children(); t++ ) {
      832       int lastchild = ((t+1)==children()) ? 1 : 0;
      833       _children[t]->draw(child_x, Y, child_w, itemfocus, tree_item_xmax, lastchild, render);
      834     }
      835     if ( has_children() && is_open() ) {
      836       Y += prefs.openchild_marginbottom(); // offset below open child tree
      837     }
      838     if ( ! lastchild ) {
      839       // Special 'clipped' calculation. (intentional variable shadowing)
      840       int clipped = ((child_y_start < tree_top) && (Y < tree_top)) ||
      841                     ((child_y_start > tree_bot) && (Y > tree_bot));
      842       if (render && !clipped )
      843         draw_vertical_connector(hconn_x, child_y_start, Y, prefs);
      844     }
      845   }
      846 }
      847
      848 #else
      849
      850 /// Draw this item and its children.
      851 ///
      852 /// \param[in] X Horizontal position for item being drawn
      853 /// \param[in,out] Y Vertical position for item being drawn, returns new position for next item
      854 /// \param[in] W Recommended width of item
      855 /// \param[in] tree The parent tree
      856 /// \param[in] itemfocus The tree's current focus item (if any)
      857 /// \param[in] prefs The tree's preferences
      858 /// \param[in] lastchild Is this item the last child in a subtree?
      859 ///
597 void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,   860 void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
598 Fl_Tree_Item *itemfocus,   861 Fl_Tree_Item *itemfocus,
599                         const Fl_Tree_Prefs &prefs, int lastchild) {   862                         const Fl_Tree_Prefs &prefs, int lastchild) {
600   if ( ! is_visible() ) return;   863   if ( ! is_visible() ) return;
601   int tree_top = tree->y();   864   int tree_top = tree->y();
602   int tree_bot = tree_top + tree->h();   865   int tree_bot = tree_top + tree->h();
603   int H = calc_item_height(prefs); // height of item   866   int H = calc_item_height(prefs); // height of item
604   int H2 = H + prefs.linespacing(); // height of item with line spacing   867   int H2 = H + prefs.linespacing(); // height of item with line spacing
605   868
606   // Update the xywh of this item   869   // Update the xywh of this item
607   _xywh[0] = X;   870   _xywh[0] = X;
608   _xywh[1] = Y;   871   _xywh[1] = Y;
609   _xywh[2] = W;   872   _xywh[2] = W;
610   _xywh[3] = H;   873   _xywh[3] = H;
611   874
612   // Determine collapse icon's xywh   875   // Determine collapse icon's xywh
613   // Note: calculate collapse icon's xywh for possible mouse click detection.   876   // Note: calculate collapse icon's xywh for possible mouse click detection.
614   // We don't care about items clipped off the viewport; they won't get mouse events.   877   // We don't care about items clipped off the viewport; they won't get mouse events.
615   //   878   //
616   int item_y_center = Y+(H/2);   879   int item_y_center = Y+(H/2);
617   _collapse_xywh[2] = prefs.openicon()->w();   880   _collapse_xywh[2] = prefs.openicon()->w();
618   int &icon_w = _collapse_xywh[2];   881   int &icon_w = _collapse_xywh[2];
619   _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3;   882   _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3;
620   int &icon_x = _collapse_xywh[0];   883   int &icon_x = _collapse_xywh[0];
621   _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2);   884   _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2);
622   int &icon_y = _collapse_xywh[1];   885   int &icon_y = _collapse_xywh[1];
623   _collapse_xywh[3] = prefs.openicon()->h();   886   _collapse_xywh[3] = prefs.openicon()->h();
624   887
625   // Horizontal connector values   888   // Horizontal connector values
626   // XXX: Must calculate these even if(clipped) because 'draw children' code (below)   889   // XXX: Must calculate these even if(clipped) because 'draw children' code (below)
627   // needs hconn_x_center value. (Otherwise, these calculations could be 'clipped')   890   // needs hconn_x_center value. (Otherwise, these calculations could be 'clipped')
628   //   891   //
629   int hconn_x = X+icon_w/2-1;   892   int hconn_x = X+icon_w/2-1;
630   int hconn_x2 = hconn_x + prefs.connectorwidth();   893   int hconn_x2 = hconn_x + prefs.connectorwidth();
631   int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2);   894   int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2);
632   int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();   895   int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();
633   int conn_w = cw1>cw2 ? cw1 : cw2;   896   int conn_w = cw1>cw2 ? cw1 : cw2;
634   897
635   // Background position   898   // Background position
636   int &bg_x = _label_xywh[0] = X+(icon_w/2-1+conn_w);   899   int &bg_x = _label_xywh[0] = X+(icon_w/2-1+conn_w);
637   int &bg_y = _label_xywh[1] = Y;   900   int &bg_y = _label_xywh[1] = Y;
638   int &bg_w = _label_xywh[2] = W-(icon_w/2-1+conn_w);   901   int &bg_w = _label_xywh[2] = W-(icon_w/2-1+conn_w);
639   int &bg_h = _label_xywh[3] = H;   902   int &bg_h = _label_xywh[3] = H;
640   903
641   // Usericon position   904   // Usericon position
642   int uicon_x = bg_x + ( (usericon() || prefs.usericon()) ? prefs.usericonmarginleft() : 0);   905   int uicon_x = bg_x + ( (usericon() || prefs.usericon()) ? prefs.usericonmarginleft() : 0);
643   int uicon_w = usericon() ? usericon()->w() : prefs.usericon() ? prefs.usericon()->w() : 0;   906   int uicon_w = usericon() ? usericon()->w() : prefs.usericon() ? prefs.usericon()->w() : 0;
644   907
645   // Label position   908   // Label position
646   int label_x = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0);   909   int label_x = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0);
647   910
648   // Recalc widget position   911   // Recalc widget position
649   // Do this whether clipped or not, so that when scrolled,   912   // Do this whether clipped or not, so that when scrolled,
650   // the widgets move to appropriate 'offscreen' positions   913   // the widgets move to appropriate 'offscreen' positions
651   // (so that they don't get mouse events, etc)   914   // (so that they don't get mouse events, etc)
652   //   915   //
653   if ( widget() ) {   916   if ( widget() ) {
654     int wx = label_x;   917     int wx = label_x;
655     int wy = bg_y;   918     int wy = bg_y;
656     int ww = widget()->w(); // use widget's width   919     int ww = widget()->w(); // use widget's width
657 #if FLTK_ABI_VERSION >= 10301   920 #if FLTK_ABI_VERSION >= 10301
658     int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET)   921     int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET)
659              ? widget()->h() : H;   922              ? widget()->h() : H;
660     if ( _label &&   923     if ( _label &&
661          (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) {   924          (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) {
662 #else /*FLTK_ABI_VERSION*/   925 #else /*FLTK_ABI_VERSION*/
663     int wh = H; // lock widget's height to item height   926     int wh = H; // lock widget's height to item height
664     if ( _label && !widget() ) { // back compat: don't draw label if widget() present   927     if ( _label && !widget() ) { // back compat: don't draw label if widget() present
665 #endif /*FLTK_ABI_VERSION*/   928 #endif /*FLTK_ABI_VERSION*/
666       fl_font(_labelfont, _labelsize); // fldescent() needs this   929       fl_font(_labelfont, _labelsize); // fldescent() needs this
667       int lw=0, lh=0;   930       int lw=0, lh=0;
668       fl_measure(_label,lw,lh); // get box around text (including white space)   931       fl_measure(_label,lw,lh); // get box around text (including white space)
669 #if FLTK_ABI_VERSION >= 10301   932 #if FLTK_ABI_VERSION >= 10301
670       // NEW   933       // NEW
671       wx += (lw + prefs.widgetmarginleft());   934       wx += (lw + prefs.widgetmarginleft());
672 #else /*FLTK_ABI_VERSION*/   935 #else /*FLTK_ABI_VERSION*/
673       // OLD   936       // OLD
674       wx += (lw + 3);   937       wx += (lw + 3);
675 #endif /*FLTK_ABI_VERSION*/   938 #endif /*FLTK_ABI_VERSION*/
676     }   939     }
677     if ( widget()->x() != wx || widget()->y() != wy ||   940     if ( widget()->x() != wx || widget()->y() != wy ||
678 widget()->w() != ww || widget()->h() != wh ) {   941 widget()->w() != ww || widget()->h() != wh ) {
679       widget()->resize(wx,wy,ww,wh); // we'll handle redraw below   942       widget()->resize(wx,wy,ww,wh); // we'll handle redraw below
680     }   943     }
681   }   944   }
682   char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;   945   char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;
683   char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;   946   char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
684   if ( !clipped ) {   947   if ( !clipped ) {
685     Fl_Color fg = is_selected() ? fl_contrast(_labelfgcolor, tree->selection_color())   948     Fl_Color fg = is_selected() ? fl_contrast(_labelfgcolor, tree->selection_color())
686 : is_active() ? _labelfgcolor   949 : is_active() ? _labelfgcolor
687 : fl_inactive(_labelfgcolor);   950 : fl_inactive(_labelfgcolor);
688     Fl_Color bg = is_selected() ? is_active() ? tree->selection_color()   951     Fl_Color bg = is_selected() ? is_active() ? tree->selection_color()
689 : fl_inactive(tree->selection_color())   952 : fl_inactive(tree->selection_color())
690 : _labelbgcolor == 0xffffffff ? tree->color() // transparent bg?   953 : _labelbgcolor == 0xffffffff ? tree->color() // transparent bg?
691 : _labelbgcolor;   954 : _labelbgcolor;
692     // See if we should draw this item   955     // See if we should draw this item
693     // If this item is root, and showroot() is disabled, don't draw.   956     // If this item is root, and showroot() is disabled, don't draw.
694     // 'clipped' is an optimization to prevent drawing anything offscreen.   957     // 'clipped' is an optimization to prevent drawing anything offscreen.
695     //   958     //
696     if ( drawthis ) { // draw this item at all?   959     if ( drawthis ) { // draw this item at all?
697       if ( tree->damage() & ~FL_DAMAGE_CHILD ) { // non-child damage?   960       if ( tree->damage() & ~FL_DAMAGE_CHILD ) { // non-child damage?
698 // Draw connectors   961 // Draw connectors
699 if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {   962 if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
700 // Horiz connector between center of icon and text   963 // Horiz connector between center of icon and text
701 // if this is root, the connector should not dangle in thin air on the left   964 // if this is root, the connector should not dangle in thin air on the left
702 if (is_root()) draw_horizontal_connector(hconn_x_center, hconn_x2, item_y_center, prefs);   965 if (is_root()) draw_horizontal_connector(hconn_x_center, hconn_x2, item_y_center, prefs);
703 else draw_horizontal_connector(hconn_x, hconn_x2, item_y_center, prefs);   966 else draw_horizontal_connector(hconn_x, hconn_x2, item_y_center, prefs);
704 // Small vertical line down to children   967 // Small vertical line down to children
705 if ( has_children() && is_open() )   968 if ( has_children() && is_open() )
706 draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs);   969 draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs);
707 // Connectors for last child   970 // Connectors for last child
708 if ( !is_root() ) {   971 if ( !is_root() ) {
709 if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs);   972 if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs);
710 else draw_vertical_connector(hconn_x, Y, Y+H2, prefs);   973 else draw_vertical_connector(hconn_x, Y, Y+H2, prefs);
711 }   974 }
712 }   975 }
713 // Draw collapse icon   976 // Draw collapse icon
714 if ( has_children() && prefs.showcollapse() ) {   977 if ( has_children() && prefs.showcollapse() ) {
715 // Draw icon image   978 // Draw icon image
716 if ( is_open() ) {   979 if ( is_open() ) {
717 prefs.closeicon()->draw(icon_x,icon_y);   980 prefs.closeicon()->draw(icon_x,icon_y);
718 } else {   981 } else {
719 prefs.openicon()->draw(icon_x,icon_y);   982 prefs.openicon()->draw(icon_x,icon_y);
720 }   983 }
721 }   984 }
722 // Draw the item   985 // Draw the item
723 #if FLTK_ABI_VERSION >= 10303   986 #if FLTK_ABI_VERSION >= 10303
724 if ( !widget() && prefs.item_draw_callback() ) {   987 if ( !widget() && prefs.item_draw_callback() ) {
725 // Draw item using user supplied custom item draw callback   988 // Draw item using user supplied custom item draw callback
726 prefs.do_item_draw_callback(this);   989 prefs.do_item_draw_callback(this);
727         }   990         }
728 else   991 else
729 #endif   992 #endif
730 {   993 {
731 // Background for this item   994 // Background for this item
732 // Draw bg only if different from tree's bg   995 // Draw bg only if different from tree's bg
733 if ( bg != tree->color() || is_selected() ) {   996 if ( bg != tree->color() || is_selected() ) {
734 if ( is_selected() ) { // Selected? Use selectbox() style   997 if ( is_selected() ) { // Selected? Use selectbox() style
735 fl_draw_box(prefs.selectbox(),bg_x,bg_y,bg_w,bg_h,bg);   998 fl_draw_box(prefs.selectbox(),bg_x,bg_y,bg_w,bg_h,bg);
736 } else { // Not Selected? use plain filled rectangle   999 } else { // Not Selected? use plain filled rectangle
737 fl_color(bg);   1000 fl_color(bg);
738 fl_rectf(bg_x,bg_y,bg_w,bg_h);   1001 fl_rectf(bg_x,bg_y,bg_w,bg_h);
739 }   1002 }
740 if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it   1003 if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it
741 }   1004 }
742 // Draw user icon (if any)   1005 // Draw user icon (if any)
743 if ( usericon() ) {   1006 if ( usericon() ) {
744 // Item has user icon? Use it   1007 // Item has user icon? Use it
745 int uicon_y = item_y_center - (usericon()->h() >> 1);   1008 int uicon_y = item_y_center - (usericon()->h() >> 1);
746 usericon()->draw(uicon_x,uicon_y);   1009 usericon()->draw(uicon_x,uicon_y);
747 } else if ( prefs.usericon() ) {   1010 } else if ( prefs.usericon() ) {
748 // Prefs has user icon? Use it   1011 // Prefs has user icon? Use it
749 int uicon_y = item_y_center - (prefs.usericon()->h() >> 1);   1012 int uicon_y = item_y_center - (prefs.usericon()->h() >> 1);
750 prefs.usericon()->draw(uicon_x,uicon_y);   1013 prefs.usericon()->draw(uicon_x,uicon_y);
751 }   1014 }
752 // Draw label   1015 // Draw label
753 #if FLTK_ABI_VERSION >= 10301   1016 #if FLTK_ABI_VERSION >= 10301
754 if ( _label &&   1017 if ( _label &&
755 ( !widget() ||   1018 ( !widget() ||
756 (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) )   1019 (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) )
757 #else /*FLTK_ABI_VERSION*/   1020 #else /*FLTK_ABI_VERSION*/
758 if ( _label && !widget() ) // back compat: don't draw label if widget() present   1021 if ( _label && !widget() ) // back compat: don't draw label if widget() present
759 #endif /*FLTK_ABI_VERSION*/   1022 #endif /*FLTK_ABI_VERSION*/
760 {   1023 {
761 fl_color(fg);   1024 fl_color(fg);
762 fl_font(_labelfont, _labelsize);   1025 fl_font(_labelfont, _labelsize);
763 int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2;   1026 int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2;
764 fl_draw(_label, label_x, label_y);   1027 fl_draw(_label, label_x, label_y);
765 }   1028 }
766         } // end non-custom draw   1029         } // end non-custom draw
767       } // end non-child damage   1030       } // end non-child damage
768       // Draw child FLTK widget?   1031       // Draw child FLTK widget?
769       if ( widget() ) {   1032       if ( widget() ) {
770         ((Fl_Tree*)tree)->draw_child(*widget()); // let group handle drawing child   1033         ((Fl_Tree*)tree)->draw_child(*widget()); // let group handle drawing child
771 if ( widget()->label() )   1034 if ( widget()->label() )
772 ((Fl_Tree*)tree)->draw_outside_label(*widget()); // label too   1035 ((Fl_Tree*)tree)->draw_outside_label(*widget()); // label too
773       }   1036       }
774       // Draw focus box around item's bg last   1037       // Draw focus box around item's bg last
775       if ( this == itemfocus &&   1038       if ( this == itemfocus &&
776            Fl::visible_focus() &&   1039            Fl::visible_focus() &&
777 Fl::focus() == tree &&   1040 Fl::focus() == tree &&
778 prefs.selectmode() != FL_TREE_SELECT_NONE ) {   1041 prefs.selectmode() != FL_TREE_SELECT_NONE ) {
779 draw_item_focus(FL_NO_BOX,fg,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1);   1042 draw_item_focus(FL_NO_BOX,fg,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1);
780       }   1043       }
781     } // end drawthis   1044     } // end drawthis
782   } // end clipped   1045   } // end clipped
783   if ( drawthis ) Y += H2; // adjust Y (even if clipped)   1046   if ( drawthis ) Y += H2; // adjust Y (even if clipped)
784   // Draw child items (if any)   1047   // Draw child items (if any)
785   if ( has_children() && is_open() ) {   1048   if ( has_children() && is_open() ) {
786     int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset children to right,   1049     int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset children to right,
787                            : X; // unless didn't drawthis   1050                            : X; // unless didn't drawthis
788     int child_w = W - (child_x-X);   1051     int child_w = W - (child_x-X);
789     int child_y_start = Y;   1052     int child_y_start = Y;
790     for ( int t=0; t<children(); t++ ) {   1053     for ( int t=0; t<children(); t++ ) {
791       int lastchild = ((t+1)==children()) ? 1 : 0;   1054       int lastchild = ((t+1)==children()) ? 1 : 0;
792       _children[t]->draw(child_x, Y, child_w, tree, itemfocus, prefs, lastchild);   1055       _children[t]->draw(child_x, Y, child_w, tree, itemfocus, prefs, lastchild);
793     }   1056     }
794     if ( has_children() && is_open() ) {   1057     if ( has_children() && is_open() ) {
795       Y += prefs.openchild_marginbottom(); // offset below open child tree   1058       Y += prefs.openchild_marginbottom(); // offset below open child tree
796     }   1059     }
797     if ( ! lastchild ) {   1060     if ( ! lastchild ) {
798       // Special 'clipped' calculation. (intentional variable shadowing)   1061       // Special 'clipped' calculation. (intentional variable shadowing)
799       int clipped = ((child_y_start < tree_top) && (Y < tree_top)) ||   1062       int clipped = ((child_y_start < tree_top) && (Y < tree_top)) ||
800                     ((child_y_start > tree_bot) && (Y > tree_bot));   1063                     ((child_y_start > tree_bot) && (Y > tree_bot));
801       if (!clipped) draw_vertical_connector(hconn_x, child_y_start, Y, prefs);   1064       if (!clipped) draw_vertical_connector(hconn_x, child_y_start, Y, prefs);
802     }   1065     }
803   }   1066   }
804 }   1067 }
      1068 #endif
805   1069
806 /// Was the event on the 'collapse' button?   1070 /// Was the event on the 'collapse' button?
807 ///   1071 ///
808 int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const {   1072 int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const {
809   if ( is_visible() && is_active() && has_children() && prefs.showcollapse() ) {   1073   if ( is_visible() && is_active() && has_children() && prefs.showcollapse() ) {
810     return(event_inside(_collapse_xywh) ? 1 : 0);   1074     return(event_inside(_collapse_xywh) ? 1 : 0);
811   } else {   1075   } else {
812     return(0);   1076     return(0);
813   }   1077   }
814 }   1078 }
815   1079
816 /// Was event on the label()?   1080 /// Was event on the label()?
817 ///   1081 ///
818 int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const {   1082 int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const {
819   if ( is_visible() && is_active() ) {   1083   if ( is_visible() && is_active() ) {
820     return(event_inside(_label_xywh) ? 1 : 0);   1084     return(event_inside(_label_xywh) ? 1 : 0);
821   } else {   1085   } else {
822     return(0);   1086     return(0);
823   }   1087   }
824 }   1088 }
825   1089
826 /// Internal: Show the FLTK widget() for this item and all children.   1090 /// Internal: Show the FLTK widget() for this item and all children.
827 /// Used by open() to re-show widgets that were hidden by a previous close()   1091 /// Used by open() to re-show widgets that were hidden by a previous close()
828 ///   1092 ///
829 void Fl_Tree_Item::show_widgets() {   1093 void Fl_Tree_Item::show_widgets() {
830   if ( _widget ) _widget->show();   1094   if ( _widget ) _widget->show();
831   if ( is_open() ) {   1095   if ( is_open() ) {
832     for ( int t=0; t<_children.total(); t++ ) {   1096     for ( int t=0; t<_children.total(); t++ ) {
833       _children[t]->show_widgets();   1097       _children[t]->show_widgets();
834     }   1098     }
835   }   1099   }
836 }   1100 }
837   1101
838 /// Internal: Hide the FLTK widget() for this item and all children.   1102 /// Internal: Hide the FLTK widget() for this item and all children.
839 /// Used by close() to hide widgets.   1103 /// Used by close() to hide widgets.
840 ///   1104 ///
841 void Fl_Tree_Item::hide_widgets() {   1105 void Fl_Tree_Item::hide_widgets() {
842   if ( _widget ) _widget->hide();   1106   if ( _widget ) _widget->hide();
843   for ( int t=0; t<_children.total(); t++ ) {   1107   for ( int t=0; t<_children.total(); t++ ) {
844     _children[t]->hide_widgets();   1108     _children[t]->hide_widgets();
845   }   1109   }
846 }   1110 }
847   1111
848 /// Open this item and all its children.   1112 /// Open this item and all its children.
849 void Fl_Tree_Item::open() {   1113 void Fl_Tree_Item::open() {
850   set_flag(OPEN,1);   1114   set_flag(OPEN,1);
851   // Tell children to show() their widgets   1115   // Tell children to show() their widgets
852   for ( int t=0; t<_children.total(); t++ ) {   1116   for ( int t=0; t<_children.total(); t++ ) {
853     _children[t]->show_widgets();   1117     _children[t]->show_widgets();
854   }   1118   }
      1119   recalc_tree(); // may change tree geometry
855 }   1120 }
856   1121
857 /// Close this item and all its children.   1122 /// Close this item and all its children.
858 void Fl_Tree_Item::close() {   1123 void Fl_Tree_Item::close() {
859   set_flag(OPEN,0);   1124   set_flag(OPEN,0);
860   // Tell children to hide() their widgets   1125   // Tell children to hide() their widgets
861   for ( int t=0; t<_children.total(); t++ ) {   1126   for ( int t=0; t<_children.total(); t++ ) {
862     _children[t]->hide_widgets();   1127     _children[t]->hide_widgets();
863   }   1128   }
      1129   recalc_tree(); // may change tree geometry
864 }   1130 }
865   1131
866 /// Returns how many levels deep this item is in the hierarchy.   1132 /// Returns how many levels deep this item is in the hierarchy.
867 ///   1133 ///
868 /// For instance; root has a depth of zero, and its immediate children   1134 /// For instance; root has a depth of zero, and its immediate children
869 /// would have a depth of 1, and so on.   1135 /// would have a depth of 1, and so on.
870 ///   1136 ///
871 int Fl_Tree_Item::depth() const {   1137 int Fl_Tree_Item::depth() const {
872   int count = 0;   1138   int count = 0;
873   const Fl_Tree_Item *item = parent();   1139   const Fl_Tree_Item *item = parent();
874   while ( item ) {   1140   while ( item ) {
875     ++count;   1141     ++count;
876     item = item->parent();   1142     item = item->parent();
877   }   1143   }
878   return(count);   1144   return(count);
879 }   1145 }
880   1146
881 /// Return the next item in the tree.   1147 /// Return the next item in the tree.
882 ///   1148 ///
883 /// This method can be used to walk the tree forward.   1149 /// This method can be used to walk the tree forward.
884 /// For an example of how to use this method, see Fl_Tree::first().   1150 /// For an example of how to use this method, see Fl_Tree::first().
885 ///   1151 ///
886 /// \returns the next item in the tree, or 0 if there's no more items.   1152 /// \returns the next item in the tree, or 0 if there's no more items.
887 ///   1153 ///
888 Fl_Tree_Item *Fl_Tree_Item::next() {   1154 Fl_Tree_Item *Fl_Tree_Item::next() {
889   Fl_Tree_Item *p, *c = this;   1155   Fl_Tree_Item *p, *c = this;
890   if ( c->has_children() ) {   1156   if ( c->has_children() ) {
891     return(c->child(0));   1157     return(c->child(0));
892   }   1158   }
893 #if FLTK_ABI_VERSION >= 10301   1159 #if FLTK_ABI_VERSION >= 10301
894   // NEW   1160   // NEW
895   while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents   1161   while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents
896     if ( c->_next_sibling ) // not last child?   1162     if ( c->_next_sibling ) // not last child?
897       return(c->_next_sibling); // return next child   1163       return(c->_next_sibling); // return next child
898     c = p; // child becomes parent to move up generation   1164     c = p; // child becomes parent to move up generation
899   } // loop: moves up to next parent   1165   } // loop: moves up to next parent
900 #else /*FLTK_ABI_VERSION*/   1166 #else /*FLTK_ABI_VERSION*/
901   // OLD   1167   // OLD
902   while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents   1168   while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents
903     int t = p->find_child(c); // find our position in parent's children[] array   1169     int t = p->find_child(c); // find our position in parent's children[] array
904     if ( ++t < p->children() ) // not last child?   1170     if ( ++t < p->children() ) // not last child?
905       return(p->child(t)); // return next child   1171       return(p->child(t)); // return next child
906     c = p; // child becomes parent to move up generation   1172     c = p; // child becomes parent to move up generation
907   } // loop: moves up to next parent   1173   } // loop: moves up to next parent
908 #endif /*FLTK_ABI_VERSION*/   1174 #endif /*FLTK_ABI_VERSION*/
909   return(0); // hit root? done   1175   return(0); // hit root? done
910 }   1176 }
911   1177
912 /// Return the previous item in the tree.   1178 /// Return the previous item in the tree.
913 ///   1179 ///
914 /// This method can be used to walk the tree backwards.   1180 /// This method can be used to walk the tree backwards.
915 /// For an example of how to use this method, see Fl_Tree::last().   1181 /// For an example of how to use this method, see Fl_Tree::last().
916 ///   1182 ///
917 /// \returns the previous item in the tree, or 0 if there's no item above this one (hit the root).   1183 /// \returns the previous item in the tree, or 0 if there's no item above this one (hit the root).
918 ///   1184 ///
919 Fl_Tree_Item *Fl_Tree_Item::prev() {   1185 Fl_Tree_Item *Fl_Tree_Item::prev() {
920 #if FLTK_ABI_VERSION >= 10301   1186 #if FLTK_ABI_VERSION >= 10301
921   // NEW   1187   // NEW
922   if ( !parent() ) return(0); // hit root? done   1188   if ( !parent() ) return(0); // hit root? done
923   if ( !_prev_sibling ) { // are we first child?   1189   if ( !_prev_sibling ) { // are we first child?
924     return(parent()); // return parent   1190     return(parent()); // return parent
925   }   1191   }
926   // Tricky: in the following example our current position   1192   // Tricky: in the following example our current position
927   // in the tree is 'j', and we need to move "up one" to 'i':   1193   // in the tree is 'j', and we need to move "up one" to 'i':
928   //   1194   //
929   // ROOT   1195   // ROOT
930   // |-- a   1196   // |-- a
931   // b-- c   1197   // b-- c
932   // | d-- e   1198   // | d-- e
933   // | | f   1199   // | | f
934   // | |   1200   // | |
935   // | g-- h   1201   // | g-- h
936   // | i   1202   // | i
937   // j   1203   // j
938   //   1204   //
939   // We do this via b->g->i:   1205   // We do this via b->g->i:
940   // 1. Find j's prev_sibling (b) _   1206   // 1. Find j's prev_sibling (b) _
941   // 2. Find b's 'last child' (g) |_ while loop   1207   // 2. Find b's 'last child' (g) |_ while loop
942   // 3. Find g's 'last child' (i) _|   1208   // 3. Find g's 'last child' (i) _|
943   //   1209   //
944   Fl_Tree_Item *p = _prev_sibling; // focus on our prev sibling   1210   Fl_Tree_Item *p = _prev_sibling; // focus on our prev sibling
945   while ( p->has_children() ) { // item has children?   1211   while ( p->has_children() ) { // item has children?
946     p = p->child(p->children()-1); // descend hierarchy finding deepest 'last child'   1212     p = p->child(p->children()-1); // descend hierarchy finding deepest 'last child'
947   }   1213   }
948   return(p);   1214   return(p);
949 #else /*FLTK_ABI_VERSION*/   1215 #else /*FLTK_ABI_VERSION*/
950   // OLD   1216   // OLD
951   Fl_Tree_Item *p=parent(); // start with parent   1217   Fl_Tree_Item *p=parent(); // start with parent
952   if ( ! p ) return(0); // hit root? done   1218   if ( ! p ) return(0); // hit root? done
953   int t = p->find_child(this); // find our position in parent's children[] array   1219   int t = p->find_child(this); // find our position in parent's children[] array
954   if ( --t == -1 ) { // are we first child?   1220   if ( --t == -1 ) { // are we first child?
955     return(p); // return immediate parent   1221     return(p); // return immediate parent
956   }   1222   }
957   p = p->child(t); // take parent's previous child   1223   p = p->child(t); // take parent's previous child
958   while ( p->has_children() ) { // has children?   1224   while ( p->has_children() ) { // has children?
959     p = p->child(p->children()-1); // take last child   1225     p = p->child(p->children()-1); // take last child
960   }   1226   }
961   return(p);   1227   return(p);
962 #endif /*FLTK_ABI_VERSION*/   1228 #endif /*FLTK_ABI_VERSION*/
963 }   1229 }
964   1230
965 /// Return this item's next sibling.   1231 /// Return this item's next sibling.
966 ///   1232 ///
967 /// Moves to the next item below us at the same level (sibling).   1233 /// Moves to the next item below us at the same level (sibling).
968 /// Use this to move down the tree without moving deeper into the tree,   1234 /// Use this to move down the tree without moving deeper into the tree,
969 /// effectively skipping over this item's children/descendents.   1235 /// effectively skipping over this item's children/descendents.
970 ///   1236 ///
971 /// \returns item's next sibling, or 0 if none.   1237 /// \returns item's next sibling, or 0 if none.
972 ///   1238 ///
973 Fl_Tree_Item *Fl_Tree_Item::next_sibling() {   1239 Fl_Tree_Item *Fl_Tree_Item::next_sibling() {
974 #if FLTK_ABI_VERSION >= 10301   1240 #if FLTK_ABI_VERSION >= 10301
975   // NEW   1241   // NEW
976   return(_next_sibling);   1242   return(_next_sibling);
977 #else /*FLTK_ABI_VERSION*/   1243 #else /*FLTK_ABI_VERSION*/
978   // OLD   1244   // OLD
979   if ( !parent() ) return(0); // No parent (root)? We have no siblings   1245   if ( !parent() ) return(0); // No parent (root)? We have no siblings
980   int index = parent()->find_child(this); // find our position in parent's child() array   1246   int index = parent()->find_child(this); // find our position in parent's child() array
981   if ( index == -1 ) return(0); // parent doesn't know us? weird   1247   if ( index == -1 ) return(0); // parent doesn't know us? weird
982   if ( (index+1) < parent()->children() ) // is there a next child?   1248   if ( (index+1) < parent()->children() ) // is there a next child?
983     return(parent()->child(index+1)); // return next child if there's one below us   1249     return(parent()->child(index+1)); // return next child if there's one below us
984   return(0); // no siblings below us   1250   return(0); // no siblings below us
985 #endif /*FLTK_ABI_VERSION*/   1251 #endif /*FLTK_ABI_VERSION*/
986 }   1252 }
987   1253
988 /// Return this item's previous sibling.   1254 /// Return this item's previous sibling.
989 ///   1255 ///
990 /// Moves to the previous item above us at the same level (sibling).   1256 /// Moves to the previous item above us at the same level (sibling).
991 /// Use this to move up the tree without moving deeper into the tree.   1257 /// Use this to move up the tree without moving deeper into the tree.
992 ///   1258 ///
993 /// \returns This item's previous sibling, or 0 if none.   1259 /// \returns This item's previous sibling, or 0 if none.
994 ///   1260 ///
995 Fl_Tree_Item *Fl_Tree_Item::prev_sibling() {   1261 Fl_Tree_Item *Fl_Tree_Item::prev_sibling() {
996 #if FLTK_ABI_VERSION >= 10301   1262 #if FLTK_ABI_VERSION >= 10301
997   // NEW   1263   // NEW
998   return(_prev_sibling);   1264   return(_prev_sibling);
999 #else /*FLTK_ABI_VERSION*/   1265 #else /*FLTK_ABI_VERSION*/
1000   // OLD   1266   // OLD
1001   if ( !parent() ) return(0); // No parent (root)? We have no siblings   1267   if ( !parent() ) return(0); // No parent (root)? We have no siblings
1002   int index = parent()->find_child(this); // find next position up in parent's child() array   1268   int index = parent()->find_child(this); // find next position up in parent's child() array
1003   if ( index == -1 ) return(0); // parent doesn't know us? weird   1269   if ( index == -1 ) return(0); // parent doesn't know us? weird
1004   if ( index > 0 ) return(parent()->child(index-1)); // return previous child if there's one above us   1270   if ( index > 0 ) return(parent()->child(index-1)); // return previous child if there's one above us
1005   return(0); // no siblings above us   1271   return(0); // no siblings above us
1006 #endif /*FLTK_ABI_VERSION*/   1272 #endif /*FLTK_ABI_VERSION*/
1007 }   1273 }
1008   1274
1009 /// Update our _prev_sibling and _next_sibling pointers to point to neighbors,   1275 /// Update our _prev_sibling and _next_sibling pointers to point to neighbors,
1010 /// given \p index as being our current position in the parent's item array.   1276 /// given \p index as being our current position in the parent's item array.
1011 /// Call this whenever items in the array are added/removed/moved/swapped.   1277 /// Call this whenever items in the array are added/removed/moved/swapped.
1012 ///   1278 ///
1013 void Fl_Tree_Item::update_prev_next(int index) {   1279 void Fl_Tree_Item::update_prev_next(int index) {
1014 #if FLTK_ABI_VERSION >= 10301   1280 #if FLTK_ABI_VERSION >= 10301
1015   // NEW   1281   // NEW
1016   int pchildren = parent() ? parent()->children() : 0;   1282   int pchildren = parent() ? parent()->children() : 0;
1017   int index_prev = index-1;   1283   int index_prev = index-1;
1018   int index_next = index+1;   1284   int index_next = index+1;
1019   // Get pointers to prev+next items   1285   // Get pointers to prev+next items
1020   Fl_Tree_Item *item_prev = (index_prev>=0)&&(index_prev<pchildren) ? parent()->child(index_prev) : 0;   1286   Fl_Tree_Item *item_prev = (index_prev>=0)&&(index_prev<pchildren) ? parent()->child(index_prev) : 0;
1021   Fl_Tree_Item *item_next = (index_next>=0)&&(index_next<pchildren) ? parent()->child(index_next) : 0;   1287   Fl_Tree_Item *item_next = (index_next>=0)&&(index_next<pchildren) ? parent()->child(index_next) : 0;
1022   // Adjust our prev+next ptrs   1288   // Adjust our prev+next ptrs
1023   _prev_sibling = item_prev;   1289   _prev_sibling = item_prev;
1024   _next_sibling = item_next;   1290   _next_sibling = item_next;
1025   // Adjust neighbors to point to us   1291   // Adjust neighbors to point to us
1026   if ( item_prev ) item_prev->_next_sibling = this;   1292   if ( item_prev ) item_prev->_next_sibling = this;
1027   if ( item_next ) item_next->_prev_sibling = this;   1293   if ( item_next ) item_next->_prev_sibling = this;
1028 #else /*FLTK_ABI_VERSION*/   1294 #else /*FLTK_ABI_VERSION*/
1029   // OLD   1295   // OLD
1030   // -- does nothing --   1296   // -- does nothing --
1031 #endif /*FLTK_ABI_VERSION*/   1297 #endif /*FLTK_ABI_VERSION*/
1032 }   1298 }
1033   1299
1034 /// Return the next visible item. (If this item has children and is closed, children are skipped)   1300 /// Return the next open, visible item.
      1301 /// (If this item has children and is closed, children are skipped)
1035 ///   1302 ///
1036 /// This method can be used to walk the tree forward, skipping items   1303 /// This method can be used to walk the tree forward, skipping items
1037 /// that are not currently visible to the user.   1304 /// that are not currently open/visible to the user.
1038 ///   1305 ///
1039 /// \returns the next visible item below us, or 0 if there's no more items.   1306 /// \returns the next open visible item below us, or 0 if there's no more items.
1040 ///   1307 ///
1041 Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) {   1308 Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) {
1042   Fl_Tree_Item *item = this;   1309   Fl_Tree_Item *item = this;
1043   while ( 1 ) {   1310   while ( 1 ) {
1044     item = item->next();   1311     item = item->next();
1045     if ( !item ) return 0;   1312     if ( !item ) return 0;
1046     if ( item->is_root() && !prefs.showroot() ) continue;   1313     if ( item->is_root() && !prefs.showroot() ) continue;
1047     if ( item->visible_r() ) return(item);   1314     if ( item->visible_r() ) return(item);
1048   }   1315   }
1049 }   1316 }
1050   1317
1051 /// Return the previous visible item. (If this item above us has children and is closed, its children are skipped)   1318 /// Return the previous open, visible item.
      1319 /// (If this item above us has children and is closed, its children are skipped)
1052 ///   1320 ///
1053 /// This method can be used to walk the tree backward,   1321 /// This method can be used to walk the tree backward,
1054 /// skipping items that are not currently visible to the user.   1322 /// skipping items that are not currently open/visible to the user.
1055 ///   1323 ///
1056 /// \returns the previous visible item above us, or 0 if there's no more items.   1324 /// \returns the previous open visible item above us, or 0 if there's no more items.
1057 ///   1325 ///
1058 Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) {   1326 Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) {
1059   Fl_Tree_Item *c = this;   1327   Fl_Tree_Item *c = this;
1060   while ( c ) {   1328   while ( c ) {
1061     c = c->prev(); // previous item   1329     c = c->prev(); // previous item
1062     if ( !c ) break; // no more items? done   1330     if ( !c ) break; // no more items? done
1063     if ( c->is_root() ) // root   1331     if ( c->is_root() ) // root
1064       return((prefs.showroot()&&c->visible()) ? c : 0); // return root if visible   1332       return((prefs.showroot()&&c->visible()) ? c : 0); // return root if visible
1065     if ( !c->visible() ) continue; // item not visible? skip   1333     if ( !c->visible() ) continue; // item not visible? skip
1066     // Check all parents to be sure none are closed.   1334     // Check all parents to be sure none are closed.
1067     // If closed, move up to that level and repeat until sure none are closed.   1335     // If closed, move up to that level and repeat until sure none are closed.
1068     Fl_Tree_Item *p = c->parent();   1336     Fl_Tree_Item *p = c->parent();
1069     while (1) {   1337     while (1) {
1070       if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c   1338       if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c
1071       if ( p->is_close() ) c = p; // found closed parent? make it current   1339       if ( p->is_close() ) c = p; // found closed parent? make it current
1072       p = p->parent(); // continue up tree   1340       p = p->parent(); // continue up tree
1073     }   1341     }
1074   }   1342   }
1075   return(0); // hit end: no more items   1343   return(0); // hit end: no more items
1076 }   1344 }
1077   1345
1078 /// Returns if item and all its parents are visible.   1346 /// Returns if item and all its parents are visible.
1079 /// Also takes into consideration if any parent is close()ed.   1347 /// Also takes into consideration if any parent is close()ed.
1080 /// \returns   1348 /// \returns
1081 /// 1 -- item and its parents are visible/open()   1349 /// 1 -- item and its parents are visible/open()
1082 /// 0 -- item (or parents) invisible or close()ed.   1350 /// 0 -- item (or parents) invisible or close()ed.
1083 ///   1351 ///
1084 int Fl_Tree_Item::visible_r() const {   1352 int Fl_Tree_Item::visible_r() const {
1085   if ( !visible() ) return(0);   1353   if ( !visible() ) return(0);
1086   for (const Fl_Tree_Item *p=parent(); p; p=p->parent())// move up through parents   1354   for (const Fl_Tree_Item *p=parent(); p; p=p->parent())// move up through parents
1087     if (!p->visible() || p->is_close()) return(0); // any parent not visible or closed?   1355     if (!p->visible() || p->is_close()) return(0); // any parent not visible or closed?
1088   return(1);   1356   return(1);
1089 }   1357 }
1090   1358
      1359 /// Call this when our geometry is changed. (Font size, label contents, etc)
      1360 /// Schedules tree to recalculate itself, as changes to us may affect tree widget's
      1361 /// scrollbar visibility and tab sizes.
      1362 ///
      1363 void Fl_Tree_Item::recalc_tree() {
      1364 #if FLTK_ABI_VERSION >= 10303
      1365   _tree->recalc_tree();
      1366 #endif
      1367 }
      1368
1091 //   1369 //
1092 // End of "$Id: Fl_Tree_Item.cxx 10018 2013-11-10 04:33:44Z greg.ercolano $".   1370 // End of "$Id: Fl_Tree_Item.cxx 10018 2013-11-10 04:33:44Z greg.ercolano $".
1093 //   1371 //

Generated by diff2html on Fri Dec 13 00:30:14 2013
Command-line:
/net/bin/diff2html -w ../fltk-1.3.x-svn-current/src/Fl_Tree_Item.cxx src/Fl_Tree_Item.cxx