|
@@ -0,0 +1,555 @@
|
|
1
|
+#include <FL/Fl.H>
|
|
2
|
+#include <FL/Fl_Widget.H>
|
|
3
|
+#include <FL/Fl_Double_Window.H>
|
|
4
|
+#include <FL/Fl_Text_Buffer.H>
|
|
5
|
+#include <FL/Fl_Text_Display.H>
|
|
6
|
+#include <FL/Fl_Tabs.H>
|
|
7
|
+#include <FL/Fl_Menu_Item.H>
|
|
8
|
+#include <FL/Fl_Menu_Bar.H>
|
|
9
|
+#include <FL/Fl_Button.H>
|
|
10
|
+#include <FL/Fl_Check_Button.H>
|
|
11
|
+#include <FL/Fl_Menu_Button.H>
|
|
12
|
+#include <FL/Fl_Value_Input.H>
|
|
13
|
+#include <FL/Fl_Value_Slider.H>
|
|
14
|
+#include <FL/Fl_Input.H>
|
|
15
|
+#include <FL/Fl_Box.H>
|
|
16
|
+#include <FL/Fl_File_Chooser.H>
|
|
17
|
+#include <FL/fl_draw.H>
|
|
18
|
+
|
|
19
|
+#include "Fl_Splitter.h"
|
|
20
|
+
|
|
21
|
+#include "cmPrefix.h"
|
|
22
|
+#include "cmGlobal.h"
|
|
23
|
+#include "cmRpt.h"
|
|
24
|
+#include "cmErr.h"
|
|
25
|
+#include "cmCtx.h"
|
|
26
|
+#include "cmMem.h"
|
|
27
|
+#include "cmMallocDebug.h"
|
|
28
|
+#include "cmFileSys.h"
|
|
29
|
+#include "cmThread.h"
|
|
30
|
+
|
|
31
|
+#include "appErr.h"
|
|
32
|
+#include "app.h"
|
|
33
|
+
|
|
34
|
+class drawWnd : public Fl_Widget
|
|
35
|
+{
|
|
36
|
+public:
|
|
37
|
+ drawWnd(app* ap, int x, int y, int w, int h, const char* label = NULL );
|
|
38
|
+ virtual ~drawWnd();
|
|
39
|
+
|
|
40
|
+ virtual int handle(int event);
|
|
41
|
+ virtual void resize(int x, int y, int w, int h );
|
|
42
|
+
|
|
43
|
+protected:
|
|
44
|
+ virtual void draw();
|
|
45
|
+
|
|
46
|
+private:
|
|
47
|
+ app* _app;
|
|
48
|
+};
|
|
49
|
+
|
|
50
|
+drawWnd::drawWnd(app* ap, int x, int y, int w, int h, const char* label )
|
|
51
|
+ : Fl_Widget(x,y,w,h,label),
|
|
52
|
+ _app(ap)
|
|
53
|
+{}
|
|
54
|
+
|
|
55
|
+drawWnd::~drawWnd()
|
|
56
|
+{}
|
|
57
|
+
|
|
58
|
+int drawWnd::handle(int event)
|
|
59
|
+{
|
|
60
|
+ switch(event)
|
|
61
|
+ {
|
|
62
|
+ case FL_PUSH:
|
|
63
|
+ {
|
|
64
|
+ const char* label;
|
|
65
|
+ switch( Fl::event_button() )
|
|
66
|
+ {
|
|
67
|
+ case FL_LEFT_MOUSE: label = "left"; break;
|
|
68
|
+ case FL_RIGHT_MOUSE: label = "right"; break;
|
|
69
|
+ case FL_MIDDLE_MOUSE: label = "middle"; break;
|
|
70
|
+ default:
|
|
71
|
+ label = "none";
|
|
72
|
+ }
|
|
73
|
+
|
|
74
|
+ _app->print("%i %i %s\n",Fl::event_x(),Fl::event_y(),label);
|
|
75
|
+ }
|
|
76
|
+ break;
|
|
77
|
+
|
|
78
|
+ default:
|
|
79
|
+ return Fl_Widget::handle(event);
|
|
80
|
+ }
|
|
81
|
+
|
|
82
|
+ return 1;
|
|
83
|
+}
|
|
84
|
+
|
|
85
|
+void drawWnd::resize(int x, int y, int w, int h )
|
|
86
|
+{
|
|
87
|
+ // must call base to make size change
|
|
88
|
+ Fl_Widget::resize(x,y,w,h);
|
|
89
|
+}
|
|
90
|
+
|
|
91
|
+void drawWnd::draw()
|
|
92
|
+{
|
|
93
|
+ int offs = 10;
|
|
94
|
+ //fl_draw_box(FL_DOWN_BOX,x()+10,y()+10,w()-20,h()-20,FL_RED);
|
|
95
|
+ //fl_frame("XXXX",x()+offs,y()+offs,w()-2*offs,h()-2*offs);
|
|
96
|
+ fl_line_style(FL_SOLID,1,NULL);
|
|
97
|
+ fl_color(FL_RED);
|
|
98
|
+ fl_line(x()+offs,y()+offs,x()+w()-offs,y()+h()-offs);
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+ int x = w()/2;
|
|
102
|
+ int y = h()/2;
|
|
103
|
+
|
|
104
|
+ fl_color(FL_BLACK);
|
|
105
|
+ fl_draw(90,"string",x,y);
|
|
106
|
+
|
|
107
|
+ // XXXXXXX
|
|
108
|
+ // X00000X
|
|
109
|
+ // X00000X
|
|
110
|
+ // X00X00X
|
|
111
|
+ // X00000X
|
|
112
|
+ // X00000X
|
|
113
|
+ // XXXXXXX
|
|
114
|
+
|
|
115
|
+ fl_rect(x-3,y-3,7,7);
|
|
116
|
+ fl_point(x,y);
|
|
117
|
+}
|
|
118
|
+
|
|
119
|
+//----------------------------------------------------------------------------------------------------
|
|
120
|
+//----------------------------------------------------------------------------------------------------
|
|
121
|
+//----------------------------------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+app::app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char* label, int argc, char* argv[])
|
|
124
|
+ : Fl_Double_Window(w,h,label), _timerPeriodSecs(0),
|
|
125
|
+ _ctx(ctx), _splt(NULL),_buf(NULL),_con(NULL),_tabs(NULL),_menu(NULL),
|
|
126
|
+ _printqH(printqH),_printFl(0)
|
|
127
|
+{
|
|
128
|
+
|
|
129
|
+ // install a callback to cleanup when the app window closes
|
|
130
|
+ // (the btn and menu callbacks also rely on a pointer to 'this' being found in app.user_data()
|
|
131
|
+ // see _getApp())
|
|
132
|
+ callback(_s_callback,this);
|
|
133
|
+
|
|
134
|
+ // the main window is divided between the menu bar on top
|
|
135
|
+ // and a horizontal splitter on the bottom
|
|
136
|
+ begin();
|
|
137
|
+ createMenu(w,kMenuH);
|
|
138
|
+ _splt = new Fl_HSplitter(0, kMenuH, w, h-kStatusH, h-kStatusH-100);
|
|
139
|
+ end();
|
|
140
|
+
|
|
141
|
+ // Create a text display object for console output and
|
|
142
|
+ // add it to the lower splitter area
|
|
143
|
+ _buf = new Fl_Text_Buffer();
|
|
144
|
+ _con = new Fl_Text_Display(_splt->container2->x(),_splt->container2->y(),_splt->container2->w(),_splt->container2->h());
|
|
145
|
+ _con->buffer(_buf);
|
|
146
|
+ _splt->container2->add(_con);
|
|
147
|
+
|
|
148
|
+ // create tabbed windows
|
|
149
|
+ const char* titles[] = { "Title 1", "Title 2" };
|
|
150
|
+ _create_tabs(2,titles);
|
|
151
|
+
|
|
152
|
+ // make the splitter the resizable group element (thereby making the menu non-resizable).
|
|
153
|
+ // see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
|
|
154
|
+ resizable(_splt);
|
|
155
|
+ show(argc, argv);
|
|
156
|
+
|
|
157
|
+ // The application is now visible.
|
|
158
|
+ // direct all output to the console window
|
|
159
|
+ cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
|
|
160
|
+ cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+ // install a timer
|
|
164
|
+ _timerPeriodSecs = 0.1;
|
|
165
|
+ Fl::add_timeout(_timerPeriodSecs,app::_s_timer_cb,this);
|
|
166
|
+
|
|
167
|
+ // install an idle callback
|
|
168
|
+ //Fl::add_idle(_s_idle_cb,this);
|
|
169
|
+
|
|
170
|
+ print("Started!\n");
|
|
171
|
+}
|
|
172
|
+
|
|
173
|
+app::~app()
|
|
174
|
+{}
|
|
175
|
+
|
|
176
|
+void app::createControls(Fl_Group* grp)
|
|
177
|
+{
|
|
178
|
+ const int vBord = 3;
|
|
179
|
+ const int ctl_width = 100;
|
|
180
|
+ int xx = grp->x() + 5;
|
|
181
|
+ int yy = grp->y() + vBord;
|
|
182
|
+
|
|
183
|
+ Fl_Check_Button* cbt = new Fl_Check_Button(xx,yy,ctl_width,kCtlH,"Check");
|
|
184
|
+ cbt->callback( _s_btn_cb, kBtn1MId );
|
|
185
|
+ yy += cbt->h() + vBord;
|
|
186
|
+
|
|
187
|
+ Fl_Button* btn = new Fl_Button(xx,yy,ctl_width,kCtlH,"Button");
|
|
188
|
+ btn->callback( _s_btn_cb, kBtn2MId );
|
|
189
|
+ yy += btn->h() + vBord;
|
|
190
|
+
|
|
191
|
+ // menu buttons callback through menuCallback() not btnCallback()
|
|
192
|
+ Fl_Menu_Button* mbt = new Fl_Menu_Button(xx,yy,ctl_width,kCtlH,"Menu");
|
|
193
|
+
|
|
194
|
+ mbt->add("Item 1",0,_s_menu_btn_cb, (void*)kMenuBtn1MId, 0);
|
|
195
|
+ mbt->add("Item 2",0,_s_menu_btn_cb, (void*)kMenuBtn2MId, 0);
|
|
196
|
+ yy += mbt->h() + vBord;
|
|
197
|
+
|
|
198
|
+ Fl_Value_Input* vip = new Fl_Value_Input(xx,yy,ctl_width/2,kCtlH,"Value In");
|
|
199
|
+ vip->callback(_s_value_cb, kValue1MId );
|
|
200
|
+ vip->align(FL_ALIGN_RIGHT); // place label to the right of the input ctl
|
|
201
|
+ // Only make the callback when the enter key is struck or the ctl loses focus and the value has changed.
|
|
202
|
+ // Removing this line causes the callback whenever the input changes.
|
|
203
|
+ vip->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE );
|
|
204
|
+ vip->bounds(-10.0,10.0);
|
|
205
|
+ vip->step(0.1);
|
|
206
|
+ yy += vip->h() + vBord;
|
|
207
|
+
|
|
208
|
+ Fl_Value_Slider* sdp = new Fl_Value_Slider(xx,yy,ctl_width,kCtlH,"Slider");
|
|
209
|
+ sdp->callback(_s_value_cb, kValue2MId );
|
|
210
|
+ sdp->align(FL_ALIGN_RIGHT);
|
|
211
|
+ sdp->type(FL_HOR_NICE_SLIDER);
|
|
212
|
+ sdp->bounds(-10.0,10.0);
|
|
213
|
+ sdp->step(0.1);
|
|
214
|
+ yy += sdp->h() + vBord;
|
|
215
|
+
|
|
216
|
+ Fl_Input* inp = new Fl_Input(xx,yy,ctl_width/2,kCtlH,"Text");
|
|
217
|
+ inp->callback(_s_input_cb,kInput1MId);
|
|
218
|
+ inp->align(FL_ALIGN_RIGHT);
|
|
219
|
+ yy += inp->h() + vBord;
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+void app::initializeTab(int tabIndex, int x, int y, int w, int h, const char* label)
|
|
226
|
+{
|
|
227
|
+ switch(tabIndex)
|
|
228
|
+ {
|
|
229
|
+ case 0:
|
|
230
|
+ {
|
|
231
|
+ Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
|
232
|
+ grp->begin();
|
|
233
|
+ createControls(grp);
|
|
234
|
+ grp->end();
|
|
235
|
+ }
|
|
236
|
+ break;
|
|
237
|
+
|
|
238
|
+ case 1:
|
|
239
|
+ {
|
|
240
|
+ Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
|
241
|
+ grp->begin();
|
|
242
|
+ _draw = new drawWnd(this,x,y,w,h,NULL);
|
|
243
|
+ grp->end();
|
|
244
|
+ }
|
|
245
|
+ break;
|
|
246
|
+ }
|
|
247
|
+
|
|
248
|
+}
|
|
249
|
+
|
|
250
|
+void app::createMenu(int w, int h)
|
|
251
|
+{
|
|
252
|
+ Fl_Menu_Item items[] =
|
|
253
|
+ {
|
|
254
|
+ { "&File", 0, 0, 0, FL_SUBMENU },
|
|
255
|
+ { "&New File", FL_COMMAND + 'n', (Fl_Callback*)_s_menu_cb, (void*)kFileNewMId },
|
|
256
|
+ { "&Open File", FL_COMMAND + 'o', (Fl_Callback*)_s_menu_cb, (void*)kFileOpenMId },
|
|
257
|
+ { 0 },
|
|
258
|
+ { "&Edit", 0, 0, 0, FL_SUBMENU },
|
|
259
|
+ { "&Copy", FL_COMMAND + 'c', (Fl_Callback*)_s_menu_cb, (void*)kEditCopyMId },
|
|
260
|
+ { "&Paste", FL_COMMAND + 'v', (Fl_Callback*)_s_menu_cb, (void*)kEditPasteMId },
|
|
261
|
+ { 0 },
|
|
262
|
+ { 0 }
|
|
263
|
+ };
|
|
264
|
+
|
|
265
|
+ _menu = new Fl_Menu_Bar(0,0,w,h);
|
|
266
|
+ _menu->copy(items);
|
|
267
|
+}
|
|
268
|
+
|
|
269
|
+void app::menuCallback(const Fl_Menu_Item* mip, long int id)
|
|
270
|
+{
|
|
271
|
+ switch(id)
|
|
272
|
+ {
|
|
273
|
+ case kFileOpenMId:
|
|
274
|
+ {
|
|
275
|
+ // file chooser demo
|
|
276
|
+
|
|
277
|
+ const char* pathStr = cmFsUserDir(); // make the default dir the user's home dir
|
|
278
|
+ const char patStr[] = "Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
|
|
279
|
+ const char titleStr[] = "Select files";
|
|
280
|
+
|
|
281
|
+ Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::MULTI,titleStr);
|
|
282
|
+
|
|
283
|
+ fc.preview(0); // default the previous option to 'off'.
|
|
284
|
+ fc.show(); // show the chooser
|
|
285
|
+
|
|
286
|
+ // make the chooser modal
|
|
287
|
+ while( fc.shown() )
|
|
288
|
+ Fl::wait();
|
|
289
|
+
|
|
290
|
+ // print the selected files
|
|
291
|
+ int i;
|
|
292
|
+ for(i=1; i<=fc.count(); ++i)
|
|
293
|
+ print("%i %s\n",i,cmStringNullGuard(fc.value(i)));
|
|
294
|
+
|
|
295
|
+ }
|
|
296
|
+ break;
|
|
297
|
+ }
|
|
298
|
+
|
|
299
|
+ print("%i %s\n",id,mip->label());
|
|
300
|
+}
|
|
301
|
+
|
|
302
|
+void app::btnCallback(const Fl_Button* bp, int id )
|
|
303
|
+{
|
|
304
|
+ print("%i %s %i\n",id,bp->label(),bp->value());
|
|
305
|
+}
|
|
306
|
+
|
|
307
|
+void app::valueCallback(const Fl_Valuator* vp, int id )
|
|
308
|
+{
|
|
309
|
+ print("%i %s %f\n",id,vp->label(),vp->value());
|
|
310
|
+}
|
|
311
|
+
|
|
312
|
+void app::inputCallback(const Fl_Input* ip, int id )
|
|
313
|
+{
|
|
314
|
+ print("%i %s %s\n",id,ip->label(),ip->value());
|
|
315
|
+}
|
|
316
|
+
|
|
317
|
+void app::appCallback(Fl_Widget* wp)
|
|
318
|
+{
|
|
319
|
+ switch( Fl::event() )
|
|
320
|
+ {
|
|
321
|
+ case FL_CLOSE:
|
|
322
|
+ {
|
|
323
|
+
|
|
324
|
+ /*
|
|
325
|
+ int cc = _closeCnt;
|
|
326
|
+
|
|
327
|
+ // attempt to shut down the pgm
|
|
328
|
+ _closeCnt += finalizePgm() == false;
|
|
329
|
+
|
|
330
|
+ // the first time the pgm fails to shut down
|
|
331
|
+ // do not allow the pgm to close the main window
|
|
332
|
+ // this will give a chance for the error messages
|
|
333
|
+ // to be diplayed in the console - all successive
|
|
334
|
+ // times the return value from finalizePgm() is
|
|
335
|
+
|
|
336
|
+ // ignored and the program is terminated.
|
|
337
|
+ if( _closeCnt == 1 && cc==0)
|
|
338
|
+ {
|
|
339
|
+ // send a strong hint that a problem occurred on shutdown
|
|
340
|
+ // and prevent the app from receiving events that might cause it to
|
|
341
|
+ // crash
|
|
342
|
+ deactivate();
|
|
343
|
+ return;
|
|
344
|
+ }
|
|
345
|
+ */
|
|
346
|
+
|
|
347
|
+ // When all windows are windows are closed then the app.
|
|
348
|
+ // will close - so hiding the application window
|
|
349
|
+ // causes the program to close.
|
|
350
|
+ //
|
|
351
|
+ // Note that simply returning from this callback will
|
|
352
|
+ // prevent the application from closing. Because the existence
|
|
353
|
+ // of the callback alone is enough to disable default
|
|
354
|
+ // event handling.
|
|
355
|
+ hide();
|
|
356
|
+ }
|
|
357
|
+ break;
|
|
358
|
+ }
|
|
359
|
+
|
|
360
|
+}
|
|
361
|
+bool app::idleCallback()
|
|
362
|
+{ return true; }
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+bool app::timerCallback()
|
|
366
|
+{
|
|
367
|
+ _checkPrintQueue();
|
|
368
|
+ return true;
|
|
369
|
+}
|
|
370
|
+
|
|
371
|
+void app::error( const char* fmt, ... )
|
|
372
|
+{
|
|
373
|
+ va_list vl;
|
|
374
|
+ va_start(vl,fmt);
|
|
375
|
+
|
|
376
|
+ int bufCharCnt = 511;
|
|
377
|
+ char buf[bufCharCnt+1];
|
|
378
|
+
|
|
379
|
+ int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
|
380
|
+
|
|
381
|
+ if( n > 0 )
|
|
382
|
+ print("%s Error: %s\n",label(),buf);
|
|
383
|
+
|
|
384
|
+ va_end(vl);
|
|
385
|
+}
|
|
386
|
+
|
|
387
|
+void app::vprint(const char* fmt, va_list vl )
|
|
388
|
+{
|
|
389
|
+ int bufCharCnt = 511;
|
|
390
|
+ char buf[bufCharCnt+1];
|
|
391
|
+
|
|
392
|
+ int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
|
393
|
+
|
|
394
|
+ if( n > 0 )
|
|
395
|
+ {
|
|
396
|
+ // if the print queue exists (it might not during startup or shutdown) ...
|
|
397
|
+ if( cmTsMp1cIsValid(_printqH) )
|
|
398
|
+ {
|
|
399
|
+ cmThRC_t thRC;
|
|
400
|
+
|
|
401
|
+ // ... enqueue the text to print
|
|
402
|
+ if((thRC = cmTsMp1cEnqueueMsg(_printqH,buf,n+1)) != kOkThRC && _printFl==0 )
|
|
403
|
+ {
|
|
404
|
+ // Print queue error msg's directly to stdout rather than throught
|
|
405
|
+ // the error mechanism - this prevents generating a stack overflow
|
|
406
|
+ // when the print queue runs out of space and attempts to print a
|
|
407
|
+ // 'queue out of memory' error msg.
|
|
408
|
+ // The queue itself does will not print errors because it does
|
|
409
|
+ // not have a valid cmRpt_t pointer. See cmMp1cCreate() above.
|
|
410
|
+ ++_printFl;
|
|
411
|
+ cmErrMsg(&_ctx->err,kQueueFailAppRC,"Print enqueue failed.");
|
|
412
|
+ --_printFl;
|
|
413
|
+ }
|
|
414
|
+ }
|
|
415
|
+ else
|
|
416
|
+ _print(buf); // ... otherwise just send the text directly to the output console
|
|
417
|
+ }
|
|
418
|
+
|
|
419
|
+}
|
|
420
|
+
|
|
421
|
+void app::print( const char* fmt, ... )
|
|
422
|
+{
|
|
423
|
+ va_list vl;
|
|
424
|
+ va_start(vl,fmt);
|
|
425
|
+ vprint(fmt,vl);
|
|
426
|
+ va_end(vl);
|
|
427
|
+}
|
|
428
|
+
|
|
429
|
+void app::_s_menu_cb(Fl_Widget* wp, void* data)
|
|
430
|
+{
|
|
431
|
+ const Fl_Menu_Item* mip;
|
|
432
|
+ app* ap;
|
|
433
|
+
|
|
434
|
+ if((ap=_getApp(wp)) != NULL )
|
|
435
|
+ if((mip = ap->_menu->mvalue()) != NULL )
|
|
436
|
+ ap->menuCallback(mip,(long int)mip->user_data());
|
|
437
|
+}
|
|
438
|
+
|
|
439
|
+void app::_s_menu_btn_cb(Fl_Widget* wp, void* data)
|
|
440
|
+{
|
|
441
|
+ const Fl_Menu_Button* bp;
|
|
442
|
+ const Fl_Menu_Item* mip;
|
|
443
|
+ app* ap;
|
|
444
|
+
|
|
445
|
+ if((ap=_getApp(wp)) != NULL )
|
|
446
|
+ if((bp = static_cast<Fl_Menu_Button*>(wp)) != NULL )
|
|
447
|
+ if((mip = bp->mvalue()) != NULL)
|
|
448
|
+ ap->menuCallback(mip,(long int)data);
|
|
449
|
+}
|
|
450
|
+
|
|
451
|
+void app::_s_btn_cb(Fl_Widget* wp, long data )
|
|
452
|
+{
|
|
453
|
+ app* ap;
|
|
454
|
+
|
|
455
|
+ if((ap = _getApp(wp)) != NULL )
|
|
456
|
+ if( wp != NULL )
|
|
457
|
+ ap->btnCallback( static_cast<const Fl_Button*>(wp),data);
|
|
458
|
+}
|
|
459
|
+
|
|
460
|
+void app::_s_value_cb( Fl_Widget* wp, long data)
|
|
461
|
+{
|
|
462
|
+ app* ap;
|
|
463
|
+ Fl_Valuator* vp;
|
|
464
|
+
|
|
465
|
+ if((ap = _getApp(wp)) != NULL )
|
|
466
|
+ if((vp = static_cast<Fl_Valuator*>(wp)) != NULL)
|
|
467
|
+ ap->valueCallback(vp,data);
|
|
468
|
+}
|
|
469
|
+
|
|
470
|
+void app::_s_input_cb( Fl_Widget* wp, long data)
|
|
471
|
+{
|
|
472
|
+ app* ap;
|
|
473
|
+ Fl_Input* inp;
|
|
474
|
+
|
|
475
|
+ if((ap = _getApp(wp)) != NULL)
|
|
476
|
+ if((inp = static_cast<Fl_Input*>(wp)) != NULL )
|
|
477
|
+ ap->inputCallback(inp,data);
|
|
478
|
+}
|
|
479
|
+
|
|
480
|
+void app::_s_callback(Fl_Widget* wp, void* data)
|
|
481
|
+{ ((app*)data)->appCallback(wp); }
|
|
482
|
+
|
|
483
|
+void app::_s_idle_cb(void *data)
|
|
484
|
+{
|
|
485
|
+ app* thisPtr = (app*)data;
|
|
486
|
+
|
|
487
|
+ if( thisPtr->idleCallback() == false )
|
|
488
|
+ Fl::remove_idle(_s_idle_cb,data);
|
|
489
|
+}
|
|
490
|
+
|
|
491
|
+void app::_s_timer_cb(void* userPtr)
|
|
492
|
+{
|
|
493
|
+ app* thisPtr = (app*)userPtr;
|
|
494
|
+
|
|
495
|
+ if( thisPtr->timerCallback() )
|
|
496
|
+ Fl::repeat_timeout(thisPtr->_timerPeriodSecs,_s_timer_cb,userPtr);
|
|
497
|
+}
|
|
498
|
+
|
|
499
|
+void app::_s_print( void* userPtr, const char* text )
|
|
500
|
+{ ((app*)userPtr)->print(text); }
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+void app::_create_tabs(int titleCnt, const char* titleArray[])
|
|
504
|
+{
|
|
505
|
+ // Create a tab view and added it to the upper splitter area
|
|
506
|
+ _tabs = new Fl_Tabs(_splt->container1->x(),_splt->container1->y(),_splt->container1->w(),_splt->container1->h());
|
|
507
|
+ _splt->container1->add(_tabs);
|
|
508
|
+
|
|
509
|
+ int tx,ty,th,tw,i;
|
|
510
|
+ _tabs->client_area(tx,ty,tw,th);
|
|
511
|
+
|
|
512
|
+ for(i=0; i<titleCnt; ++i)
|
|
513
|
+ {
|
|
514
|
+ _tabs->begin();
|
|
515
|
+ initializeTab(i,tx,ty,tw,th,titleArray[i]);
|
|
516
|
+ _tabs->end();
|
|
517
|
+ }
|
|
518
|
+
|
|
519
|
+ // Create an empty tab group and make it resizable
|
|
520
|
+ // to prevent the other tab groups from being resizable.
|
|
521
|
+ _tabs->begin();
|
|
522
|
+ _tabs->resizable(new Fl_Group(tx,ty+30,1,1));
|
|
523
|
+ _tabs->end();
|
|
524
|
+}
|
|
525
|
+
|
|
526
|
+app* app::_getApp( Fl_Widget* w )
|
|
527
|
+{
|
|
528
|
+ // walk up the widget tree until the top widget is found
|
|
529
|
+ Fl_Group* gp = w->parent();
|
|
530
|
+ while( gp->parent() != NULL )
|
|
531
|
+ gp=gp->parent();
|
|
532
|
+
|
|
533
|
+ // the user data for the top widget is a pointer app - as set in: callback(_s_callback,this);
|
|
534
|
+ return (app*)gp->user_data();
|
|
535
|
+}
|
|
536
|
+
|
|
537
|
+cmRC_t app::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
|
|
538
|
+{
|
|
539
|
+ app* ap = (app*)userCbPtr;
|
|
540
|
+ ap->_print((const char*)msgDataPtr);
|
|
541
|
+ return cmOkRC;
|
|
542
|
+}
|
|
543
|
+
|
|
544
|
+void app::_checkPrintQueue()
|
|
545
|
+{
|
|
546
|
+ while( cmTsMp1cMsgWaiting(_printqH) )
|
|
547
|
+ if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC )
|
|
548
|
+ error("Print dequeue failed.");
|
|
549
|
+}
|
|
550
|
+
|
|
551
|
+void app::_print( const char* text )
|
|
552
|
+{
|
|
553
|
+ if( _con != NULL )
|
|
554
|
+ _con->insert(text);
|
|
555
|
+}
|