mirror of https://github.com/fltk/fltk.git
FLTK - Fast Light Tool Kit - https://github.com/fltk/fltk - cross platform GUI development
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
16 KiB
485 lines
16 KiB
// |
|
// "$Id$" |
|
// |
|
|
|
#ifndef FL_TREE_ITEM_H |
|
#define FL_TREE_ITEM_H |
|
|
|
#include <FL/Fl.H> |
|
#include <FL/Fl_Widget.H> |
|
#include <FL/Fl_Image.H> |
|
#include <FL/fl_draw.H> |
|
|
|
#include <FL/Fl_Tree_Item_Array.H> |
|
#include <FL/Fl_Tree_Prefs.H> |
|
|
|
////////////////////// |
|
// FL/Fl_Tree_Item.H |
|
////////////////////// |
|
// |
|
// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK |
|
// Copyright (C) 2009-2010 by Greg Ercolano. |
|
// |
|
// This library is free software. Distribution and use rights are outlined in |
|
// the file "COPYING" which should have been included with this file. If this |
|
// file is missing or damaged, see the license at: |
|
// |
|
// http://www.fltk.org/COPYING.php |
|
// |
|
// Please report all bugs and problems on the following page: |
|
// |
|
// http://www.fltk.org/str.php |
|
// |
|
|
|
/// |
|
/// \file |
|
/// \brief This file contains the definitions for Fl_Tree_Item |
|
/// |
|
|
|
/// \class Fl_Tree_Item |
|
/// \brief Tree widget item. |
|
/// |
|
/// This class is a single tree item, and manages all of the item's attributes. |
|
/// Fl_Tree_Item is used by Fl_Tree, which is comprised of many instances of Fl_Tree_Item. |
|
/// |
|
/// Fl_Tree_Item is hierarchical; it dynamically manages an Fl_Tree_Item_Array of children |
|
/// that are themselves instances of Fl_Tree_Item. Each item can have zero or more children. |
|
/// When an item has children, close() and open() can be used to hide or show them. |
|
/// |
|
/// Items have their own attributes; font size, face, color. |
|
/// Items maintain their own hierarchy of children. |
|
/// |
|
/// When you make changes to items, you'll need to tell the tree to redraw() |
|
/// for the changes to show up. |
|
/// |
|
/// New 1.3.3 ABI feature: |
|
/// You can define custom items by either adding a custom widget to the item |
|
/// with Fl_Tree_Item::widget(), or override the draw_item_content() method |
|
/// if you want to just redefine how the label is drawn. |
|
/// |
|
/// The following shows the Fl_Tree_Item's dimensions, useful when overriding |
|
/// the draw_item_content() method: |
|
/// |
|
/// \image html Fl_Tree_Item-dimensions.png "Fl_Tree_Item's internal dimensions." width=6cm |
|
/// \image latex Fl_Tree_Item-dimensions.png "Fl_Tree_Item's internal dimensions." width=6cm |
|
/// |
|
class Fl_Tree; |
|
class FL_EXPORT Fl_Tree_Item { |
|
#if FLTK_ABI_VERSION >= 10303 |
|
Fl_Tree *_tree; // parent tree |
|
#endif |
|
const char *_label; // label (memory managed) |
|
Fl_Font _labelfont; // label's font face |
|
Fl_Fontsize _labelsize; // label's font size |
|
Fl_Color _labelfgcolor; // label's fg color |
|
Fl_Color _labelbgcolor; // label's bg color (0xffffffff is 'transparent') |
|
#if FLTK_ABI_VERSION >= 10303 |
|
/// \enum Fl_Tree_Item_Flags |
|
enum Fl_Tree_Item_Flags { |
|
#else |
|
/// \enum |
|
enum { |
|
#endif |
|
OPEN = 1<<0, ///> item is open |
|
VISIBLE = 1<<1, ///> item is visible |
|
ACTIVE = 1<<2, ///> item is active |
|
SELECTED = 1<<3 ///> item is selected |
|
}; |
|
#if FLTK_ABI_VERSION >= 10301 |
|
// NEW |
|
unsigned short _flags; // misc flags |
|
#else /*FLTK_ABI_VERSION*/ |
|
// OLD: this will go away after 1.3.x |
|
char _open; // item is open? |
|
char _visible; // item is visible? |
|
char _active; // item activated? |
|
char _selected; // item selected? |
|
#endif /*FLTK_ABI_VERSION*/ |
|
int _xywh[4]; // xywh of this widget (if visible) |
|
int _collapse_xywh[4]; // xywh of collapse icon (if visible) |
|
int _label_xywh[4]; // xywh of label |
|
Fl_Widget *_widget; // item's label widget (optional) |
|
Fl_Image *_usericon; // item's user-specific icon (optional) |
|
Fl_Tree_Item_Array _children; // array of child items |
|
Fl_Tree_Item *_parent; // parent item (=0 if root) |
|
void *_userdata; // user data that can be associated with an item |
|
#if FLTK_ABI_VERSION >= 10301 |
|
Fl_Tree_Item *_prev_sibling; // previous sibling (same level) |
|
Fl_Tree_Item *_next_sibling; // next sibling (same level) |
|
#endif /*FLTK_ABI_VERSION*/ |
|
// Protected methods |
|
protected: |
|
void _Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree); |
|
void show_widgets(); |
|
void hide_widgets(); |
|
void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs); |
|
void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs); |
|
void recalc_tree(); |
|
int calc_item_height(const Fl_Tree_Prefs &prefs) const; |
|
#if FLTK_ABI_VERSION >= 10303 |
|
Fl_Color drawfgcolor() const; |
|
Fl_Color drawbgcolor() const; |
|
#endif |
|
|
|
public: |
|
Fl_Tree_Item(const Fl_Tree_Prefs &prefs); // CTOR -- backwards compatible |
|
#if FLTK_ABI_VERSION >= 10303 |
|
Fl_Tree_Item(Fl_Tree *tree); // CTOR -- ABI 1.3.3+ |
|
#endif |
|
~Fl_Tree_Item(); // DTOR |
|
Fl_Tree_Item(const Fl_Tree_Item *o); // COPY CTOR |
|
/// The item's x position relative to the window |
|
int x() const { return(_xywh[0]); } |
|
/// The item's y position relative to the window |
|
int y() const { return(_xywh[1]); } |
|
/// The entire item's width to right edge of Fl_Tree's inner width |
|
/// within scrollbars. |
|
int w() const { return(_xywh[2]); } |
|
/// The item's height |
|
int h() const { return(_xywh[3]); } |
|
/// The item's label x position relative to the window |
|
/// \version 1.3.3 |
|
int label_x() const { return(_label_xywh[0]); } |
|
/// The item's label y position relative to the window |
|
/// \version 1.3.3 |
|
int label_y() const { return(_label_xywh[1]); } |
|
/// The item's maximum label width to right edge of Fl_Tree's inner width |
|
/// within scrollbars. |
|
/// \version 1.3.3 |
|
int label_w() const { return(_label_xywh[2]); } |
|
/// The item's label height |
|
/// \version 1.3.3 |
|
int label_h() const { return(_label_xywh[3]); } |
|
#if FLTK_ABI_VERSION >= 10303 |
|
virtual int draw_item_content(int render); |
|
void draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus, |
|
int &tree_item_xmax, int lastchild=1, int render=1); |
|
#else |
|
void draw(int X, int &Y, int W, Fl_Widget *tree, |
|
Fl_Tree_Item *itemfocus, const Fl_Tree_Prefs &prefs, int lastchild=1); |
|
#endif |
|
void show_self(const char *indent = "") const; |
|
void label(const char *val); |
|
const char *label() const; |
|
|
|
/// Set a user-data value for the item. |
|
inline void user_data( void* data ) { _userdata = data; } |
|
|
|
/// Retrieve the user-data value that has been assigned to the item. |
|
inline void* user_data() const { return _userdata; } |
|
|
|
/// Set item's label font face. |
|
void labelfont(Fl_Font val) { |
|
_labelfont = val; |
|
recalc_tree(); // may change tree geometry |
|
} |
|
/// Get item's label font face. |
|
Fl_Font labelfont() const { |
|
return(_labelfont); |
|
} |
|
/// Set item's label font size. |
|
void labelsize(Fl_Fontsize val) { |
|
_labelsize = val; |
|
recalc_tree(); // may change tree geometry |
|
} |
|
/// Get item's label font size. |
|
Fl_Fontsize labelsize() const { |
|
return(_labelsize); |
|
} |
|
/// Set item's label foreground text color. |
|
void labelfgcolor(Fl_Color val) { |
|
_labelfgcolor = val; |
|
} |
|
/// Return item's label foreground text color. |
|
Fl_Color labelfgcolor() const { |
|
return(_labelfgcolor); |
|
} |
|
/// Set item's label text color. Alias for labelfgcolor(Fl_Color)). |
|
void labelcolor(Fl_Color val) { |
|
labelfgcolor(val); |
|
} |
|
/// Return item's label text color. Alias for labelfgcolor() const). |
|
Fl_Color labelcolor() const { |
|
return labelfgcolor(); |
|
} |
|
/// Set item's label background color. |
|
/// A special case is made for color 0xffffffff which uses the parent tree's bg color. |
|
void labelbgcolor(Fl_Color val) { |
|
_labelbgcolor = val; |
|
} |
|
/// Return item's label background text color. |
|
/// If the color is 0xffffffff, the default behavior is the parent tree's |
|
/// bg color will be used. (An overloaded draw_item_content() can override |
|
/// this behavior.) |
|
Fl_Color labelbgcolor() const { |
|
return(_labelbgcolor); |
|
} |
|
/// Assign an FLTK widget to this item. |
|
void widget(Fl_Widget *val) { |
|
_widget = val; |
|
recalc_tree(); // may change tree geometry |
|
} |
|
/// Return FLTK widget assigned to this item. |
|
Fl_Widget *widget() const { |
|
return(_widget); |
|
} |
|
/// Return the number of children this item has. |
|
int children() const { |
|
return(_children.total()); |
|
} |
|
/// Return the child item for the given 'index'. |
|
Fl_Tree_Item *child(int index) { |
|
return(_children[index]); |
|
} |
|
/// Return the const child item for the given 'index'. |
|
const Fl_Tree_Item *child(int t) const; |
|
/// See if this item has children. |
|
int has_children() const { |
|
return(children()); |
|
} |
|
int find_child(const char *name); |
|
int find_child(Fl_Tree_Item *item); |
|
int remove_child(Fl_Tree_Item *item); |
|
int remove_child(const char *new_label); |
|
void clear_children(); |
|
void swap_children(int ax, int bx); |
|
int swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b); |
|
const Fl_Tree_Item *find_child_item(const char *name) const; |
|
Fl_Tree_Item *find_child_item(const char *name); |
|
const Fl_Tree_Item *find_child_item(char **arr) const; |
|
Fl_Tree_Item *find_child_item(char **arr); |
|
const Fl_Tree_Item *find_item(char **arr) const; |
|
Fl_Tree_Item *find_item(char **arr); |
|
////////////////// |
|
// Adding items |
|
////////////////// |
|
Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, |
|
const char *new_label, |
|
Fl_Tree_Item *newitem); |
|
Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, |
|
const char *new_label); |
|
Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, |
|
char **arr, |
|
Fl_Tree_Item *newitem); |
|
Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, |
|
char **arr); |
|
#if FLTK_ABI_VERSION >= 10303 |
|
Fl_Tree_Item *replace(Fl_Tree_Item *new_item); |
|
Fl_Tree_Item *replace_child(Fl_Tree_Item *olditem, Fl_Tree_Item *newitem); |
|
#endif |
|
Fl_Tree_Item *insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos=0); |
|
Fl_Tree_Item *insert_above(const Fl_Tree_Prefs &prefs, const char *new_label); |
|
int depth() const; |
|
Fl_Tree_Item *prev(); |
|
Fl_Tree_Item *next(); |
|
Fl_Tree_Item *next_sibling(); |
|
Fl_Tree_Item *prev_sibling(); |
|
void update_prev_next(int index); |
|
Fl_Tree_Item *next_displayed(Fl_Tree_Prefs &prefs); // deprecated |
|
Fl_Tree_Item *prev_displayed(Fl_Tree_Prefs &prefs); // deprecated |
|
Fl_Tree_Item *next_visible(Fl_Tree_Prefs &prefs); |
|
Fl_Tree_Item *prev_visible(Fl_Tree_Prefs &prefs); |
|
|
|
/// Return the parent for this item. Returns NULL if we are the root. |
|
Fl_Tree_Item *parent() { |
|
return(_parent); |
|
} |
|
/// Return the const parent for this item. Returns NULL if we are the root. |
|
const Fl_Tree_Item *parent() const { |
|
return(_parent); |
|
} |
|
/// Set the parent for this item. |
|
/// Should only be used by Fl_Tree's internals. |
|
/// |
|
void parent(Fl_Tree_Item *val) { |
|
_parent = val; |
|
} |
|
#if FLTK_ABI_VERSION >= 10303 |
|
const Fl_Tree_Prefs& prefs() const; |
|
/// Return the tree for this item. |
|
const Fl_Tree *tree() const { |
|
return(_tree); |
|
} |
|
#endif |
|
////////////////// |
|
// State |
|
////////////////// |
|
void open(); |
|
void close(); |
|
/// See if the item is 'open'. |
|
int is_open() const { |
|
return(is_flag(OPEN)); |
|
} |
|
/// See if the item is 'closed'. |
|
int is_close() const { |
|
return(is_flag(OPEN)?0:1); |
|
} |
|
/// Toggle the item's open/closed state. |
|
void open_toggle() { |
|
is_open()?close():open(); // handles calling recalc_tree() |
|
} |
|
/// Change the item's selection state to the optionally specified 'val'. |
|
/// If 'val' is not specified, the item will be selected. |
|
/// |
|
void select(int val=1) { |
|
set_flag(SELECTED, val); |
|
} |
|
/// Toggle the item's selection state. |
|
void select_toggle() { |
|
if ( is_selected() ) { |
|
deselect(); // deselect if selected |
|
} else { |
|
select(); // select if deselected |
|
} |
|
} |
|
/// Select item and all its children. |
|
/// Returns count of how many items were in the 'deselected' state, |
|
/// ie. how many items were "changed". |
|
/// |
|
int select_all() { |
|
int count = 0; |
|
if ( ! is_selected() ) { |
|
select(); |
|
++count; |
|
} |
|
for ( int t=0; t<children(); t++ ) { |
|
count += child(t)->select_all(); |
|
} |
|
return(count); |
|
} |
|
/// Disable the item's selection state. |
|
void deselect() { |
|
set_flag(SELECTED, 0); |
|
} |
|
/// Deselect item and all its children. |
|
/// Returns count of how many items were in the 'selected' state, |
|
/// ie. how many items were "changed". |
|
/// |
|
int deselect_all() { |
|
int count = 0; |
|
if ( is_selected() ) { |
|
deselect(); |
|
++count; |
|
} |
|
for ( int t=0; t<children(); t++ ) { |
|
count += child(t)->deselect_all(); |
|
} |
|
return(count); |
|
} |
|
/// See if the item is selected. |
|
char is_selected() const { |
|
return(is_flag(SELECTED)); |
|
} |
|
/// Change the item's activation state to the optionally specified 'val'. |
|
/// |
|
/// When deactivated, the item will be 'grayed out'; the callback() |
|
/// won't be invoked if the user clicks on the label. If a widget() |
|
/// is associated with the item, its activation state will be changed as well. |
|
/// |
|
/// If 'val' is not specified, the item will be activated. |
|
/// |
|
void activate(int val=1) { |
|
set_flag(ACTIVE,val); |
|
if ( _widget && val != (int)_widget->active() ) { |
|
if ( val ) { |
|
_widget->activate(); |
|
} else { |
|
_widget->deactivate(); |
|
} |
|
_widget->redraw(); |
|
} |
|
} |
|
/// Deactivate the item; the callback() won't be invoked when clicked. |
|
/// Same as activate(0) |
|
/// |
|
void deactivate() { |
|
activate(0); |
|
} |
|
/// See if the item is activated. |
|
char is_activated() const { |
|
return(is_flag(ACTIVE)); |
|
} |
|
/// See if the item is activated. Alias for is_activated(). |
|
char is_active() const { |
|
return(is_activated()); |
|
} |
|
/// See if the item is visible. Alias for is_visible(). |
|
int visible() const { |
|
return(is_visible()); |
|
} |
|
/// See if the item is visible. |
|
int is_visible() const { |
|
return(is_flag(VISIBLE)); |
|
} |
|
int visible_r() const; |
|
|
|
/// Set the item's user icon to an Fl_Image. '0' will disable. |
|
void usericon(Fl_Image *val) { |
|
_usericon = val; |
|
recalc_tree(); // may change tree geometry |
|
} |
|
/// Get the item's user icon as an Fl_Image. Returns '0' if disabled. |
|
Fl_Image *usericon() const { |
|
return(_usericon); |
|
} |
|
////////////////// |
|
// Events |
|
////////////////// |
|
#if FLTK_ABI_VERSION >= 10303 |
|
const Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0) const; |
|
Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0); |
|
#else |
|
const Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs) const; |
|
Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs); |
|
#endif |
|
int event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const; |
|
int event_on_label(const Fl_Tree_Prefs &prefs) const; |
|
/// Is this item the root of the tree? |
|
int is_root() const { |
|
return(_parent==0?1:0); |
|
} |
|
|
|
// Protected methods |
|
// TODO: move these to top 'protected:' section |
|
protected: |
|
#if FLTK_ABI_VERSION >= 10301 |
|
/// Set a flag to an on or off value. val is 0 or 1. |
|
inline void set_flag(unsigned short flag,int val) { |
|
if ( flag==OPEN || flag==VISIBLE ) { |
|
recalc_tree(); // may change tree geometry |
|
} |
|
if ( val ) _flags |= flag; else _flags &= ~flag; |
|
} |
|
/// See if flag set. Returns 0 or 1. |
|
inline int is_flag(unsigned short val) const { |
|
return(_flags & val ? 1 : 0); |
|
} |
|
#else /*FLTK_ABI_VERSION*/ |
|
/// Set a flag to an on or off value. val is 0 or 1. |
|
void set_flag(unsigned short flag,int val) { |
|
switch (flag) { |
|
case OPEN: _open = val; break; |
|
case VISIBLE: _visible = val; break; |
|
case ACTIVE: _active = val; break; |
|
case SELECTED: _selected = val; break; |
|
} |
|
} |
|
/// See if flag set. Returns 0 or 1. |
|
int is_flag(unsigned short flag) const { |
|
switch (flag) { |
|
case OPEN: return(_open ? 1 : 0); |
|
case VISIBLE: return(_visible ? 1 : 0); |
|
case ACTIVE: return(_active ? 1 : 0); |
|
case SELECTED: return(_selected ? 1 : 0); |
|
default: return(0); |
|
} |
|
} |
|
#endif /*FLTK_ABI_VERSION*/ |
|
|
|
}; |
|
|
|
#endif /*FL_TREE_ITEM_H*/ |
|
|
|
// |
|
// End of "$Id$". |
|
//
|
|
|