/fltk/src/Fl_Tree_Item.cxx
C++ | 730 lines | 506 code | 39 blank | 185 comment | 154 complexity | 34e78031679b3cdbbdc51def0723cc67 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-3.0, 0BSD
- //
- // "$Id: Fl_Tree_Item.cxx 7627 2010-06-03 15:46:59Z greg.ercolano $"
- //
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <FL/Fl_Widget.H>
- #include <FL/Fl_Tree_Item.H>
- #include <FL/Fl_Tree_Prefs.H>
-
- //////////////////////
- // Fl_Tree_Item.cxx
- //////////////////////
- //
- // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
- // Copyright (C) 2009 by Greg Ercolano.
- //
- // This library is free software; you can redistribute it and/or
- // modify it under the terms of the GNU Library General Public
- // License as published by the Free Software Foundation; either
- // version 2 of the License, or (at your option) any later version.
- //
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- // Library General Public License for more details.
- //
- // You should have received a copy of the GNU Library General Public
- // License along with this library; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- // USA.
- //
-
- // Was the last event inside the specified xywh?
- static int event_inside(const int xywh[4]) {
- return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3]));
- }
-
- /// Constructor.
- /// Makes a new instance of Fl_Tree_Item using defaults from 'prefs'.
- ///
- Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) {
- _label = 0;
- _labelfont = prefs.labelfont();
- _labelsize = prefs.labelsize();
- _labelfgcolor = prefs.fgcolor();
- _labelbgcolor = prefs.bgcolor();
- _widget = 0;
- _open = 1;
- _visible = 1;
- _active = 1;
- _selected = 0;
- _xywh[0] = 0;
- _xywh[1] = 0;
- _xywh[2] = 0;
- _xywh[3] = 0;
- _collapse_xywh[0] = 0;
- _collapse_xywh[1] = 0;
- _collapse_xywh[2] = 0;
- _collapse_xywh[3] = 0;
- _label_xywh[0] = 0;
- _label_xywh[1] = 0;
- _label_xywh[2] = 0;
- _label_xywh[3] = 0;
- _usericon = 0;
- _userdata = 0;
- _parent = 0;
- }
-
- // DTOR
- Fl_Tree_Item::~Fl_Tree_Item() {
- if ( _label ) {
- free((void*)_label);
- _label = 0;
- }
- _widget = 0; // Fl_Group will handle destruction
- _usericon = 0; // user handled allocation
- //_children.clear(); // array's destructor handles itself
- }
-
- /// Copy constructor.
- Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {
- _label = o->label() ? strdup(o->label()) : 0;
- _labelfont = o->labelfont();
- _labelsize = o->labelsize();
- _labelfgcolor = o->labelfgcolor();
- _labelbgcolor = o->labelbgcolor();
- _widget = o->widget();
- _open = o->_open;
- _visible = o->_visible;
- _active = o->_active;
- _selected = o->_selected;
- _xywh[0] = o->_xywh[0];
- _xywh[1] = o->_xywh[1];
- _xywh[2] = o->_xywh[2];
- _xywh[3] = o->_xywh[3];
- _collapse_xywh[0] = o->_collapse_xywh[0];
- _collapse_xywh[1] = o->_collapse_xywh[1];
- _collapse_xywh[2] = o->_collapse_xywh[2];
- _collapse_xywh[3] = o->_collapse_xywh[3];
- _label_xywh[0] = o->_label_xywh[0];
- _label_xywh[1] = o->_label_xywh[1];
- _label_xywh[2] = o->_label_xywh[2];
- _label_xywh[3] = o->_label_xywh[3];
- _usericon = o->usericon();
- _userdata = o->user_data();
- _parent = o->_parent;
- }
-
- /// Print the tree as 'ascii art' to stdout.
- /// Used mainly for debugging.
- ///
- void Fl_Tree_Item::show_self(const char *indent) const {
- if ( label() ) {
- printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n",
- indent,label(),children(),(void*)this, (void*)_parent, depth());
- }
- if ( children() ) {
- char *i2 = (char*)malloc(strlen(indent) + 2);
- strcpy(i2, indent);
- strcat(i2, " |");
- for ( int t=0; t<children(); t++ ) {
- child(t)->show_self(i2);
- }
- }
- fflush(stdout);
- }
-
- /// Set the label. Makes a copy of the name.
- void Fl_Tree_Item::label(const char *name) {
- if ( _label ) { free((void*)_label); _label = 0; }
- _label = name ? strdup(name) : 0;
- }
-
- /// Return the label.
- const char *Fl_Tree_Item::label() const {
- return(_label);
- }
-
- /// Return child item for the specified 'index'.
- const Fl_Tree_Item *Fl_Tree_Item::child(int index) const {
- return(_children[index]);
- }
-
- /// Clear all the children for this item.
- void Fl_Tree_Item::clear_children() {
- _children.clear();
- }
-
- /// Return the index of the immediate child of this item that has the label 'name'.
- ///
- /// \returns index of found item, or -1 if not found.
- ///
- int Fl_Tree_Item::find_child(const char *name) {
- if ( name ) {
- for ( int t=0; t<children(); t++ ) {
- if ( child(t)->label() ) {
- if ( strcmp(child(t)->label(), name) == 0 ) {
- return(t);
- }
- }
- }
- }
- return(-1);
- }
-
- /// Find item by descending array of names.
- /// Only Fl_Tree should need this method.
- ///
- /// \returns item, or 0 if not found
- ///
- const Fl_Tree_Item *Fl_Tree_Item::find_item(char **arr) const {
- for ( int t=0; t<children(); t++ ) {
- if ( child(t)->label() ) {
- if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?
- if ( *(arr+1) ) { // more in arr? descend
- return(_children[t]->find_item(arr+1));
- } else { // end of arr? done
- return(_children[t]);
- }
- }
- }
- }
- return(0);
- }
-
- /// Find item by by descending array of names.
- /// Only Fl_Tree should need this method.
- ///
- /// \returns item, or 0 if not found
- ///
- Fl_Tree_Item *Fl_Tree_Item::find_item(char **arr) {
- for ( int t=0; t<children(); t++ ) {
- if ( child(t)->label() ) {
- if ( strcmp(child(t)->label(), *arr) == 0 ) { // match?
- if ( *(arr+1) ) { // more in arr? descend
- return(_children[t]->find_item(arr+1));
- } else { // end of arr? done
- return(_children[t]);
- }
- }
- }
- }
- return(0);
- }
-
- /// Find the index number for the specified 'item'
- /// in the current item's list of children.
- ///
- /// \returns the index, or -1 if not found.
- ///
- int Fl_Tree_Item::find_child(Fl_Tree_Item *item) {
- for ( int t=0; t<children(); t++ ) {
- if ( item == child(t) ) {
- return(t);
- }
- }
- return(-1);
- }
-
- /// Add a new child to this item with the name 'new_label', with defaults from 'prefs'.
- /// An internally managed copy is made of the label string.
- /// Adds the item based on the value of prefs.sortorder().
- ///
- Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) {
- Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
- item->label(new_label);
- item->_parent = this;
- switch ( prefs.sortorder() ) {
- case FL_TREE_SORT_NONE: {
- _children.add(item);
- return(item);
- }
- case FL_TREE_SORT_ASCENDING: {
- for ( int t=0; t<_children.total(); t++ ) {
- Fl_Tree_Item *c = _children[t];
- if ( c->label() && strcmp(c->label(), new_label) > 0 ) {
- _children.insert(t, item);
- return(item);
- }
- }
- _children.add(item);
- return(item);
- }
- case FL_TREE_SORT_DESCENDING: {
- for ( int t=0; t<_children.total(); t++ ) {
- Fl_Tree_Item *c = _children[t];
- if ( c->label() && strcmp(c->label(), new_label) < 0 ) {
- _children.insert(t, item);
- return(item);
- }
- }
- _children.add(item);
- return(item);
- }
- }
- return(item);
- }
-
- /// Descend into the path specified by \p arr, and add a new child there.
- /// Should be used only by Fl_Tree's internals.
- /// Adds the item based on the value of prefs.sortorder().
- /// \returns the item added.
- ///
- Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {
- int t = find_child(*arr);
- Fl_Tree_Item *item;
- if ( t == -1 ) {
- item = (Fl_Tree_Item*)add(prefs, *arr);
- } else {
- item = (Fl_Tree_Item*)child(t);
- }
- if ( *(arr+1) ) { // descend?
- return(item->add(prefs, arr+1));
- } else {
- return(item); // end? done
- }
- }
-
- /// Insert a new item into current item's children at a specified position.
- /// \returns the new item inserted.
- ///
- Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) {
- Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
- item->label(new_label);
- item->_parent = this;
- _children.insert(pos, item);
- return(item);
- }
-
- /// Insert a new item above this item.
- /// \returns the new item inserted, or 0 if an error occurred.
- ///
- Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) {
- Fl_Tree_Item *p = _parent;
- if ( ! p ) return(0);
- // Walk our parent's children to find ourself
- for ( int t=0; t<p->children(); t++ ) {
- Fl_Tree_Item *c = p->child(t);
- if ( this == c ) {
- return(p->insert(prefs, new_label, t));
- }
- }
- return(0);
- }
-
- /// Remove child by item.
- /// \returns 0 if removed, -1 if item not an immediate child.
- ///
- int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) {
- for ( int t=0; t<children(); t++ ) {
- if ( child(t) == item ) {
- item->clear_children();
- _children.remove(t);
- return(0);
- }
- }
- return(-1);
- }
-
- /// Remove immediate child (and its children) by its label 'name'.
- /// \returns 0 if removed, -1 if not found.
- ///
- int Fl_Tree_Item::remove_child(const char *name) {
- for ( int t=0; t<children(); t++ ) {
- if ( child(t)->label() ) {
- if ( strcmp(child(t)->label(), name) == 0 ) {
- _children.remove(t);
- return(0);
- }
- }
- }
- return(-1);
- }
-
- /// Swap two of our children, given two child index values.
- /// Use this eg. for sorting.
- ///
- /// This method is FAST, and does not involve lookups.
- ///
- /// No range checking is done on either index value.
- ///
- /// \returns
- /// - 0 : OK
- /// - -1 : failed: 'a' or 'b' is not our immediate child
- ///
- void Fl_Tree_Item::swap_children(int ax, int bx) {
- _children.swap(ax, bx);
- }
-
- /// Swap two of our children, given item pointers.
- /// Use this eg. for sorting.
- ///
- /// This method is SLOW because it involves linear lookups.
- /// For speed, use swap_children(int,int) instead.
- ///
- /// \returns
- /// - 0 : OK
- /// - -1 : failed: 'a' or 'b' is not our immediate child
- ///
- int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) {
- int ax = -1, bx = -1;
- for ( int t=0; t<children(); t++ ) { // find index for a and b
- if ( _children[t] == a ) { ax = t; if ( bx != -1 ) break; else continue; }
- if ( _children[t] == b ) { bx = t; if ( ax != -1 ) break; else continue; }
- }
- if ( ax == -1 || bx == -1 ) return(-1); // not found? fail
- swap_children(ax,bx);
- return(0);
- }
-
- /// Internal: Horizontal connector line based on preference settings.
- void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) {
- fl_color(prefs.connectorcolor());
- switch ( prefs.connectorstyle() ) {
- case FL_TREE_CONNECTOR_SOLID:
- y |= 1; // force alignment w/dot pattern
- fl_line(x1,y,x2,y);
- return;
- case FL_TREE_CONNECTOR_DOTTED:
- {
- y |= 1; // force alignment w/dot pattern
- for ( int xx=x1; xx<=x2; xx++ ) {
- if ( !(xx & 1) ) fl_point(xx, y);
- }
- }
- return;
- case FL_TREE_CONNECTOR_NONE:
- return;
- }
- }
-
- /// Internal: Vertical connector line based on preference settings.
- void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) {
- fl_color(prefs.connectorcolor());
- switch ( prefs.connectorstyle() ) {
- case FL_TREE_CONNECTOR_SOLID:
- y1 |= 1; // force alignment w/dot pattern
- y2 |= 1; // force alignment w/dot pattern
- fl_line(x,y1,x,y2);
- return;
- case FL_TREE_CONNECTOR_DOTTED:
- {
- y1 |= 1; // force alignment w/dot pattern
- y2 |= 1; // force alignment w/dot pattern
- for ( int yy=y1; yy<=y2; yy++ ) {
- if ( yy & 1 ) fl_point(x, yy);
- }
- }
- return;
- case FL_TREE_CONNECTOR_NONE:
- return;
- }
- }
-
- /// Find the item that the last event was over.
- ///
- /// Returns the item if its visible, and mouse is over it.
- /// Works even if widget deactivated.
- /// Use event_on_collapse_icon() to determine if collapse button was pressed.
- ///
- /// \returns const visible item under the event if found, or 0 if none.
- ///
- const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const {
- if ( ! _visible ) return(0);
- if ( is_root() && !prefs.showroot() ) {
- // skip event check if we're root but root not being shown
- } else {
- // See if event is over us
- if ( event_inside(_xywh) ) { // event within this item?
- return(this); // found
- }
- }
- if ( is_open() ) { // open? check children of this item
- for ( int t=0; t<children(); t++ ) {
- const Fl_Tree_Item *item;
- if ( ( item = _children[t]->find_clicked(prefs) ) != NULL) { // check child and its descendents
- return(item); // found?
- }
- }
- }
- return(0);
- }
-
- /// Non-const version of the above.
- /// Find the item that the last event was over.
- ///
- /// Returns the item if its visible, and mouse is over it.
- /// Works even if widget deactivated.
- /// Use event_on_collapse_icon() to determine if collapse button was pressed.
- ///
- /// \returns the visible item under the event if found, or 0 if none.
- ///
- Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) {
- if ( ! _visible ) return(0);
- if ( is_root() && !prefs.showroot() ) {
- // skip event check if we're root but root not being shown
- } else {
- // See if event is over us
- if ( event_inside(_xywh) ) { // event within this item?
- return(this); // found
- }
- }
- if ( is_open() ) { // open? check children of this item
- for ( int t=0; t<children(); t++ ) {
- Fl_Tree_Item *item;
- if ( ( item = _children[t]->find_clicked(prefs) ) != NULL ) { // check child and its descendents
- return(item); // found?
- }
- }
- }
- return(0);
- }
-
- /// Draw this item and its children.
- void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
- const Fl_Tree_Prefs &prefs, int lastchild) {
- if ( ! _visible ) return;
- fl_font(_labelfont, _labelsize);
- int H = _labelsize;
- if(usericon() && H < usericon()->h()) H = usericon()->h();
- H += prefs.linespacing() + fl_descent();
- // Colors, fonts
- Fl_Color fg = _selected ? prefs.bgcolor() : _labelfgcolor;
- Fl_Color bg = _selected ? prefs.selectcolor() : _labelbgcolor;
- if ( ! _active ) {
- fg = fl_inactive(fg);
- if ( _selected ) bg = fl_inactive(bg);
- }
- // Update the xywh of this item
- _xywh[0] = X;
- _xywh[1] = Y;
- _xywh[2] = W;
- _xywh[3] = H;
- // Text size
- int textw=0, texth=0;
- fl_measure(_label, textw, texth, 0);
- int textycenter = Y+(H/2);
- int &icon_x = _collapse_xywh[0] = X-1;
- int &icon_y = _collapse_xywh[1] = textycenter - (prefs.openicon()->h()/2);
- int &icon_w = _collapse_xywh[2] = prefs.openicon()->w();
- _collapse_xywh[3] = prefs.openicon()->h();
- // Horizontal connector values
- int hstartx = X+icon_w/2-1;
- int hendx = hstartx + prefs.connectorwidth();
- int hcenterx = X + icon_w + ((hendx - (X + icon_w)) / 2);
-
- // See if we should draw this item
- // If this item is root, and showroot() is disabled, don't draw.
- //
- char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
- if ( drawthis ) {
- // Draw connectors
- if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
- // Horiz connector between center of icon and text
- draw_horizontal_connector(hstartx, hendx, textycenter, prefs);
- if ( has_children() && is_open() ) {
- // Small vertical line down to children
- draw_vertical_connector(hcenterx, textycenter, Y+H, prefs);
- }
- // Connectors for last child
- if ( ! is_root() ) {
- if ( lastchild ) {
- draw_vertical_connector(hstartx, Y, textycenter, prefs);
- } else {
- draw_vertical_connector(hstartx, Y, Y+H, prefs);
- }
- }
- }
- // Draw collapse icon
- if ( has_children() && prefs.showcollapse() ) {
- // Draw icon image
- if ( is_open() ) {
- prefs.closeicon()->draw(icon_x,icon_y);
- } else {
- prefs.openicon()->draw(icon_x,icon_y);
- }
- }
- // Background for this item
- int &bx = _label_xywh[0] = X+(icon_w/2-1+prefs.connectorwidth());
- int &by = _label_xywh[1] = Y;
- int &bw = _label_xywh[2] = W-(icon_w/2-1+prefs.connectorwidth());
- int &bh = _label_xywh[3] = H;
- // Draw bg only if different from tree's bg
- if ( bg != tree->color() || is_selected() ) {
- if ( is_selected() ) {
- // Selected? Use selectbox() style
- fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg);
- } else {
- // Not Selected? use plain filled rectangle
- fl_color(bg);
- fl_rectf(bx, by, bw, bh);
- }
- }
- // Draw user icon (if any)
- int useroff = (icon_w/2-1+prefs.connectorwidth());
- if ( usericon() ) {
- // Item has user icon? Use it
- useroff += prefs.usericonmarginleft();
- icon_y = textycenter - (usericon()->h() >> 1);
- usericon()->draw(X+useroff,icon_y);
- useroff += usericon()->w();
- } else if ( prefs.usericon() ) {
- // Prefs has user icon? Use it
- useroff += prefs.usericonmarginleft();
- icon_y = textycenter - (prefs.usericon()->h() >> 1);
- prefs.usericon()->draw(X+useroff,icon_y);
- useroff += prefs.usericon()->w();
- }
- useroff += prefs.labelmarginleft();
- // Draw label
- if ( widget() ) {
- // Widget? Draw it
- int lx = X+useroff;
- int ly = by;
- int lw = widget()->w();
- int lh = bh;
- if ( widget()->x() != lx || widget()->y() != ly ||
- widget()->w() != lw || widget()->h() != lh ) {
- widget()->resize(lx, ly, lw, lh); // fltk will handle drawing this
- }
- } else {
- // No label widget? Draw text label
- if ( _label ) {
- fl_color(fg);
- fl_draw(_label, X+useroff, Y+H-fl_descent()-1);
- }
- }
- Y += H;
- } // end drawthis
- // Draw children
- if ( has_children() && is_open() ) {
- int child_x = drawthis ? // offset children to right,
- (hcenterx - (icon_w/2) + 1) : X; // unless didn't drawthis
- int child_w = W - (child_x-X);
- int child_y_start = Y;
- for ( int t=0; t<children(); t++ ) {
- int lastchild = ((t+1)==children()) ? 1 : 0;
- _children[t]->draw(child_x, Y, child_w, tree, prefs, lastchild);
- }
- if ( has_children() && is_open() ) {
- Y += prefs.openchild_marginbottom(); // offset below open child tree
- }
- if ( ! lastchild ) {
- draw_vertical_connector(hstartx, child_y_start, Y, prefs);
- }
- }
- }
-
- /// Was the event on the 'collapse' button?
- ///
- int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const {
- if ( _visible && _active && has_children() && prefs.showcollapse() ) {
- return(event_inside(_collapse_xywh) ? 1 : 0);
- } else {
- return(0);
- }
- }
-
- /// Was event on the label()?
- ///
- int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const {
- if ( _visible && _active ) {
- return(event_inside(_label_xywh) ? 1 : 0);
- } else {
- return(0);
- }
- }
-
- /// Internal: Show the FLTK widget() for this item and all children.
- /// Used by open() to re-show widgets that were hidden by a previous close()
- ///
- void Fl_Tree_Item::show_widgets() {
- if ( _widget ) _widget->show();
- if ( is_open() ) {
- for ( int t=0; t<_children.total(); t++ ) {
- _children[t]->show_widgets();
- }
- }
- }
-
- /// Internal: Hide the FLTK widget() for this item and all children.
- /// Used by close() to hide widgets.
- ///
- void Fl_Tree_Item::hide_widgets() {
- if ( _widget ) _widget->hide();
- for ( int t=0; t<_children.total(); t++ ) {
- _children[t]->hide_widgets();
- }
- }
-
- /// Open this item and all its children.
- void Fl_Tree_Item::open() {
- _open = 1;
- // Tell children to show() their widgets
- for ( int t=0; t<_children.total(); t++ ) {
- _children[t]->show_widgets();
- }
- }
-
- /// Close this item and all its children.
- void Fl_Tree_Item::close() {
- _open = 0;
- // Tell children to hide() their widgets
- for ( int t=0; t<_children.total(); t++ ) {
- _children[t]->hide_widgets();
- }
- }
-
- /// Returns how many levels deep this item is in the hierarchy.
- ///
- /// For instance; root has a depth of zero, and its immediate children
- /// would have a depth of 1, and so on.
- ///
- int Fl_Tree_Item::depth() const {
- int count = 0;
- const Fl_Tree_Item *item = parent();
- while ( item ) {
- ++count;
- item = item->parent();
- }
- return(count);
- }
-
- /// Return the next item in the tree.
- ///
- /// This method can be used to walk the tree forward.
- /// For an example of how to use this method, see Fl_Tree::first().
- ///
- /// \returns the next item in the tree, or 0 if there's no more items.
- ///
- Fl_Tree_Item *Fl_Tree_Item::next() {
- Fl_Tree_Item *p, *c = this;
- if ( c->has_children() ) {
- return(c->child(0));
- }
- while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents
- int t = p->find_child(c); // find our position in parent's children[] array
- if ( ++t < p->children() ) // not last child?
- return(p->child(t)); // return next child
- c = p; // child becomes parent to move up generation
- } // loop: moves up to next parent
- return(0); // hit root? done
- }
-
- /// Return the previous item in the tree.
- ///
- /// This method can be used to walk the tree backwards.
- /// For an example of how to use this method, see Fl_Tree::last().
- ///
- /// \returns the previous item in the tree, or 0 if there's no item above this one (hit the root).
- ///
- Fl_Tree_Item *Fl_Tree_Item::prev() {
- Fl_Tree_Item *p=parent(); // start with parent
- if ( ! p ) return(0); // hit root? done
- int t = p->find_child(this); // find our position in parent's children[] array
- if ( --t == -1 ) { // are we first child?
- return(p); // return immediate parent
- }
- p = p->child(t); // take parent's previous child
- while ( p->has_children() ) { // has children?
- p = p->child(p->children()-1); // take last child
- }
- return(p);
- }
-
- //
- // End of "$Id: Fl_Tree_Item.cxx 7627 2010-06-03 15:46:59Z greg.ercolano $".
- //