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 = {};