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 
15 #include <string.h>
16 
17 #include "DXApplication.h"
18 #include "DrivenNode.h"
19 #include "Parameter.h"
20 #include "AttributeParameter.h"
21 #include "ErrorDialogManager.h"
22 
23 // for java stuff
24 #include "Ark.h"
25 #include "ListIterator.h"
26 
27 //
28 // Constructor
29 //
DrivenNode(NodeDefinition * nd,Network * net,int instance)30 DrivenNode::DrivenNode(NodeDefinition *nd,
31 			Network *net, int instance) :
32                         ModuleMessagingNode(nd, net, instance)
33 {
34     this->visualNotificationDeferrals = 0;
35     this->visualsNeedNotification = FALSE;
36     this->handlingLongMessage = FALSE;
37 }
38 
39 //
40 // Update any inputs that are being updated by the server (i.e. the
41 // module that is doing the data-driven operations).  These inputs
42 // are updated in a special way since we don't want to change the
43 // defaulting/set status of the parameter, we don't want it sent back
44 // to the server, and we don't want to mark it as dirty.
45 //
setInputAttributeFromServer(int index,const char * val,Type t)46 Type DrivenNode::setInputAttributeFromServer(int index,
47 				const char *val, Type t)
48 {
49 
50     Parameter *p = this->getInputParameter(index);
51     ASSERT(p->isA(ClassAttributeParameter));
52     boolean was_dirty = p->isDirty();
53 #if 11
54     boolean r = this->setInputAttributeParameter(index,val);
55 #else   // We now do this to fix GRESH883, with the thinking being that when
56 	// we get a value from the server, the real parameter (not just the
57 	// attribute parameter) should be updated, regardless of whether or
58 	// not it type matches with the attribute.
59 	// Also, see AttributeParamter::setAttributeValue().
60     boolean r = this->setInputAttributeParameter(index,val, TRUE);
61 #endif
62     if (!was_dirty)
63 	this->clearInputDirty(index);
64     ASSERT(r);
65     if (t == DXType::UndefinedType) {
66 	AttributeParameter *ap = (AttributeParameter*)p;
67 	t = ap->getAttributeValueType();
68     }
69     return t;
70 }
71 
72 //
73 // Check all input parameters to see if any are connected.
74 // If connected, then we consider the ModuleMessagingNode to be data-driven
75 // (at this level of the the class hierarchy) and return TRUE,
76 // otherwise FALSE.
77 //
isDataDriven()78 boolean DrivenNode::isDataDriven()
79 {
80     int i, icnt = this->getInputCount();
81     boolean driven = FALSE;
82 
83     for (i=1 ; !driven && i<=icnt ; i++)  {
84 	if (this->isInputViewable(i))
85 #if 0	// 8/9/93
86 	    driven = this->isInputConnected(i) || !this->isInputDefaulting(i);
87 #else
88 	    driven = !this->isInputDefaulting(i);
89 #endif
90     }
91 
92     return driven;
93 }
94 //
95 // Notify anybody that needs to know that a parameter has changed.
96 // At the level we notify all instances that the label has changed.
97 //
ioParameterStatusChanged(boolean input,int index,NodeParameterStatusChange status)98 void DrivenNode::ioParameterStatusChanged(boolean input, int index,
99 					NodeParameterStatusChange status)
100 {
101     if ((input) && (status & Node::ParameterArkChanged)) {
102 	//
103 	// If we become un data driven, then we must make sure the
104 	// outputs get sent on the next execution.
105 	//
106 	boolean driven = this->isDataDriven();
107 	if (driven) {
108 	    int i, ocnt = this->getOutputCount();
109 	    for (i=1 ; i<=ocnt ; i++)
110 		this->setOutputDirty(i);
111 	    // Don't need to send them because the network will get marked
112 	    // dirty as a result of an arc change.
113 	}
114     }
115 
116     this->ModuleMessagingNode::ioParameterStatusChanged(input,index, status);
117 
118     //
119     // Update the UI visuals for this node when ever any of our viewable
120     // input arcs or values change, which may lead to a sensitivity change
121     //  on one of the UI visuals for this node.
122     //
123     if (input && ((status & Node::ParameterVisibilityChanged) == 0) &&
124 		  this->isInputViewable(index))
125 	this->notifyVisualsOfStateChange();
126 }
127 //
128 // Set the message id parameter for a data-driven node.
129 // We assume that the id parameter is always parameter found in
130 // the parameter indexed by this->getMessageIdParamNumber().
131 // Returns TRUE/FALSE.  If FALSE, an error message is given.
132 //
setMessageIdParameter(int id_index)133 boolean DrivenNode::setMessageIdParameter(int id_index)
134 {
135     const char *id = this->getModuleMessageIdString();
136 
137     if (id_index == 0) {
138 	id_index = this->getMessageIdParamNumber();
139     	if (id_index == 0)
140 	    return TRUE;
141     }
142 
143     if (this->setInputValue(id_index, id, DXType::StringType, FALSE) ==
144 						DXType::UndefinedType) {
145         ErrorMessage(
146         "Error setting message id string for node %s, check ui.mdf\n",
147                 this->getNameString());
148 	return FALSE;
149     }
150     return TRUE;
151 }
152 #if 0
153 //
154 // Called at the end of a long message.
155 // This can be overridden by those derived classes that  expect long messages.
156 // At this level, this method is a no-op.
157 //
158 void DrivenNode::completeLongMessage()
159 {
160 }
161 #endif
162 //
163 //
164 // Called when a message is received from the executive after
165 // this->ExecModuleMessageHandler() is registered in
166 // this->Node::netPrintNode() to receive messages for this node.
167 // We parse all the common information and then the class specific.
168 // If any relevant info was found then we call this->reflectStateChange().
169 //
execModuleMessageHandler(int id,const char * line)170 void DrivenNode::execModuleMessageHandler(int id, const char *line)
171 {
172     const char *p;
173     int  values;
174     boolean do_notify;
175 
176 #ifdef DEBUG
177     printf("%s: receiving message #%d...\n", this->getNameString(), id);
178     printf("%s\n",line);
179 #endif
180 
181     this->deferVisualNotification();
182 
183     //
184     // Parse the attributes specific to the derived class
185     //
186     p = strchr(line,':');	// Skip over '%d:'
187     ASSERT(p);
188     p = strchr(p+1,':');	// Skip over 'Node-name_%d:'
189     ASSERT(p);
190 	if (!this->handlingLongMessage && EqualString(p,":  begin")) {
191 		//
192 		// Begin handling a long message.
193 		//
194 		this->handlingLongMessage = TRUE;
195 		//
196 		// Don't notify visuals during a long message.
197 		//
198 		do_notify = FALSE;
199 	} else if (EqualString(p,":  end")) {
200 		//
201 		// End of long message  encountered.
202 		//
203 		this->handlingLongMessage = FALSE;
204 		//
205 		// Always notify visuals after a long message.
206 		//
207 		do_notify = TRUE;
208 	} else {
209 		//
210 		// Handle both long and short messages.
211 		// Only do notification on short messages.
212 		//
213 		values = this->handleNodeMsgInfo(line);
214 		do_notify = (!this->handlingLongMessage && values > 0);
215 	}
216 
217 	//
218 	// Notify the visuals if requested.
219 	//
220 	if (do_notify)
221 		this->notifyVisualsOfStateChange();
222 
223 	this->undeferVisualNotification(TRUE);
224 }
225 //
226 // Return TRUE/FALSE, indicating whether or not we expect to receive
227 // a message from the UI when our module executes in the executive.
228 // By default, a module only executes in the executive for data-driven
229 // nodes and so we don't expect messages unless the node
230 // is data-driven.
231 //
expectingModuleMessage()232 boolean DrivenNode::expectingModuleMessage()
233 {
234     return this->isDataDriven();
235 }
236 
237 //
238 // Notify all UI visuals that the attributes have changed.
239 // This calls this->reflectStateChange() if notification is not
240 // deferred.
241 //
notifyVisualsOfStateChange(boolean unmanage)242 void DrivenNode::notifyVisualsOfStateChange(boolean unmanage)
243 {
244     if (!this->isVisualNotificationDeferred()) {
245         this->visualsNeedNotification = FALSE;
246         this->reflectStateChange(unmanage);
247     } else {
248         this->visualsNeedNotification = TRUE;
249     }
250 }
251 //
252 // Determine if the give attribute/paramater is visually writeable (i.e.
253 // settable from something other than the CDB, like the SetAttrDialog).
254 //
isAttributeVisuallyWriteable(int input_index)255 boolean DrivenNode::isAttributeVisuallyWriteable(int input_index)
256 {
257     if (!this->isDataDriven())
258 	return TRUE;
259 
260     Parameter *p = this->getInputParameter(input_index);
261     ASSERT(p->isA(ClassAttributeParameter));
262     AttributeParameter *ap = (AttributeParameter*)p;
263     return ap->isAttributeVisuallyWriteable();
264 }
265 //
266 // Initialize the value of an attribute parameter.
267 //
initInputAttributeParameter(int index,const char * val)268 boolean DrivenNode::initInputAttributeParameter(int index, const char *val)
269 {
270     AttributeParameter *p = (AttributeParameter*)
271 				this->getInputParameter(index);
272     return p->initAttributeValue(val);
273 }
274 //
275 // Set the value of an attribute parameter.
276 // If forceSync is TRUE (default = FALSE), then force the primary
277 // parameters of the AttributeParameter to be updated regardless of
278 // whether or not the types match.
279 //
setInputAttributeParameter(int index,const char * val,boolean forceSync)280 boolean DrivenNode::setInputAttributeParameter(int index,
281 			const char *val, boolean forceSync)
282 {
283     AttributeParameter *p = (AttributeParameter*)
284 				this->getInputParameter(index);
285     return p->setAttributeValue(val,forceSync);
286 }
287 //
288 // Get the value of an attribute parameter.
289 //
getInputAttributeParameterValue(int index)290 const char *DrivenNode::getInputAttributeParameterValue(int index)
291 {
292     AttributeParameter *p = (AttributeParameter*)
293 				this->getInputParameter(index);
294     return p->getAttributeValueString();
295 }
296 //
297 // Determine if this node is of the given class.
298 //
isA(Symbol classname)299 boolean DrivenNode::isA(Symbol classname)
300 {
301     Symbol s = theSymbolManager->registerSymbol(ClassDrivenNode);
302     if (s == classname)
303 	return TRUE;
304     else
305 	return this->ModuleMessagingNode::isA(classname);
306 }
307 //
308 //  Sync all the attribute values with the actual parameter values.
309 //
syncAttributeParameters()310 void DrivenNode::syncAttributeParameters()
311 {
312     int i, cnt = this->getInputCount();
313 
314 
315     for (i=1 ; i<=cnt ; i++) {
316     	Parameter *p = this->getInputParameter(i);
317 	ASSERT(p);
318 	if (p->isA(ClassAttributeParameter)) {
319 	    AttributeParameter *ap = (AttributeParameter*)p;
320 	    ap->syncAttributeValue();
321 	}
322     }
323 }
324 
assignNewInstanceNumber()325 int DrivenNode::assignNewInstanceNumber()
326 {
327     int t = this->ModuleMessagingNode::assignNewInstanceNumber();
328     int index = this->getMessageIdParamNumber();
329     if (index > 0)
330 	this->setMessageIdParameter(index);
331     return t;
332 }
333 
334 
335 
336 
337