|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_Tree_Item.cxx 7903 2010-11-28 21:06:39Z matt $" 00003 // 00004 00005 #include <stdio.h> 00006 #include <stdlib.h> 00007 #include <string.h> 00008 #include <FL/Fl_Widget.H> 00009 #include <FL/Fl_Tree_Item.H> 00010 #include <FL/Fl_Tree_Prefs.H> 00011 00013 // Fl_Tree_Item.cxx 00015 // 00016 // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK 00017 // Copyright (C) 2009-2010 by Greg Ercolano. 00018 // 00019 // This library is free software; you can redistribute it and/or 00020 // modify it under the terms of the GNU Library General Public 00021 // License as published by the Free Software Foundation; either 00022 // version 2 of the License, or (at your option) any later version. 00023 // 00024 // This library is distributed in the hope that it will be useful, 00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 // Library General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU Library General Public 00030 // License along with this library; if not, write to the Free Software 00031 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00032 // USA. 00033 // 00034 00035 // Was the last event inside the specified xywh? 00036 static int event_inside(const int xywh[4]) { 00037 return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3])); 00038 } 00039 00043 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) { 00044 _label = 0; 00045 _labelfont = prefs.labelfont(); 00046 _labelsize = prefs.labelsize(); 00047 _labelfgcolor = prefs.fgcolor(); 00048 _labelbgcolor = prefs.bgcolor(); 00049 _widget = 0; 00050 _open = 1; 00051 _visible = 1; 00052 _active = 1; 00053 _selected = 0; 00054 _xywh[0] = 0; 00055 _xywh[1] = 0; 00056 _xywh[2] = 0; 00057 _xywh[3] = 0; 00058 _collapse_xywh[0] = 0; 00059 _collapse_xywh[1] = 0; 00060 _collapse_xywh[2] = 0; 00061 _collapse_xywh[3] = 0; 00062 _label_xywh[0] = 0; 00063 _label_xywh[1] = 0; 00064 _label_xywh[2] = 0; 00065 _label_xywh[3] = 0; 00066 _usericon = 0; 00067 _userdata = 0; 00068 _parent = 0; 00069 } 00070 00071 // DTOR 00072 Fl_Tree_Item::~Fl_Tree_Item() { 00073 if ( _label ) { 00074 free((void*)_label); 00075 _label = 0; 00076 } 00077 _widget = 0; // Fl_Group will handle destruction 00078 _usericon = 0; // user handled allocation 00079 //_children.clear(); // array's destructor handles itself 00080 } 00081 00083 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) { 00084 _label = o->label() ? strdup(o->label()) : 0; 00085 _labelfont = o->labelfont(); 00086 _labelsize = o->labelsize(); 00087 _labelfgcolor = o->labelfgcolor(); 00088 _labelbgcolor = o->labelbgcolor(); 00089 _widget = o->widget(); 00090 _open = o->_open; 00091 _visible = o->_visible; 00092 _active = o->_active; 00093 _selected = o->_selected; 00094 _xywh[0] = o->_xywh[0]; 00095 _xywh[1] = o->_xywh[1]; 00096 _xywh[2] = o->_xywh[2]; 00097 _xywh[3] = o->_xywh[3]; 00098 _collapse_xywh[0] = o->_collapse_xywh[0]; 00099 _collapse_xywh[1] = o->_collapse_xywh[1]; 00100 _collapse_xywh[2] = o->_collapse_xywh[2]; 00101 _collapse_xywh[3] = o->_collapse_xywh[3]; 00102 _label_xywh[0] = o->_label_xywh[0]; 00103 _label_xywh[1] = o->_label_xywh[1]; 00104 _label_xywh[2] = o->_label_xywh[2]; 00105 _label_xywh[3] = o->_label_xywh[3]; 00106 _usericon = o->usericon(); 00107 _userdata = o->user_data(); 00108 _parent = o->_parent; 00109 } 00110 00114 void Fl_Tree_Item::show_self(const char *indent) const { 00115 if ( label() ) { 00116 printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n", 00117 indent,label(),children(),(void*)this, (void*)_parent, depth()); 00118 } 00119 if ( children() ) { 00120 char *i2 = (char*)malloc(strlen(indent) + 2); 00121 strcpy(i2, indent); 00122 strcat(i2, " |"); 00123 for ( int t=0; t<children(); t++ ) { 00124 child(t)->show_self(i2); 00125 } 00126 } 00127 fflush(stdout); 00128 } 00129 00131 void Fl_Tree_Item::label(const char *name) { 00132 if ( _label ) { free((void*)_label); _label = 0; } 00133 _label = name ? strdup(name) : 0; 00134 } 00135 00137 const char *Fl_Tree_Item::label() const { 00138 return(_label); 00139 } 00140 00142 const Fl_Tree_Item *Fl_Tree_Item::child(int index) const { 00143 return(_children[index]); 00144 } 00145 00147 void Fl_Tree_Item::clear_children() { 00148 _children.clear(); 00149 } 00150 00155 int Fl_Tree_Item::find_child(const char *name) { 00156 if ( name ) { 00157 for ( int t=0; t<children(); t++ ) { 00158 if ( child(t)->label() ) { 00159 if ( strcmp(child(t)->label(), name) == 0 ) { 00160 return(t); 00161 } 00162 } 00163 } 00164 } 00165 return(-1); 00166 } 00167 00173 const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const { 00174 for ( int t=0; t<children(); t++ ) { 00175 if ( child(t)->label() ) { 00176 if ( strcmp(child(t)->label(), *arr) == 0 ) { // match? 00177 if ( *(arr+1) ) { // more in arr? descend 00178 return(_children[t]->find_item(arr+1)); 00179 } else { // end of arr? done 00180 return(_children[t]); 00181 } 00182 } 00183 } 00184 } 00185 return(0); 00186 } 00187 00193 Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) { 00194 for ( int t=0; t<children(); t++ ) { 00195 if ( child(t)->label() ) { 00196 if ( strcmp(child(t)->label(), *arr) == 0 ) { // match? 00197 if ( *(arr+1) ) { // more in arr? descend 00198 return(_children[t]->find_item(arr+1)); 00199 } else { // end of arr? done 00200 return(_children[t]); 00201 } 00202 } 00203 } 00204 } 00205 return(0); 00206 } 00207 00213 const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const { 00214 if ( label() && strcmp(label(), *names) == 0 ) { // match self? 00215 if ( *(names+1) == 0 ) { // end of names, 00216 return(this); // found ourself. 00217 } 00218 } 00219 if ( children() ) { // check children.. 00220 return(find_child_item(names)); 00221 } 00222 return(0); 00223 } 00224 00230 Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) { 00231 if ( label() && strcmp(label(), *names) == 0 ) { // match self? 00232 if ( *(names+1) == 0 ) { // end of names, 00233 return(this); // found ourself. 00234 } 00235 } 00236 if ( children() ) { // check children.. 00237 return(find_child_item(names)); 00238 } 00239 return(0); 00240 } 00241 00247 int Fl_Tree_Item::find_child(Fl_Tree_Item *item) { 00248 for ( int t=0; t<children(); t++ ) { 00249 if ( item == child(t) ) { 00250 return(t); 00251 } 00252 } 00253 return(-1); 00254 } 00255 00260 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) { 00261 Fl_Tree_Item *item = new Fl_Tree_Item(prefs); 00262 item->label(new_label); 00263 item->_parent = this; 00264 switch ( prefs.sortorder() ) { 00265 case FL_TREE_SORT_NONE: { 00266 _children.add(item); 00267 return(item); 00268 } 00269 case FL_TREE_SORT_ASCENDING: { 00270 for ( int t=0; t<_children.total(); t++ ) { 00271 Fl_Tree_Item *c = _children[t]; 00272 if ( c->label() && strcmp(c->label(), new_label) > 0 ) { 00273 _children.insert(t, item); 00274 return(item); 00275 } 00276 } 00277 _children.add(item); 00278 return(item); 00279 } 00280 case FL_TREE_SORT_DESCENDING: { 00281 for ( int t=0; t<_children.total(); t++ ) { 00282 Fl_Tree_Item *c = _children[t]; 00283 if ( c->label() && strcmp(c->label(), new_label) < 0 ) { 00284 _children.insert(t, item); 00285 return(item); 00286 } 00287 } 00288 _children.add(item); 00289 return(item); 00290 } 00291 } 00292 return(item); 00293 } 00294 00300 Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) { 00301 int t = find_child(*arr); 00302 Fl_Tree_Item *item; 00303 if ( t == -1 ) { 00304 item = (Fl_Tree_Item*)add(prefs, *arr); 00305 } else { 00306 item = (Fl_Tree_Item*)child(t); 00307 } 00308 if ( *(arr+1) ) { // descend? 00309 return(item->add(prefs, arr+1)); 00310 } else { 00311 return(item); // end? done 00312 } 00313 } 00314 00318 Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) { 00319 Fl_Tree_Item *item = new Fl_Tree_Item(prefs); 00320 item->label(new_label); 00321 item->_parent = this; 00322 _children.insert(pos, item); 00323 return(item); 00324 } 00325 00329 Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) { 00330 Fl_Tree_Item *p = _parent; 00331 if ( ! p ) return(0); 00332 // Walk our parent's children to find ourself 00333 for ( int t=0; t<p->children(); t++ ) { 00334 Fl_Tree_Item *c = p->child(t); 00335 if ( this == c ) { 00336 return(p->insert(prefs, new_label, t)); 00337 } 00338 } 00339 return(0); 00340 } 00341 00345 int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) { 00346 for ( int t=0; t<children(); t++ ) { 00347 if ( child(t) == item ) { 00348 item->clear_children(); 00349 _children.remove(t); 00350 return(0); 00351 } 00352 } 00353 return(-1); 00354 } 00355 00359 int Fl_Tree_Item::remove_child(const char *name) { 00360 for ( int t=0; t<children(); t++ ) { 00361 if ( child(t)->label() ) { 00362 if ( strcmp(child(t)->label(), name) == 0 ) { 00363 _children.remove(t); 00364 return(0); 00365 } 00366 } 00367 } 00368 return(-1); 00369 } 00370 00382 void Fl_Tree_Item::swap_children(int ax, int bx) { 00383 _children.swap(ax, bx); 00384 } 00385 00396 int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) { 00397 int ax = -1, bx = -1; 00398 for ( int t=0; t<children(); t++ ) { // find index for a and b 00399 if ( _children[t] == a ) { ax = t; if ( bx != -1 ) break; else continue; } 00400 if ( _children[t] == b ) { bx = t; if ( ax != -1 ) break; else continue; } 00401 } 00402 if ( ax == -1 || bx == -1 ) return(-1); // not found? fail 00403 swap_children(ax,bx); 00404 return(0); 00405 } 00406 00408 void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) { 00409 fl_color(prefs.connectorcolor()); 00410 switch ( prefs.connectorstyle() ) { 00411 case FL_TREE_CONNECTOR_SOLID: 00412 y |= 1; // force alignment w/dot pattern 00413 fl_line(x1,y,x2,y); 00414 return; 00415 case FL_TREE_CONNECTOR_DOTTED: 00416 { 00417 y |= 1; // force alignment w/dot pattern 00418 for ( int xx=x1; xx<=x2; xx++ ) { 00419 if ( !(xx & 1) ) fl_point(xx, y); 00420 } 00421 } 00422 return; 00423 case FL_TREE_CONNECTOR_NONE: 00424 return; 00425 } 00426 } 00427 00429 void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) { 00430 fl_color(prefs.connectorcolor()); 00431 switch ( prefs.connectorstyle() ) { 00432 case FL_TREE_CONNECTOR_SOLID: 00433 y1 |= 1; // force alignment w/dot pattern 00434 y2 |= 1; // force alignment w/dot pattern 00435 fl_line(x,y1,x,y2); 00436 return; 00437 case FL_TREE_CONNECTOR_DOTTED: 00438 { 00439 y1 |= 1; // force alignment w/dot pattern 00440 y2 |= 1; // force alignment w/dot pattern 00441 for ( int yy=y1; yy<=y2; yy++ ) { 00442 if ( yy & 1 ) fl_point(x, yy); 00443 } 00444 } 00445 return; 00446 case FL_TREE_CONNECTOR_NONE: 00447 return; 00448 } 00449 } 00450 00459 const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const { 00460 if ( ! _visible ) return(0); 00461 if ( is_root() && !prefs.showroot() ) { 00462 // skip event check if we're root but root not being shown 00463 } else { 00464 // See if event is over us 00465 if ( event_inside(_xywh) ) { // event within this item? 00466 return(this); // found 00467 } 00468 } 00469 if ( is_open() ) { // open? check children of this item 00470 for ( int t=0; t<children(); t++ ) { 00471 const Fl_Tree_Item *item; 00472 if ( ( item = _children[t]->find_clicked(prefs) ) != NULL) { // check child and its descendents 00473 return(item); // found? 00474 } 00475 } 00476 } 00477 return(0); 00478 } 00479 00489 Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { 00490 if ( ! _visible ) return(0); 00491 if ( is_root() && !prefs.showroot() ) { 00492 // skip event check if we're root but root not being shown 00493 } else { 00494 // See if event is over us 00495 if ( event_inside(_xywh) ) { // event within this item? 00496 return(this); // found 00497 } 00498 } 00499 if ( is_open() ) { // open? check children of this item 00500 for ( int t=0; t<children(); t++ ) { 00501 Fl_Tree_Item *item; 00502 if ( ( item = _children[t]->find_clicked(prefs) ) != NULL ) { // check child and its descendents 00503 return(item); // found? 00504 } 00505 } 00506 } 00507 return(0); 00508 } 00509 00510 static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H) { 00511 if (!Fl::visible_focus()) return; 00512 switch (B) { 00513 case FL_DOWN_BOX: 00514 case FL_DOWN_FRAME: 00515 case FL_THIN_DOWN_BOX: 00516 case FL_THIN_DOWN_FRAME: 00517 X ++; 00518 Y ++; 00519 default: 00520 break; 00521 } 00522 fl_color(fl_contrast(FL_BLACK, C)); 00523 00524 #if defined(USE_X11) || defined(__APPLE_QUARTZ__) 00525 fl_line_style(FL_DOT); 00526 fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B), 00527 W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1); 00528 fl_line_style(FL_SOLID); 00529 #else 00530 // Some platforms don't implement dotted line style, so draw 00531 // every other pixel around the focus area... 00532 // 00533 // Also, QuickDraw (MacOS) does not support line styles specifically, 00534 // and the hack we use in fl_line_style() will not draw horizontal lines 00535 // on odd-numbered rows... 00536 int i, xx, yy; 00537 00538 X += Fl::box_dx(B); 00539 Y += Fl::box_dy(B); 00540 W -= Fl::box_dw(B) + 2; 00541 H -= Fl::box_dh(B) + 2; 00542 00543 for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y); 00544 for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy); 00545 for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H); 00546 for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy); 00547 #endif 00548 } 00549 00551 void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, 00552 Fl_Tree_Item *itemfocus, 00553 const Fl_Tree_Prefs &prefs, int lastchild) { 00554 if ( ! _visible ) return; 00555 fl_font(_labelfont, _labelsize); 00556 int H = _labelsize; 00557 if(usericon() && H < usericon()->h()) H = usericon()->h(); 00558 H += prefs.linespacing() + fl_descent(); 00559 // adjust horizontally if we draw no connecting lines 00560 if ( is_root() && prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE ) { 00561 X -= prefs.openicon()->w(); 00562 W += prefs.openicon()->w(); 00563 } 00564 // Colors, fonts 00565 Fl_Color fg = _selected ? prefs.bgcolor() : _labelfgcolor; 00566 Fl_Color bg = _selected ? prefs.selectcolor() : _labelbgcolor; 00567 if ( ! _active ) { 00568 fg = fl_inactive(fg); 00569 if ( _selected ) bg = fl_inactive(bg); 00570 } 00571 // Update the xywh of this item 00572 _xywh[0] = X; 00573 _xywh[1] = Y; 00574 _xywh[2] = W; 00575 _xywh[3] = H; 00576 // Text size 00577 int textw=0, texth=0; 00578 fl_measure(_label, textw, texth, 0); 00579 int textycenter = Y+(H/2); 00580 int &icon_w = _collapse_xywh[2] = prefs.openicon()->w(); 00581 int &icon_x = _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; 00582 int &icon_y = _collapse_xywh[1] = textycenter - (prefs.openicon()->h()/2); 00583 _collapse_xywh[3] = prefs.openicon()->h(); 00584 // Horizontal connector values 00585 int hstartx = X+icon_w/2-1; 00586 int hendx = hstartx + prefs.connectorwidth(); 00587 int hcenterx = X + icon_w + ((hendx - (X + icon_w)) / 2); 00588 00589 // See if we should draw this item 00590 // If this item is root, and showroot() is disabled, don't draw. 00591 // 00592 char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; 00593 if ( drawthis ) { 00594 // Draw connectors 00595 if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) { 00596 // Horiz connector between center of icon and text 00597 // if this is root, the connector should not dangle in thin air on the left 00598 if (is_root()) 00599 draw_horizontal_connector(hcenterx, hendx, textycenter, prefs); 00600 else 00601 draw_horizontal_connector(hstartx, hendx, textycenter, prefs); 00602 if ( has_children() && is_open() ) { 00603 // Small vertical line down to children 00604 draw_vertical_connector(hcenterx, textycenter, Y+H, prefs); 00605 } 00606 // Connectors for last child 00607 if ( ! is_root() ) { 00608 if ( lastchild ) { 00609 draw_vertical_connector(hstartx, Y, textycenter, prefs); 00610 } else { 00611 draw_vertical_connector(hstartx, Y, Y+H, prefs); 00612 } 00613 } 00614 } 00615 // Draw collapse icon 00616 if ( has_children() && prefs.showcollapse() ) { 00617 // Draw icon image 00618 if ( is_open() ) { 00619 prefs.closeicon()->draw(icon_x,icon_y); 00620 } else { 00621 prefs.openicon()->draw(icon_x,icon_y); 00622 } 00623 } 00624 // Background for this item 00625 int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth(); 00626 int cwidth = cw1>cw2 ? cw1 : cw2; 00627 int &bx = _label_xywh[0] = X+(icon_w/2-1+cwidth); 00628 int &by = _label_xywh[1] = Y; 00629 int &bw = _label_xywh[2] = W-(icon_w/2-1+cwidth); 00630 int &bh = _label_xywh[3] = H; 00631 // Draw bg only if different from tree's bg 00632 if ( bg != tree->color() || is_selected() ) { 00633 if ( is_selected() ) { 00634 // Selected? Use selectbox() style 00635 fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg); 00636 } else { 00637 // Not Selected? use plain filled rectangle 00638 fl_color(bg); 00639 fl_rectf(bx, by, bw, bh); 00640 } 00641 } 00642 // Draw user icon (if any) 00643 int useroff = (icon_w/2-1+cwidth); 00644 if ( usericon() ) { 00645 // Item has user icon? Use it 00646 useroff += prefs.usericonmarginleft(); 00647 icon_y = textycenter - (usericon()->h() >> 1); 00648 usericon()->draw(X+useroff,icon_y); 00649 useroff += usericon()->w(); 00650 } else if ( prefs.usericon() ) { 00651 // Prefs has user icon? Use it 00652 useroff += prefs.usericonmarginleft(); 00653 icon_y = textycenter - (prefs.usericon()->h() >> 1); 00654 prefs.usericon()->draw(X+useroff,icon_y); 00655 useroff += prefs.usericon()->w(); 00656 } 00657 useroff += prefs.labelmarginleft(); 00658 // Draw label 00659 if ( widget() ) { 00660 // Widget? Draw it 00661 int lx = X+useroff; 00662 int ly = by; 00663 int lw = widget()->w(); 00664 int lh = bh; 00665 if ( widget()->x() != lx || widget()->y() != ly || 00666 widget()->w() != lw || widget()->h() != lh ) { 00667 widget()->resize(lx, ly, lw, lh); // fltk will handle drawing this 00668 } 00669 } else { 00670 // No label widget? Draw text label 00671 if ( _label ) { 00672 fl_color(fg); 00673 fl_draw(_label, X+useroff, Y+H-fl_descent()-1); 00674 } 00675 } 00676 if ( this == itemfocus && Fl::visible_focus() && Fl::focus() == tree) { 00677 // Draw focus box around this item 00678 draw_item_focus(FL_NO_BOX,bg,bx+1,by+1,bw-1,bh-1); 00679 } 00680 Y += H; 00681 } // end drawthis 00682 // Draw children 00683 if ( has_children() && is_open() ) { 00684 int child_x = drawthis ? // offset children to right, 00685 (hcenterx - (icon_w/2) + 1) : X; // unless didn't drawthis 00686 int child_w = W - (child_x-X); 00687 int child_y_start = Y; 00688 for ( int t=0; t<children(); t++ ) { 00689 int lastchild = ((t+1)==children()) ? 1 : 0; 00690 _children[t]->draw(child_x, Y, child_w, tree, itemfocus, prefs, lastchild); 00691 } 00692 if ( has_children() && is_open() ) { 00693 Y += prefs.openchild_marginbottom(); // offset below open child tree 00694 } 00695 if ( ! lastchild ) { 00696 draw_vertical_connector(hstartx, child_y_start, Y, prefs); 00697 } 00698 } 00699 } 00700 00703 int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const { 00704 if ( _visible && _active && has_children() && prefs.showcollapse() ) { 00705 return(event_inside(_collapse_xywh) ? 1 : 0); 00706 } else { 00707 return(0); 00708 } 00709 } 00710 00713 int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const { 00714 if ( _visible && _active ) { 00715 return(event_inside(_label_xywh) ? 1 : 0); 00716 } else { 00717 return(0); 00718 } 00719 } 00720 00724 void Fl_Tree_Item::show_widgets() { 00725 if ( _widget ) _widget->show(); 00726 if ( is_open() ) { 00727 for ( int t=0; t<_children.total(); t++ ) { 00728 _children[t]->show_widgets(); 00729 } 00730 } 00731 } 00732 00736 void Fl_Tree_Item::hide_widgets() { 00737 if ( _widget ) _widget->hide(); 00738 for ( int t=0; t<_children.total(); t++ ) { 00739 _children[t]->hide_widgets(); 00740 } 00741 } 00742 00744 void Fl_Tree_Item::open() { 00745 _open = 1; 00746 // Tell children to show() their widgets 00747 for ( int t=0; t<_children.total(); t++ ) { 00748 _children[t]->show_widgets(); 00749 } 00750 } 00751 00753 void Fl_Tree_Item::close() { 00754 _open = 0; 00755 // Tell children to hide() their widgets 00756 for ( int t=0; t<_children.total(); t++ ) { 00757 _children[t]->hide_widgets(); 00758 } 00759 } 00760 00766 int Fl_Tree_Item::depth() const { 00767 int count = 0; 00768 const Fl_Tree_Item *item = parent(); 00769 while ( item ) { 00770 ++count; 00771 item = item->parent(); 00772 } 00773 return(count); 00774 } 00775 00783 Fl_Tree_Item *Fl_Tree_Item::next() { 00784 Fl_Tree_Item *p, *c = this; 00785 if ( c->has_children() ) { 00786 return(c->child(0)); 00787 } 00788 while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents 00789 int t = p->find_child(c); // find our position in parent's children[] array 00790 if ( ++t < p->children() ) // not last child? 00791 return(p->child(t)); // return next child 00792 c = p; // child becomes parent to move up generation 00793 } // loop: moves up to next parent 00794 return(0); // hit root? done 00795 } 00796 00804 Fl_Tree_Item *Fl_Tree_Item::prev() { 00805 Fl_Tree_Item *p=parent(); // start with parent 00806 if ( ! p ) return(0); // hit root? done 00807 int t = p->find_child(this); // find our position in parent's children[] array 00808 if ( --t == -1 ) { // are we first child? 00809 return(p); // return immediate parent 00810 } 00811 p = p->child(t); // take parent's previous child 00812 while ( p->has_children() ) { // has children? 00813 p = p->child(p->children()-1); // take last child 00814 } 00815 return(p); 00816 } 00817 00826 Fl_Tree_Item *Fl_Tree_Item::next_sibling() { 00827 if ( !parent() ) return(0); // No parent (root)? We have no siblings 00828 int index = parent()->find_child(this); // find our position in parent's child() array 00829 if ( index == -1 ) return(0); // parent doesn't know us? weird 00830 if ( (index+1) < parent()->children() ) // is there a next child? 00831 return(parent()->child(index+1)); // return next child if there's one below us 00832 return(0); // no siblings below us 00833 } 00834 00842 Fl_Tree_Item *Fl_Tree_Item::prev_sibling() { 00843 if ( !parent() ) return(0); // No parent (root)? We have no siblings 00844 int index = parent()->find_child(this); // find next position up in parent's child() array 00845 if ( index == -1 ) return(0); // parent doesn't know us? weird 00846 if ( index > 0 ) return(parent()->child(index-1)); // return previous child if there's one above us 00847 return(0); // no siblings above us 00848 } 00849 00857 Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { 00858 Fl_Tree_Item *c = this; 00859 while ( c ) { 00860 if ( c->is_root() && !prefs.showroot() ) { // on root and can't show it? 00861 c = c->next(); // skip ahead, try again 00862 continue; 00863 } 00864 if ( c->has_children() && c->is_close() ) { // item has children and: invisible or closed? 00865 // Skip children, take next sibling. If none, try parent's sibling, repeat 00866 while ( c ) { 00867 Fl_Tree_Item *sib = c->next_sibling(); // get sibling 00868 if ( sib ) { c = sib; break; } // Found? let outer loop test it 00869 c = c->parent(); // No sibling? move up tree, try parent's sibling 00870 } 00871 } else { // has children and isn't closed, or no children 00872 c = c->next(); // use normal 'next' 00873 } 00874 if ( !c ) return(0); // no more? done 00875 // Check all parents to be sure none are closed. 00876 // If closed, move up to that level and repeat until sure none are closed. 00877 Fl_Tree_Item *p = c->parent(); 00878 while (1) { 00879 if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c 00880 if ( p->is_close() ) c = p; // found closed parent? make it current 00881 p = p->parent(); // continue up tree 00882 } 00883 if ( c && c->visible() ) return(c); // item visible? return it 00884 } 00885 return(0); // hit end: no more items 00886 } 00887 00895 Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { 00896 Fl_Tree_Item *c = this; 00897 while ( c ) { 00898 c = c->prev(); // previous item 00899 if ( !c ) break; // no more items? done 00900 if ( c->is_root() ) // root 00901 return((prefs.showroot()&&c->visible()) ? c : 0); // return root if visible 00902 if ( !c->visible() ) continue; // item not visible? skip 00903 // Check all parents to be sure none are closed. 00904 // If closed, move up to that level and repeat until sure none are closed. 00905 Fl_Tree_Item *p = c->parent(); 00906 while (1) { 00907 if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c 00908 if ( p->is_close() ) c = p; // found closed parent? make it current 00909 p = p->parent(); // continue up tree 00910 } 00911 } 00912 return(0); // hit end: no more items 00913 } 00914 00921 int Fl_Tree_Item::visible_r() const { 00922 for (const Fl_Tree_Item *p=this; p; p=p->parent()) // move up through parents 00923 if (!p->visible() || p->is_close()) return(0); // any parent not visible or closed? 00924 return(1); 00925 } 00926 00927 // 00928 // End of "$Id: Fl_Tree_Item.cxx 7903 2010-11-28 21:06:39Z matt $". 00929 //