1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12
13
14 #include "ToggleNode.h"
15 #include "ToggleInstance.h"
16 #include "ErrorDialogManager.h"
17 #include "AttributeParameter.h"
18
19 #include "DXApplication.h"
20 #include "MacroDefinition.h"
21
22 //
23 // The following define the mapping of parameter indices to parameter
24 // functionality in the module that is used to 'data-drive' the
25 // ToggleNode class and Nodes derived from it.
26 // These MUST match the entries in the ui.mdf file for the interactors
27 // that expect to be implemented by the ToggleInteractor class.
28 //
29 #define ID_PARAM_NUM 1 // Id used for UI messages
30 #define CVAL_PARAM_NUM 2 // The current output
31 #define ISSET_PARAM_NUM 3 // is the toggle set
32 #define SET_PARAM_NUM 4 // The dd set value
33 #define RESET_PARAM_NUM 5 // The dd unset value
34 #define LABEL_PARAM_NUM 6 // Label
35 #define EXPECTED_SELECTOR_INPUTS LABEL_PARAM_NUM
36
37
38 #define SEND_NOW 1
39 #define NO_SEND 0
40 #define SEND_QUIET -1
41
42 //
43 // Constructor
44 //
ToggleNode(NodeDefinition * nd,Network * net,int instance)45 ToggleNode::ToggleNode(NodeDefinition *nd,
46 Network *net, int instance) :
47 InteractorNode(nd, net, instance)
48 {
49 this->outputType = DXType::UndefinedType;
50 this->is_set = FALSE;
51 }
~ToggleNode()52 ToggleNode::~ToggleNode()
53 {
54 }
55 //
56 // Called after allocation is complete.
57 // The work done here is to assigned default values to the InteractorNode inputs
58 // so that we can use them later when setting the attributes for the
59 // Interactor.
60 //
initialize()61 boolean ToggleNode::initialize()
62 {
63
64 if (this->getInputCount() != EXPECTED_SELECTOR_INPUTS) {
65 fprintf(stderr,
66 "Expected %d inputs for %s interactor, please check the mdf file.\n",
67 EXPECTED_SELECTOR_INPUTS,
68 this->getNameString());
69 return FALSE;
70 }
71
72 //
73 // Make the default set/reset values be 1/0 and make the output set.
74 //
75 if (!this->setToggleValues("1", "0")) {
76 ErrorMessage(
77 "Error setting default attributes for %s interactor, check ui.mdf\n",
78 this->getNameString());
79 return FALSE;
80 }
81
82 //
83 // Make the shadows defaulting (even though we have a current output)
84 // so that the executive module can tell when it is executing a just
85 // placed module and one that is read in from a .net or .cfg file.
86 // When read in, the output will be set again which should make the
87 // corresponding shadowing input be non-defaulting.
88 //
89 this->setShadowingInputsDefaulting();
90
91 // Set the input id for the executive module.
92 //
93 this->setMessageIdParameter();
94
95 return TRUE;
96 }
97 //
98 // Create a new interactor instance for this class.
99 //
newInteractorInstance()100 InteractorInstance *ToggleNode::newInteractorInstance()
101 {
102 return new ToggleInstance(this);
103 }
setToggle(boolean setit,boolean send)104 boolean ToggleNode::setToggle(boolean setit, boolean send)
105 {
106 return this->setTheToggle(setit,(send ? SEND_NOW : NO_SEND));
107 }
setToggleQuietly(boolean setit)108 boolean ToggleNode::setToggleQuietly(boolean setit)
109 {
110 return this->setTheToggle(setit,SEND_QUIET);
111 }
112 //
113 // Set the output and send it if requested.
114 // If setit is TRUE, then set the output to the first of the toggle values
115 // otherwise the 2nd of toggle values.
116 // If how is 1, then send the value.
117 // If how is 0, then don't send the value.
118 // If how is -1, then send the value quietly.
119 //
setTheToggle(boolean setit,int how)120 boolean ToggleNode::setTheToggle(boolean setit, int how)
121 {
122 boolean r;
123 char *val;
124
125 if (setit)
126 val = this->getSetValue();
127 else
128 val = this->getResetValue();
129
130 ASSERT(val);
131
132 //
133 // Do this before setting the value so that if/when it succeeds, the
134 // interactors that update their value from this->isSet() will get
135 // the correct answer.
136 // FIXME: setting the ISSET_PARAM_NUM may be better done in
137 // this->setOutputValue[Quietly](), but since this is the
138 // only occurence of setOutputValue() in this file, and all
139 // others are either done while parsing (when it doesn't matter)
140 // not done at all and instead use this->set/reset().
141 //
142 this->is_set = setit;
143 r = this->setInputValue(ISSET_PARAM_NUM, setit?"1":"0",
144 DXType::UndefinedType, FALSE) &&
145 this->setOutputValue(1,val,DXType::UndefinedType, FALSE);
146 ASSERT(r);
147
148 if (how == SEND_NOW)
149 this->sendValues(FALSE);
150 else if (how == SEND_QUIET)
151 this->sendValuesQuietly();
152
153
154 delete val;
155
156 return r;
157 }
158
159 //
160 // Set the two potential output values. The 1st corresponds to the
161 // set (toggle down) state and the second to the reset state (toggle up).
162 // If how is 1, then send the values.
163 // If how is 0, then don't send the values.
164 // If how is -1, then send the values quietly.
165 //
changeToggleValues(const char * set,const char * reset,int how)166 boolean ToggleNode::changeToggleValues(const char *set,
167 const char *reset, int how)
168 {
169 boolean was_set, r = TRUE;
170
171 was_set = this->isSet();
172
173 if (set) {
174 r = this->setInputSetValue(SET_PARAM_NUM,set,
175 DXType::UndefinedType,FALSE);
176 }
177 if (r && reset) {
178 r = this->setInputSetValue(RESET_PARAM_NUM,reset,
179 DXType::UndefinedType,FALSE);
180 }
181
182 if (r) {
183 if (set && was_set)
184 this->set(FALSE);
185 else if (reset && !was_set)
186 this->reset(FALSE);
187
188
189 if (how == SEND_NOW)
190 this->sendValues(FALSE);
191 else if (how == SEND_QUIET)
192 this->sendValuesQuietly();
193 }
194 return r;
195
196 }
197
198 //
199 // Initialize the two potential output values. The 1st corresponds to the
200 // set (toggle down) state and the second to the reset state (toggle up).
201 // This (init) is called at creation, where as setToggleValues() is called
202 // after initialization.
203 //
initToggleValues(const char * set,const char * reset)204 boolean ToggleNode::initToggleValues(const char *set, const char *reset)
205 {
206 ASSERT(0);// we should get rid of this method
207 return this->changeToggleValues(set,reset,NO_SEND);
208 }
209 //
210 // Set the two potential output values. The 1st corresponds to the
211 // set (toggle down) state and the second to the reset state (toggle up).
212 //
setToggleValues(const char * set,const char * reset)213 boolean ToggleNode::setToggleValues(const char *set, const char *reset)
214 {
215 return this->changeToggleValues(set,reset,NO_SEND);
216 }
217 //
218 //
219 // Get the values that are output for the set and reset states.
220 // The returned string must be freed by the caller.
221 //
getToggleValue(boolean setval)222 char *ToggleNode::getToggleValue(boolean setval)
223 {
224 int pindex;
225
226 if (setval)
227 pindex = SET_PARAM_NUM;
228 else
229 pindex = RESET_PARAM_NUM;
230
231 return DuplicateString(this->getInputSetValueString(pindex));
232 }
233
handleInteractorMsgInfo(const char * line)234 int ToggleNode::handleInteractorMsgInfo(const char *line)
235 {
236 int values = 0;
237 char *p;
238
239 //
240 // Handle the 'unset=...' part of the message.
241 //
242 if ( (p = strstr((char*)line,"unset=")) ) {
243 values++;
244 while (*p != '=') p++;
245 p++;
246 this->changeToggleValues(NULL,p,NO_SEND);
247 } else if ( (p = strstr((char*)line,"set=")) ) {
248 //
249 // Handle the 'set=...' part of the message.
250 //
251 values++;
252 while (*p != '=') p++;
253 p++;
254 this->changeToggleValues(p,NULL,NO_SEND);
255 }
256
257 if (values) {
258 //
259 // These two params may have gotten marked dirty, but we certainly
260 // don't need to send them back to the exec as these parameters
261 // are what triggered these messages.
262 //
263 this->clearInputDirty(SET_PARAM_NUM);
264 this->clearInputDirty(RESET_PARAM_NUM);
265 //
266 // Send the values, but don't cause an execution
267 //
268 this->sendValuesQuietly();
269 }
270
271 return values;
272 }
273 //
274 // Determine if this node is of the given class.
275 //
isA(Symbol classname)276 boolean ToggleNode::isA(Symbol classname)
277 {
278 Symbol s = theSymbolManager->registerSymbol(ClassToggleNode);
279 if (s == classname)
280 return TRUE;
281 else
282 return this->InteractorNode::isA(classname);
283 }
284 //
285 // Print the standard .cfg comment and
286 // and the 'toggle: %d, set = %s, reset = %s' comment.
287 //
cfgPrintInteractorComment(FILE * f)288 boolean ToggleNode::cfgPrintInteractorComment(FILE *f)
289 {
290 return this->InteractorNode::cfgPrintInteractorComment(f) &&
291 this->printToggleComment(f,"", TRUE);
292 }
293 //
294 // Parse the standard .cfg comment and
295 // and the 'toggle: %d, set = %s, reset = %s' comment.
296 //
cfgParseInteractorComment(const char * comment,const char * filename,int lineno)297 boolean ToggleNode::cfgParseInteractorComment(const char* comment,
298 const char* filename, int lineno)
299 {
300 return this->InteractorNode::cfgParseInteractorComment(
301 comment,filename,lineno) ||
302 this->parseToggleComment(comment, filename,lineno, TRUE);
303 }
304 //
305 // Print the standard .net comment and
306 // and the 'toggle: %d, set = %s, reset = %s' comment.
307 //
netPrintAuxComment(FILE * f)308 boolean ToggleNode::netPrintAuxComment(FILE *f)
309 {
310 return this->InteractorNode::netPrintAuxComment(f) &&
311 this->printToggleComment(f," ", FALSE);
312 }
313 //
314 // Parse the standard comment and
315 // and the 'toggle: %d, set = %s, reset = %s' comment.
316 //
netParseAuxComment(const char * comment,const char * filename,int lineno)317 boolean ToggleNode::netParseAuxComment(const char* comment,
318 const char* filename, int lineno)
319 {
320 return this->InteractorNode::netParseAuxComment(comment,filename,lineno) ||
321 this->parseToggleComment(comment, filename,lineno, FALSE);
322 }
323 //
324 // Print the 'toggle: %d, set = %s, reset = %s' comment.
325 //
printToggleComment(FILE * f,const char * indent,boolean includeValues)326 boolean ToggleNode::printToggleComment(FILE *f, const char *indent,
327 boolean includeValues)
328 {
329 boolean r = TRUE;
330
331 if (fprintf(f,"%s// toggle : %d", indent, this->isSet() ? 1 : 0) <= 0)
332 return FALSE;
333
334 if (includeValues) {
335 char *setval = this->getSetValue();
336 char *resetval = this->getResetValue();
337 ASSERT(setval && resetval && indent);
338 if (fprintf(f,", set = %s, reset = %s", setval, resetval) <= 0)
339 r = FALSE;
340 delete setval;
341 delete resetval;
342 }
343
344 if (r && (fprintf(f,"\n") <= 0))
345 r = FALSE;
346
347 return r;
348
349 }
350 //
351 // Parse the 'toggle: %d, set = %s, reset = %s' comment.
352 //
parseToggleComment(const char * comment,const char * filename,int lineno,boolean includeValues)353 boolean ToggleNode::parseToggleComment(const char* comment,
354 const char* filename, int lineno,
355 boolean includeValues)
356 {
357 int items, set;
358 char *setstr, *resetstr, *p, *dup = NULL;
359
360 if (strncmp(comment," toggle",7))
361 return FALSE;
362
363 items = sscanf(comment," toggle : %d",&set);
364 if (items != 1)
365 goto parse_error;
366
367 if (includeValues) {
368 dup = DuplicateString(comment);
369
370 //
371 // Get the set and reset values
372 //
373 setstr = strstr(dup, "set = ");
374 if (!setstr) goto parse_error;
375 setstr += 6; // First character of set value
376 p = resetstr = strstr(dup, "reset = ");
377 if (!resetstr) goto parse_error;
378 while (*p!=',' && p!=dup && *p) p--; // Skip back to find ','
379 if (*p != ',') goto parse_error;
380 *p = '\0'; // Now the setstr is set.
381 resetstr += 8; // First character of reset value
382 if ( (p = strchr(resetstr,'\n')) )
383 *p = '\0';
384 // Now the resetstr is set.
385
386 //
387 // Set the two values for the set/reset states.
388 //
389 if (!this->setToggleValues(setstr, resetstr))
390 goto parse_error;
391 }
392 #if 000
393 else {
394 //
395 // Get the values that were read in the 'input[]...' comments
396 // and stuff them in to the AttributeParameters.
397 //
398 this->setToggleValues(this->getInputSetValueString(SET_PARAM_NUM),
399 this->getInputSetValueString(RESET_PARAM_NUM));
400 }
401 #endif
402
403 //
404 // Set but don't send since we are in the middle of reading the net.
405 //
406 if (set == 1)
407 this->set(FALSE);
408 else
409 this->reset(FALSE);
410
411 if (dup) delete dup;
412 return TRUE;
413
414 parse_error:
415 if (dup) delete dup;
416 ErrorMessage("Can't parse 'toggle : ' comment, file %s, line %d",
417 filename, lineno);
418 return FALSE;
419
420 }
421
getShadowingInput(int output_index)422 int ToggleNode::getShadowingInput(int output_index)
423 {
424 if (output_index == 1)
425 return CVAL_PARAM_NUM;
426 else
427 return 0;
428 }
isSetAttributeVisuallyWriteable()429 boolean ToggleNode::isSetAttributeVisuallyWriteable()
430 {
431 return this->isInputDefaulting(SET_PARAM_NUM);
432 }
isResetAttributeVisuallyWriteable()433 boolean ToggleNode::isResetAttributeVisuallyWriteable()
434 {
435 return this->isInputDefaulting(RESET_PARAM_NUM);
436 }
437
438 #if SYSTEM_MACROS // 3/13/95 - begin work for nodes to use system macros
netNodeString(const char * prefix)439 char *ToggleNode::netNodeString(const char *prefix)
440 {
441 return Node::netNodeString(prefix);
442 }
sendValues(boolean ignoreDirty)443 boolean ToggleNode::sendValues(boolean ignoreDirty)
444 {
445 const char *macname = this->getExecModuleNameString();
446
447 MacroDefinition *md = (MacroDefinition*)
448 theNodeDefinitionDictionary->findDefinition(macname);
449 if (md && md->getNetwork()->isDirty()) {
450 md->updateServer();
451 md->getNetwork()->clearDirty();
452 }
453
454 return InteractorNode::sendValues(ignoreDirty);
455 }
456
printValues(FILE * f,const char * prefix,PrintType dest)457 boolean ToggleNode::printValues(FILE *f, const char *prefix, PrintType dest)
458 {
459
460 const char *macname = this->getExecModuleNameString();
461
462 MacroDefinition *md = (MacroDefinition*)
463 theNodeDefinitionDictionary->findDefinition(macname);
464 if (md && md->getNetwork()->isDirty()) {
465 md->printNetworkBody(f,PrintExec);
466 md->getNetwork()->clearDirty();
467 }
468
469
470 return InteractorNode::printValues(f,prefix, dest);
471 }
472
netBeginningOfMacroNodeString(const char * prefix)473 char *ToggleNode::netBeginningOfMacroNodeString(const char *prefix)
474 {
475 const char *macname = this->getExecModuleNameString();
476
477 MacroDefinition *md = (MacroDefinition*)
478 theNodeDefinitionDictionary->findDefinition(macname);
479 if (md && md->loadNetworkBody())
480 md->getNetwork()->setDirty();
481 return NULL;
482 }
483 #endif // 000
484
485
486
printJavaValue(FILE * jf)487 boolean ToggleNode::printJavaValue (FILE* jf)
488 {
489 const char* indent = " ";
490 const char* var_name = this->getJavaVariable();
491
492 //
493 // Load items into the java interactor
494 //
495 fprintf (jf, "%sVector %s_vn = new Vector(2);\n", indent, var_name);
496 fprintf (jf, "%sVector %s_vo = new Vector(2);\n", indent, var_name);
497
498 int i;
499 for (i=1; i<=2; i++) {
500 char* head;
501 if (i==1) head = this->getSetValue();
502 else head = this->getResetValue();
503
504 char* optvalue = head;
505 int k;
506 for (k=strlen(optvalue)-1; k>=0; k--)
507 if ((optvalue[k] == ' ') || (optvalue[k] == '"')) optvalue[k] = '\0';
508 else break;
509 while (*optvalue) {
510 if ((*optvalue == ' ') || (*optvalue == '"')) optvalue++;
511 else break;
512 }
513
514
515 fprintf (jf, "%s%s_vn.addElement(\"%s\");\n", indent,var_name, "set_value");
516 fprintf (jf, "%s%s_vo.addElement(\"%s\");\n", indent,var_name, optvalue);
517
518 delete head;
519 }
520 fprintf(jf, "%s%s.setValues(%s_vn, %s_vo);\n", indent, var_name, var_name, var_name);
521
522 if (this->isSet())
523 if (fprintf (jf, "%s%s.selectOption(1);\n", indent, var_name) <= 0)
524 return FALSE;
525
526 return TRUE;
527 }
528
printJavaType(FILE * jf,const char * indent,const char * var)529 boolean ToggleNode::printJavaType(FILE* jf, const char* indent, const char* var)
530 {
531 Parameter *p = this->getOutputParameter(1);
532 if (p->hasValue()) {
533 Type t = p->getValueType();
534 if (t & DXType::StringType) {
535 fprintf (jf, "%s%s.setOutputType(BinaryInstance.STRING);\n", indent,var);
536 } else if (t & DXType::IntegerType) {
537 fprintf (jf, "%s%s.setOutputType(BinaryInstance.INTEGER);\n", indent,var);
538 } else if (t & DXType::ScalarType) {
539 fprintf (jf, "%s%s.setOutputType(BinaryInstance.SCALAR);\n", indent,var);
540 }
541 } else {
542 fprintf (jf, "%s// The output has no value saved in the net\n", indent);
543 fprintf (jf, "%s%s.setOutputType(BinaryInstance.STRING);\n", indent,var);
544 }
545 return TRUE;
546 }
547
548