/***********************************************************************/ /* 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 "UIConfig.h" #include "defines.h" #include "TransmitterNode.h" #include "Arc.h" #include "ConfigurationDialog.h" #include "ListIterator.h" #include "ReceiverNode.h" #include "ErrorDialogManager.h" #include "WarningDialogManager.h" #include "InfoDialogManager.h" #include "Network.h" #include "DXVersion.h" #include "Node.h" #include "lex.h" static boolean initializing = FALSE; TransmitterNode::TransmitterNode(NodeDefinition *nd, Network *net, int instnc) : UniqueNameNode(nd, net, instnc) { } boolean TransmitterNode::initialize() { char s[100]; sprintf(s, "wireless_%d", this->getInstanceNumber()); initializing = TRUE; this->setLabelString(s); initializing = FALSE; return TRUE; } TransmitterNode::~TransmitterNode() { } char *TransmitterNode::netNodeString(const char *prefix) { char *string = new char[200]; char *source; int len; Parameter *p = this->getInputParameter(1); source = this->inputParameterNamesString(prefix); sprintf(string, "%s = %s;\n", this->getLabelString(), source); delete source; return string; } boolean TransmitterNode::setLabelString(const char *label) { List *l; Node *node; ListIterator li; if (EqualString(label, this->getLabelString())) return TRUE; if (initializing || this->getNetwork()->isReadingNetwork()) { if (initializing == FALSE) { // // Because of an old bug (hopefully fixed in 3.1.4), we need to scan // for existing receivers with the same name. These receivers are supposed // to be placed later in the .net file than the transmitter. Network:: // mergeNetworks() was not connecting up transmitters and receivers properly // until 3.1.4. So this check will work around a bug. // Network* net = this->getNetwork(); int net_major = net->getNetMajorVersion(); int net_minor = net->getNetMinorVersion(); int net_micro = net->getNetMicroVersion(); int net_version = VERSION_NUMBER( net_major, net_minor, net_micro); int fixed_version = VERSION_NUMBER(3,1,1); if (net_version < fixed_version) { // grab up any receivers that already have this name l = this->getNetwork()->makeClassifiedNodeList(ClassReceiverNode, FALSE); if (l) { li.setList(*l); ReceiverNode *node; while (node = (ReceiverNode*)li.getNext()) { if (!node->isTransmitterConnected() && EqualString(node->getLabelString(), label)) { Network* net = this->getNetwork(); if (!net->checkForCycle (this, node)) { // link me to receiver Arc *a = new Arc(this, 1, node, 1); } else { WarningMessage ( "This network contains Transmitter/Receiver\n" "pair \"%s\" which would cause a cyclic \n" "connection. Executing this network will yield \n" "unpredictable results until this is fixed.", this->getLabelString() ); break; } } } delete l; } } } return this->UniqueNameNode::setLabelString(label); } if (!this->verifyRestrictedLabel(label)) return FALSE; const char* conflict = this->getNetwork()->nameConflictExists(this, label); if (conflict) { ErrorMessage("A %s with name \"%s\" already exists.", conflict, label); return FALSE; } // // Check for cyclic connections before changing anyone's name. (There is // similar code in ReceiverNode.C) Do this only when NOT reading a network. // It's pointless to do this while reading a net file, because the ui doesn't // have the ability to write out .net file with a cycle. // if (this->getNetwork()->isReadingNetwork() == FALSE) { l = this->getNetwork()->makeClassifiedNodeList(ClassReceiverNode, FALSE); if (l) { li.setList(*l); ReceiverNode *node; while (node = (ReceiverNode*)li.getNext()) { if (!node->isTransmitterConnected() && EqualString(node->getLabelString(), label)) { Network* net = this->getNetwork(); if (net->checkForCycle (this, node)) { ErrorMessage ( "Unable to rename Transmitter \"%s\" to \"%s\"\n" "because it would create a cyclic connection.", this->getLabelString(), label ); delete l; return FALSE; } } } delete l; } } if (!this->UniqueNameNode::setLabelString(label)) return FALSE; // rename our receivers l = (List*)this->getOutputArcs(1); li.setList(*l); Arc *a; while (a = (Arc*)li.getNext()) { int dummy; Node *rcvr = a->getDestinationNode(dummy); rcvr->setLabelString(label); } // // grab up any receivers that already have this name // We've already done the check for cyclic connections. // l = this->getNetwork()->makeClassifiedNodeList(ClassReceiverNode, FALSE); if (l) { li.setList(*l); ReceiverNode *node; while (node = (ReceiverNode*)li.getNext()) { if (!node->isTransmitterConnected() && EqualString(node->getLabelString(), label)) { // link me to receiver Arc *a = new Arc(this, 1, node, 1); } } delete l; } return TRUE; } // // Determine if this node is of the given class. // boolean TransmitterNode::isA(Symbol classname) { Symbol s = theSymbolManager->registerSymbol(ClassTransmitterNode); if (s == classname) return TRUE; else return this->UniqueNameNode::isA(classname); } // // Switch the node from one net to another. Resolve any name space collisions. // void TransmitterNode::switchNetwork(Network *from, Network *to) { const char* label = this->getLabelString(); const char* conflict = to->nameConflictExists(this, label); char new_name[100]; boolean name_change_required = FALSE; if (conflict) { sprintf(new_name, "wireless_%d", this->getInstanceNumber()); name_change_required = TRUE; } // // If we would create a cyclic connection then reset the name // List* l = to->makeClassifiedNodeList(ClassReceiverNode, FALSE); if (l) { ListIterator li; li.setList(*l); ReceiverNode *node; const char* cp = (name_change_required? new_name : label); while (node = (ReceiverNode*)li.getNext()) { if (!node->isTransmitterConnected() && EqualString(node->getLabelString(), cp)) { if (to->checkForCycle(this, node)) { sprintf (new_name, "cyclic_connection_%d", this->getInstanceNumber()); name_change_required = TRUE; break; } } } delete l; } if (name_change_required) { InfoMessage("Transmitter %s has been relabeled %s", label, new_name); this->setLabelString(new_name); label = this->getLabelString(); } // // grab up any receivers that already have this name // We've already done the check for cyclic connections. // l = to->makeClassifiedNodeList(ClassReceiverNode, FALSE); if (l) { ListIterator li; li.setList(*l); ReceiverNode *node; while (node = (ReceiverNode*)li.getNext()) { if (!node->isTransmitterConnected() && EqualString(node->getLabelString(), label)) { // link me to receiver Arc *a = new Arc(this, 1, node, 1); } } delete l; } this->UniqueNameNode::switchNetwork(from,to); } boolean TransmitterNode::namesConflict (const char* his_label, const char* my_label, const char* his_classname) { // // You can always match names with other ReceiverNodes. // if (EqualString (his_classname, ClassReceiverNode)) return FALSE; return this->UniqueNameNode::namesConflict (his_label, my_label, his_classname); }