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