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