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