summaryrefslogtreecommitdiff
path: root/examples/tree-custom-draw-items.cxx
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2014-01-20 21:23:24 +0000
committerGreg Ercolano <erco@seriss.com>2014-01-20 21:23:24 +0000
commitabdc83470530c5fa8e15370a2032093cd91dace7 (patch)
treedea9946420c6788e8fde4bcabd839e599138666b /examples/tree-custom-draw-items.cxx
parentaa71c2f6e1d7c78acc4eb7c6603761423d859390 (diff)
o Added draw_item_content() to Fl_Tree_Item,
a volatile method that can be overridden by subclasses to take drawing control of tree item's content. This replaces the old "item_draw_callback()" technique added a few months ago as an ABI feature; turned out the new technique is a better way to go. o The examples/tree-custom-draw-items.cxx demo adjusted accordingly. o Added missing docs for some methods that had none, including label_[xywh](). o Added related methods needed to implement this, including: Fl_Tree_Item_Array::replace() Fl_Tree_Item::replace() Fl_Tree::root(item) Fl_Tree::add() variations Fl_Tree_Item::drawbgcolor()/drawfgcolor() o Carefully worked the FLTK_ABI_VERSION macros so as to be ABI compatible with 1.3.0. o Verified 1.3.0 ABI compatibility with ABI Compliance Checker 1.99.8.5: http://ispras.linuxbase.org/index.php/ABI_compliance_checker git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10071 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'examples/tree-custom-draw-items.cxx')
-rw-r--r--examples/tree-custom-draw-items.cxx163
1 files changed, 127 insertions, 36 deletions
diff --git a/examples/tree-custom-draw-items.cxx b/examples/tree-custom-draw-items.cxx
index 57ac85c31..fbee62700 100644
--- a/examples/tree-custom-draw-items.cxx
+++ b/examples/tree-custom-draw-items.cxx
@@ -17,68 +17,159 @@
// http://www.fltk.org/str.php
//
#include <stdio.h>
-#include <math.h> // sin(3)
+#include <time.h> /* ctime.. */
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Tree.H>
+#ifndef MAX
+#define MAX(a,b) ((a)>(b))?(a):(b)
+#endif
+
#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);
+// DERIVE CUSTOM CLASS FROM Fl_Tree_Item TO IMPLEMENT SHOWING THE TIME OF DAY
+// This demonstrates that item content can be dynamic and highly customized.
+//
+class MyTimeItem : public Fl_Tree_Item {
+ const char *time_format;
+protected:
+ // Remove trailing crlf
+ const char* StripCrlf(char *s)
+ { char *ss = strchr(s, '\n'); if (ss) *ss = 0; return s; }
+ const struct tm* GetTimeStruct() {
+ time_t t = time(NULL);
+ if ( strcmp(time_format, "Local") == 0 ) return localtime(&t);
+ if ( strcmp(time_format, "GMT" ) == 0 ) return gmtime(&t);
+ return 0;
+ }
+public:
+ MyTimeItem(Fl_Tree *tree, const char *time_format) : Fl_Tree_Item(tree) {
+ label(time_format);
+ this->time_format = time_format;
+ }
+ // Handle custom drawing of the item
+ // Fl_Tree has already handled drawing everything to the left
+ // of the label area, including any 'user icon', collapse buttons,
+ // connector lines, etc.
+ //
+ // All we're responsible for is drawing the 'label' area of the item
+ // and it's background. Fl_Tree gives us a hint as to what the
+ // foreground and background colors should be via the fg/bg parameters,
+ // and whether we're supposed to render anything or not.
+ //
+ // The only other thing we must do is return the maximum X position
+ // of scrollable content, i.e. the right most X position of content
+ // that we want the user to be able to use the horizontal scrollbar
+ // to reach.
+ //
+ int draw_item_content(int render) {
+ Fl_Color fg = drawfgcolor();
+ Fl_Color bg = drawbgcolor();
+ // Show the date and time as two small strings
+ // one on top of the other in a single item.
+ //
+ // Our item's label dimensions
+ int X = label_x(), Y = label_y(),
+ W = label_w(), H = label_h();
+ // Render background
+ if ( render ) {
+ if ( is_selected() ) { // Selected? Use selectbox() style
+ fl_draw_box(prefs().selectbox(),X,Y,W,H,bg);
+ } else { // Not Selected? use plain filled rectangle
+ fl_color(bg); fl_rectf(X,Y,W,H);
+ }
+ }
+ // Render the label
+ if ( render ) {
+ fl_color(fg);
+ if ( label() ) fl_draw(label(), X,Y,W,H, FL_ALIGN_LEFT);
+ }
+ int lw=0, lh=0;
+ if ( label() ) {
+ lw=0; lh=0; fl_measure(label(), lw, lh);
+ }
+ X += lw + 8;
+ // Draw some red/grn/blu boxes
+ if ( render ) {
+ fl_color(FL_RED); fl_rectf(X+0, Y+2, 10, H-4);
+ fl_color(FL_GREEN); fl_rectf(X+10, Y+2, 10, H-4);
+ fl_color(FL_BLUE); fl_rectf(X+20, Y+2, 10, H-4);
+ }
+ X += 35;
+ // Render the date and time, one over the other
+ fl_font(labelfont(), 8); // small font
+ const struct tm *tm = GetTimeStruct();
+ char s[80];
+ sprintf(s, "Date: %02d/%02d/%02d", tm->tm_mon+1, tm->tm_mday, tm->tm_year % 100);
+ lw=0, lh=0; fl_measure(s, lw, lh); // get box around text (including white space)
+ if ( render ) fl_draw(s, X,Y+4,W,H, FL_ALIGN_LEFT|FL_ALIGN_TOP);
+ sprintf(s, "Time: %02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
+ if ( render ) fl_draw(s, X,Y+H/2,W,H/2, FL_ALIGN_LEFT|FL_ALIGN_TOP);
+ int lw2=0, lh2=0; fl_measure(s, lw2, lh2);
+ X += MAX(lw, lw2);
+ return X; // return right most edge of what we've rendered
}
+};
+
+// TIMER TO HANDLE DYNAMIC CONTENT IN THE TREE
+void Timer_CB(void *data) {
+ Fl_Tree *tree = (Fl_Tree*)data;
+ tree->redraw(); // keeps time updated
+ Fl::repeat_timeout(0.2, Timer_CB, data);
}
int main(int argc, char *argv[]) {
Fl::scheme("gtk+");
- Fl_Double_Window *win = new Fl_Double_Window(250, 400, "Simple Tree");
+ Fl_Double_Window *win = new Fl_Double_Window(350, 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
+ tree->showroot(0); // don't show root of tree
+ tree->selectmode(FL_TREE_SELECT_MULTI); // multiselect
// 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");
+ {
+ MyTimeItem *myitem;
+ myitem = new MyTimeItem(tree, "Local"); // create custom item
+ myitem->labelsize(20);
+ tree->add("Time Add Item/Local", myitem);
+
+ myitem = new MyTimeItem(tree, "GMT"); // create custom item
+ myitem->labelsize(20);
+ tree->add("Time Add Item/GMT", myitem);
+ }
+ // 'Replace' approach
+ {
+ Fl_Tree_Item *item;
+ MyTimeItem *myitem;
+ item = tree->add("Time Replace Item/Local Time");
+ // Replace the 'Local' item with our own
+ myitem = new MyTimeItem(tree, "Local"); // create custom item
+ myitem->labelsize(20);
+ item->replace(myitem); // replace normal item with custom
+
+ item = tree->add("Time Replace Item/GMT Time");
+ // Replace the 'GMT' item with our own
+ myitem = new MyTimeItem(tree, "GMT"); // create custom item
+ myitem->labelsize(20);
+ item->replace(myitem); // replace normal item with custom
+ }
tree->add("Superjail/Warden");
tree->add("Superjail/Jared");
tree->add("Superjail/Alice");
tree->add("Superjail/Jailbot");
+ tree->show_self();
+
// Start with some items closed
- tree->close("Simpsons");
tree->close("Superjail");
+
+ // Set up a timer to keep time in tree updated
+ Fl::add_timeout(0.2, Timer_CB, (void*)tree);
}
win->end();
win->resizable(win);