1 //
2 // "$Id$"
3 //
4 //	Demonstrate Fl_Tree custom item draw callback. - erco 11/09/2013
5 //
6 // Copyright 2013 Greg Ercolano.
7 // Copyright 1998-2013 by Bill Spitzak and others.
8 //
9 // This library is free software. Distribution and use rights are outlined in
10 // the file "COPYING" which should have been included with this file.  If this
11 // file is missing or damaged, see the license at:
12 //
13 //     http://www.fltk.org/COPYING.php
14 //
15 // Please report all bugs and problems on the following page:
16 //
17 //     http://www.fltk.org/str.php
18 //
19 #include <stdio.h>
20 #include <time.h>		/* ctime.. */
21 #include <FL/Fl.H>
22 #include <FL/Fl_Double_Window.H>
23 #include <FL/Fl_Tree.H>
24 
25 #ifndef MAX
26 #define MAX(a,b) ((a)>(b))?(a):(b)
27 #endif
28 
29 #if FLTK_ABI_VERSION >= 10303
30 // DERIVE CUSTOM CLASS FROM Fl_Tree_Item TO IMPLEMENT SHOWING THE TIME OF DAY
31 //     This demonstrates that item content can be dynamic and highly customized.
32 //
33 class MyTimeItem : public Fl_Tree_Item {
34   const char *time_format;
35 protected:
36   // Remove trailing crlf
StripCrlf(char * s)37   const char* StripCrlf(char *s)
38     { char *ss = strchr(s, '\n'); if (ss) *ss = 0; return s; }
GetTimeStruct()39   const struct tm* GetTimeStruct() {
40     time_t t = time(NULL);
41     if ( strcmp(time_format, "Local") == 0 ) return localtime(&t);
42     if ( strcmp(time_format, "GMT"  ) == 0 ) return gmtime(&t);
43     return 0;
44   }
45 public:
MyTimeItem(Fl_Tree * tree,const char * time_format)46   MyTimeItem(Fl_Tree *tree, const char *time_format) : Fl_Tree_Item(tree) {
47     label(time_format);
48     this->time_format = time_format;
49   }
50   // Handle custom drawing of the item
51   //    Fl_Tree has already handled drawing everything to the left
52   //    of the label area, including any 'user icon', collapse buttons,
53   //    connector lines, etc.
54   //
55   //    All we're responsible for is drawing the 'label' area of the item
56   //    and it's background. Fl_Tree gives us a hint as to what the
57   //    foreground and background colors should be via the fg/bg parameters,
58   //    and whether we're supposed to render anything or not.
59   //
60   //    The only other thing we must do is return the maximum X position
61   //    of scrollable content, i.e. the right most X position of content
62   //    that we want the user to be able to use the horizontal scrollbar
63   //    to reach.
64   //
draw_item_content(int render)65   int draw_item_content(int render) {
66     Fl_Color fg = drawfgcolor();
67     Fl_Color bg = drawbgcolor();
68     //    Show the date and time as two small strings
69     //    one on top of the other in a single item.
70     //
71     // Our item's label dimensions
72     int X = label_x(), Y = label_y(),
73         W = label_w(), H = label_h();
74     // Render background
75     if ( render ) {
76       if ( is_selected() ) {			// Selected? Use selectbox() style
77         fl_draw_box(prefs().selectbox(),X,Y,W,H,bg);
78       } else {					// Not Selected? use plain filled rectangle
79         fl_color(bg); fl_rectf(X,Y,W,H);
80       }
81     }
82     // Render the label
83     if ( render ) {
84       fl_color(fg);
85       if ( label() ) fl_draw(label(), X,Y,W,H, FL_ALIGN_LEFT);
86     }
87     int lw=0, lh=0;
88     if ( label() ) {
89       lw=0; lh=0; fl_measure(label(), lw, lh);
90     }
91     X += lw + 8;
92     // Draw some red/grn/blu boxes
93     if ( render ) {
94       fl_color(FL_RED);   fl_rectf(X+0,  Y+2, 10, H-4);
95       fl_color(FL_GREEN); fl_rectf(X+10, Y+2, 10, H-4);
96       fl_color(FL_BLUE);  fl_rectf(X+20, Y+2, 10, H-4);
97     }
98     X += 35;
99     // Render the date and time, one over the other
100     fl_font(labelfont(), 8);			// small font
101     const struct tm *tm = GetTimeStruct();
102     char s[80];
103     sprintf(s, "Date: %02d/%02d/%02d", tm->tm_mon+1, tm->tm_mday, tm->tm_year % 100);
104     lw=0, lh=0; fl_measure(s, lw, lh);		// get box around text (including white space)
105     if ( render ) fl_draw(s, X,Y+4,W,H, FL_ALIGN_LEFT|FL_ALIGN_TOP);
106     sprintf(s, "Time: %02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
107     if ( render ) fl_draw(s, X,Y+H/2,W,H/2, FL_ALIGN_LEFT|FL_ALIGN_TOP);
108     int lw2=0, lh2=0; fl_measure(s, lw2, lh2);
109     X += MAX(lw, lw2);
110     return X;			// return right most edge of what we've rendered
111   }
112 };
113 
114 // TIMER TO HANDLE DYNAMIC CONTENT IN THE TREE
Timer_CB(void * data)115 void Timer_CB(void *data) {
116   Fl_Tree *tree = (Fl_Tree*)data;
117   tree->redraw();	// keeps time updated
118   Fl::repeat_timeout(0.2, Timer_CB, data);
119 }
120 
main(int argc,char * argv[])121 int main(int argc, char *argv[]) {
122   Fl::scheme("gtk+");
123   Fl_Double_Window *win = new Fl_Double_Window(350, 400, "Simple Tree");
124   win->begin();
125   {
126     // Create the tree
127     Fl_Tree *tree = new Fl_Tree(0, 0, win->w(), win->h());
128     tree->showroot(0);				// don't show root of tree
129     tree->selectmode(FL_TREE_SELECT_MULTI);	// multiselect
130 
131     // Add some items
132     tree->add("Flintstones/Fred");
133     tree->add("Flintstones/Wilma");
134     tree->add("Flintstones/Pebbles");
135     {
136       MyTimeItem *myitem;
137       myitem = new MyTimeItem(tree, "Local");	// create custom item
138       myitem->labelsize(20);
139       tree->add("Time Add Item/Local", myitem);
140 
141       myitem = new MyTimeItem(tree, "GMT");	// create custom item
142       myitem->labelsize(20);
143       tree->add("Time Add Item/GMT", myitem);
144     }
145     // 'Replace' approach
146     {
147       Fl_Tree_Item *item;
148       MyTimeItem *myitem;
149       item = tree->add("Time Replace Item/Local Time");
150       // Replace the 'Local' item with our own
151       myitem = new MyTimeItem(tree, "Local");	// create custom item
152       myitem->labelsize(20);
153       item->replace(myitem);			// replace normal item with custom
154 
155       item = tree->add("Time Replace Item/GMT Time");
156       // Replace the 'GMT' item with our own
157       myitem = new MyTimeItem(tree, "GMT");	// create custom item
158       myitem->labelsize(20);
159       item->replace(myitem);			// replace normal item with custom
160     }
161     tree->add("Superjail/Warden");
162     tree->add("Superjail/Jared");
163     tree->add("Superjail/Alice");
164     tree->add("Superjail/Jailbot");
165 
166     tree->show_self();
167 
168     // Start with some items closed
169     tree->close("Superjail");
170 
171     // Set up a timer to keep time in tree updated
172     Fl::add_timeout(0.2, Timer_CB, (void*)tree);
173   }
174   win->end();
175   win->resizable(win);
176   win->show(argc, argv);
177   return(Fl::run());
178 }
179 #else
180 #include <FL/Fl.H>
181 #include <FL/fl_message.H>
main(int,char **)182 int main(int, char**) {
183   fl_alert("This demo is dependent on an ABI feature.\n"
184            "FLTK_ABI_VERSION must be set to 10303 (or higher) in Enumerations.H");
185   return 1;
186 }
187 #endif
188 
189 //
190 // End of "$Id$".
191 //
192