1 /********************************************************************************
2 *                                                                               *
3 *                                 Data Target Test                              *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1997,2021 by Jeroen van der Zijp.   All Rights Reserved.        *
7 ********************************************************************************/
8 #include "fx.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/stat.h>
12 #include <signal.h>
13 #ifndef WIN32
14 #include <unistd.h>
15 #endif
16 
17 
18 /*******************************************************************************/
19 
20 
21 // Mini application object
22 class DataTargetWindow : public FXMainWindow {
23   FXDECLARE(DataTargetWindow)
24 protected:
25   FXMenuBar*         menubar;
26   FXMenuPane*        filemenu;
27   FXMenuPane*        optionmenu;
28   FXPopup*           popup;
29   FXMatrix*          matrix;
30   FXint              some_int;
31   FXdouble           some_double;
32   FXint              some_option;
33   FXString           some_string;
34   FXColor            some_color;
35   FXint              some_progress;
36   FXDataTarget       int_target;
37   FXDataTarget       double_target;
38   FXDataTarget       string_target;
39   FXDataTarget       option_target;
40   FXDataTarget       color_target;
41   FXDataTarget       progress_target;
42   FXProgressDialog  *progressdialog;
43 public:
44   long onCmdTimer(FXObject*,FXSelector,void*);
45   long onCmdQuit(FXObject*,FXSelector,void*);
46   long onCmdProgress(FXObject*,FXSelector,void*);
47 public:
DataTargetWindow()48   DataTargetWindow(){}
49 public:
50   enum {
51     ID_TIMER=FXMainWindow::ID_LAST,
52     ID_PROGRESS,
53     ID_QUIT
54     };
55 public:
56   DataTargetWindow(FXApp *a);
57   void create();
58   virtual ~DataTargetWindow();
59   };
60 
61 
62 
63 /*******************************************************************************/
64 
65 // Map
66 FXDEFMAP(DataTargetWindow) DataTargetWindowMap[]={
67   FXMAPFUNC(SEL_CLOSE,  0,                             DataTargetWindow::onCmdQuit),
68   FXMAPFUNC(SEL_SIGNAL, DataTargetWindow::ID_QUIT,     DataTargetWindow::onCmdQuit),
69   FXMAPFUNC(SEL_TIMEOUT,DataTargetWindow::ID_TIMER,    DataTargetWindow::onCmdTimer),
70   FXMAPFUNC(SEL_COMMAND,DataTargetWindow::ID_PROGRESS, DataTargetWindow::onCmdProgress),
71   };
72 
73 
74 // Object implementation
FXIMPLEMENT(DataTargetWindow,FXMainWindow,DataTargetWindowMap,ARRAYNUMBER (DataTargetWindowMap))75 FXIMPLEMENT(DataTargetWindow,FXMainWindow,DataTargetWindowMap,ARRAYNUMBER(DataTargetWindowMap))
76 
77 
78 
79 // Make some windows
80 DataTargetWindow::DataTargetWindow(FXApp* a):FXMainWindow(a,"Data Target Test",NULL,NULL,DECOR_ALL,20,20,700,460){
81 
82   // Initialize some simple variables
83   some_int = 10;
84   some_double = 3.1415927;
85   some_string = "FOX";
86   some_color = FXRGB(255,0,0);
87   some_option = 0;
88   some_progress = 0;
89 
90 
91   // Connect INTEGER target
92   int_target.connect(some_int);
93 
94   // Connect DOUBLE target
95   double_target.connect(some_double);
96 
97   // Connect STRING target
98   string_target.connect(some_string);
99 
100   // Connect COLOR target
101   color_target.connect(some_color);
102 
103   // Connect option target
104   option_target.connect(some_option);
105 
106   // Connect progress target
107   progress_target.connect(some_progress);
108 
109   // Create progress dialog
110   progressdialog=new FXProgressDialog(this,"Progress","We zijn druk, we zijn druk\nWe zijn ongelooflijk druk.",PROGRESSDIALOG_CANCEL|DECOR_BORDER|DECOR_RESIZE|DECOR_TITLE);
111   progressdialog->setTarget(&int_target);
112   progressdialog->setSelector(FXDataTarget::ID_VALUE);
113 
114   // Menubar
115   menubar=new FXMenuBar(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X);
116 
117   // File menu
118   filemenu=new FXMenuPane(this);
119     new FXMenuCommand(filemenu,"Progress dialog...",NULL,this,ID_PROGRESS);
120     new FXMenuCommand(filemenu,"&Quit\tCtl-Q",NULL,getApp(),FXApp::ID_QUIT);
121   new FXMenuTitle(menubar,"&File",NULL,filemenu);
122 
123   // Option menu
124   optionmenu=new FXMenuPane(this);
125 
126     // The menu radios change the "some_option" variable via the option_target
127     new FXMenuRadio(optionmenu,"Option 1",&option_target,FXDataTarget::ID_OPTION+0);
128     new FXMenuRadio(optionmenu,"Option 2",&option_target,FXDataTarget::ID_OPTION+1);
129     new FXMenuRadio(optionmenu,"Option 3",&option_target,FXDataTarget::ID_OPTION+2);
130     new FXMenuRadio(optionmenu,"Option 4",&option_target,FXDataTarget::ID_OPTION+3);
131 
132   new FXMenuTitle(menubar,"&Option",NULL,optionmenu);
133 
134 
135   // Lone progress bar at the bottom, which reflects the value of variable "some_progress"
136   new FXProgressBar(this,&progress_target,FXDataTarget::ID_VALUE,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK);
137 
138   new FXHorizontalSeparator(this,LAYOUT_SIDE_TOP|SEPARATOR_GROOVE|LAYOUT_FILL_X);
139 
140   FXHorizontalFrame *horframe=new FXHorizontalFrame(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X);
141 
142   new FXLabel(horframe,
143     "FXDataTarget can be used to connect a Widget to an application variable without any of the\n"
144     "tradional \"glue\" programming code.\n\n"
145     "The widgets below are connected (via FXDataTarget) to an integer, real, string, option, and\n"
146     "color variable, respectively.\n\n"
147     "Changing one of them will cause all widgets connected to the same FXDataTarget to \n"
148     "update so as to reflect the value of the application variable.\n\n"
149     "The progress bar below shows a time-varying variable, demonstrating that widgets\n"
150     "can be updated via FXDataTarget's regardless how the variables are changed.\n\n"
151     "Note that the \"Option\" pulldown menu is also connected to the option variable!",
152     NULL,LAYOUT_LEFT|JUSTIFY_LEFT);
153 
154   new FXProgressBar(horframe,&int_target,FXDataTarget::ID_VALUE,PROGRESSBAR_PERCENTAGE|PROGRESSBAR_DIAL|LAYOUT_RIGHT|LAYOUT_FILL_Y|LAYOUT_FILL_X);
155 
156   new FXHorizontalSeparator(this,LAYOUT_SIDE_TOP|SEPARATOR_GROOVE|LAYOUT_FILL_X);
157   new FXSlider(this,&int_target,FXDataTarget::ID_VALUE,SLIDER_VERTICAL|SLIDER_INSIDE_BAR|LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH,0,0,20,0);
158 
159   // Arange nicely
160   matrix=new FXMatrix(this,9,MATRIX_BY_COLUMNS|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
161 
162   // First row
163   new FXLabel(matrix,"&Integer",NULL,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|JUSTIFY_RIGHT|LAYOUT_FILL_ROW);
164 
165   // The value of variable "some_int" may be changed by any of these widgets below
166   new FXTextField(matrix,10,&int_target,FXDataTarget::ID_VALUE,TEXTFIELD_INTEGER|JUSTIFY_RIGHT|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
167   new FXTextField(matrix,10,&int_target,FXDataTarget::ID_VALUE,TEXTFIELD_INTEGER|JUSTIFY_RIGHT|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
168   new FXSlider(matrix,&int_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_ROW|LAYOUT_FIX_WIDTH,0,0,100);
169   new FXDial(matrix,&int_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_ROW|LAYOUT_FIX_WIDTH|DIAL_HORIZONTAL|DIAL_HAS_NOTCH,0,0,100);
170   new FXKnob(matrix,&int_target,FXDataTarget::ID_VALUE,KNOB_TICKS|LAYOUT_CENTER_Y|LAYOUT_CENTER_X);
171   new FXSpinner(matrix,5,&int_target,FXDataTarget::ID_VALUE,SPIN_CYCLIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW);
172   new FXProgressBar(matrix,&int_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK|PROGRESSBAR_PERCENTAGE|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
173   FX7Segment *seven=new FX7Segment(matrix,FXString::null,SEVENSEGMENT_SHADOW|JUSTIFY_RIGHT|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW|LAYOUT_FIX_WIDTH,0,0,40,0);
174   seven->setTarget(&int_target);
175   seven->setSelector(FXDataTarget::ID_VALUE);
176 
177 
178   // Second row
179   new FXLabel(matrix,"&Real",NULL,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|JUSTIFY_RIGHT|LAYOUT_FILL_ROW);
180 
181   // The value of variable "some_double" may be changed by the widgets below
182   new FXTextField(matrix,10,&double_target,FXDataTarget::ID_VALUE,TEXTFIELD_REAL|JUSTIFY_RIGHT|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
183   new FXTextField(matrix,10,&double_target,FXDataTarget::ID_VALUE,TEXTFIELD_REAL|JUSTIFY_RIGHT|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
184   FXRealSlider *rslider=new FXRealSlider(matrix,&double_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW|LAYOUT_FIX_WIDTH,0,0,100);
185   rslider->setRange(0.0,10.0);
186   rslider->setGranularity(0.01);
187   new FXDial(matrix,&double_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW|LAYOUT_FIX_WIDTH|DIAL_HORIZONTAL|DIAL_HAS_NOTCH,0,0,100);
188 
189   FXRealSpinner *rspinner=new FXRealSpinner(matrix,8,&double_target,FXDataTarget::ID_VALUE,REALSPIN_CYCLIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW);
190   rspinner->setRange(-10.0,10.0);
191   rspinner->setIncrement(0.01);
192   rspinner->setGranularity(0.01);
193   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
194   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
195   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
196 
197   // Third row
198   new FXLabel(matrix,"&String",NULL,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|JUSTIFY_RIGHT|LAYOUT_FILL_ROW);
199 
200   // The string variable "some_string" can be changed by these text fields
201   new FXTextField(matrix,10,&string_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
202   new FXTextField(matrix,10,&string_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
203   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
204   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
205   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
206   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
207   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
208   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
209 
210   // Fourth row
211   new FXLabel(matrix,"&Option",NULL,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|JUSTIFY_RIGHT|LAYOUT_FILL_ROW);
212 
213   // The variable "some_option" is changed by the following widgets
214   new FXTextField(matrix,10,&option_target,FXDataTarget::ID_VALUE,TEXTFIELD_INTEGER|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_ROW);
215   new FXRadioButton(matrix,"Option &1",&option_target,FXDataTarget::ID_OPTION+0,LAYOUT_CENTER_Y|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|ICON_BEFORE_TEXT);
216   new FXRadioButton(matrix,"Option &2",&option_target,FXDataTarget::ID_OPTION+1,LAYOUT_CENTER_Y|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|ICON_BEFORE_TEXT);
217   new FXRadioButton(matrix,"Option &3",&option_target,FXDataTarget::ID_OPTION+2,LAYOUT_CENTER_Y|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|ICON_BEFORE_TEXT);
218   new FXRadioButton(matrix,"Option &4",&option_target,FXDataTarget::ID_OPTION+3,LAYOUT_CENTER_Y|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|ICON_BEFORE_TEXT);
219 
220   // Even option menus can be hooked up
221   popup=new FXPopup(this);
222   new FXOption(popup,"First",NULL,&option_target,FXDataTarget::ID_OPTION+0,JUSTIFY_HZ_APART|ICON_AFTER_TEXT);
223   new FXOption(popup,"Second",NULL,&option_target,FXDataTarget::ID_OPTION+1,JUSTIFY_HZ_APART|ICON_AFTER_TEXT);
224   new FXOption(popup,"Third",NULL,&option_target,FXDataTarget::ID_OPTION+2,JUSTIFY_HZ_APART|ICON_AFTER_TEXT);
225   new FXOption(popup,"Fourth",NULL,&option_target,FXDataTarget::ID_OPTION+3,JUSTIFY_HZ_APART|ICON_AFTER_TEXT);
226   FXOptionMenu *optionsmenu=new FXOptionMenu(matrix,popup,LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART|ICON_AFTER_TEXT);
227   optionsmenu->setTarget(&option_target);
228   optionsmenu->setSelector(FXDataTarget::ID_VALUE);
229 
230   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
231   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
232 
233   // Fifth
234   new FXLabel(matrix,"&Color",NULL,LAYOUT_CENTER_Y|LAYOUT_CENTER_X|JUSTIFY_RIGHT|LAYOUT_FILL_ROW);
235 
236   // Two colorwells connect to the variable "some_color"
237   new FXColorWell(matrix,0,&color_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW|FRAME_SUNKEN|FRAME_THICK,0,0,0,0, 0,0,0,0);
238   new FXColorWell(matrix,0,&color_target,FXDataTarget::ID_VALUE,LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW|FRAME_SUNKEN|FRAME_THICK,0,0,0,0, 0,0,0,0);
239   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
240   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
241   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
242   new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
243 //  new FXFrame(matrix,LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
244   new FXSpinner(matrix,5,&progress_target,FXDataTarget::ID_VALUE,FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW);
245 
246   // Install an accelerator
247   getAccelTable()->addAccel("Ctl-Q",getApp(),FXSEL(SEL_COMMAND,FXApp::ID_QUIT));
248 
249   }
250 
251 
252 // Clean up
~DataTargetWindow()253 DataTargetWindow::~DataTargetWindow(){
254   getApp()->removeTimeout(this,ID_TIMER);
255   delete progressdialog;
256   delete filemenu;
257   delete optionmenu;
258   delete popup;
259   }
260 
261 
262 // Timer
onCmdTimer(FXObject *,FXSelector,void *)263 long DataTargetWindow::onCmdTimer(FXObject*,FXSelector,void*){
264 
265   // Increment modulo 100
266   some_progress=(some_progress+1)%100;
267 
268   // Reset timer for next time
269   getApp()->addTimeout(this,ID_TIMER,80000000);
270   return 1;
271   }
272 
273 
274 // Quit
onCmdQuit(FXObject *,FXSelector,void *)275 long DataTargetWindow::onCmdQuit(FXObject*,FXSelector,void*){
276   getApp()->exit(0);
277   return 1;
278   }
279 
280 
281 // Show progress
onCmdProgress(FXObject *,FXSelector,void *)282 long DataTargetWindow::onCmdProgress(FXObject*,FXSelector,void*){
283   progressdialog->show(PLACEMENT_OWNER);
284   return 1;
285   }
286 
287 
288 // Start
create()289 void DataTargetWindow::create(){
290 
291   // Create windows
292   FXMainWindow::create();
293 
294   // Kick off the timer
295   getApp()->addTimeout(this,ID_TIMER,80000000);
296 
297   // Show
298   show(PLACEMENT_SCREEN);
299   }
300 
301 
302 /*******************************************************************************/
303 
304 
305 // Start the whole thing
main(int argc,char * argv[])306 int main(int argc,char *argv[]){
307 
308   // Make application
309   FXApp application("DataTarget","FoxTest");
310 
311   // Open display
312   application.init(argc,argv);
313 
314   // Main window
315   DataTargetWindow* window=new DataTargetWindow(&application);
316 
317   // Handle interrupt to save stuff nicely
318   application.addSignal(SIGINT,window,DataTargetWindow::ID_QUIT);
319 
320   // Create app
321   application.create();
322 
323   // Run
324   return application.run();
325   }
326