bool GraphComponent::closeSelectedPlugins () { DBG ("GraphComponent::closeSelectedPlugins"); jassert (host != 0); if (selectedNodes.getNumSelected () > 0) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); BasePlugin* plugin = (BasePlugin*) selected->getUserData (); if (plugin) { if (owner->isPluginEditorWindowOpen (plugin)) owner->closePluginEditorWindow (plugin); host->closePlugin (plugin); selectedNodes.deselect (selected); deletePluginNode (selected); } } selectedNodes.deselectAll (); graphChanged (); return true; } return false; }
GraphNodeComponent* GraphComponent::findNodeByUserData (void* data) { for (int i = nodes.size(); --i >= 0;) { GraphNodeComponent* node = nodes.getUnchecked (i); if (node->getUserData () == data) return node; } return 0; }
//============================================================================== void GraphLinkComponent::mouseUp (const MouseEvent& e) { if (e.mods.isRightButtonDown()) { GraphNodeComponent* node = (to ? to->getParentGraphComponent () : (from ? from->getParentGraphComponent () : 0)); if (node) node->notifyLinkPopupMenuSelected (this); } }
void GraphComponent::nodeSelected (GraphNodeComponent* node) { DBG ("GraphComponent::nodeSelected"); jassert (node != 0) switch (selectedNodes.getNumSelected ()) { case 0: // no items selected { BasePlugin* plugin = (BasePlugin*) node->getUserData (); if (plugin) plugin->setValue (PROP_GRAPHSELECTED, 1); selectedNodes.addToSelection (node); node->repaint (); } break; default: // one or more items selected { if (! selectedNodes.isSelected (node)) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); BasePlugin* plugin = (BasePlugin*) selected->getUserData (); if (plugin) plugin->setValue (PROP_GRAPHSELECTED, 0); selected->repaint (); } selectedNodes.deselectAll (); BasePlugin* plugin = (BasePlugin*) node->getUserData (); if (plugin) plugin->setValue (PROP_GRAPHSELECTED, 1); selectedNodes.addToSelection (node); node->repaint (); } } break; } }
//============================================================================== void GraphComponent::findLassoItemsInArea (Array<GraphNodeComponent*> &itemsFound, int x, int y, int width, int height) { for (int i = 0; i < nodes.size (); i++) { GraphNodeComponent* node = nodes.getUnchecked (i); if ((node->getX() >= x && node->getX() < x + width) && (node->getY() >= y && node->getY() < y + height)) { itemsFound.addIfNotAlreadyThere (node); selectedNodes.addToSelection (node); } else { selectedNodes.deselect (node); } } }
//============================================================================== void GraphLinkComponent::paint (Graphics& g) { Colour wireColour = Colours::black; if ((to != 0 && from != 0)) { GraphNodeComponent* node = to->getParentGraphComponent (); wireColour = node->getConnectorColour (to, isMouseOverOrDragging()); } else { if (to) { GraphNodeComponent* node = to->getParentGraphComponent (); wireColour = node->getConnectorColour (to, true); } else if (from) { GraphNodeComponent* node = from->getParentGraphComponent (); wireColour = node->getConnectorColour (from, true); } } g.setColour (wireColour); g.strokePath (path, PathStrokeType (lineThickness));
void GraphComponent::nodeMoved (GraphNodeComponent* node, const int deltaX, const int deltaY) { // DBG ("GraphComponent::nodeMoved " + String (deltaX) + " " + String (deltaY)); jassert (node != 0); for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); if (selected && selected != node && ! selected->isLocked ()) { BasePlugin* plugin = (BasePlugin*) selected->getUserData (); if (plugin) { int x = selected->getX() + deltaX; int y = selected->getY() + deltaY; x = jmax (0, jmin (getWidth () - selected->getWidth(), x)); y = jmax (0, jmin (getHeight () - selected->getHeight(), y)); plugin->setValue (PROP_GRAPHXPOS, x); plugin->setValue (PROP_GRAPHYPOS, y); selected->setTopLeftPosition (x, y); } } } BasePlugin* plugin = (BasePlugin*) node->getUserData (); if (plugin) { plugin->setValue (PROP_GRAPHXPOS, node->getX()); plugin->setValue (PROP_GRAPHYPOS, node->getY()); } Viewport* parent = findParentComponentOfClass ((Viewport*) 0); if (parent) { parent->notifyComponentChanged (); } }
//============================================================================== bool GraphComponent::createPluginNode (BasePlugin* plugin) { if (plugin) { DBG ("GraphComponent::createPluginNode"); GraphNodeComponent* component; addAndMakeVisible (component = new GraphNodeComponent()); component->setNodeListener (this); // set common data component->setUserData (plugin); component->setUniqueID (plugin->getUniqueHash()); component->setText (plugin->getName ()); component->setLeftToRight (leftToRight); component->setNodeColour (Colour::fromString (plugin->getValue (PROP_GRAPHCOLOUR, T("0xff808080")))); // read properties // int maxPortCount = jmax (plugin->getNumInputs () + plugin->getNumMidiInputs (), // plugin->getNumOutputs () + plugin->getNumMidiOutputs ()); // TODO - if (maxPortCount * portWidth > defaultNodeWidth) ... int pluginType = plugin->getType(); int w = defaultNodeWidth, h = defaultNodeHeight; int numIns = plugin->getNumInputs () + plugin->getNumMidiInputs (); int numOuts = plugin->getNumOutputs () + plugin->getNumMidiOutputs (); if (leftToRight) { h = jmax (h, (jmax (numIns, numOuts) + 1) * 16); const int textHeight = currentFont.getStringWidth (plugin->getName()); h = jmax (h, 16 + jmin (textHeight, 300)); } else { w = jmax (w, (jmax (numIns, numOuts) + 1) * 16); const int textWidth = currentFont.getStringWidth (plugin->getName()); w = jmax (w, 16 + jmin (textWidth, 300)); } int wasLocked = plugin->getIntValue (PROP_GRAPHLOCKED, -1); if (wasLocked < 0) wasLocked = 0; int wasSelected = plugin->getIntValue (PROP_GRAPHSELECTED, 0); int xPos = plugin->getIntValue (PROP_GRAPHXPOS, -1); int yPos = plugin->getIntValue (PROP_GRAPHYPOS, -1); int wSize = plugin->getIntValue (PROP_GRAPHWSIZE, w); if (wSize < 0) wSize = defaultNodeWidth; int hSize = plugin->getIntValue (PROP_GRAPHHSIZE, h); if (hSize < 0) hSize = defaultNodeHeight; String pluginTooltip = plugin->getName (); // input plugin if (pluginType == JOST_PLUGINTYPE_INPUT) { inputs = component; if (xPos < 0) xPos = leftToRight ? 2 : (getWidth () - w) / 2; if (yPos < 0) yPos = leftToRight ? (getHeight() - h) / 2 : 2; } // output plugin else if (pluginType == JOST_PLUGINTYPE_OUTPUT) { outputs = component; if (xPos < 0) xPos = leftToRight ? getWidth () - w - 2 : (getWidth () - w) / 2; if (yPos < 0) yPos = leftToRight ? (getHeight() - h) / 2 : getHeight() - h - 2; } // generic plugin else { if (xPos < 0) xPos = getBounds().getCentreX(); if (yPos < 0) yPos = getBounds().getCentreY(); pluginTooltip = plugin->getFile ().getFullPathName (); } component->setBounds (xPos, yPos, wSize, hSize); component->setLocked (wasLocked); component->setTooltip (pluginTooltip); component->setVisible (true); if (wasSelected) selectedNodes.addToSelection (component); plugin->setValue (PROP_GRAPHXPOS, xPos); plugin->setValue (PROP_GRAPHYPOS, yPos); plugin->setValue (PROP_GRAPHWSIZE, wSize); plugin->setValue (PROP_GRAPHHSIZE, hSize); // restore audio input / output ports if (pluginType != JOST_PLUGINTYPE_INPUT) for (int j = 0; j < plugin->getNumInputs (); j++) component->addInputConnector (JOST_LINKTYPE_AUDIO); // audio cable if (pluginType != JOST_PLUGINTYPE_OUTPUT) for (int j = 0; j < plugin->getNumOutputs (); j++) component->addOutputConnector (JOST_LINKTYPE_AUDIO); // audio cable // restore midi input / output ports if (pluginType != JOST_PLUGINTYPE_INPUT) for (int j = 0; j < plugin->getNumMidiInputs (); j++) component->addInputConnector (JOST_LINKTYPE_MIDI); // midi cable if (pluginType != JOST_PLUGINTYPE_OUTPUT) for (int j = 0; j < plugin->getNumMidiOutputs (); j++) component->addOutputConnector (JOST_LINKTYPE_MIDI); // midi cable nodes.add (component); Viewport* parent = findParentComponentOfClass ((Viewport*) 0); if (parent) { parent->notifyComponentChanged (); } return true; } return false; }
void GraphComponent::updateDisplayPlugins () { DBG ("GraphComponent::updateDisplayPlugins"); jassert (host != 0); cleanInternalGraph (); // rebuild nodes ! for (int i = 0; i < host->getPluginsCount (); i++) { createPluginNode (host->getPluginByIndex (i)); } // update audio / midi connection links ! ProcessingGraph* audioGraph = host->getAudioGraph (); for (int i = 0; i < audioGraph->getNodeCount (); i++) { ProcessingNode* source = audioGraph->getNode (i); BasePlugin* sourceData = (BasePlugin*) source->getData (); GraphNodeComponent* sourceNode = findNodeByUserData (sourceData); if (sourceNode != 0) { for (int j = source->getLinksCount (JOST_LINKTYPE_AUDIO); --j >= 0;) { ProcessingLink* link = source->getLink (JOST_LINKTYPE_AUDIO, j); BasePlugin* destData = (BasePlugin*) link->destination->getData (); GraphNodeComponent* destNode = findNodeByUserData (destData); if (destNode != 0) { sourceNode->connectToNode (link->sourcePort, destNode, link->destinationPort, false); } } } } for (int i = 0; i < audioGraph->getNodeCount (); i++) { ProcessingNode* source = audioGraph->getNode (i); BasePlugin* sourceData = (BasePlugin*) source->getData (); GraphNodeComponent* sourceNode = findNodeByUserData (sourceData); if (sourceNode != 0) { for (int j = source->getLinksCount (JOST_LINKTYPE_MIDI); --j >= 0;) { ProcessingLink* link = source->getLink (JOST_LINKTYPE_MIDI, j); BasePlugin* destData = (BasePlugin*) link->destination->getData (); GraphNodeComponent* destNode = findNodeByUserData (destData); if (destNode != 0) { sourceNode->connectToNode (link->sourcePort + sourceNode->getFirstOutputOfType (JOST_LINKTYPE_MIDI), destNode, link->destinationPort + destNode->getFirstInputOfType (JOST_LINKTYPE_MIDI), false); } } } } // update connectors graphChanged (); // update fixed node size and position resized (); }
bool GraphComponent::keyPressed (const KeyPress& key) { if (key.isKeyCode (KeyPress::leftKey)) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); if (selected != inputs && selected != outputs) selected->setTopLeftPosition (selected->getX() - 1, selected->getY()); } } else if (key.isKeyCode (KeyPress::rightKey)) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); if (selected != inputs && selected != outputs) selected->setTopLeftPosition (selected->getX() + 1, selected->getY()); } } else if (key.isKeyCode (KeyPress::upKey)) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); if (selected != inputs && selected != outputs) selected->setTopLeftPosition (selected->getX(), selected->getY() - 1); } } else if (key.isKeyCode (KeyPress::downKey)) { for (int i = 0; i < selectedNodes.getNumSelected (); i++) { GraphNodeComponent* selected = selectedNodes.getSelectedItem (i); if (selected != inputs && selected != outputs) selected->setTopLeftPosition (selected->getX(), selected->getY() + 1); } } else if (key.isKeyCode (KeyPress::deleteKey)) { closeSelectedPlugins (); } else { return Component::keyPressed (key); } return true; }
//============================================================================== void GraphComponent::recalculateConnectionsRecursive (GraphNodeComponent* node, ProcessingGraph* graph, const int insertIndex, // const int connectorType, const bool createConnection) { BasePlugin* source = (BasePlugin*) node->getUserData (); if (source != 0 && ! graph->contains (source)) { graph->insertNode (insertIndex, source); int currentIndex = insertIndex + 1; for (int i = 0; i < node->getOutputConnectorCount (); i++) { int sourceOutputMidiOffset = node->getFirstOutputOfType (JOST_LINKTYPE_MIDI); int destOutputMidiOffset = 0; GraphConnectorComponent* connector = node->getOutputConnector (i); // if (connector->getType () == connectorType) { // we are the same type, get linked connectors Array <GraphConnectorComponent*> linked; connector->getLinkedConnectors (linked); for (int j = 0; j < linked.size (); j++) { GraphConnectorComponent* other = linked.getUnchecked (j); GraphNodeComponent* otherNode = other->getParentGraphComponent(); // breath first recalculateConnectionsRecursive (otherNode, graph, currentIndex, // connectorType, createConnection); // create link here ! if (createConnection) { BasePlugin* destination = (BasePlugin*) otherNode->getUserData (); if (destination != 0) { if (connector->getType () == JOST_LINKTYPE_AUDIO) { graph->connectTo (source, connector->getConnectorID(), destination, other->getConnectorID(), JOST_LINKTYPE_AUDIO); } else if (connector->getType () == JOST_LINKTYPE_MIDI) { destOutputMidiOffset = otherNode->getFirstInputOfType (JOST_LINKTYPE_MIDI); graph->connectTo (source, connector->getConnectorID() - sourceOutputMidiOffset, destination, other->getConnectorID() - destOutputMidiOffset, JOST_LINKTYPE_MIDI); } } } // end create link ! } } } } }