#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Tree_Item.H>
#include <FL/Fl_Tree_Prefs.H>
#include <FL/Fl_Tree.H>
#include <FL/fl_string_functions.h>
#include "Fl_System_Driver.H"
static int event_inside(const int xywh[4]) {
return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3]));
}
Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) {
_Init(prefs, 0);
}
void Fl_Tree_Item::_Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree) {
_tree = tree;
_label = 0;
_labelfont = prefs.labelfont();
_labelsize = prefs.labelsize();
_labelfgcolor = prefs.labelfgcolor();
_labelbgcolor = prefs.labelbgcolor();
_widget = 0;
_flags = OPEN|VISIBLE|ACTIVE;
_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;
_userdeicon = 0;
_userdata = 0;
_parent = 0;
_children.manage_item_destroy(1); _prev_sibling = 0;
_next_sibling = 0;
}
Fl_Tree_Item::Fl_Tree_Item(Fl_Tree *tree) {
_Init(tree->_prefs, tree);
}
Fl_Tree_Item::~Fl_Tree_Item() {
if ( _label ) {
free((void*)_label);
_label = 0;
}
_widget = 0; _usericon = 0; _userdeicon = 0; if ( _tree && this == _tree->_item_focus )
{ _tree->_item_focus = 0; }
}
Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {
_tree = o->_tree;
_label = o->label() ? fl_strdup(o->label()) : 0;
_labelfont = o->labelfont();
_labelsize = o->labelsize();
_labelfgcolor = o->labelfgcolor();
_labelbgcolor = o->labelbgcolor();
_widget = o->widget();
_flags = o->_flags;
_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;
_prev_sibling = 0; _next_sibling = 0; }
void Fl_Tree_Item::show_self(const char *indent) const {
const char *thelabel = label() ? label() : "(NULL)";
printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n",
indent, thelabel, children(), (void*)this, (void*)_parent,
(void*)_prev_sibling, (void*)_next_sibling, depth());
if ( children() ) {
char *i2 = new char [strlen(indent)+3]; strcpy(i2, indent);
strcat(i2, " |");
for ( int t=0; t<children(); t++ ) {
child(t)->show_self(i2);
}
delete[] i2;
}
fflush(stdout);
}
void Fl_Tree_Item::label(const char *name) {
if ( _label ) { free((void*)_label); _label = 0; }
_label = name ? fl_strdup(name) : 0;
recalc_tree(); }
const char *Fl_Tree_Item::label() const {
return(_label);
}
const Fl_Tree_Item *Fl_Tree_Item::child(int index) const {
return(_children[index]);
}
void Fl_Tree_Item::clear_children() {
_children.clear();
recalc_tree(); }
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);
}
const Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) const {
if ( name )
for ( int t=0; t<children(); t++ )
if ( child(t)->label() )
if ( strcmp(child(t)->label(), name) == 0 )
return(child(t));
return(0);
}
Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) {
return(const_cast<Fl_Tree_Item*>(
static_cast<const Fl_Tree_Item &>(*this).find_child_item(name)));
}
const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const {
for ( int t=0; t<children(); t++ ) {
if ( child(t)->label() ) {
if ( strcmp(child(t)->label(), *arr) == 0 ) { if ( *(arr+1) ) { return(_children[t]->find_child_item(arr+1));
} else { return(_children[t]);
}
}
}
}
return(0);
}
Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) {
return(const_cast<Fl_Tree_Item*>(
static_cast<const Fl_Tree_Item &>(*this).find_child_item(arr)));
}
const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const {
if ( ! *names ) return(0);
if ( label() && strcmp(label(), *names) == 0 ) { ++names; if ( *names == 0 ) return(this); }
if ( children() ) { return(find_child_item(names));
}
return(0);
}
Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) {
return(const_cast<Fl_Tree_Item*>(
static_cast<const Fl_Tree_Item &>(*this).find_item(names)));
}
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);
}
Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs,
const char *new_label) {
return(add(prefs, new_label, (Fl_Tree_Item*)0));
}
Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs,
const char *new_label,
Fl_Tree_Item *item) {
if ( !item )
{ item = new Fl_Tree_Item(_tree); item->label(new_label); }
recalc_tree(); 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);
}
Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {
return add(prefs, arr, 0);
}
Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs,
char **arr,
Fl_Tree_Item *newitem) {
if ( !*arr ) return 0;
Fl_Tree_Item *child = find_child_item(*arr);
if ( child ) { if ( *(arr+1) == 0 ) { if ( !newitem ) { return 0; } else {
return child->add(prefs, newitem->label(), newitem);
}
}
return child->add(prefs, arr+1, newitem); }
if ( *(arr+1) == 0 ) return add(prefs, *arr, newitem);
Fl_Tree_Item *newchild;
return (newchild=add(prefs, *arr)) ? newchild->add(prefs,arr+1,newitem) : 0; }
Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) {
(void) prefs; Fl_Tree_Item *item = new Fl_Tree_Item(_tree);
item->label(new_label);
item->_parent = this;
_children.insert(pos, item);
recalc_tree(); return(item);
}
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);
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);
}
Fl_Tree_Item* Fl_Tree_Item::deparent(int pos) {
Fl_Tree_Item *orphan = _children[pos];
if ( _children.deparent(pos) < 0 ) return NULL;
return orphan;
}
int Fl_Tree_Item::reparent(Fl_Tree_Item *newchild, int pos) {
int ret;
if ( (ret = _children.reparent(newchild, this, pos)) < 0 ) return ret;
newchild->parent(this); return 0;
}
int Fl_Tree_Item::move(int to, int from) {
return _children.move(to, from);
}
int Fl_Tree_Item::move(Fl_Tree_Item *item, int op, int pos) {
Fl_Tree_Item *from_parent, *to_parent;
int from, to;
switch (op) {
case 0: from_parent = this->parent();
to_parent = item->parent();
if ( !from_parent || !to_parent ) return -1;
from = from_parent->find_child(this);
to = to_parent->find_child(item);
break;
case 1: from_parent = this->parent();
to_parent = item->parent();
if ( !from_parent || !to_parent ) return -1;
from = from_parent->find_child(this);
to = to_parent->find_child(item);
break;
case 2: from_parent = this->parent();
if ( !from_parent ) return -1;
to_parent = item;
from = from_parent->find_child(this);
to = pos;
break;
default:
return -3;
}
if ( !from_parent || !to_parent ) return -1;
if ( from < 0 || to < 0 ) return -2;
if ( from_parent == to_parent ) { switch (op) { case 0: if ( from < to && to > 0 ) --to; break;
case 1: if ( from > to && to < to_parent->children() ) ++to; break;
}
if ( from_parent->move(to, from) < 0 ) return -4;
} else { if ( to > to_parent->children() ) return -4;
if ( from_parent->deparent(from) == NULL ) return -5;
if ( to_parent->reparent(this, to) < 0 ) { to_parent->reparent(this, 0); return -6;
}
}
return 0;
}
int Fl_Tree_Item::move_above(Fl_Tree_Item *item) {
return move(item, 0, 0);
}
int Fl_Tree_Item::move_below(Fl_Tree_Item *item) {
return move(item, 1, 0);
}
int Fl_Tree_Item::move_into(Fl_Tree_Item *item, int pos) {
return move(item, 2, pos);
}
const Fl_Tree_Prefs& Fl_Tree_Item::prefs() const {
return(_tree->_prefs);
}
Fl_Tree_Item *Fl_Tree_Item::replace(Fl_Tree_Item *newitem) {
Fl_Tree_Item *p = parent();
if ( !p ) { _tree->root(newitem); return newitem;
}
return p->replace_child(this, newitem);
}
Fl_Tree_Item *Fl_Tree_Item::replace_child(Fl_Tree_Item *olditem,
Fl_Tree_Item *newitem) {
int pos = find_child(olditem); if ( pos == -1 ) return(NULL);
newitem->_parent = this;
_children.replace(pos, newitem);
recalc_tree(); return newitem;
}
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);
recalc_tree(); return(0);
}
}
return(-1);
}
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);
recalc_tree(); return(0);
}
}
}
return(-1);
}
void Fl_Tree_Item::swap_children(int ax, int bx) {
_children.swap(ax, bx);
}
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++ ) { 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); swap_children(ax,bx);
return(0);
}
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:
fl_line(x1,y,x2,y);
return;
case FL_TREE_CONNECTOR_DOTTED:
{
x1 |= 1; for ( int xx=x1; xx<=x2; xx+=2 ) {
fl_point(xx, y);
}
return;
}
case FL_TREE_CONNECTOR_NONE:
return;
}
}
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; y2 |= 1; fl_line(x,y1,x,y2);
return;
case FL_TREE_CONNECTOR_DOTTED:
{
y1 |= 1; y2 |= 1; for ( int yy=y1; yy<=y2; yy+=2 ) {
fl_point(x, yy);
}
return;
}
case FL_TREE_CONNECTOR_NONE:
return;
}
}
const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) const {
if ( ! is_visible() ) return(0);
if ( is_root() && !prefs.showroot() ) {
} else {
if ( yonly ) {
if ( Fl::event_y() >= _xywh[1] &&
Fl::event_y() <= (_xywh[1]+_xywh[3]) ) {
return(this);
}
} else {
if ( event_inside(_xywh) ) { return(this); }
}
}
if ( is_open() ) { for ( int t=0; t<children(); t++ ) {
const Fl_Tree_Item *item;
if ( (item = _children[t]->find_clicked(prefs, yonly)) != NULL) return(item); }
}
return(0);
}
Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) {
return(const_cast<Fl_Tree_Item*>(
static_cast<const Fl_Tree_Item &>(*this).find_clicked(prefs, yonly)));
}
int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const {
if ( ! is_visible() ) return(0);
int H = 0;
if ( _label ) {
fl_font(_labelfont, _labelsize); H = _labelsize + fl_descent() + 1; }
if ( widget() &&
(prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) &&
H < widget()->h()) {
H = widget()->h();
}
if ( has_children() && H < prefs.openicon_h() )
H = prefs.openicon_h();
if ( usericon() && H<usericon()->h() )
H = usericon()->h();
return(H);
}
Fl_Color Fl_Tree_Item::drawfgcolor() const {
return is_selected() ? fl_contrast(_labelfgcolor, tree()->selection_color())
: (is_active() && tree()->active_r()) ? _labelfgcolor
: fl_inactive(_labelfgcolor);
}
Fl_Color Fl_Tree_Item::drawbgcolor() const {
const Fl_Color unspecified = 0xffffffff;
return is_selected() ? is_active() && tree()->active_r() ? tree()->selection_color()
: fl_inactive(tree()->selection_color())
: _labelbgcolor == unspecified ? tree()->color()
: _labelbgcolor;
}
int Fl_Tree_Item::draw_item_content(int render) {
Fl_Color fg = drawfgcolor();
Fl_Color bg = drawbgcolor();
const Fl_Tree_Prefs &prefs = tree()->prefs();
int xmax = label_x();
if ( render && (bg != tree()->color() || is_selected()) ) {
if ( is_selected() ) { fl_draw_box(prefs.selectbox(),
label_x(), label_y(), label_w(), label_h(), bg);
} else { fl_color(bg);
fl_rectf(label_x(), label_y(), label_w(), label_h());
}
if ( widget() ) widget()->damage(FL_DAMAGE_ALL); }
if ( _label &&
( !widget() ||
(prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) {
if ( render ) {
fl_color(fg);
fl_font(_labelfont, _labelsize);
}
int lx = label_x()+(_label ? prefs.labelmarginleft() : 0);
int ly = label_y()+(label_h()/2)+(_labelsize/2)-fl_descent()/2;
int lw=0, lh=0;
fl_measure(_label, lw, lh); if ( render ) fl_draw(_label, lx, ly);
xmax = lx + lw; }
return xmax;
}
void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus,
int &tree_item_xmax, int lastchild, int render) {
Fl_Tree_Prefs &prefs = _tree->_prefs;
if ( !is_visible() ) return;
int tree_top = tree()->_tiy;
int tree_bot = tree_top + tree()->_tih;
int H = calc_item_height(prefs); int H2 = H + prefs.linespacing();
_xywh[0] = X;
_xywh[1] = Y;
_xywh[2] = W;
_xywh[3] = H;
int item_y_center = (Y+(H/2))|1; _collapse_xywh[2] = prefs.openicon_w();
int &icon_w = _collapse_xywh[2];
_collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3;
int &icon_x = _collapse_xywh[0];
_collapse_xywh[1] = item_y_center - prefs.openicon_h()/2;
int &icon_y = _collapse_xywh[1];
_collapse_xywh[3] = prefs.openicon_h();
int hconn_x = X+icon_w/2-1;
int hconn_x2 = hconn_x + prefs.connectorwidth();
int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2);
int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();
int conn_w = cw1>cw2 ? cw1 : cw2;
int uicon_x = X+(icon_w/2-1+conn_w) + ( (usericon() || prefs.usericon())
? prefs.usericonmarginleft() : 0);
int uicon_w = usericon() ? usericon()->w()
: prefs.usericon() ? prefs.usericon()->w() : 0;
_label_xywh[0] = uicon_x + uicon_w + prefs.labelmarginleft();
_label_xywh[1] = Y;
_label_xywh[2] = tree()->_tix + tree()->_tiw - _label_xywh[0];
_label_xywh[3] = H;
int xmax = 0;
if ( widget() ) {
int wx = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0);
int wy = label_y();
int ww = widget()->w(); int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET)
? widget()->h() : H;
if ( _label &&
(prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) {
fl_font(_labelfont, _labelsize); int lw=0, lh=0;
fl_measure(_label,lw,lh); wx += (lw + prefs.widgetmarginleft());
}
if ( widget()->x() != wx || widget()->y() != wy ||
widget()->w() != ww || widget()->h() != wh ) {
widget()->resize(wx,wy,ww,wh); }
}
char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;
if (!render) clipped = 0; char active = (is_active() && tree()->active_r()) ? 1 : 0;
char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
if ( !clipped ) {
Fl_Color fg = drawfgcolor();
Fl_Color bg = drawbgcolor();
if ( drawthis ) { if ( (tree()->damage() & ~FL_DAMAGE_CHILD) || !render ) { if ( render && prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
draw_horizontal_connector(hconn_x, hconn_x_center, item_y_center, prefs);
if ( has_children() && is_open() )
draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs);
if ( !is_root() ) {
if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs);
else draw_vertical_connector(hconn_x, Y, Y+H2, prefs);
}
}
if ( render && has_children() && prefs.showcollapse() ) {
if ( is_open() ) {
if ( prefs.closeicon() ) {
if ( active ) prefs.closeicon()->draw(icon_x, icon_y);
else prefs.closedeicon()->draw(icon_x, icon_y);
} else {
Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, false, active);
}
} else {
if ( prefs.openicon() ) {
if ( active ) prefs.openicon()->draw(icon_x, icon_y);
else prefs.opendeicon()->draw(icon_x, icon_y);
} else {
Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, true, active);
}
}
}
if ( render && usericon() ) {
int uicon_y = item_y_center - (usericon()->h() >> 1);
if ( active ) usericon()->draw(uicon_x,uicon_y);
else if ( userdeicon() ) userdeicon()->draw(uicon_x,uicon_y);
} else if ( render && prefs.usericon() ) {
int uicon_y = item_y_center - (prefs.usericon()->h() >> 1);
if ( active ) prefs.usericon()->draw(uicon_x,uicon_y);
else if ( prefs.userdeicon() ) prefs.userdeicon()->draw(uicon_x,uicon_y);
}
xmax = draw_item_content(render);
} if ( widget() ) {
if (render)
tree()->draw_child(*widget()); if ( widget()->label() && render )
tree()->draw_outside_label(*widget()); xmax = widget()->x() + widget()->w(); }
if ( render &&
this == itemfocus &&
Fl::visible_focus() &&
Fl::focus() == tree() &&
prefs.selectmode() != FL_TREE_SELECT_NONE ) {
fl_draw_box_focus(FL_NO_BOX, label_x()+1, label_y()+1, label_w()-1, label_h()-1, fg, bg);
}
} } if ( drawthis ) Y += H2; if ( xmax > tree_item_xmax )
tree_item_xmax = xmax;
if ( has_children() && is_open() ) {
int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) : X; int child_w = W - (child_x-X);
int child_y_start = Y;
for ( int t=0; t<children(); t++ ) {
int is_lastchild = ((t+1)==children()) ? 1 : 0;
_children[t]->draw(child_x, Y, child_w, itemfocus, tree_item_xmax, is_lastchild, render);
}
if ( has_children() && is_open() ) {
Y += prefs.openchild_marginbottom(); }
if ( ! lastchild ) {
int ytop = child_y_start;
int ybot = Y;
int is_clipped = ((ytop < tree_top) && (ybot < tree_top)) || ((ytop > tree_bot) && (ybot > tree_bot)); if (render && !is_clipped ) {
ytop = (ytop < tree_top) ? tree_top : ytop;
ybot = (ybot > tree_bot) ? tree_bot : ybot;
draw_vertical_connector(hconn_x, ytop, ybot, prefs);
}
}
}
}
int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const {
if ( is_visible() && is_active() && has_children() && prefs.showcollapse() ) {
return(event_inside(_collapse_xywh) ? 1 : 0);
} else {
return(0);
}
}
int Fl_Tree_Item::event_on_user_icon(const Fl_Tree_Prefs &prefs) const {
if ( !is_visible() ) return 0; if ( !event_inside(_xywh) ) return 0; if ( event_on_collapse_icon(prefs) ) return 0; if ( Fl::event_x() >= _label_xywh[0] ) return 0; Fl_Image *ui = 0;
if ( is_active() ) {
if ( usericon() ) ui = usericon(); else if ( prefs.usericon() ) ui = prefs.usericon(); } else {
if ( userdeicon() ) ui = userdeicon(); else if ( prefs.userdeicon() ) ui = prefs.userdeicon(); }
if ( !ui ) return 0; int uix = _label_xywh[0]-ui->w(); if ( Fl::event_x() < uix ) return 0; return 1; }
int Fl_Tree_Item::event_on_item(const Fl_Tree_Prefs &prefs) const {
(void) prefs; return(event_inside(_xywh) ? 1 : 0);
}
int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const {
(void) prefs; if ( is_visible() && is_active() ) {
return(event_inside(_label_xywh) ? 1 : 0);
} else {
return(0);
}
}
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();
}
}
}
void Fl_Tree_Item::hide_widgets() {
if ( _widget ) _widget->hide();
for ( int t=0; t<_children.total(); t++ ) {
_children[t]->hide_widgets();
}
}
void Fl_Tree_Item::open() {
set_flag(OPEN,1);
for ( int t=0; t<_children.total(); t++ ) {
_children[t]->show_widgets();
}
recalc_tree(); }
void Fl_Tree_Item::close() {
set_flag(OPEN,0);
for ( int t=0; t<_children.total(); t++ ) {
_children[t]->hide_widgets();
}
recalc_tree(); }
int Fl_Tree_Item::depth() const {
int count = 0;
const Fl_Tree_Item *item = parent();
while ( item ) {
++count;
item = item->parent();
}
return(count);
}
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 ) { if ( c->_next_sibling ) return(c->_next_sibling); c = p; } return(0); }
Fl_Tree_Item *Fl_Tree_Item::prev() {
if ( !parent() ) return(0); if ( !_prev_sibling ) { return(parent()); }
Fl_Tree_Item *p = _prev_sibling; while ( p->has_children() ) { p = p->child(p->children()-1); }
return(p);
}
Fl_Tree_Item *Fl_Tree_Item::next_sibling() {
return(_next_sibling);
}
Fl_Tree_Item *Fl_Tree_Item::prev_sibling() {
return(_prev_sibling);
}
void Fl_Tree_Item::update_prev_next(int index) {
if ( index == -1 ) { _parent = 0;
_prev_sibling = 0;
_next_sibling = 0;
return;
}
int pchildren = parent() ? parent()->children() : 0;
int index_prev = index-1;
int index_next = index+1;
Fl_Tree_Item *item_prev = (index_prev>=0)&&(index_prev<pchildren) ? parent()->child(index_prev) : 0;
Fl_Tree_Item *item_next = (index_next>=0)&&(index_next<pchildren) ? parent()->child(index_next) : 0;
_prev_sibling = item_prev;
_next_sibling = item_next;
if ( item_prev ) item_prev->_next_sibling = this;
if ( item_next ) item_next->_prev_sibling = this;
}
Fl_Tree_Item *Fl_Tree_Item::next_visible(Fl_Tree_Prefs &prefs) {
Fl_Tree_Item *item = this;
while ( 1 ) {
item = item->next();
if ( !item ) return 0;
if ( item->is_root() && !prefs.showroot() ) continue;
if ( item->visible_r() ) return(item);
}
}
Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) {
return next_visible(prefs);
}
Fl_Tree_Item *Fl_Tree_Item::prev_visible(Fl_Tree_Prefs &prefs) {
Fl_Tree_Item *c = this;
while ( c ) {
c = c->prev(); if ( !c ) break; if ( c->is_root() ) return((prefs.showroot()&&c->visible()) ? c : 0); if ( !c->visible() ) continue; Fl_Tree_Item *p = c->parent();
while (1) {
if ( !p || p->is_root() ) return(c); if ( p->is_close() ) c = p; p = p->parent(); }
}
return(0); }
Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) {
return prev_visible(prefs);
}
int Fl_Tree_Item::is_visible_r() const {
if ( !visible() ) return(0);
for (const Fl_Tree_Item *p=parent(); p; p=p->parent()) if (!p->visible() || p->is_close()) return(0); return(1);
}
void Fl_Tree_Item::recalc_tree() {
_tree->recalc_tree();
}