/***********************************************************************/ /* 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 #ifndef _Network_h #define _Network_h #include "defines.h" #include "enums.h" #include "Base.h" #include "List.h" #include "NodeList.h" #include "Parse.h" #include "SymbolManager.h" #include "PacketIF.h" #include "WorkSpaceInfo.h" typedef long CPNodeStatus; // Also defined in ControlPanel.h // // Class name definition: // #define ClassNetwork "Network" // // Defines the default output remapping mode. // When FALSE, outputs are not to be remapped by the executive. // This is however only advisor, it is up to the DrivenInteractorNodes and // their derived classes to read their Network's remap mode an use it. // #define DEFAULT_REMAP_INTERACTOR_MODE FALSE // // Referenced classes: // class Dictionary; class EditorWindow; class GetSetConversionDialog; class ImageWindow; class ControlPanel; class CommandScope; class Command; class Node; class StandIn; class SaveAsDialog; class Dialog; class SequencerNode; class DeferrableAction; class EditorWorkSpace; class TransmitterNode; class MacroDefinition; class MacroParameterNode; class ParameterDefinition; class PanelGroupManager; class PanelAccessManager; class DXApplication; class CascadeMenu; class Decorator; class UniqueNameNode; #define FOR_EACH_NETWORK_NODE(network, node, iterator) \ for (iterator.setList(network->nodeList) ; node = (Node*)iterator.getNext() ; ) #define FOR_EACH_NETWORK_PANEL(network, cp, iterator) \ for (iterator.setList(network->panelList) ; \ cp = (ControlPanel*)iterator.getNext() ; ) #define FOR_EACH_NETWORK_DECORATOR(network, decor, iterator) \ for (iterator.setList(network->decoratorList); decor = (Decorator*)iterator.getNext(); ) // // Network class definition: // class Network : public Base { friend class DXApplication; // For the constructor private: // // Methods for extern "C" functions reference by yacc. // void parseComment(char *comment); void parseFunctionID(char *name); void parseArgument(char *name, const boolean isVarname); void parseLValue(char *name); void parseRValue(char *name); void parseStringAttribute(char *name, char *value); void parseIntAttribute(char *name, int value); void parseEndOfMacroDefinition(); // // Parse all .net file comments. // void parseVersionComment(const char* comment, boolean netfile); boolean netParseComments(const char* comment, const char *file, int lineno); void netParseMacroComment(const char* comment); void netParseMODULEComment(const char* comment); void netParseVersionComment(const char* comment); void netParseCATEGORYComment(const char* comment); void netParseDESCRIPTIONComment(const char* comment); void netParseCommentComment(const char* comment); void netParseNodeComment(const char* comment); // // Parse all .cfg file comments. // boolean cfgParseComments(const char* comment, const char *file, int lineno); void cfgParsePanelComment(const char* comment); void cfgParseInteractorComment(const char* comment); void cfgParseNodeComment(const char* comment); void cfgParseVersionComment(const char* comment); ControlPanel *selectionOwner; // // Parsing routines used by yacc. // friend void ParseComment(char* comment); friend void ParseFunctionID(char* name); friend void ParseArgument(char* name, const boolean isVarname); friend void ParseLValue(char* name); friend void ParseRValue(char* name); friend void ParseIntAttribute(char* name, int value); friend void ParseStringAttribute(char* name, char* value); friend void ParseEndOfMacroDefinition(); friend void yyerror(char *, ...); int visitNodes(Node *n); boolean markAndCheckForCycle(Node *srcNode, Node *dstNode); // // Static methods used by the DeferrableAction // class member below. // static void AddNodeWork(void *staticData, void *requestData); static void RemoveNodeWork(void *staticData, void *requestData); // // Static method used by the sendNetwork DeferrableAction // class member below. // static void SendNetwork(void *staticData, void *requestData); // // CommandInterfaces that use these two commands must arrange to set // the instance number of the desired panel in the local data using // UIComponent::setLocalData(). Further, these are never de/activated() // and are created activated. These are set up this way, because // anything that allows opening specific panels will have to be dynamic // (given an editor and the fact that the indices are kept in the // CommandInterface). The CommandInterfaces that use these are created // in this->fillPanelCascade(). // Command* openPanelByInstanceCmd; Command* openPanelGroupByIndexCmd; // // Used by prepareFor/completeNewNetwork() and addNode() to defer // notifying the editor of the new nodes. Instead we notify the editor // after the network is complete. // boolean readingNetwork; // // Add the given panel this network and if the instance number is 0 // then allocate a new instance number for the panel. // boolean addPanel(ControlPanel *p, int instance = 0); // // Check version numbers using rules taken from ParseVersionComment // If there is a problem post on Info Message // boolean versionMismatchQuery (boolean netfile, const char *file); // // If the net came from a file and the file was encrypted, // then this is set to TRUE. // boolean netFileWasEncoded; static Decorator* lastObjectParsed; // Print decorator comments in the .net file. static void SetOwner(void*); static void DeleteSelections(void*); static void Select(void*); virtual boolean parseDecoratorComment (const char *comment, const char *filename, int lineno); // // This is a helper function for optimizeNodeOutputCacheability() that // returns a list of Nodes that are connected to the given output of the // given node. This would be trivial, except for Transmitters and // Receivers, In which case we need to traverse all Receivers for a // given Transmitter and all output arcs for each receiver. // If destList is given, then we append the Nodes to that list, // otherwise we allocate one internally. In either case, we return a // list. In the latter case, the user should delete the returned list. // static List *GetDestinationNodes(Node *src, int output_index, List *destList, boolean rcvrsOk = FALSE); // // Do a recursive depth-first search of this network for macro nodes. // and append their MacroDefinitions to the given list. The list will // come back in depth-first order and will NOT contain duplicates. // This has the side effect of loading the network bodies for all the // returned MacroDefinitions. // void getReferencedMacros(List *macros, List *visted = NULL); class ParseState { public: // // This is state that is defined over a whole .net or .cfg file // static Network *network; static char *parse_file; static boolean error_occurred; static boolean stop_parsing; static boolean issued_version_error; static boolean ignoreUndefinedModules; static Dictionary *undefined_modules; static Dictionary *redefined_modules; static int parse_mode; static boolean main_macro_parsed; ParseState(); ~ParseState(); void initializeForParse(Network *n, int mode, const char *filename); void cleanupAfterParse(); // // This is state that is set for parsing a macro within a .net file // int parse_state; #if WORKSPACE_PAGES // // What did we just parse? Was it a node or a decorator? There are // stateful comments which could apply to either and we must know // wether to parseDecoratorComment or node->netParseComment. // group comments belong to either node or decorator. // int parse_sub_state; #endif Node *node; int input_index; int output_index; boolean node_error_occurred; ControlPanel *control_panel; } parseState; // // Keep track if whether or not the .net had a Get or a Set in it. // boolean fileHadGetOrSetNodes; // Set during parse of .net file // // See fixupTransmitter() below for comment. // static List* RenameTransmitterList; #if WORKSPACE_PAGES Dictionary* groupManagers; #endif protected: friend class StandIn; friend class EditorWindow; friend class GetSetConversionDialog; // for getReferencedMacros // // Protected member data: // EditorWindow* editor; // editor for this network List imageList; // image window list List panelList; // control panel list NodeList nodeList; // network node list List decoratorList; // LabelDecorators in the vpe #if 00 List pickList; // List of pick nodes List transmitterList;// Contains transmitters so that // receivers can find them. List receiverList; // Contains receivers without // transmitters so that // new transmitters can find them. List probeList; // list of all probe nodes. #endif char *description; char *comment; Symbol category; Symbol name; char *prefix; boolean remapInteractorOutputs; DeferrableAction *deferrableRemoveNode; DeferrableAction *deferrableAddNode; DeferrableAction *deferrableSendNetwork; struct { short major; short minor; short micro; } netVersion; struct { short major; short minor; short micro; } dxVersion; CommandScope* commandScope; Command* openAllPanelsCmd; Command* closeAllPanelsCmd; Command* newCmd; Command* saveAsCmd; Command* saveCmd; Command* saveCfgCmd; Command* openCfgCmd; Command* setNameCmd; Command* helpOnNetworkCmd; boolean parse(FILE *f); boolean dirty; boolean fileDirty; char* fileName; boolean macro; MacroDefinition *definition; boolean deleting; // True during destructor. SaveAsDialog *saveAsDialog; Dialog *saveCfgDialog; Dialog *openCfgDialog; Dialog *setNameDialog; Dialog *setCommentDialog; Dialog *helpOnNetworkDialog; // // Parse any network specific info out of the .cfg comments. // boolean cfgParseComment(const char *name, const char *file, int lineno); // // Used to allocate uniq ids for control panels in this network. // int lastPanelInstanceNumber; PanelGroupManager* panelGroupManager; PanelAccessManager* panelAccessManager; // // This will reset the image count for isLastImage(); int imageCount; void resetImageCount(); // // Deletes a given panel from the panel list. // Should you be using this->closeControlPanel(...). // boolean deletePanel(ControlPanel* panel, boolean destroyPanelsNow = FALSE); // // Do any work that is necessary to read in a new .cfg file and/or // clear the network of any .cfg information. // void clearCfgInformation(boolean destroyPanelsNow = FALSE); // // The work space grid to be used by the editor. // WorkSpaceInfo workSpaceInfo; // // Ask various windows to reset their titles. // void resetWindowTitles(); // // Do whatever is necessary to speed up the process of reading in a // new network. This includes letting the EditorWindow know by calling // editor->prepareFor/completeNewNetwork(). // void prepareForNewNetwork(); void completeNewNetwork(); #ifdef DXUI_DEVKIT // // Print the visual program as a .c file that uses libDX calls. // An error message is printed if there was an error. // boolean printAsCCode(FILE *f); #endif // DXUI_DEVKIT // // Print comments and 'include' statements for the macros that are // referenced in this network. If nested is TRUE, then we don't print // the 'include' statements. Return TRUE on sucess or FALSE on failure. // nested and processedMacros args are only really intended to be // used in the recursive calls (i.e. not by generic users). // virtual boolean printMacroReferences(FILE *f, boolean inline_define, PacketIFCallback echoCallback, void *echoClientData); // // Constructor: // THIS CONSTRUCTOR SHOULD NEVER BE CALLED FROM ANYWHERE BUT // DXApplication::newNetwork OR A SUBCLASS OF NETWORK. ANY // SUBCLASSES CONSTRUCTOR SHOULD ONLY BE CALLED FROM A VIRTUAL // REPLACEMENT OF DXApplication::newNetwork. // Network(); // // For editing operations which automatically chop arcs and replace // them with transmitters/receivers. // boolean chopInputArc(Node*, int, Dictionary*, Dictionary*); public: SequencerNode* sequencer; // FIXME! does this need to be public. // // Destructor: // ~Network(); // // Adds a given image window to the image window list. // Deletes a given image window from the image window list. // boolean addImage(ImageWindow* image); List *getImageList() { return &this->imageList; } int getImageCount() { return this->imageList.getSize(); } boolean removeImage(ImageWindow* image); // // Posts the sequencer void postSequencer(); void setRemapInteractorOutputMode(boolean val = TRUE); boolean isRemapInteractorOutputMode() { return this->remapInteractorOutputs; } #if 00 // Maintain the Transmitter and Receiver lists. // The transmitter list contains all transmitters, and the receiver // list contains only "transmitter-less" receivers. boolean addTransmitter(Node *n); boolean removeTransmitter(Node *n); Node *getTransmitter(int i); int getTransmitterCount(); boolean addReceiver(Node *n); boolean removeReceiver(Node *n); Node *getReceiver(int i); int getReceiverCount(); #endif // // Probe management: // #if 00 boolean addProbe(Node*); boolean deleteProbe(Node*); boolean changeProbe(Node*); int getProbeListSize(); List *getProbeList(); #endif // // Pick management: // #if 00 boolean addPick(Node*); boolean deletePick(Node*); boolean changePick(Node*); int getPickListSize(); List *getPickList(); #endif // // Find a panel by index (indexed from 1). // ControlPanel *getPanelByIndex(int index) { ASSERT(index > 0); return (ControlPanel*) this->panelList.getElement(index); } int getPanelCount() { return this->panelList.getSize(); } ControlPanel *getPanelByInstance(int instance); List *getNonEmptyPanels(); // // Close the given panel indicated by panelInstance. // If panelInstance is 0, unmanage all panels. // If the given panel(s) contain 0 interactors, then also call // this->deletePanel() on the panel. // If do_unmanage is true, then unmanage the control panel(s). // do_unmanage should be FALSE when call from the control panel's // close callback. // void closeControlPanel(int panelInstance, boolean do_unmanage = TRUE); // // Open the given panel indicated by panelInstance. // If panelInstance is 0, manage all panels. // void openControlPanel(int panelInstance); // // Open the given panel group indicated by groupIndex. // Group indices are 1 based. // void openControlPanelGroup(int groupIndex); // // Access routines: // EditorWindow* getEditor() { return this->editor; } Command* getCloseAllPanelsCommand() { return this->closeAllPanelsCmd; } Command* getOpenAllPanelsCommand() { return this->openAllPanelsCmd; } Command* getNewCommand() { return this->newCmd; } Command* getSaveAsCommand() { return this->saveAsCmd; } Command* getSaveCommand() { return this->saveCmd; } // // These don't really belong in Network, however their inclusion // here obviates the need to include JavaNet.h in other places // virtual Command* getSaveWebPageCommand() { return NUL(Command*); } virtual Command* getSaveAppletCommand() { return NUL(Command*); } virtual Command* getSaveBeanCommand() { return NUL(Command*); } Command* getSaveCfgCommand() { return this->saveCfgCmd; } Command* getOpenCfgCommand() { return this->openCfgCmd; } Command* getSetNameCommand() { return this->setNameCmd; } Command* getHelpOnNetworkCommand() { return this->helpOnNetworkCmd; } boolean clear(boolean destroyPanelsNow = FALSE); // // Net file format version access functions // int getDXMajorVersion() { return this->dxVersion.major; } int getDXMinorVersion() { return this->dxVersion.minor; } int getDXMicroVersion() { return this->dxVersion.micro; } // // Net file format version access functions // int getNetMajorVersion() { return this->netVersion.major; } int getNetMinorVersion() { return this->netVersion.minor; } int getNetMicroVersion() { return this->netVersion.micro; } void getVersion(int &maj, int& min, int& mic) { maj = this->netVersion.major; min = this->netVersion.minor; mic = this->netVersion.micro; } // // Name and Category manipulations // void setDescription(const char *description, boolean markDirty = TRUE); Symbol setCategory(const char *cat, boolean markDirty = TRUE); Symbol setName(const char *n); const char *getDescriptionString(); const char *getCategoryString() { return theSymbolManager->getSymbolString(category); } Symbol getCategorySymbol() { return category; } const char *getNameString() { return theSymbolManager->getSymbolString(name); } Symbol getNameSymbol() { return name; } const char *getPrefix(); const char *getNetworkComment() { return this->comment; } virtual void setNetworkComment(const char *s); // // Printing/sending script representations of this network // virtual boolean printNetwork(FILE *f, PrintType dest); virtual boolean printHeader(FILE *f, PrintType dest, PacketIFCallback echoCallback = NULL, void *echoClientData = NULL); virtual boolean printBody(FILE *f, PrintType dest, PacketIFCallback echoCallback = NULL, void *echoClientData = NULL); virtual boolean printTrailer(FILE *f, PrintType dest, PacketIFCallback echoCallback = NULL, void *echoClientData = NULL); virtual boolean printValues(FILE *f, PrintType dest); virtual boolean sendNetwork(); virtual boolean sendValues(boolean force = FALSE); // // Convert a filename (with or without corresponding extensions) // to a filename with the correct extension. // static char *FilenameToNetname(const char *filename); static char *FilenameToCfgname(const char *filename); // // Determine if the network is in a state that can be saved to disk. // If so, then return TRUE, otherwise return FALSE and issue an error. // boolean isNetworkSavable(); // // Save the network as a file in the .net and .cfg files // virtual boolean saveNetwork(const char *name, boolean force = FALSE); boolean openCfgFile(const char *name, boolean openStartup = FALSE, boolean send = TRUE); boolean saveCfgFile(const char *name); // // markNetwork sets the flag marked[j] (0 based) if note j // is connected to node i (0 based) in the d direction where d < 0 // means above (to its inputs), and d > 0 means below (to its outputs), // and 0 means in both directions. int connectedNodes(boolean *marked, int i, int d); void sortNetwork(); boolean checkForCycle(Node *srcNode, Node *dstNode); virtual boolean readNetwork(const char *netfile, const char *cfgfile = NULL, boolean ignoreUndefinedModules = FALSE); // These are called by readNetwork() and any other functions that want to // READ a .net file. Returns FILE* and deals with encoded networks. // The static version is provided for others to open and read .net files, // but they must save and pass the wasEncoded value into // CloseNetworkFILE(). // NOTE that encoding is done outside dxui (by dxencode). // static FILE* OpenNetworkFILE(const char *netfile, boolean *wasEncoded, char **errmsg = NULL); FILE* openNetworkFILE(const char *netfile, char **errmsg = NULL); // // Close the .net file that was opened with [Oo]penNetworkFILE(). // static void CloseNetworkFILE(FILE *f, boolean wasEncoded); void closeNetworkFILE(FILE *f); // // Save the network as a file in the .net and .cfg files and any // per Node files (auxiliary) // boolean netPrintNetwork(const char *name); boolean cfgPrintNetwork(const char *name, PrintType dest = PrintFile); void setCPSelectionOwner (ControlPanel *cp) { this->selectionOwner = cp; } ControlPanel *getSelectionOwner () { return this->selectionOwner; } boolean auxPrintNetwork(); boolean isDirty() { return this->dirty; } void setDirty(); void clearDirty() { this->dirty = FALSE; } void setFileDirty(boolean val = TRUE) { this->fileDirty = val; } void clearFileDirty() { this->fileDirty = FALSE; } // // Is the network different than that on disk. Before using this, // be careful, to be sure you shouldn't be using saveToFileRequired() // instead. // boolean isFileDirty() { return this->fileDirty; } // // Return true if the network is different from that on disk, and the // application allows saving of .net and .cfg files. // boolean saveToFileRequired(); // Add a node to the network's node list. void addNode(Node *node, EditorWorkSpace *where = NULL); void deleteNode(Node *node); Node *findNode(Symbol name, int instance); Node *findNode(const char* name, int* startpos = NULL, boolean byLabel = FALSE); void postSaveAsDialog(Widget parent, Command* cmd = NULL); void postSaveCfgDialog(Widget parent); void postOpenCfgDialog(Widget parent); boolean postNameDialog(); void editNetworkComment(); void postHelpOnNetworkDialog(); // // isMacro returns true if this network can be considered a macro. // canBeMacro returns true if there is nothing in the net that prevents // it from being a macro. // makeMacro makes this network a macro if do is true, else it makes it // be a "normal" net. boolean isMacro(); boolean canBeMacro(); boolean makeMacro(boolean make); ParameterDefinition *getInputDefinition(int i); ParameterDefinition *getOutputDefinition(int i); int getInputCount(); int getOutputCount(); boolean moveInputPosition(MacroParameterNode *n, int index); boolean moveOutputPosition(MacroParameterNode *n, int index); void setDefinition(MacroDefinition *md); MacroDefinition *getDefinition(); // // Colormap Management functions // void openColormap(boolean openAll); Node *getNode(const char *name, int instance); // // Manipulate the panel instance numbers for panels in this network. // void resetPanelInstanceNumber() { this->lastPanelInstanceNumber = 0; } void setLastPanelInstanceNumber(int last) { ASSERT(last >= 0); this->lastPanelInstanceNumber = last; } int getLastPanelInstanceNumber() { return this->lastPanelInstanceNumber; } int newPanelInstanceNumber() { return ++this->lastPanelInstanceNumber; } // // Allocate a new control panel that belongs to this network. // ControlPanel *newControlPanel(int instance = 0); PanelAccessManager* getPanelAccessManager() { return this->panelAccessManager; } PanelGroupManager* getPanelGroupManager() { return this->panelGroupManager; } const char* getFileName() { return this->fileName; } WorkSpaceInfo *getWorkSpaceInfo() { return &this->workSpaceInfo; } // // Returns true if the caller is the last element of the image list. // It is assumed that each member of this list will determine, during // Node::prepareToSendNode, will call this to see if it's the last one. boolean isLastImage(); // // Given lists of old and new NodeDefinitions, redefine any nodes // in the current network. // boolean redefineNodes(Dictionary *newdefs, Dictionary *olddefs); // // Find the first free index (indices start from 1) for nodes with the // given name. // Currently, this only works for Input/Output nodes. // int findFreeNodeIndex(const char *nodename); boolean isDeleted() {return this->deleting;} int getNodeCount(); // // Place menu items (ButtonInterfaces) in the CascadeMenu, that when // executed cause individually named panels and panel groups to be opened. // If a PanelAccessManager, then only those ControlPanels defined to be // accessible are placed in the CascadeMenu. // NOTE: to optimize this method, if the menu is returned deactivated() // it may not contain the correct contents and so should no be activated() // except through subsequent calls to this method. // void fillPanelCascade(CascadeMenu *menu, PanelAccessManager *pam); // // Merge two nets together, resolving instance collisions. Delete the // net being passed in. // boolean mergeNetworks(Network *, List *panels, boolean all); boolean mergePanels (Network *); // // The decorators are held in this->decoratorList (no interactors in the list) // void addDecoratorToList (void *e); void removeDecoratorFromList (void *e); // // get and set x,y,width,height of a net in the vpe // void setTopLeftPos(int, int); void getBoundingBox (int *x1, int *y1, int *x2, int *y2); // // look through the network list and make a node list of the given class. // If classname == NULL, then all nodes are included in the list. // If classname != NULL, and includeSubclasses = FALSE, then nodes must // be of the given class and not derived from the given class. // If no nodes were found then NULL is returned. // The returned List must be deleted by the caller. // List *makeClassifiedNodeList(const char *classname, boolean includeSubclasses = TRUE); List *makeNamedControlPanelList(const char *name); List *makeLabelledNodeList(const char *label); // // Search the network for a node of the given class and return TRUE // if found. // boolean containsClassOfNode(const char *classname); // // look through the network list and make a list of the nodes with // the give name. // If no nodes were found then NULL is returned. // The returned List must be deleted by the caller. // List *makeNamedNodeList(const char *nodename); boolean isReadingNetwork() { return this->readingNetwork; } #ifdef DXUI_DEVKIT // // Print the visual program as a .c file that uses libDX calls. // If the filename does not have a '.c' extension, one is added. // An error message is printed if there was an error. // boolean saveAsCCode(const char *filename); #endif // DXUI_DEVKIT //static void Network::GetDestinationNodes (Node*, int, List*, List*); // // Optimally set the output cacheability of all nodes within the network. // We only operate on those that have writable cacheability. // void optimizeNodeOutputCacheability(); boolean wasNetFileEncoded() { return this->netFileWasEncoded;} // // See if the given label is unique among nodes requiring uniqueness. // Return NUL(char*) if unique. Otherwise return the node name of the // guy with whom we have a conflict. // const char* nameConflictExists(UniqueNameNode* passed_in, const char* label); const char* nameConflictExists(const char* label); // // Maintain a list of transmitters which need fixing up after a network read. // Older versions of dx weren't restrictive about name conflicts. Now it // you aren't allowed name conflicts among Transmitter,Receiver,Input,Output. // So when reading a net with a name conflict, let it pass. Just maintain a list // of the conflicts and go back and fix them after the read. // It's only necessary to fix the transmitters because changing them automatically // fixes the receivers. (See renameTransmitters(), and RenameList.) // If/when fixes are applied, we'll form a message string to show the user and // store the string in a list. EditorWindow can show the list if/when there // is a vpe for the network. No vpe/no display messages. // void fixupTransmitter(TransmitterNode*); void renameTransmitters(); List* editorMessages; void addEditorMessage(const char* msg); void showEditorMessages(); // // Called by Remove/AddNodeWork(), but can also be called directly. // This had always been protected but is now public because we need to // revisit command activation for reasons other than adding/removing nodes. // virtual void changeExistanceWork(Node *n, boolean adding); #if WORKSPACE_PAGES Dictionary* getGroupManagers() { return this->groupManagers; } void copyGroupInfo (Node* , List* ); void copyGroupInfo (Node* , Node* ); boolean chopArcs(List*, Dictionary*, Dictionary*); boolean replaceInputArcs(List*, List*); #endif virtual boolean isJavified() { return FALSE; } // // Returns a pointer to the class name. // const char* getClassName() { return ClassNetwork; } }; #endif // _Network_h