/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include "../base/defines.h" #include #include "DXApplication.h" #include "DrivenNode.h" #include "Parameter.h" #include "AttributeParameter.h" #include "ErrorDialogManager.h" // for java stuff #include "Ark.h" #include "ListIterator.h" // // Constructor // DrivenNode::DrivenNode(NodeDefinition *nd, Network *net, int instance) : ModuleMessagingNode(nd, net, instance) { this->visualNotificationDeferrals = 0; this->visualsNeedNotification = FALSE; this->handlingLongMessage = FALSE; } // // Update any inputs that are being updated by the server (i.e. the // module that is doing the data-driven operations). These inputs // are updated in a special way since we don't want to change the // defaulting/set status of the parameter, we don't want it sent back // to the server, and we don't want to mark it as dirty. // Type DrivenNode::setInputAttributeFromServer(int index, const char *val, Type t) { Parameter *p = this->getInputParameter(index); ASSERT(p->isA(ClassAttributeParameter)); boolean was_dirty = p->isDirty(); #if 11 boolean r = this->setInputAttributeParameter(index,val); #else // We now do this to fix GRESH883, with the thinking being that when // we get a value from the server, the real parameter (not just the // attribute parameter) should be updated, regardless of whether or // not it type matches with the attribute. // Also, see AttributeParamter::setAttributeValue(). boolean r = this->setInputAttributeParameter(index,val, TRUE); #endif if (!was_dirty) this->clearInputDirty(index); ASSERT(r); if (t == DXType::UndefinedType) { AttributeParameter *ap = (AttributeParameter*)p; t = ap->getAttributeValueType(); } return t; } // // Check all input parameters to see if any are connected. // If connected, then we consider the ModuleMessagingNode to be data-driven // (at this level of the the class hierarchy) and return TRUE, // otherwise FALSE. // boolean DrivenNode::isDataDriven() { int i, icnt = this->getInputCount(); boolean driven = FALSE; for (i=1 ; !driven && i<=icnt ; i++) { if (this->isInputViewable(i)) #if 0 // 8/9/93 driven = this->isInputConnected(i) || !this->isInputDefaulting(i); #else driven = !this->isInputDefaulting(i); #endif } return driven; } // // Notify anybody that needs to know that a parameter has changed. // At the level we notify all instances that the label has changed. // void DrivenNode::ioParameterStatusChanged(boolean input, int index, NodeParameterStatusChange status) { if ((input) && (status & Node::ParameterArkChanged)) { // // If we become un data driven, then we must make sure the // outputs get sent on the next execution. // boolean driven = this->isDataDriven(); if (driven) { int i, ocnt = this->getOutputCount(); for (i=1 ; i<=ocnt ; i++) this->setOutputDirty(i); // Don't need to send them because the network will get marked // dirty as a result of an arc change. } } this->ModuleMessagingNode::ioParameterStatusChanged(input,index, status); // // Update the UI visuals for this node when ever any of our viewable // input arcs or values change, which may lead to a sensitivity change // on one of the UI visuals for this node. // if (input && ((status & Node::ParameterVisibilityChanged) == 0) && this->isInputViewable(index)) this->notifyVisualsOfStateChange(); } // // Set the message id parameter for a data-driven node. // We assume that the id parameter is always parameter found in // the parameter indexed by this->getMessageIdParamNumber(). // Returns TRUE/FALSE. If FALSE, an error message is given. // boolean DrivenNode::setMessageIdParameter(int id_index) { const char *id = this->getModuleMessageIdString(); if (id_index == 0) { id_index = this->getMessageIdParamNumber(); if (id_index == 0) return TRUE; } if (this->setInputValue(id_index, id, DXType::StringType, FALSE) == DXType::UndefinedType) { ErrorMessage( "Error setting message id string for node %s, check ui.mdf\n", this->getNameString()); return FALSE; } return TRUE; } #if 0 // // Called at the end of a long message. // This can be overridden by those derived classes that expect long messages. // At this level, this method is a no-op. // void DrivenNode::completeLongMessage() { } #endif // // // Called when a message is received from the executive after // this->ExecModuleMessageHandler() is registered in // this->Node::netPrintNode() to receive messages for this node. // We parse all the common information and then the class specific. // If any relevant info was found then we call this->reflectStateChange(). // void DrivenNode::execModuleMessageHandler(int id, const char *line) { const char *p; int values; boolean do_notify; #ifdef DEBUG printf("%s: receiving message #%d...\n", this->getNameString(), id); printf("%s\n",line); #endif this->deferVisualNotification(); // // Parse the attributes specific to the derived class // p = strchr(line,':'); // Skip over '%d:' ASSERT(p); p = strchr(p+1,':'); // Skip over 'Node-name_%d:' ASSERT(p); if (!this->handlingLongMessage && EqualString(p,": begin")) { // // Begin handling a long message. // this->handlingLongMessage = TRUE; // // Don't notify visuals during a long message. // do_notify = FALSE; } else if (EqualString(p,": end")) { // // End of long message encountered. // this->handlingLongMessage = FALSE; // // Always notify visuals after a long message. // do_notify = TRUE; } else { // // Handle both long and short messages. // Only do notification on short messages. // values = this->handleNodeMsgInfo(line); do_notify = (!this->handlingLongMessage && values > 0); } // // Notify the visuals if requested. // if (do_notify) this->notifyVisualsOfStateChange(); this->undeferVisualNotification(TRUE); } // // Return TRUE/FALSE, indicating whether or not we expect to receive // a message from the UI when our module executes in the executive. // By default, a module only executes in the executive for data-driven // nodes and so we don't expect messages unless the node // is data-driven. // boolean DrivenNode::expectingModuleMessage() { return this->isDataDriven(); } // // Notify all UI visuals that the attributes have changed. // This calls this->reflectStateChange() if notification is not // deferred. // void DrivenNode::notifyVisualsOfStateChange(boolean unmanage) { if (!this->isVisualNotificationDeferred()) { this->visualsNeedNotification = FALSE; this->reflectStateChange(unmanage); } else { this->visualsNeedNotification = TRUE; } } // // Determine if the give attribute/paramater is visually writeable (i.e. // settable from something other than the CDB, like the SetAttrDialog). // boolean DrivenNode::isAttributeVisuallyWriteable(int input_index) { if (!this->isDataDriven()) return TRUE; Parameter *p = this->getInputParameter(input_index); ASSERT(p->isA(ClassAttributeParameter)); AttributeParameter *ap = (AttributeParameter*)p; return ap->isAttributeVisuallyWriteable(); } // // Initialize the value of an attribute parameter. // boolean DrivenNode::initInputAttributeParameter(int index, const char *val) { AttributeParameter *p = (AttributeParameter*) this->getInputParameter(index); return p->initAttributeValue(val); } // // Set the value of an attribute parameter. // If forceSync is TRUE (default = FALSE), then force the primary // parameters of the AttributeParameter to be updated regardless of // whether or not the types match. // boolean DrivenNode::setInputAttributeParameter(int index, const char *val, boolean forceSync) { AttributeParameter *p = (AttributeParameter*) this->getInputParameter(index); return p->setAttributeValue(val,forceSync); } // // Get the value of an attribute parameter. // const char *DrivenNode::getInputAttributeParameterValue(int index) { AttributeParameter *p = (AttributeParameter*) this->getInputParameter(index); return p->getAttributeValueString(); } // // Determine if this node is of the given class. // boolean DrivenNode::isA(Symbol classname) { Symbol s = theSymbolManager->registerSymbol(ClassDrivenNode); if (s == classname) return TRUE; else return this->ModuleMessagingNode::isA(classname); } // // Sync all the attribute values with the actual parameter values. // void DrivenNode::syncAttributeParameters() { int i, cnt = this->getInputCount(); for (i=1 ; i<=cnt ; i++) { Parameter *p = this->getInputParameter(i); ASSERT(p); if (p->isA(ClassAttributeParameter)) { AttributeParameter *ap = (AttributeParameter*)p; ap->syncAttributeValue(); } } } int DrivenNode::assignNewInstanceNumber() { int t = this->ModuleMessagingNode::assignNewInstanceNumber(); int index = this->getMessageIdParamNumber(); if (index > 0) this->setMessageIdParameter(index); return t; }