diff --git a/core/add-value-to-set-at.js b/core/add-value-to-set-at.js new file mode 100644 index 00000000..ad7fe4ce --- /dev/null +++ b/core/add-value-to-set-at.js @@ -0,0 +1,18 @@ +module.exports = addValueToSetAt; +function addValueToSetAt(set, value, index) { + var node = new set.order.Node(value); + if (!set.store.has(node)) { + if (set.dispatchesRangeChanges) { + set.dispatchBeforeRangeChange([value], [], index); + } + set.order.splice(index, 0, value); + node = set.order.scan(index); + set.store.add(node); + set.length++; + if (set.dispatchesRangeChanges) { + set.dispatchRangeChange([value], [], index); + } + return true; + } + return false; +} diff --git a/core/reel-document.js b/core/reel-document.js index e2a868aa..70b0c37a 100644 --- a/core/reel-document.js +++ b/core/reel-document.js @@ -16,7 +16,8 @@ var Montage = require("montage").Montage, URL = require("core/node/url"), PropertyBlueprint = require("montage/core/meta/property-blueprint").PropertyBlueprint, EventBlueprint = require("montage/core/meta/event-blueprint").EventBlueprint, - ObjectReferences = require("core/object-references").ObjectReferences; + ObjectReferences = require("core/object-references").ObjectReferences, + addValueToSetAt = require("core/add-value-to-set-at"); // The ReelDocument is used for editing Montage Reels exports.ReelDocument = EditingDocument.specialize({ @@ -1605,7 +1606,7 @@ exports.ReelDocument = EditingDocument.specialize({ // Owner blueprint addOwnerBlueprintProperty: { - value: function (name, valueType, cardinality, collectionValueType) { + value: function (name, index, valueType, cardinality, collectionValueType) { var self = this; return this.undoManager.register( "Add owner property", @@ -1623,7 +1624,13 @@ exports.ReelDocument = EditingDocument.specialize({ } blueprint.addPropertyBlueprint(propertyBlueprint); - blueprint.addPropertyBlueprintToGroupNamed(propertyBlueprint, self._exportName); + + if (index !== void 0) { + blueprint.propertyBlueprintGroupForName(self._exportName).splice(index, 0, propertyBlueprint); + } else { + blueprint.addPropertyBlueprintToGroupNamed(propertyBlueprint, self._exportName); + } + return [self.removeOwnerBlueprintProperty, self, name]; }) ); @@ -1657,16 +1664,19 @@ exports.ReelDocument = EditingDocument.specialize({ "Remove owner property", this._ownerBlueprint.then(function (blueprint) { var propertyBlueprint = blueprint.propertyBlueprintForName(name); + + var index = blueprint.propertyBlueprintGroupForName(self._exportName).indexOf(propertyBlueprint); + blueprint.removePropertyBlueprint(propertyBlueprint); blueprint.removePropertyBlueprintFromGroupNamed(propertyBlueprint, self._exportName); - return [self.addOwnerBlueprintProperty, self, name, propertyBlueprint.valueType, propertyBlueprint.cardinality, propertyBlueprint.collectionValueType]; + return [self.addOwnerBlueprintProperty, self, name, index, propertyBlueprint.valueType, propertyBlueprint.cardinality, propertyBlueprint.collectionValueType]; }) ); } }, addOwnerBlueprintEvent: { - value: function (name) { + value: function (name, index) { var self = this; return this.undoManager.register( "Add owner event", @@ -1677,6 +1687,10 @@ exports.ReelDocument = EditingDocument.specialize({ ); blueprint.addEventBlueprint(eventBlueprint); + if (index !== void 0) { + blueprint.ownEventBlueprints.delete(eventBlueprint); + addValueToSetAt(blueprint.ownEventBlueprints, eventBlueprint, index); + } return [self.removeOwnerBlueprintEvent, self, name]; }) ); @@ -1690,8 +1704,13 @@ exports.ReelDocument = EditingDocument.specialize({ "Remove owner event", this._ownerBlueprint.then(function (blueprint) { var eventBlueprint = blueprint.eventBlueprintForName(name); + + var order = blueprint.ownEventBlueprints.order; + var index = order.find(eventBlueprint).index; + blueprint.removeEventBlueprint(eventBlueprint); - return [self.addOwnerBlueprintEvent, self, name]; + + return [self.addOwnerBlueprintEvent, self, name, index]; }) ); } diff --git a/test/all.js b/test/all.js index 14ffedc2..fed9af65 100644 --- a/test/all.js +++ b/test/all.js @@ -6,6 +6,7 @@ require("montage-testing").run(require, [ "test/core/file-descriptor-spec", "test/core/node-proxy-spec", "test/core/object-references-spec", + "test/core/add-value-to-set-at-spec", "test/core/project-controller-extensions-spec", "test/core/project-controller-file-spec", "test/core/project-controller-filesystem-spec", diff --git a/test/core/add-value-to-set-at-spec.js b/test/core/add-value-to-set-at-spec.js new file mode 100644 index 00000000..06079b81 --- /dev/null +++ b/test/core/add-value-to-set-at-spec.js @@ -0,0 +1,76 @@ +var Set = require("montage/collections/set"); +var addValueToSetAt = require("core/add-value-to-set-at"); + +describe("core/add-value-to-set-at", function () { + var set; + beforeEach(function () { + set = new Set(); + set.add("a"); + set.add("b"); + set.add("c"); + }); + + describe("addAt", function () { + it("does not add en existing item", function () { + expect(addValueToSetAt(set, "c", 0)).toEqual(false); + expect(set.toArray()).toEqual(["a", "b", "c"]); + }); + + it("adds at the given position", function () { + expect(addValueToSetAt(set, "X", 1)).toEqual(true); + expect(set.toArray()).toEqual(["a", "X", "b", "c"]); + }); + + it("adds at the end when position exceeds the length", function () { + addValueToSetAt(set, "X", 100); + expect(set.toArray()).toEqual(["a", "b", "c", "X"]); + }); + + it("leaves set.order with the correct length", function () { + addValueToSetAt(set, "X", 1); + expect(set.order.length).toEqual(4); + }); + }); + + describe("pop", function () { + it("works after addAt", function () { + addValueToSetAt(set, "X", 0); + expect(set.pop()).toEqual("c"); + expect(set.toArray()).toEqual(["X", "a", "b"]); + + }); + }); + + describe("delete", function () { + it("works after addAt", function () { + addValueToSetAt(set, "X", 1); + expect(set.delete("X")).toEqual(true); + expect(set.toArray()).toEqual(["a", "b", "c"]); + }); + }); + + describe("range changes", function () { + it("dispatches before range change", function () { + var spy = jasmine.createSpy(); + set.addBeforeRangeChangeListener(spy); + addValueToSetAt(set, "X", 1); + + expect(spy).toHaveBeenCalled(); + expect(spy.mostRecentCall.args[0]).toEqual(["X"]); + expect(spy.mostRecentCall.args[1]).toEqual([]); + expect(spy.mostRecentCall.args[2]).toEqual(1); + }); + + it("dispatches range change", function () { + var spy = jasmine.createSpy(); + set.addRangeChangeListener(spy); + addValueToSetAt(set, "X", 1); + + expect(spy).toHaveBeenCalled(); + expect(spy.mostRecentCall.args[0]).toEqual(["X"]); + expect(spy.mostRecentCall.args[1]).toEqual([]); + expect(spy.mostRecentCall.args[2]).toEqual(1); + }); + }); + +}); diff --git a/test/core/reel-blueprint-editing-spec.js b/test/core/reel-blueprint-editing-spec.js index 3d167df4..a2f66123 100644 --- a/test/core/reel-blueprint-editing-spec.js +++ b/test/core/reel-blueprint-editing-spec.js @@ -57,6 +57,27 @@ describe("core/reel-blueprint-editing-spec", function () { }); }); + it("creates with the given properties", function () { + return reelDocumentPromise.then(function (reelDocument) { + return reelDocument.addOwnerBlueprintProperty("pass", void 0, "string", Infinity, "list") + .then(function () { + expect(defaultGroup[2].name).toBe("pass"); + expect(defaultGroup[2].valueType).toBe("string"); + expect(defaultGroup[2].cardinality).toBe(Infinity); + expect(defaultGroup[2].collectionValueType).toBe("list"); + }); + }); + }); + + it("inserts at the given position", function () { + return reelDocumentPromise.then(function (reelDocument) { + return reelDocument.addOwnerBlueprintProperty("pass", 1) + .then(function () { + expect(defaultGroup[1].name).toBe("pass"); + }); + }); + }); + it("adds a group named after the component if one doesn't exist", function () { return reelDocumentPromise.then(function (reelDocument) { blueprint = new Blueprint(); @@ -98,15 +119,15 @@ describe("core/reel-blueprint-editing-spec", function () { it("correctly undos", function () { return reelDocumentPromise.then(function (reelDocument) { - defaultGroup[1].valueType = "number"; - return reelDocument.removeOwnerBlueprintProperty("b") + defaultGroup[0].valueType = "number"; + return reelDocument.removeOwnerBlueprintProperty("a") .then(function () { return reelDocument.undoManager.undo(); }) .then(function () { expect(defaultGroup.length).toBe(2); - expect(defaultGroup[1].name).toBe("b"); - expect(defaultGroup[1].valueType).toBe("number"); + expect(defaultGroup[0].name).toBe("a"); + expect(defaultGroup[0].valueType).toBe("number"); }); }); }); @@ -165,13 +186,13 @@ describe("core/reel-blueprint-editing-spec", function () { it("correctly undos", function () { return reelDocumentPromise.then(function (reelDocument) { - return reelDocument.removeOwnerBlueprintEvent("b") + return reelDocument.removeOwnerBlueprintEvent("a") .then(function () { return reelDocument.undoManager.undo(); }) .then(function () { expect(eventBlueprints.length).toBe(2); - expect(eventBlueprints[1].name).toBe("b"); + expect(eventBlueprints[0].name).toBe("a"); }); }); }); diff --git a/ui/template-explorer.reel/content/edit-properties.reel/edit-properties.js b/ui/template-explorer.reel/content/edit-properties.reel/edit-properties.js index 88785344..0dce86e1 100644 --- a/ui/template-explorer.reel/content/edit-properties.reel/edit-properties.js +++ b/ui/template-explorer.reel/content/edit-properties.reel/edit-properties.js @@ -72,7 +72,7 @@ exports.EditProperties = Component.specialize({ if (value) { // add... returns the existing group if it already exists this.propertiesController.content = value.addPropertyBlueprintGroupNamed(this.ownerObject.exportName); - this.eventsController.content = value.eventBlueprints; + this.eventsController.content = value.ownEventBlueprints; } } },