diff options
| -rw-r--r-- | FL/Fl_Tree.H | 10 | ||||
| -rw-r--r-- | FL/Fl_Tree_Item.H | 4 | ||||
| -rw-r--r-- | FL/Fl_Tree_Prefs.H | 26 | ||||
| -rw-r--r-- | examples/Makefile | 1 | ||||
| -rw-r--r-- | examples/tree-custom-draw-items.cxx | 100 | ||||
| -rw-r--r-- | src/Fl_Tree.cxx | 50 | ||||
| -rw-r--r-- | src/Fl_Tree_Item.cxx | 78 | ||||
| -rw-r--r-- | src/Fl_Tree_Prefs.cxx | 4 |
8 files changed, 235 insertions, 38 deletions
diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index f29161c01..ed2a2d526 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -96,6 +96,8 @@ /// Items can be found by their pathname using find_item(const char*), /// and an item's pathname can be found with item_pathname(). /// The selected items' colors are controlled by selection_color() (inherited from Fl_Widget). +/// A hook is provided to allow you to redefine how item's labels are drawn +/// via Fl_Tree::item_draw_callback(). /// /// \b SELECTION OF ITEMS /// @@ -465,7 +467,13 @@ public: Fl_Tree_Item_Draw_Mode item_draw_mode() const; void item_draw_mode(Fl_Tree_Item_Draw_Mode mode); void item_draw_mode(int mode); -#endif /*FLTK_ABI_VERSION*/ +#endif +#if FLTK_ABI_VERSION >= 10303 + void item_draw_callback(Fl_Tree_Item_Draw_Callback *cb, void *data=0); + Fl_Tree_Item_Draw_Callback* item_draw_callback() const; + void* item_draw_user_data() const; + void do_item_draw_callback(Fl_Tree_Item *o) const; +#endif int displayed(Fl_Tree_Item *item); void show_item(Fl_Tree_Item *item, int yoff); void show_item(Fl_Tree_Item *item); diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H index 5a3a8d6db..81c73fd64 100644 --- a/FL/Fl_Tree_Item.H +++ b/FL/Fl_Tree_Item.H @@ -98,6 +98,10 @@ public: int y() const { return(_xywh[1]); } int w() const { return(_xywh[2]); } int h() const { return(_xywh[3]); } + int label_x() const { return(_label_xywh[0]); } + int label_y() const { return(_label_xywh[1]); } + int label_w() const { return(_label_xywh[2]); } + int label_h() const { return(_label_xywh[3]); } int calc_item_height(const Fl_Tree_Prefs &prefs) const; void draw(int X, int &Y, int W, Fl_Widget *tree, Fl_Tree_Item *itemfocus, const Fl_Tree_Prefs &prefs, int lastchild=1); void show_self(const char *indent = "") const; diff --git a/FL/Fl_Tree_Prefs.H b/FL/Fl_Tree_Prefs.H index b01033e78..5ced88f4b 100644 --- a/FL/Fl_Tree_Prefs.H +++ b/FL/Fl_Tree_Prefs.H @@ -93,6 +93,11 @@ enum Fl_Tree_Item_Draw_Mode { }; #endif /*FLTK_ABI_VERSION*/ +#if FLTK_ABI_VERSION >= 10303 +class Fl_Tree_Item; +typedef void (Fl_Tree_Item_Draw_Callback)(Fl_Tree_Item*, void*); +#endif + /// \class Fl_Tree_Prefs /// /// \brief Fl_Tree's Preferences class. @@ -134,6 +139,10 @@ class FL_EXPORT Fl_Tree_Prefs { Fl_Tree_Item_Reselect_Mode _itemreselectmode; // controls item selection callback() behavior Fl_Tree_Item_Draw_Mode _itemdrawmode; // controls how items draw label + widget() #endif /*FLTK_ABI_VERSION*/ +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item_Draw_Callback *_itemdrawcallback; // callback to handle drawing items (0=none) + void *_itemdrawuserdata; // data for drawing items (0=none) +#endif public: Fl_Tree_Prefs(); @@ -412,7 +421,22 @@ public: inline void item_draw_mode(Fl_Tree_Item_Draw_Mode val) { _itemdrawmode = val; } -#endif /*FLTK_ABI_VERSION*/ +#endif +#if FLTK_ABI_VERSION >= 10303 + void item_draw_callback(Fl_Tree_Item_Draw_Callback *cb, void *data=0) { + _itemdrawcallback = cb; + _itemdrawuserdata = data; + } + Fl_Tree_Item_Draw_Callback* item_draw_callback() const { + return(_itemdrawcallback); + } + void* item_draw_user_data() const { + return(_itemdrawuserdata); + } + void do_item_draw_callback(Fl_Tree_Item *o) const { + _itemdrawcallback(o, _itemdrawuserdata); + } +#endif }; #endif /*FL_TREE_PREFS_H*/ diff --git a/examples/Makefile b/examples/Makefile index 60003f56a..a9a4f6175 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -24,6 +24,7 @@ ALL = howto-add_fd-and-popen$(EXEEXT) \ texteditor-simple$(EXEEXT) \ tree-simple$(EXEEXT) \ tree-as-container$(EXEEXT) \ + tree-custom-draw-items$(EXEEXT) \ tree-of-tables$(EXEEXT) \ wizard-simple$(EXEEXT) diff --git a/examples/tree-custom-draw-items.cxx b/examples/tree-custom-draw-items.cxx new file mode 100644 index 000000000..57ac85c31 --- /dev/null +++ b/examples/tree-custom-draw-items.cxx @@ -0,0 +1,100 @@ +// +// "$Id$" +// +// Demonstrate Fl_Tree custom item draw callback. - erco 11/09/2013 +// +// Copyright 2013 Greg Ercolano. +// Copyright 1998-2013 by Bill Spitzak and others. +// +// 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 +// +#include <stdio.h> +#include <math.h> // sin(3) +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Tree.H> + +#if FLTK_ABI_VERSION >= 10303 +static void draw_item(Fl_Tree_Item *item, void *data) { + Fl_Tree *tree = (Fl_Tree*)data; + int X=item->label_x(), Y=item->label_y(), + W=item->label_w(), H=item->label_h(); + // Draw the background + fl_color(item->is_selected() ? tree->selection_color() : item->labelbgcolor()); + fl_rectf(X,Y,W,H); + // Draw some red/grn/blu boxes + int x = X + 5; + fl_color(FL_RED); fl_rectf(x, Y+2, 10, H-4); x += 10; + fl_color(FL_GREEN); fl_rectf(x, Y+2, 10, H-4); x += 10; + fl_color(FL_BLUE); fl_rectf(x, Y+2, 10, H-4); x += 10; + x += 5; + // Draw text + fl_font(item->labelfont(), item->labelsize()); + fl_color(item->labelfgcolor()); + char s[80]; + sprintf(s, "Custom: '%s'", item->label()?item->label():"---"); + fl_draw(s, x+tree->labelmarginleft(),Y,W,H, FL_ALIGN_LEFT); + int fw=0,fh=0; + fl_measure(s,fw,fh); + x += fw + 10; + // Draw a red sine wave past the text to end of xywh area + fl_color(FL_RED); + for ( float a=0.0; x<(X+W); x++,a+=.1) { + int y = Y + sin(a) * ((H-2)/2) + (H/2); + fl_point(x,y); + } +} + +int main(int argc, char *argv[]) { + Fl::scheme("gtk+"); + Fl_Double_Window *win = new Fl_Double_Window(250, 400, "Simple Tree"); + win->begin(); + { + // Create the tree + Fl_Tree *tree = new Fl_Tree(0, 0, win->w(), win->h()); + tree->showroot(0); // don't show root of tree + tree->item_draw_callback(draw_item, (void*)tree); // setup a callback for the tree + + // Add some items + tree->add("Flintstones/Fred"); + tree->add("Flintstones/Wilma"); + tree->add("Flintstones/Pebbles"); + tree->add("Simpsons/Homer"); + tree->add("Simpsons/Marge"); + tree->add("Simpsons/Bart"); + tree->add("Simpsons/Lisa"); + tree->add("Superjail/Warden"); + tree->add("Superjail/Jared"); + tree->add("Superjail/Alice"); + tree->add("Superjail/Jailbot"); + + // Start with some items closed + tree->close("Simpsons"); + tree->close("Superjail"); + } + win->end(); + win->resizable(win); + win->show(argc, argv); + return(Fl::run()); +} +#else +#include <FL/Fl.H> +#include <FL/fl_message.H> +int main(int, char**) { + fl_alert("This demo is dependent on an ABI feature.\n" + "FLTK_ABI_VERSION must be set to 10303 (or higher) in Enumerations.H"); + return 1; +} +#endif + +// +// End of "$Id$". +// diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index ba37dab3f..455aba716 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -936,7 +936,7 @@ Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item) { /// ..do stuff with each selected item.. /// } /// \endcode -/// \param[in] items The returned array of selected items. +/// \param[in] ret_items The returned array of selected items. /// \returns The number of items in the returned array. /// \see first_selected_item(), next_selected_item() /// @@ -1787,7 +1787,9 @@ Fl_Tree_Item_Reselect_Mode Fl_Tree::item_reselect_mode() const { void Fl_Tree::item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) { _prefs.item_reselect_mode(mode); } +#endif +#if FLTK_ABI_VERSION >= 10303 /// Get the 'item draw mode' used for the tree Fl_Tree_Item_Draw_Mode Fl_Tree::item_draw_mode() const { return(_prefs.item_draw_mode()); @@ -1804,7 +1806,51 @@ void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode val) { void Fl_Tree::item_draw_mode(int val) { _prefs.item_draw_mode(Fl_Tree_Item_Draw_Mode(val)); } -#endif /*FLTK_ABI_VERSION*/ + +/// Set a callback to be invoked to handle drawing the Fl_Tree_Item +/// instead of the default label drawing behavior. Lets one define +/// custom drawing behavior for Fl_Tree_Item's. eg: +/// \code +/// static void draw_item(Fl_Tree_Item *item, void *data) { +/// Fl_Tree *tree = (Fl_Tree*)data; +/// int X=item->label_x(), Y=item->label_y(), +/// W=item->label_w(), H=item->label_h(); +/// // Draw the background +/// fl_color(item->is_selected() ? tree->selection_color() : item->labelbgcolor()); +/// fl_rectf(X,Y,W,H); +/// // Draw text +/// fl_font(item->labelfont(), item->labelsize()); +/// fl_color(item->labelfgcolor()); +/// fl_draw("Some text", X+tree->labelmarginleft(),Y,W,H, FL_ALIGN_LEFT); +/// } +/// .. +/// int main() { +/// Fl_Tree *tree = new Fl_Tree(0,0,100,100); +/// tree->item_draw_callback(draw_item, (void*)tree); +/// [..] +/// \endcode +/// +/// Note: This only affects the drawing of item's labels; +/// it does not affect the drawing of widgets assigned with +/// Fl_Tree_Item::widget(). +/// +void Fl_Tree::item_draw_callback(Fl_Tree_Item_Draw_Callback *cb, void *data) { + _prefs.item_draw_callback(cb,data); +} +/// Get the current item draw callback. Returns 0 if none. +Fl_Tree_Item_Draw_Callback* Fl_Tree::item_draw_callback() const { + return(_prefs.item_draw_callback()); +} +/// Get the current item draw callback's user data. +void* Fl_Tree::item_draw_user_data() const { + return(_prefs.item_draw_user_data()); +} +/// Invoke the configured item_draw_callback(). +// Do NOT call this if no item_draw_callback() was configured. +void Fl_Tree::do_item_draw_callback(Fl_Tree_Item *o) const { + _prefs.do_item_draw_callback(o); +} +#endif /// See if \p item is currently displayed on-screen (visible within the widget). /// This can be used to detect if the item is scrolled off-screen. diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index daccbdbde..2bbbb107c 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -529,7 +529,7 @@ Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { return(0); } -static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H) { +static void draw_item_focus(Fl_Boxtype B, Fl_Color fg, Fl_Color bg, int X, int Y, int W, int H) { if (!Fl::visible_focus()) return; switch (B) { case FL_DOWN_BOX: @@ -541,7 +541,7 @@ static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H default: break; } - fl_color(fl_contrast(FL_BLACK, C)); + fl_color(fl_contrast(fg, bg)); #if defined(USE_X11) || defined(__APPLE_QUARTZ__) fl_line_style(FL_DOT); @@ -719,41 +719,51 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, prefs.openicon()->draw(icon_x,icon_y); } } - // Background for this item - // 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(),bg_x,bg_y,bg_w,bg_h,bg); - } else { // Not Selected? use plain filled rectangle - fl_color(bg); - fl_rectf(bg_x,bg_y,bg_w,bg_h); + // Draw the item +#if FLTK_ABI_VERSION >= 10303 + if ( !widget() && prefs.item_draw_callback() ) { + // Draw item using user supplied custom item draw callback + prefs.do_item_draw_callback(this); + } + else +#endif + { + // Background for this item + // 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(),bg_x,bg_y,bg_w,bg_h,bg); + } else { // Not Selected? use plain filled rectangle + fl_color(bg); + fl_rectf(bg_x,bg_y,bg_w,bg_h); + } + if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it } - if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it - } - // Draw user icon (if any) - if ( usericon() ) { - // Item has user icon? Use it - int uicon_y = item_y_center - (usericon()->h() >> 1); - usericon()->draw(uicon_x,uicon_y); - } else if ( prefs.usericon() ) { - // Prefs has user icon? Use it - int uicon_y = item_y_center - (prefs.usericon()->h() >> 1); - prefs.usericon()->draw(uicon_x,uicon_y); - } - // Draw label + // Draw user icon (if any) + if ( usericon() ) { + // Item has user icon? Use it + int uicon_y = item_y_center - (usericon()->h() >> 1); + usericon()->draw(uicon_x,uicon_y); + } else if ( prefs.usericon() ) { + // Prefs has user icon? Use it + int uicon_y = item_y_center - (prefs.usericon()->h() >> 1); + prefs.usericon()->draw(uicon_x,uicon_y); + } + // Draw label #if FLTK_ABI_VERSION >= 10301 - if ( _label && - ( !widget() || - (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) + if ( _label && + ( !widget() || + (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) #else /*FLTK_ABI_VERSION*/ - if ( _label && !widget() ) // back compat: don't draw label if widget() present + if ( _label && !widget() ) // back compat: don't draw label if widget() present #endif /*FLTK_ABI_VERSION*/ - { - fl_color(fg); - fl_font(_labelfont, _labelsize); - int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2; - fl_draw(_label, label_x, label_y); - } + { + fl_color(fg); + fl_font(_labelfont, _labelsize); + int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2; + fl_draw(_label, label_x, label_y); + } + } // end non-custom draw } // end non-child damage // Draw child FLTK widget? if ( widget() ) { @@ -766,7 +776,7 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, Fl::visible_focus() && Fl::focus() == tree && prefs.selectmode() != FL_TREE_SELECT_NONE ) { - draw_item_focus(FL_NO_BOX,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1); + draw_item_focus(FL_NO_BOX,fg,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1); } } // end drawthis } // end clipped diff --git a/src/Fl_Tree_Prefs.cxx b/src/Fl_Tree_Prefs.cxx index b52724aef..3fc9c4355 100644 --- a/src/Fl_Tree_Prefs.cxx +++ b/src/Fl_Tree_Prefs.cxx @@ -156,6 +156,10 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { _itemreselectmode = FL_TREE_SELECTABLE_ONCE; _itemdrawmode = FL_TREE_ITEM_DRAW_DEFAULT; #endif +#if FLTK_ABI_VERSION >= 10303 + _itemdrawcallback = 0; + _itemdrawuserdata = 0; +#endif // Let fltk's current 'scheme' affect defaults if ( Fl::scheme() ) { if ( strcmp(Fl::scheme(), "gtk+") == 0 ) { |
