diff --git a/examples/WiringEditor/embedded.html b/examples/WiringEditor/embedded.html
index 2c5179d8..7d376675 100644
--- a/examples/WiringEditor/embedded.html
+++ b/examples/WiringEditor/embedded.html
@@ -108,6 +108,7 @@
+
@@ -193,7 +194,12 @@
Infos
-
+
+ Grouping
+
+
diff --git a/js/Container.js b/js/Container.js
index 39ec8d8c..68f14b24 100644
--- a/js/Container.js
+++ b/js/Container.js
@@ -67,6 +67,10 @@ WireIt.Container = function(options, layer) {
*/
this.eventRemoveWire = new util.CustomEvent("eventRemoveWire");
+ this.eventFocus = new util.CustomEvent("eventFocus");
+
+ this.eventBlur = new util.CustomEvent("eventBlur");
+
// Render the div object
this.render();
@@ -256,7 +260,7 @@ WireIt.Container.prototype = {
* Called when the user made a mouse down on the container and sets the focus to this container (only if within a Layer)
* @method onMouseDown
*/
- onMouseDown: function() {
+ onMouseDown: function(event) {
if(this.layer) {
if(this.layer.focusedContainer && this.layer.focusedContainer != this) {
this.layer.focusedContainer.removeFocus();
@@ -272,6 +276,8 @@ WireIt.Container.prototype = {
*/
setFocus: function() {
Dom.addClass(this.el, CSS_PREFIX+"Container-focused");
+
+ this.eventFocus.fire(this);
},
/**
@@ -280,6 +286,8 @@ WireIt.Container.prototype = {
*/
removeFocus: function() {
Dom.removeClass(this.el, CSS_PREFIX+"Container-focused");
+
+ this.eventBlur.fire(this);
},
/**
diff --git a/js/GroupFormContainer.js b/js/GroupFormContainer.js
index 4d60a51c..e9cfcacd 100644
--- a/js/GroupFormContainer.js
+++ b/js/GroupFormContainer.js
@@ -61,15 +61,17 @@ YAHOO.lang.extend(WireIt.GroupFormContainer, WireIt.FormContainer, {
var expandedContainers = [];
- for (var mI in this.group.modules)
+ for (var mI in this.group.internalConfig.modules)
{
- var m = this.group.modules[mI]
+ var m = this.group.internalConfig.modules[mI];
+
var baseContainerConfig = this.getBaseConfig(m.name);
- YAHOO.lang.augmentObject(m.config, baseContainerConfig); //TODO: Might not want to modify the module config here (in case the group can be reshrunk and old vars are used)
- m.config.title = m.name;
- var newPos = this.translatePosition(m.config.position, position);
- m.config.position = newPos;
- var container = this.layer.addContainer(m.config);
+ var newConfig = YAHOO.lang.JSON.parse( YAHOO.lang.JSON.stringify( m.config ) ) //TODO: nasty deep clone, probably breaks if you have DOM elements in your config or something
+ YAHOO.lang.augmentObject(newConfig , baseContainerConfig);
+ newConfig.title = m.name;
+ var newPos = this.translatePosition(newConfig.position, position);
+ newConfig.position = newPos;
+ var container = this.layer.addContainer(newConfig);
//Dom.addClass(container.el, "WiringEditor-module-"+m.name);
container.setValue(m.value);
@@ -79,16 +81,16 @@ YAHOO.lang.extend(WireIt.GroupFormContainer, WireIt.FormContainer, {
for (var fI in this.form.inputsNames)
{
var f = this.form.inputsNames[fI];
- var internal = this.group.externalToInternalFieldMap[fI];
+ var internal = this.group.externalToInternalMap.fields[fI];
var container = expandedContainers[internal.moduleId];
container.form.inputsNames[internal.name].setValue(f.getValue());
}
- for (var wI in this.group.wires)
+ for (var wI in this.group.internalConfig.wires)
{
- var w = this.group.wires[wI]
+ var w = this.group.internalConfig.wires[wI]
this.layer.addWire(
{
@@ -113,7 +115,7 @@ YAHOO.lang.extend(WireIt.GroupFormContainer, WireIt.FormContainer, {
{
var w = t.wires[wI]
- var internal = this.group.externalToInternalTerminalMap[t.options.name];
+ var internal = this.group.externalToInternalMap.terminals[t.options.name];
var wire = {}
diff --git a/js/Grouper.js b/js/Grouper.js
index cc931a42..181d5cf9 100644
--- a/js/Grouper.js
+++ b/js/Grouper.js
@@ -84,6 +84,377 @@
this.remove(container)
},
+ collapse: function()
+ {
+ var containers = this.containers;
+
+ var groupConfig = {};
+
+ groupConfig.externalToInternalMap = {};
+
+ var visibles = this.workOutVisibleTerminalsAndFields(containers);
+ var getDefaultPrefix = function(i) { return containers[i].title + "_"; };
+ var resolvedFields = this.mapFields(visibles.fields, getDefaultPrefix);
+ groupConfig.externalToInternalMap.fields = resolvedFields.fields;
+ groupConfig.externalToInternalMap.terminals = this.mapTerminals(visibles.terminals, getDefaultPrefix, resolvedFields.terminals);
+
+ groupConfig.fields = this.getFieldConfigs(groupConfig.externalToInternalMap.fields, containers);
+ groupConfig.terminals = this.getTerminalConfigs(groupConfig.externalToInternalMap.terminals, containers);
+
+ groupConfig.internalConfig = {};
+ var center = this.workOutCenter(containers);
+ groupConfig.internalConfig.modules = this.getInternalModuleConfig(containers, center);
+ var wireConfig = this.getWireConfig(this.getWires(containers), containers, this.layer.containers);
+
+ groupConfig.internalConfig.wires = wireConfig.internal;
+
+
+
+ var gc = this.layer.addContainer(
+ {
+ "xtype": "WireIt.GroupFormContainer",
+ "title": "Group",
+
+ "collapsible": true,
+ "fields": [ ],
+ "legend": "Inner group fields",
+ "getBaseConfigFunction" : this.baseConfigFunction,
+ position : center
+ }
+ )
+
+ gc.setValue(groupConfig);
+
+ this.addExternalWires(gc, wireConfig.external);
+
+ this.collapsing = true;
+ for (var i in this.containers)
+ {
+ var elem = this.containers[i]
+ this.layer.removeContainer(elem);
+ }
+ this.collapsing = false;
+
+ this.containers = [];
+ //this.configUITerminalMap = [];
+ this.lastGroupFormContainer = gc;
+ //this.panel.panelElement.hide();
+ gc.groupObject = new WireIt.Group({"containers" : [gc]}, Dom.get("groupConfig"));
+ },
+
+ workOutVisibleTerminalsAndFields: function(containers)
+ {
+ var ret = {terminals : [], fields : []};
+
+ var terminalHasExternalWire = function(t, internalContainers)
+ {
+ for (var wI in t.wires)
+ {
+ var w = t.wires[wI];
+
+ if (internalContainers.indexOf(w.terminal1.container) == -1 ||
+ internalContainers.indexOf(w.terminal2.container) == -1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ for (var cI in containers)
+ {
+ var c = containers[cI];
+ var containerFields = {};
+ var fieldTerminals = {};
+ var add = false;
+
+ if (lang.isValue(c.form))
+ {
+ for (var fI in c.form.inputs)
+ {
+ var f = c.form.inputs[fI];
+
+ if (lang.isValue(f.terminal))
+ {
+ if (terminalHasExternalWire(f.terminal, containers))
+ {
+ containerFields[f.options.name] = {"index" : fI, "field" : f};
+ add = true;
+ }
+ }
+ }
+ }
+
+ if (add)
+ ret.fields[cI] = containerFields
+
+
+ var containerTerminals = {};
+ add = false;
+
+ for (var tI in c.terminals)
+ {
+ var t = c.terminals[tI];
+
+ //Make sure the terminal isn't a field terminal
+ if (!lang.isValue(containerFields[t.options.name]))
+ {
+ if (terminalHasExternalWire(t, containers))
+ {
+ containerTerminals[t.options.name] = {"index" : tI, "terminal" : t};
+ add = true;
+ }
+ }
+ }
+
+ if (add)
+ ret.terminals[cI] = containerTerminals;
+ }
+
+ return ret;
+ },
+
+ mapFields: function(containersFields, getDefaultPrefix)
+ {
+ var usedNames = {};
+
+ var used = function(name)
+ {
+ return lang.isValue(usedNames[name]);
+ };
+
+ for (var cI in containersFields)
+ {
+ var cf = containersFields[cI];
+
+ for (var fI in cf)
+ {
+ var cff = cf[fI];
+ var f = cff.field;
+
+ var name = f.options.name;
+ var externalName = name;
+
+ if (used(externalName))
+ {
+ externalName = getDefaultPrefix(cI) + name;
+
+ if (used(externalName))
+ {
+ var i = 0;
+ var current = externalName;
+
+ do
+ {
+ externalName = current + i;
+ }
+ while(used(externalName))
+ }
+ }
+
+ usedNames[externalName]= {"moduleId" : cI, "name" : name, "type" : "field", "index" : cff.index};
+ }
+ }
+
+ return {
+ fields: usedNames,
+ terminals: usedNames
+ }
+ },
+
+ mapTerminals: function(containersTerminals, getDefaultPrefix, fieldTerminals)
+ {
+ var usedNames = {};
+
+ var used = function(name)
+ {
+ return lang.isValue(usedNames[name]);
+ };
+
+ for (var uI in fieldTerminals)
+ {
+ var ft = fieldTerminals[uI];
+ usedNames[uI] = lang.merge(ft);
+ }
+
+ for (var cI in containersTerminals)
+ {
+ var ct = containersTerminals[cI];
+
+ for (var tI in ct)
+ {
+ var tff = ct[tI];
+ var t = tff.terminal;
+
+ var name = t.options.name;
+ var externalName = name;
+
+ if (used(externalName))
+ {
+ externalName = getDefaultPrefix(cI) + name;
+
+ if (used(externalName))
+ {
+ var i = 0;
+ var current = externalName;
+
+ do
+ {
+ externalName = current + i;
+ }
+ while(used(externalName))
+ }
+ }
+
+ usedNames[externalName]= {"moduleId" : cI, "name" : name, "type" : "terminal", "index" : tff.index};
+ }
+ }
+
+ return usedNames;
+ },
+
+ getFieldConfigs: function(fields, containers)
+ {
+ var fieldConfigs = [];
+
+ for (var fName in fields)
+ {
+ var map = fields[fName];
+ var c = containers[map.moduleId];
+
+ var fI = map.index;
+ var fieldConfig = c.form.inputsNames[fI];
+
+ var config = lang.merge(fieldConfig);
+ config.inputParams = lang.merge(fieldConfig.inputParams);
+ config.inputParams.name = fName;
+ config.inputParams.value = c.form.inputs[fI].getValue();
+
+ fieldConfigs.push(config);
+ }
+
+ return fieldConfigs;
+ },
+
+ getTerminalConfigs: function(terminals, containers)
+ {
+ var terminalConfigs = [];
+
+ for (var tName in terminals)
+ {
+ var map = terminals[tName];
+ var c = containers[map.moduleId];
+ var t = c.terminals[map.index];
+
+ var config = {};
+ config.name = tName;
+ config.direction = t.options.direction;
+ config.offsetPosition = {
+ left : 100 /*positionByNumber(nI, N)*/,
+ top : -15
+ };
+
+ config.ddConfig = t.options.ddConfig;
+
+ terminalConfigs.push(config);
+ }
+
+ return terminalConfigs;
+ },
+
+ getInternalModuleConfig : function(containers)
+ {
+ var modules = []
+ var center = this.workOutCenter(containers);
+
+ for (var cI in containers)
+ {
+ var c = containers[cI];
+ var mConfig = c.getConfig();
+
+ mConfig.position[0] = mConfig.position[0] - center[0];
+ mConfig.position[1] = mConfig.position[1] - center[1];
+
+ //Add container to group
+ modules.push( {name: c.options.title, value: c.getValue(), config: mConfig});
+ }
+
+ return modules;
+ },
+
+ getWires: function(containers)
+ {
+ var wires = [];
+
+ for (var cI in containers)
+ {
+ var c = containers[cI];
+
+ for (var wI in c.wires)
+ {
+ var w = c.wires[wI];
+
+ if (wires.indexOf(w) == -1) //TODO: is there a nicer way of checking the wire hasn't already been added? if you can't have two wires linking the same terminals maybe make a key from moduleId_Terminal + moduleId_Terminal
+ wires.push(c.wires[wI])
+ }
+ }
+
+ return wires;
+ },
+
+ getWireConfig: function(wires, internalContainers, layerContainers)
+ {
+ var externalWires = [];
+ var internalWires = []
+
+ for (var wI in wires)
+ {
+ var w = wires[wI];
+
+ var srcIndex = internalContainers.indexOf(w.terminal1.container)
+ var tgtIndex = internalContainers.indexOf(w.terminal2.container)
+
+ var ret = {};
+ var et, gt;
+
+ if (srcIndex != -1 && tgtIndex != -1)
+ {
+ internalWires.push(
+ {
+ src: {moduleId: srcIndex, terminal: w.terminal1.options.name},
+ tgt: {moduleId: tgtIndex, terminal: w.terminal2.options.name}
+ }
+ );
+ }
+ else
+ {
+ if (srcIndex == -1)
+ {
+ ret.groupIsSource = false;
+ et = w.terminal1;
+ gt = w.terminal2;
+ }
+ else
+ {
+ ret.groupIsSource = true;
+ et = w.terminal2
+ gt = w.terminal1;
+ }
+
+ var ret = {};
+ ret.groupTerminalName = gt.options.name;
+ ret.external = {}
+ ret.external.moduleId = layerContainers.indexOf(et.container);
+ ret.external.terminal = et.options.name;
+
+ externalWires.push(ret);
+ }
+ }
+
+ return {"external" : externalWires, "internal" : internalWires};
+ },
+ /*
collapse: function()
{
@@ -434,7 +805,7 @@
return fields;
},
-
+ */
addExternalWires: function(groupContainer, wireMap)
{
for (var wI in wireMap)
@@ -461,7 +832,7 @@
this.layer.addWire(wireConfig);
}
},
-
+ /*
groupConfig: function(containers, config)
{
var getWireType = function(wire, layer)
@@ -588,7 +959,7 @@
"wires" : {"external" : externalWires, "cut" : cutWires}
};
},
-
+ */
workOutCenter: function(containers)
{
var bounds = {};