Skip to content

Commit

Permalink
Added op creation to fab. Fixes #177 (#185)
Browse files Browse the repository at this point in the history
WIP #177 Added button

Added necessary callbacks to mixin WIP #177

WIP #177. Added PipelineWidget to use callbacks from mixin
  • Loading branch information
brollb committed Jun 2, 2016
1 parent 317f033 commit 12439b1
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 60 deletions.
126 changes: 126 additions & 0 deletions src/common/viz/PipelineControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/* globals define */
// Shared methods for editing pipelines
define([
'panels/EasyDAG/EasyDAGControl',
'deepforge/viz/OperationControl',
'widgets/EasyDAG/AddNodeDialog',
'underscore'
], function(
EasyDAGControl,
OperationControl,
AddNodeDialog,
_
) {
'use strict';

var PipelineControl = function() {
};

_.extend(PipelineControl.prototype, OperationControl.prototype);

PipelineControl.prototype.DEFAULT_DECORATOR = 'OperationDecorator';

PipelineControl.prototype._getAllDescendentIds =
EasyDAGControl.prototype._getAllDescendentIds;
PipelineControl.prototype._getAllValidChildren =
EasyDAGControl.prototype._getAllValidChildren;
PipelineControl.prototype._getNodeDecorator =
EasyDAGControl.prototype._getNodeDecorator;

PipelineControl.prototype.onCreateInitialNode = function() {
var initialNodes = this.getValidInitialNodes(),
initialNode = initialNodes[0];

if (initialNodes.length > 1) {
// Create the modal view with all possible subsequent nodes
var dialog = new AddNodeDialog();

dialog.show(null, initialNodes.map(node => {
return {node};
}));
dialog.onSelect = nodeInfo => {
if (nodeInfo) {
this.createNode(nodeInfo.node.id);
}
};
} else {
this.createNode(initialNode.id);
}
};

PipelineControl.prototype.getValidInitialNodes = function () {
// Get all nodes that have no inputs
return this._getAllValidChildren(this._currentNodeId)
.map(id => this._client.getNode(id))
.filter(node => !node.isAbstract() && !node.isConnection())
// Checking the name (below) is simply convenience so we can
// still create operation prototypes from Operation (which we
// wouldn't be able to do if it was abstract - which it probably
// should be)
.filter(node => node.getAttribute('name') !== 'Operation' &&
this.getOperationInputs(node).length === 0)
.map(node => this._getObjectDescriptor(node.getId()));
};

PipelineControl.prototype.createNode = function(baseId) {
var parentId = this._currentNodeId,
newNodeId = this._client.createChild({parentId, baseId});

return newNodeId;
};

PipelineControl.prototype._getObjectDescriptor = function(id) {
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id),
node = this._client.getNode(id);

if (this.hasMetaName(id, 'Operation')) {
// Only decorate operations in the currently active node
if (this._currentNodeId !== desc.parentId) {
return desc;
}

// Add inputs and outputs
var childrenIds = node.getChildrenIds(),
inputId = childrenIds.find(cId => this.hasMetaName(cId, 'Inputs')),
outputId = childrenIds.find(cId => this.hasMetaName(cId, 'Outputs')),
inputs,
outputs;

inputs = inputId ? this._client.getNode(inputId).getChildrenIds() : [];
outputs = outputId ? this._client.getNode(outputId).getChildrenIds() : [];

// Add the inputs, outputs in the form:
// [ name, baseId ]
desc.inputs = inputs.map(id => this.formatIO(id));
desc.outputs = outputs.map(id => this.formatIO(id));

// Remove the 'code' attribute
if (desc.attributes.code) {
delete desc.attributes.code;
}

} else if (desc.isConnection) {
// Set src, dst to siblings and add srcPort, dstPort
desc.srcPort = desc.src;
desc.dstPort = desc.dst;

// Get the src/dst that are in the currentNode
desc.src = this.getSiblingContaining(desc.src);
desc.dst = this.getSiblingContaining(desc.dst);

if (desc.src === null || desc.dst === null) {
this._logger.warn(`Could not get src/dst for ${desc.id}`);
}
} else if (this.hasMetaName(desc.id, 'Data')) { // port
// Add nodeId for container
desc.nodeId = this.getSiblingContaining(desc.id);
// It is a data port if it has a parentId and the parent is either
// 'Inputs' or 'Outputs'
desc.isDataPort = desc.parentId &&
(this.hasMetaName(desc.parentId, 'Inputs') || this.hasMetaName(desc.parentId, 'Outputs'));
}
return desc;
};

return PipelineControl;
});
13 changes: 11 additions & 2 deletions src/visualizers/panels/ForgeActionButton/Actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ define([
action: create.Architecture
}
],
// FIXME: the next two should also add the created node to
// the meta
MyDataTypes: [
{
name: 'Create new data type',
Expand All @@ -164,6 +162,17 @@ define([
icon: 'queue',
action: create.Operation
}
],

Pipeline: [
{
name: 'Create new node',
icon: 'queue',
priority: 2,
action: function() {
this.onCreateInitialNode();
}
}
]
};
});
12 changes: 11 additions & 1 deletion src/visualizers/panels/ForgeActionButton/ForgeActionButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
define([
'js/Constants',
'panel/FloatingActionButton/FloatingActionButton',
'deepforge/viz/PipelineControl',
'./Actions',
'text!./PluginConfig.json'
], function (
CONSTANTS,
PluginButton,
PipelineControl,
ACTIONS,
PluginConfig
) {
Expand All @@ -17,6 +19,7 @@ define([
var ForgeActionButton= function (layoutManager, params) {
PluginButton.call(this, layoutManager, params);
this._pluginConfig = JSON.parse(PluginConfig);
this._client = this.client;
this._actions = [];

WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
Expand All @@ -26,7 +29,11 @@ define([
};

// inherit from PanelBaseWithHeader
_.extend(ForgeActionButton.prototype, PluginButton.prototype);
_.extend(
ForgeActionButton.prototype,
PluginButton.prototype,
PipelineControl.prototype
);

ForgeActionButton.prototype.findActionsFor = function(nodeId) {
var node = this.client.getNode(nodeId),
Expand Down Expand Up @@ -58,5 +65,8 @@ define([
this.update();
};

// Add the ability to create initial nodes
// TODO

return ForgeActionButton;
});
60 changes: 3 additions & 57 deletions src/visualizers/panels/PipelineEditor/PipelineEditorControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

define([
'panels/EasyDAG/EasyDAGControl',
'deepforge/viz/OperationControl',
'deepforge/viz/PipelineControl',
'common/core/coreQ',
'common/storage/constants',
'q',
'underscore'
], function (
EasyDAGControl,
OperationControl,
PipelineControl,
Core,
STORAGE_CONSTANTS,
Q,
Expand All @@ -29,10 +29,9 @@ define([
_.extend(
PipelineEditorControl.prototype,
EasyDAGControl.prototype,
OperationControl.prototype
PipelineControl.prototype
);

PipelineEditorControl.prototype.DEFAULT_DECORATOR = 'OperationDecorator';
PipelineEditorControl.prototype.TERRITORY_RULE = {children: 3};
PipelineEditorControl.prototype.selectedObjectChanged = function (nodeId) {
var desc = this._getObjectDescriptor(nodeId);
Expand Down Expand Up @@ -101,59 +100,6 @@ define([
return node.getAttribute('name');
};

PipelineEditorControl.prototype._getObjectDescriptor = function(id) {
var desc = EasyDAGControl.prototype._getObjectDescriptor.call(this, id),
node = this._client.getNode(id);

if (this.hasMetaName(id, 'Operation')) {
// Only decorate operations in the currently active node
if (this._currentNodeId !== desc.parentId) {
return desc;
}

// Add inputs and outputs
var childrenIds = node.getChildrenIds(),
inputId = childrenIds.find(cId => this.hasMetaName(cId, 'Inputs')),
outputId = childrenIds.find(cId => this.hasMetaName(cId, 'Outputs')),
inputs,
outputs;

inputs = inputId ? this._client.getNode(inputId).getChildrenIds() : [];
outputs = outputId ? this._client.getNode(outputId).getChildrenIds() : [];

// Add the inputs, outputs in the form:
// [ name, baseId ]
desc.inputs = inputs.map(id => this.formatIO(id));
desc.outputs = outputs.map(id => this.formatIO(id));

// Remove the 'code' attribute
if (desc.attributes.code) {
delete desc.attributes.code;
}

} else if (desc.isConnection) {
// Set src, dst to siblings and add srcPort, dstPort
desc.srcPort = desc.src;
desc.dstPort = desc.dst;

// Get the src/dst that are in the currentNode
desc.src = this.getSiblingContaining(desc.src);
desc.dst = this.getSiblingContaining(desc.dst);

if (desc.src === null || desc.dst === null) {
this._logger.warn(`Could not get src/dst for ${desc.id}`);
}
} else if (this.hasMetaName(desc.id, 'Data')) { // port
// Add nodeId for container
desc.nodeId = this.getSiblingContaining(desc.id);
// It is a data port if it has a parentId and the parent is either
// 'Inputs' or 'Outputs'
desc.isDataPort = desc.parentId &&
(this.hasMetaName(desc.parentId, 'Inputs') || this.hasMetaName(desc.parentId, 'Outputs'));
}
return desc;
};

PipelineEditorControl.prototype.getSiblingContaining = function(containedId) {
var n = this._client.getNode(containedId);
while (n && n.getParentId() !== this._currentNodeId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

define([
'widgets/EasyDAG/EasyDAGWidget',
'deepforge/viz/PipelineControl',
'./OperationNode',
'underscore',
'css!./styles/PipelineEditorWidget.css'
], function (
EasyDAGWidget,
PipelineControl,
OperationNode,
_
) {
Expand All @@ -29,6 +31,9 @@ define([
_.extend(PipelineEditorWidget.prototype, EasyDAGWidget.prototype);
PipelineEditorWidget.prototype.ItemClass = OperationNode;

PipelineEditorWidget.prototype.onCreateInitialNode =
PipelineControl.prototype.onCreateInitialNode;

//////////////////// Port Support ////////////////////
PipelineEditorWidget.prototype.addPort = function(desc) {
this.items[desc.nodeId].addPort(desc);
Expand Down

0 comments on commit 12439b1

Please sign in to comment.