From 8ef667315ca6a81bb1369943eaf3643ae2db5037 Mon Sep 17 00:00:00 2001 From: Jon Reid Date: Mon, 26 Mar 2012 17:04:28 -0700 Subject: Timeline: Drag and Drop of layers. --- images/transparent.png | Bin 0 -> 158 bytes js/panels/Timeline/Layer.reel/Layer.html | 32 +---- js/panels/Timeline/Layer.reel/Layer.js | 83 ++++++++--- .../Timeline/TimelinePanel.reel/TimelinePanel.html | 2 +- .../Timeline/TimelinePanel.reel/TimelinePanel.js | 152 +++++++++++++++++++++ .../TimelinePanel.reel/css/TimelinePanel.css | 3 + 6 files changed, 224 insertions(+), 48 deletions(-) create mode 100644 images/transparent.png diff --git a/images/transparent.png b/images/transparent.png new file mode 100644 index 00000000..c1411593 Binary files /dev/null and b/images/transparent.png differ diff --git a/js/panels/Timeline/Layer.reel/Layer.html b/js/panels/Timeline/Layer.reel/Layer.html index ef98bdd5..454c2742 100644 --- a/js/panels/Timeline/Layer.reel/Layer.html +++ b/js/panels/Timeline/Layer.reel/Layer.html @@ -23,7 +23,8 @@ "transformCollapser" : {"@" : "transformCollapser"}, "styleCollapser" : {"@" : "styleCollapser"}, "clickerMain" : {"#" : "clicker-main"}, - "myLabel" : {"#" : "myLabel"} + "myLabel" : {"#" : "myLabel"}, + "dragDrop" : {"@" : "DragDrop"} } }, "dtext1" : { @@ -315,34 +316,7 @@ "oneway" : false } } - }, - - "DragDrop": { - "module": "js/panels/Timeline/DragDrop.js", - "name": "DragDropComposer", - "properties": { - "element": {"#": "myLabel"}, - "component": {"@": "owner"} - }, - "listeners": [ - { - "type": "dragStart", - "listener": {"@": "owner"} - }, - { - "type": "dropHover", - "listener": {"@": "owner"} - }, - { - "type": "dropped", - "listener": {"@": "owner"} - }, - { - "type": "dropEnd", - "listener": {"@": "owner"} - } - ] - } + } } diff --git a/js/panels/Timeline/Layer.reel/Layer.js b/js/panels/Timeline/Layer.reel/Layer.js index bddfcd3e..9cf321b1 100644 --- a/js/panels/Timeline/Layer.reel/Layer.js +++ b/js/panels/Timeline/Layer.reel/Layer.js @@ -102,6 +102,7 @@ var Layer = exports.Layer = Montage.create(Component, { }, set:function(value){ this._layerID = value; + this.layerData.layerID = value; } }, @@ -119,7 +120,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextPositionX !== value) { this._dtextPositionX = value; - //this.needsDraw = true; + this.layerData.dtextPositionX = value; } } @@ -138,7 +139,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextPositionY !== value) { this._dtextPositionY = value; - //this.needsDraw = true; + this.layerData.dtextPositionY = value; } } @@ -157,7 +158,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextScaleX !== value) { this._dtextScaleX = value; - //this.needsDraw = true; + this.layerData.dtextScaleX = value; } } @@ -176,7 +177,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextScaleY !== value) { this._dtextScaleY = value; - //this.needsDraw = true; + this.layerData.dtextScaleY = value; } } @@ -195,7 +196,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextSkewX !== value) { this._dtextSkewX = value; - //this.needsDraw = true; + this.layerData.dtextSkewX = value; } } @@ -214,7 +215,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextSkewY !== value) { this._dtextSkewY = value; - //this.needsDraw = true; + this.layerData.dtextSkewY = value; } } @@ -233,7 +234,7 @@ var Layer = exports.Layer = Montage.create(Component, { set:function(value){ if (this._dtextRotate !== value) { this._dtextRotate = value; - //this.needsDraw = true; + this.layerData.dtextRotate = value; } } @@ -278,6 +279,7 @@ var Layer = exports.Layer = Montage.create(Component, { }, set: function(newVal) { this._isActive = newVal; + this.layerData.isActive = newVal; } }, @@ -294,6 +296,7 @@ var Layer = exports.Layer = Montage.create(Component, { }, set:function(value){ this._isAnimated = value; + this.layerData.isAnimated = newVal; } }, _justAdded: { @@ -384,11 +387,15 @@ var Layer = exports.Layer = Montage.create(Component, { set: function(newVal) { if (newVal !== this._bypassAnimation) { this._bypassAnimation = newVal; - this.layerData.bypassAnimation = newVal; - //this.triggerOutgoingBinding(); + this.layerData.bypassAnimation = newVal; } } }, + + // Is this the first draw? + _isFirstDraw : { + value: true + }, _layerData:{ serializable:true, @@ -459,12 +466,6 @@ var Layer = exports.Layer = Montage.create(Component, { } } }, - - // Is this the first draw? - _isFirstDraw : { - value: true - }, - /* END: Models */ /* Begin: Draw cycle */ @@ -507,7 +508,12 @@ var Layer = exports.Layer = Montage.create(Component, { this.element.addEventListener("click", this, false); // Drag and drop event hanlders - this.element.addEventListener("dropped", this, false); + this.element.addEventListener("mouseover", this.handleMouseover.bind(this), false); + this.element.addEventListener("mouseout", this.handleMouseout.bind(this), false); + this.element.addEventListener("dragover", this.handleDragover.bind(this), false); + this.element.addEventListener("dragleave", this.handleDragleave.bind(this), false); + this.element.addEventListener("dragstart", this.handleDragstart.bind(this), false); + this.element.addEventListener("drop", this.handleDrop.bind(this), false); } }, @@ -545,6 +551,8 @@ var Layer = exports.Layer = Montage.create(Component, { this.titleSelector = this.label.querySelector(".collapsible-label"); this.buttonAddStyle = this.element.querySelector(".button-add"); this.buttonDeleteStyle = this.element.querySelector(".button-delete"); + + } }, @@ -786,9 +794,48 @@ var Layer = exports.Layer = Montage.create(Component, { this.triggerOutgoingBinding(); } }, - handleDropped : { + handleMouseover: { value: function(event) { - console.log('wheeee! WWEWWEWWWWEEEEEEEEE') + this.element.draggable = true; + } + }, + handleMouseout: { + value: function(event) { + this.element.draggable = false; + } + }, + handleDragenter: { + value: function(event) { + } + }, + handleDragleave: { + value: function(event) { + this.element.classList.remove("dragOver"); + } + }, + handleDragstart: { + value: function(event) { + this.parentComponent.parentComponent.dragLayerID = this.layerID; + event.dataTransfer.setData('Text', 'Layer'); + } + }, + handleDragover: { + value: function(event) { + event.preventDefault(); + this.element.classList.add("dragOver"); + event.dataTransfer.dropEffect = "move"; + return false; + } + }, + + handleDrop : { + value: function(event) { + event.stopPropagation(); + this.element.classList.remove("dragOver"); + if (this.parentComponent.parentComponent.dragLayerID !== this.layerID) { + this.parentComponent.parentComponent.dropLayerID = this.layerID; + } + return false; } }, /* End: Event handlers */ diff --git a/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.html b/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.html index 2e0bf7dd..3833a891 100644 --- a/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.html +++ b/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.html @@ -162,7 +162,7 @@
Master Layer
-
+
diff --git a/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.js b/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.js index bc474a46..ffcd6686 100644 --- a/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.js +++ b/js/panels/Timeline/TimelinePanel.reel/TimelinePanel.js @@ -238,6 +238,57 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { timeMarkerHolder:{ value:null }, + _dragAndDropHelper : { + value: false + }, + _dragAndDropHelperCoords: { + value: false + }, + _dragAndDropHelperOffset : { + value: false + }, + _dragLayerID : { + value: null + }, + dragLayerID : { + get: function() { + return this._dragLayerID; + }, + set: function(newVal) { + if (newVal !== this._dragLayerID) { + this._dragLayerID = newVal; + } + } + }, + _dropLayerID : { + value: null + }, + dropLayerID : { + get: function() { + return this._dropLayerID; + }, + set: function(newVal) { + if (newVal !== this._dropLayerID) { + this._dropLayerID = newVal; + + // Create a snapshot of arrLayers so we can manipulate it safely + var arrLayers = this.arrLayers, + dragLayerIndex = this.getLayerIndexByID(this.dragLayerID), + dropLayerIndex = this.getLayerIndexByID(this.dropLayerID), + dragLayer = arrLayers[dragLayerIndex]; + + arrLayers.splice(dragLayerIndex, 1); + arrLayers.splice(dropLayerIndex, 0, dragLayer); + + // Update the repetition! + this.arrLayers = arrLayers; + + // Clear for future DnD + this._dropLayerID = null; + this._dragLayerID = null; + } + } + }, /* === END: Models === */ /* === BEGIN: Draw cycle === */ prepareForDraw:{ @@ -247,6 +298,12 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { this.eventManager.addEventListener("onOpenDocument", this.handleDocumentChange.bind(this), false); this.eventManager.addEventListener("closeDocument", this.handleDocumentChange.bind(this), false); this.eventManager.addEventListener("switchDocument", this.handleDocumentChange.bind(this), false); + + // Bind drag and drop event handlers + this.container_layers.addEventListener("dragstart", this.handleLayerDragStart.bind(this), false); + this.container_layers.addEventListener("dragend", this.handleLayerDragEnd.bind(this), false); + this.container_layers.addEventListener("dragover", this.handleLayerDragover.bind(this), false); + this.container_layers.addEventListener("drop", this.handleLayerDrop.bind(this), false); } }, @@ -258,6 +315,25 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { } } }, + + draw: { + value: function() { + + // Drag and Drop: + // Do we have a helper to append? + if (this._appendHelper === true) { + this.container_layers.appendChild(this._dragAndDropHelper); + this._appendHelper = false; + } + // Do we need to move the helper? + if (this._dragAndDropHelperCoords !== false) { + if (this._dragAndDropHelper !== null) { + this._dragAndDropHelper.style.top = this._dragAndDropHelperCoords; + } + this._dragAndDropHelperCoords = false; + } + } + }, /* === END: Draw cycle === */ /* === BEGIN: Controllers === */ // Create an empty layer template object with minimal defaults and return it for use @@ -365,6 +441,7 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { this.layout_tracks = this.element.querySelector(".layout-tracks"); this.layout_markers = this.element.querySelector(".layout_markers"); this.timeline_leftpane.addEventListener("mousedown", this.timelineLeftPaneMousedown.bind(this), false); + this.timeline_leftpane.addEventListener("mouseup", this.timelineLeftPaneMouseup.bind(this), false); this.layout_tracks.addEventListener("scroll", this.updateLayerScroll.bind(this), false); this.user_layers.addEventListener("scroll", this.updateLayerScroll.bind(this), false); this.end_hottext.addEventListener("changing", this.updateTrackContainerWidth.bind(this), false); @@ -586,6 +663,13 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { var myIndex = this.getActiveLayerIndex(); this.selectLayer(myIndex, true); } + this._isMousedown = true; + } + }, + + timelineLeftPaneMouseup:{ + value:function (event) { + this._isMousedown = false; } }, @@ -891,6 +975,74 @@ var TimelinePanel = exports.TimelinePanel = Montage.create(Component, { } } }, + + handleLayerDragStart : { + value: function(event) { + var dragIcon = document.createElement("img"); + event.dataTransfer.effectAllowed = 'move'; + event.dataTransfer.setData('Text', this.identifier); + dragIcon.src = "/images/transparent.png"; + dragIcon.width = 1; + event.dataTransfer.setDragImage(dragIcon, 0, 0); + + // Clone the element we're dragging + this._dragAndDropHelper = event.target.cloneNode(true); + this._dragAndDropHelper.style.opacity = 0.8; + this._dragAndDropHelper.style.position = "absolute"; + this._dragAndDropHelper.style.top = "0px"; + this._dragAndDropHelper.style.left = "0px"; + this._dragAndDropHelper.style.zIndex = 700; + + this._dragAndDropHelper.style.width = window.getComputedStyle(this.container_layers, null).getPropertyValue("width"); + this._dragAndDropHelper.classList.add("timeline-dnd-helper"); + + // Get the offset + var findYOffset = function(obj) { + var curleft = curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + + } while (obj = obj.offsetParent); + } + return curtop; + } + this._dragAndDropHelperOffset = findYOffset(this.container_layers); + this._appendHelper = true; + // this.container_layers.appendChild(this._dragAndDropHelper); + } + }, + handleLayerDragover: { + value: function(event) { + var currPos = 0; + currPos = event.y - this._dragAndDropHelperOffset -28; + this._dragAndDropHelperCoords = currPos + "px"; + this.needsDraw = true; + } + }, + handleLayerDragEnd : { + value: function(event) { + // Delete the helper and clean up + if (this._dragAndDropHelper !== null) { + this.container_layers.removeChild(this._dragAndDropHelper); + this._dragAndDropHelper = null; + } + } + }, + handleLayerDrop : { + value: function(event) { + event.stopPropagation(); + event.preventDefault(); + // Usually drop fires after dragend, but sometimes + // dragend doesn't fire. So if we're here in drop + // and there's still a helper, we need to manually fire dragend. + if (this._dragAndDropHelper !== null) { + this.container_layers.removeChild(this._dragAndDropHelper); + this._dragAndDropHelper = null; + } + } + }, /* === END: Controllers === */ /* === BEGIN: Logging routines === */ diff --git a/js/panels/Timeline/TimelinePanel.reel/css/TimelinePanel.css b/js/panels/Timeline/TimelinePanel.reel/css/TimelinePanel.css index 129b9771..b9d45979 100644 --- a/js/panels/Timeline/TimelinePanel.reel/css/TimelinePanel.css +++ b/js/panels/Timeline/TimelinePanel.reel/css/TimelinePanel.css @@ -284,3 +284,6 @@ display: none; box-shadow: rgb(17, 17, 17) 0px 0px 14px inset; } +.timeline-dnd-helper { + -webkit-transform: scale(.9, .9); +} -- cgit v1.2.3