1 /********************************************************************************
2 * *
3 * D a t a T a r g e t *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1997,2020 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
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 *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "fxkeys.h"
26 #include "FXArray.h"
27 #include "FXHash.h"
28 #include "FXMutex.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXSize.h"
32 #include "FXPoint.h"
33 #include "FXRectangle.h"
34 #include "FXStringDictionary.h"
35 #include "FXSettings.h"
36 #include "FXRegistry.h"
37 #include "FXEvent.h"
38 #include "FXWindow.h"
39 #include "FXApp.h"
40 #include "FXDataTarget.h"
41
42
43 /*
44 Notes:
45 - DataTarget connects GUI to basic values such as flags (FXbool), integral
46 or real numbers, and strings (FXString).
47 - Values in the application program may get updated from the GUI, and
48 vice-versa GUI gets updated when the program has changed a value as well.
49 - Would be nice to set value from message ID also...
50 - When the sender of onCmdValue does not understand the ID_GETXXXXVALUE message,
51 the data target keeps the same value as before.
52 - Catch SEL_CHANGED when we have expunged this from FXTextField.
53 - DT_VOID, i.e. unconnected FXDataTarget maybe it should grey out corresponding
54 widgets.
55 - Need to add ID_GETLONGVALUE/ID_SETLONGVALUE message handlers some day.
56 - onCmdValue, onUpdValue, onCmdOption, and onUpdOption now return 0 if the type
57 variable is not one of the known types. This allows more easy subclassing of
58 FXDataTarget to add custom data types.
59 - When the type is DT_VOID, a change message does not change any data but simply
60 passes along the message to data target's target; an update message will be a
61 no-op, but return 1 so that the sending message will remain sensitized if auto-
62 gray is on.
63 */
64
65 using namespace FX;
66
67 /*******************************************************************************/
68
69 namespace FX {
70
71 // Map
72 FXDEFMAP(FXDataTarget) FXDataTargetMap[]={
73 FXMAPFUNC(SEL_COMMAND,FXDataTarget::ID_VALUE,FXDataTarget::onCmdValue),
74 FXMAPFUNC(SEL_CHANGED,FXDataTarget::ID_VALUE,FXDataTarget::onCmdValue),
75 FXMAPFUNC(SEL_UPDATE,FXDataTarget::ID_VALUE,FXDataTarget::onUpdValue),
76 FXMAPFUNCS(SEL_COMMAND,FXDataTarget::ID_OPTION-10001,FXDataTarget::ID_OPTION+10000,FXDataTarget::onCmdOption),
77 FXMAPFUNCS(SEL_UPDATE,FXDataTarget::ID_OPTION-10001,FXDataTarget::ID_OPTION+10000,FXDataTarget::onUpdOption),
78 };
79
80
81 // Object implementation
FXIMPLEMENT(FXDataTarget,FXObject,FXDataTargetMap,ARRAYNUMBER (FXDataTargetMap))82 FXIMPLEMENT(FXDataTarget,FXObject,FXDataTargetMap,ARRAYNUMBER(FXDataTargetMap))
83
84
85 // Value changed from widget
86 long FXDataTarget::onCmdValue(FXObject* sender,FXSelector sel,void*){
87 FXdouble d;
88 FXint i;
89 switch(type){
90 case DT_VOID:
91 break;
92 case DT_BOOL:
93 i=*((FXbool*)data);
94 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),(void*)&i);
95 *((FXbool*)data)=(i!=0);
96 break;
97 case DT_CHAR:
98 i=*((FXchar*)data);
99 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),(void*)&i);
100 *((FXchar*)data)=i;
101 break;
102 case DT_UCHAR:
103 i=*((FXuchar*)data);
104 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),(void*)&i);
105 *((FXuchar*)data)=i;
106 break;
107 case DT_SHORT:
108 i=*((FXshort*)data);
109 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),(void*)&i);
110 *((FXshort*)data)=i;
111 break;
112 case DT_USHORT:
113 i=*((FXushort*)data);
114 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),(void*)&i);
115 *((FXushort*)data)=i;
116 break;
117 case DT_INT:
118 case DT_UINT:
119 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETINTVALUE),data);
120 break;
121 case DT_LONG:
122 case DT_ULONG:
123 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETLONGVALUE),data);
124 break;
125 case DT_FLOAT:
126 d=*((FXfloat*)data);
127 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETREALVALUE),(void*)&d);
128 *((FXfloat*)data)=(FXfloat)d;
129 break;
130 case DT_DOUBLE:
131 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETREALVALUE),data);
132 break;
133 case DT_STRING:
134 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_GETSTRINGVALUE),data);
135 break;
136 default:
137 return 0;
138 }
139 if(target){
140 target->handle(this,FXSEL(FXSELTYPE(sel),message),data);
141 }
142 return 1;
143 }
144
145
146 // Widget changed from value
onUpdValue(FXObject * sender,FXSelector,void *)147 long FXDataTarget::onUpdValue(FXObject* sender,FXSelector,void*){
148 FXdouble d;
149 FXint i;
150 switch(type){
151 case DT_VOID:
152 break;
153 case DT_BOOL:
154 i=*((FXbool*)data);
155 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&i);
156 break;
157 case DT_CHAR:
158 i=*((FXchar*)data);
159 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&i);
160 break;
161 case DT_UCHAR:
162 i=*((FXuchar*)data);
163 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&i);
164 break;
165 case DT_SHORT:
166 i=*((FXshort*)data);
167 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&i);
168 break;
169 case DT_USHORT:
170 i=*((FXushort*)data);
171 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&i);
172 break;
173 case DT_INT:
174 case DT_UINT:
175 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),data);
176 break;
177 case DT_LONG:
178 case DT_ULONG:
179 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETLONGVALUE),data);
180 break;
181 case DT_FLOAT:
182 d=*((FXfloat*)data);
183 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETREALVALUE),(void*)&d);
184 break;
185 case DT_DOUBLE:
186 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETREALVALUE),data);
187 break;
188 case DT_STRING:
189 sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETSTRINGVALUE),data);
190 break;
191 default:
192 return 0;
193 }
194 return 1;
195 }
196
197
198 // Value set from message id
onCmdOption(FXObject *,FXSelector sel,void *)199 long FXDataTarget::onCmdOption(FXObject*,FXSelector sel,void*){
200 FXint num=((FXint)FXSELID(sel))-ID_OPTION;
201 switch(type){
202 case DT_VOID:
203 break;
204 case DT_BOOL:
205 *((FXbool*)data)=(num!=0);
206 break;
207 case DT_CHAR:
208 *((FXchar*)data)=num;
209 break;
210 case DT_UCHAR:
211 *((FXuchar*)data)=num;
212 break;
213 case DT_SHORT:
214 *((FXshort*)data)=num;
215 break;
216 case DT_USHORT:
217 *((FXushort*)data)=num;
218 break;
219 case DT_INT:
220 *((FXint*)data)=num;
221 break;
222 case DT_UINT:
223 *((FXuint*)data)=num;
224 break;
225 case DT_LONG:
226 *((FXlong*)data)=num;
227 break;
228 case DT_ULONG:
229 *((FXulong*)data)=num;
230 break;
231 case DT_FLOAT:
232 *((FXfloat*)data)=(FXfloat)num;
233 break;
234 case DT_DOUBLE:
235 *((FXdouble*)data)=num;
236 break;
237 default:
238 return 0;
239 }
240 if(target){
241 target->handle(this,FXSEL(FXSELTYPE(sel),message),data);
242 }
243 return 1;
244 }
245
246
247 // Check widget whose message id matches
onUpdOption(FXObject * sender,FXSelector sel,void *)248 long FXDataTarget::onUpdOption(FXObject* sender,FXSelector sel,void*){
249 FXint num=((FXint)FXSELID(sel))-ID_OPTION;
250 FXint i=0;
251 switch(type){
252 case DT_VOID:
253 break;
254 case DT_BOOL:
255 i=*((FXbool*)data);
256 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
257 break;
258 case DT_CHAR:
259 i=*((FXchar*)data);
260 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
261 break;
262 case DT_UCHAR:
263 i=*((FXuchar*)data);
264 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
265 break;
266 case DT_SHORT:
267 i=*((FXshort*)data);
268 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
269 break;
270 case DT_USHORT:
271 i=*((FXushort*)data);
272 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
273 break;
274 case DT_INT:
275 i=*((FXint*)data);
276 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
277 break;
278 case DT_UINT:
279 i=*((FXuint*)data);
280 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
281 break;
282 case DT_LONG:
283 i=(FXint) *((FXlong*)data);
284 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
285 break;
286 case DT_ULONG:
287 i=(FXint) *((FXulong*)data);
288 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
289 break;
290 case DT_FLOAT:
291 i=(FXint) *((FXfloat*)data);
292 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
293 break;
294 case DT_DOUBLE:
295 i=(FXint) *((FXdouble*)data);
296 sender->handle(this,(num==i)?FXSEL(SEL_COMMAND,FXWindow::ID_CHECK):FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
297 break;
298 default:
299 return 0;
300 }
301 return 1;
302 }
303
304
305 // Destroy
~FXDataTarget()306 FXDataTarget::~FXDataTarget(){
307 target=(FXObject*)-1L;
308 data=(void*)-1L;
309 }
310
311 }
312
313