Tweak themes for more color consistency.
[ntk.git] / test / demo.cxx
blob49e544c3ed1705412c4e7f5ba1ccd2420f25b30c
1 //
2 // "$Id: demo.cxx 8252 2011-01-11 10:36:44Z manolo $"
3 //
4 // Main demo program for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #if defined(WIN32) && !defined(__CYGWIN__)
32 # include <direct.h>
33 # ifndef __WATCOMC__
34 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
35 // on Windows, which is supposed to be POSIX compliant...
36 # define chdir _chdir
37 # define putenv _putenv
38 # endif // !__WATCOMC__
39 #elif defined USING_XCODE
40 #include <ApplicationServices/ApplicationServices.h>
41 #include <unistd.h> // for chdir()
42 #include <stdio.h>
43 #include <stdlib.h> // for system()
44 #include <string.h>
45 #else
46 # include <unistd.h>
47 #endif
48 #include <FL/Fl.H>
49 #include <FL/Fl_Double_Window.H>
50 #include <FL/Fl_Box.H>
51 #include <FL/Fl_Button.H>
52 #include <FL/Fl_Choice.H>
53 #include <FL/filename.H>
54 #include <FL/x.H>
56 /* The form description */
58 void doexit(Fl_Widget *, void *);
59 void doback(Fl_Widget *, void *);
60 void dobut(Fl_Widget *, long);
61 void doscheme(Fl_Choice *c, void *) {
62 Fl::scheme(c->text(c->value()));
65 Fl_Double_Window *form;
66 Fl_Button *but[9];
68 void create_the_forms() {
69 Fl_Widget *obj;
70 form = new Fl_Double_Window(350, 440);
71 obj = new Fl_Box(FL_FRAME_BOX,10,15,330,40,"FLTK Demonstration");
72 obj->color(FL_GRAY-4);
73 obj->labelsize(24);
74 obj->labelfont(FL_BOLD);
75 obj->labeltype(FL_ENGRAVED_LABEL);
76 obj = new Fl_Box(FL_FRAME_BOX,10,65,330,330,0);
77 obj->color(FL_GRAY-8);
78 obj = new Fl_Button(280,405,60,25,"Exit");
79 obj->callback(doexit);
80 Fl_Choice *choice = new Fl_Choice(75, 405, 100, 25, "Scheme:");
81 choice->labelfont(FL_HELVETICA_BOLD);
82 choice->add("none");
83 choice->add("gtk+");
84 choice->add("plastic");
85 choice->callback((Fl_Callback *)doscheme);
86 Fl::scheme(NULL);
87 if (!Fl::scheme()) choice->value(0);
88 else if (!strcmp(Fl::scheme(), "gtk+")) choice->value(1);
89 else choice->value(2);
90 obj = new Fl_Button(10,15,330,380); obj->type(FL_HIDDEN_BUTTON);
91 obj->callback(doback);
92 obj = but[0] = new Fl_Button( 30, 85,90,90);
93 obj = but[1] = new Fl_Button(130, 85,90,90);
94 obj = but[2] = new Fl_Button(230, 85,90,90);
95 obj = but[3] = new Fl_Button( 30,185,90,90);
96 obj = but[4] = new Fl_Button(130,185,90,90);
97 obj = but[5] = new Fl_Button(230,185,90,90);
98 obj = but[6] = new Fl_Button( 30,285,90,90);
99 obj = but[7] = new Fl_Button(130,285,90,90);
100 obj = but[8] = new Fl_Button(230,285,90,90);
101 for (int i=0; i<9; i++) {
102 but[i]->align(FL_ALIGN_WRAP);
103 but[i]->callback(dobut, i);
105 form->end();
108 /* Maintaining and building up the menus. */
110 typedef struct {
111 char name[64];
112 int numb;
113 char iname[9][64];
114 char icommand[9][64];
115 } MENU;
117 #define MAXMENU 32
119 MENU menus[MAXMENU];
120 int mennumb = 0;
122 int find_menu(const char* nnn)
123 /* Returns the number of a given menu name. */
125 int i;
126 for (i=0; i<mennumb; i++)
127 if (strcmp(menus[i].name,nnn) == 0) return i;
128 return -1;
131 void create_menu(const char* nnn)
132 /* Creates a new menu with name nnn */
134 if (mennumb == MAXMENU -1) return;
135 strcpy(menus[mennumb].name,nnn);
136 menus[mennumb].numb = 0;
137 mennumb++;
140 void addto_menu(const char* men, const char* item, const char* comm)
141 /* Adds an item to a menu */
143 int n = find_menu(men);
144 if (n<0) { create_menu(men); n = find_menu(men); }
145 if (menus[n].numb == 9) return;
146 strcpy(menus[n].iname[menus[n].numb],item);
147 strcpy(menus[n].icommand[menus[n].numb],comm);
148 menus[n].numb++;
151 /* Button to Item conversion and back. */
153 int b2n[][9] = {
154 { -1, -1, -1, -1, 0, -1, -1, -1, -1},
155 { -1, -1, -1, 0, -1, 1, -1, -1, -1},
156 { 0, -1, -1, -1, 1, -1, -1, -1, 2},
157 { 0, -1, 1, -1, -1, -1, 2, -1, 3},
158 { 0, -1, 1, -1, 2, -1, 3, -1, 4},
159 { 0, -1, 1, 2, -1, 3, 4, -1, 5},
160 { 0, -1, 1, 2, 3, 4, 5, -1, 6},
161 { 0, 1, 2, 3, -1, 4, 5, 6, 7},
162 { 0, 1, 2, 3, 4, 5, 6, 7, 8}
164 int n2b[][9] = {
165 { 4, -1, -1, -1, -1, -1, -1, -1, -1},
166 { 3, 5, -1, -1, -1, -1, -1, -1, -1},
167 { 0, 4, 8, -1, -1, -1, -1, -1, -1},
168 { 0, 2, 6, 8, -1, -1, -1, -1, -1},
169 { 0, 2, 4, 6, 8, -1, -1, -1, -1},
170 { 0, 2, 3, 5, 6, 8, -1, -1, -1},
171 { 0, 2, 3, 4, 5, 6, 8, -1, -1},
172 { 0, 1, 2, 3, 5, 6, 7, 8, -1},
173 { 0, 1, 2, 3, 4, 5, 6, 7, 8}
176 int but2numb(int bnumb, int maxnumb)
177 /* Transforms a button number to an item number when there are
178 maxnumb items in total. -1 if the button should not exist. */
179 { return b2n[maxnumb][bnumb]; }
181 int numb2but(int inumb, int maxnumb)
182 /* Transforms an item number to a button number when there are
183 maxnumb items in total. -1 if the item should not exist. */
184 { return n2b[maxnumb][inumb]; }
186 /* Pushing and Popping menus */
188 char stack[64][32];
189 int stsize = 0;
191 void push_menu(const char* nnn)
192 /* Pushes a menu to be visible */
194 int n,i,bn;
195 int men = find_menu(nnn);
196 if (men < 0) return;
197 n = menus[men].numb;
198 for (i=0; i<9; i++) but[i]->hide();
199 for (i=0; i<n; i++)
201 bn = numb2but(i,n-1);
202 but[bn]->show();
203 but[bn]->label(menus[men].iname[i]);
204 if (menus[men].icommand[i][0] != '@') but[bn]->tooltip(menus[men].icommand[i]);
205 else but[bn]->tooltip(0);
207 if (stack[stsize]!=nnn)
208 strcpy(stack[stsize],nnn);
209 stsize++;
212 void pop_menu()
213 /* Pops a menu */
215 if (stsize<=1) return;
216 stsize -= 2;
217 push_menu(stack[stsize]);
220 /* The callback Routines */
222 void dobut(Fl_Widget *, long arg)
223 /* handles a button push */
225 int men = find_menu(stack[stsize-1]);
226 int n = menus[men].numb;
227 int bn = but2numb( (int) arg, n-1);
228 if (menus[men].icommand[bn][0] == '@')
229 push_menu(menus[men].icommand[bn]);
230 else {
232 #ifdef WIN32
233 STARTUPINFO suInfo; // Process startup information
234 PROCESS_INFORMATION prInfo; // Process information
236 memset(&suInfo, 0, sizeof(suInfo));
237 suInfo.cb = sizeof(suInfo);
239 int icommand_length = strlen(menus[men].icommand[bn]);
241 char* copy_of_icommand = new char[icommand_length+1];
242 strcpy(copy_of_icommand,menus[men].icommand[bn]);
244 // On WIN32 the .exe suffix needs to be appended to the command
245 // whilst leaving any additional parameters unchanged - this
246 // is required to handle the correct conversion of cases such as :
247 // `../fluid/fluid valuators.fl' to '../fluid/fluid.exe valuators.fl'.
249 // skip leading spaces.
250 char* start_command = copy_of_icommand;
251 while(*start_command == ' ') ++start_command;
253 // find the space between the command and parameters if one exists.
254 char* start_parameters = strchr(start_command,' ');
256 char* command = new char[icommand_length+6]; // 6 for extra 'd.exe\0'
258 if (start_parameters==NULL) { // no parameters required.
259 # ifdef _DEBUG
260 sprintf(command, "%sd.exe", start_command);
261 # else
262 sprintf(command, "%s.exe", start_command);
263 # endif // _DEBUG
264 } else { // parameters required.
265 // break the start_command at the intermediate space between
266 // start_command and start_parameters.
267 *start_parameters = 0;
268 // move start_paremeters to skip over the intermediate space.
269 ++start_parameters;
271 # ifdef _DEBUG
272 sprintf(command, "%sd.exe %s", start_command, start_parameters);
273 # else
274 sprintf(command, "%s.exe %s", start_command, start_parameters);
275 # endif // _DEBUG
278 CreateProcess(NULL, command, NULL, NULL, FALSE,
279 NORMAL_PRIORITY_CLASS, NULL, NULL, &suInfo, &prInfo);
281 delete[] command;
282 delete[] copy_of_icommand;
284 #elif defined USING_XCODE
285 char *cmd = strdup(menus[men].icommand[bn]);
286 char *arg = strchr(cmd, ' ');
288 char command[2048], path[2048], app_path[2048];
290 // this neat litle block of code ensures that the current directory is set
291 // to the location of the Demo application.
292 CFBundleRef app = CFBundleGetMainBundle();
293 CFURLRef url = CFBundleCopyBundleURL(app);
294 CFStringRef cc_app_path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
295 CFStringGetCString(cc_app_path, app_path, 2048, kCFStringEncodingUTF8);
296 if (*app_path) {
297 char *n = strrchr(app_path, '/');
298 if (n) {
299 *n = 0;
300 chdir(app_path);
304 if (arg) {
305 *arg = 0;
306 if (strcmp(cmd, "../fluid/fluid")==0) {
307 fl_filename_absolute(path, 2048, "../../../../test/");
308 sprintf(command, "open Fluid.app --args %s%s", path, arg+1);
309 } else {
310 fl_filename_absolute(path, 2048, "../../../../test/");
311 sprintf(command, "open %s.app --args %s%s", cmd, path, arg+1);
313 } else {
314 sprintf(command, "open %s.app", cmd);
316 // puts(command);
317 system(command);
319 free(cmd);
320 #else // NON WIN32 systems.
322 int icommand_length = strlen(menus[men].icommand[bn]);
323 char* command = new char[icommand_length+5]; // 5 for extra './' and ' &\0'
325 sprintf(command, "./%s &", menus[men].icommand[bn]);
326 if (system(command)==-1) { /* ignore */ }
328 delete[] command;
329 #endif // WIN32
333 void doback(Fl_Widget *, void *) {pop_menu();}
335 void doexit(Fl_Widget *, void *) {exit(0);}
337 int load_the_menu(const char* fname)
338 /* Loads the menu file. Returns whether successful. */
340 FILE *fin = 0;
341 char line[256], mname[64],iname[64],cname[64];
342 int i, j;
343 fin = fl_fopen(fname,"r");
344 #if defined ( USING_XCODE )
345 if (fin == NULL) {
346 // mac os bundle menu detection:
347 char* pos = strrchr(fname,'/');
348 if (!pos) return 0;
349 *pos='\0';
350 pos = strrchr(fname,'/');
351 if (!pos) return 0;
352 strcpy(pos,"/Resources/demo.menu");
353 fin = fl_fopen(fname,"r");
355 #endif
356 if (fin == NULL) {
357 return 0;
359 for (;;) {
360 if (fgets(line,256,fin) == NULL) break;
361 // remove all carriage returns that Cygwin may have inserted
362 char *s = line, *d = line;
363 for (;;++d) {
364 while (*s=='\r') s++;
365 *d = *s++;
366 if (!*d) break;
368 // interprete the line
369 j = 0; i = 0;
370 while (line[i] == ' ' || line[i] == '\t') i++;
371 if (line[i] == '\n') continue;
372 if (line[i] == '#') continue;
373 while (line[i] != ':' && line[i] != '\n') mname[j++] = line[i++];
374 mname[j] = '\0';
375 if (line[i] == ':') i++;
376 j = 0;
377 while (line[i] != ':' && line[i] != '\n')
379 if (line[i] == '\\') {
380 i++;
381 if (line[i] == 'n') iname[j++] = '\n';
382 else iname[j++] = line[i];
383 i++;
384 } else
385 iname[j++] = line[i++];
387 iname[j] = '\0';
388 if (line[i] == ':') i++;
389 j = 0;
390 while (line[i] != ':' && line[i] != '\n') cname[j++] = line[i++];
391 cname[j] = '\0';
392 addto_menu(mname,iname,cname);
394 fclose(fin);
395 return 1;
398 int main(int argc, char **argv) {
399 putenv((char *)"FLTK_DOCDIR=../documentation/html");
400 char buf[FL_PATH_MAX];
401 strcpy(buf, argv[0]);
402 #if ( defined _MSC_VER || defined __MWERKS__ ) && defined _DEBUG
403 // MS_VisualC appends a 'd' to debugging executables. remove it.
404 fl_filename_setext( buf, "" );
405 buf[ strlen(buf)-1 ] = 0;
406 #endif
407 fl_filename_setext(buf,".menu");
408 const char *fname = buf;
409 int i = 0;
410 if (!Fl::args(argc,argv,i) || i < argc-1)
411 Fl::fatal("Usage: %s <switches> <menufile>\n%s",argv[0],Fl::help);
412 if (i < argc) fname = argv[i];
414 create_the_forms();
416 if (!load_the_menu(fname)) Fl::fatal("Can't open %s",fname);
417 if (buf!=fname)
418 strcpy(buf,fname);
419 const char *c = fl_filename_name(buf);
420 if (c > buf) {
421 buf[c-buf] = 0;
422 if (chdir(buf)==-1) { /* ignore */ }
424 push_menu("@main");
425 form->show(argc,argv);
426 Fl::run();
427 return 0;
431 // End of "$Id: demo.cxx 8252 2011-01-11 10:36:44Z manolo $".