From ae15f82bb66d1fc3401ebdca4c941d17d7616954 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Thu, 5 Jun 2014 17:31:11 -0700 Subject: [PATCH] sizing and drag hint --- elements/design-canvas/design-canvas.html | 85 ++++++++++++++++++- elements/design-frame/design-frame.css | 19 +++++ elements/design-tree/design-tree.html | 7 +- .../designer-element/designer-element.html | 4 +- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/elements/design-canvas/design-canvas.html b/elements/design-canvas/design-canvas.html index 6f1bf434..bbc7acea 100644 --- a/elements/design-canvas/design-canvas.html +++ b/elements/design-canvas/design-canvas.html @@ -35,6 +35,11 @@ 'drag-start': 'drag' }, + observe: { + 'dragInfo.dropTarget': 'updateDropTarget' + }, + + resizeNubSize: 10, grid: 10, selected: null, @@ -164,7 +169,12 @@ switch(event.keyCode) { // ESC case 27: - this.selectParentElement(); + // context handling for esc based on drag state + if (this.dragInfo) { + this.selectParentDropHint(); + } else { + this.selectParentElement(); + } break; // backspace? delete? case 8: @@ -184,6 +194,11 @@ return; } dragInfo.origin = dragInfo.element.getBoundingClientRect(); + // delegate to size API + if (this.dragShouldSize(dragInfo.event, dragInfo.origin)) { + this.sizeStart(dragInfo); + return; + } // delegate to drag API this.dragStart(dragInfo); // multiplex drop @@ -197,6 +212,34 @@ this.selected = dragInfo.element; }, + dragShouldSize: function(event, rect) { + return (Math.abs(rect.right - event.clientX) < this.resizeNubSize) && + (Math.abs(rect.bottom - event.clientY) < this.resizeNubSize); + }, + + sizeStart: function(dragInfo) { + this.classList.add('sizing'); + this.selected = dragInfo.element; + // + // contextualize utilities + // + var snap = this.snap.bind(this); + var rule = this.ruleForElement(dragInfo.element); + // + // attach handlers to the dragInfo + // + dragInfo.drag = function() { + var p = snap(this.origin.width + this.event.dx, this.origin.height + this.event.dy); + rule.style.width = p.x + 'px'; + rule.style.height = p.y + 'px'; + }; + var canvas = this; + dragInfo.drop = function() { + canvas.classList.remove('sizing'); + canvas.notify(); + }; + }, + // // abstracted drag API // @@ -209,6 +252,7 @@ // dragStart: function(dragInfo) { + this.dragInfo = dragInfo; // TODO(sjmiles): if this is an element from the design-canvas, it's immediately // pulled out of it's original context if (dragInfo.element.parentNode != this) { @@ -231,6 +275,7 @@ var snap = this.snap.bind(this); var rule = this.ruleForElement(dragInfo.element); var drop = this.drop.bind(this); + var dropHint = this.dropHint.bind(this); var scope = function(target) { return this.scopedTarget(this, target) }.bind(this); @@ -242,14 +287,17 @@ var p = snap(this.start.x + this.event.dx, this.start.y + this.event.dy); rule.style.left = p.x + 'px'; rule.style.top = p.y + 'px'; + dropHint(this); }; dragInfo.drop = function() { - this.dropTarget = scope(this.event.relatedTarget); + this.dropTarget = this.dropTarget || scope(this.event.relatedTarget); + this.dropTarget.classList.remove('drop-target'); return drop(this); }; }, drop: function(dragInfo) { + this.dragInfo = null; // remove dragging affordances (e.g. absolutely positioned) this.unsetDraggableStyleRules(dragInfo.element); // TODO(sjmiles): restore clipping (ad hoc) @@ -276,6 +324,39 @@ } }, + dropHint: function(dragInfo) { + this.job('hint-job', function() { + var event = { + clientX: dragInfo.event.clientX, + clientY: dragInfo.event.clientY, + target: dragInfo.dropTarget + } + dragInfo.dropTarget = PolymerGestures.targetFinding.findTarget(event); + }); + }, + + selectParentDropHint: function() { + console.log('selectParentDropHint'); + var hint = this.dragInfo && this.dragInfo.dropTarget; + if (hint) { + var parent = this.findContainer(this.dragInfo.element, hint.parentNode); + if (parent) { + this.dragInfo.dropTarget = parent; + } + } + console.log(this.dragInfo.dropTarget); + }, + + updateDropTarget: function(old) { + if (old) { + old.classList.remove('drop-target'); + } + var target = this.dragInfo && this.dragInfo.dropTarget; + if (target) { + target.classList.add('drop-target'); + } + }, + // utility update: function() { diff --git a/elements/design-frame/design-frame.css b/elements/design-frame/design-frame.css index bd9491d6..fed3d8d0 100644 --- a/elements/design-frame/design-frame.css +++ b/elements/design-frame/design-frame.css @@ -15,4 +15,23 @@ #canvas .selected-element { outline: solid 3px rgba(66, 87, 203, 0.8); outline-offset: -3px; +} + +#canvas *::after { + position: absolute; + content: ' '; + bottom: 0; + right: 0; + height: 10px; + width: 10px; + cursor: se-resize; +} + +#canvas.sizing { + cursor: se-resize; +} + +#canvas .drop-target { + outline: dotted 2px black; + outline-offset: -2px; } \ No newline at end of file diff --git a/elements/design-tree/design-tree.html b/elements/design-tree/design-tree.html index 988f6d14..8f97a938 100644 --- a/elements/design-tree/design-tree.html +++ b/elements/design-tree/design-tree.html @@ -52,9 +52,14 @@ Polymer({ components: null, canvas: null, + dirty: 0, observe: { - 'canvas selected': 'update' + 'canvas selected dirty': 'update' + }, + + forceUpdate: function() { + this.dirty++; }, update: function() { diff --git a/elements/designer-element/designer-element.html b/elements/designer-element/designer-element.html index 734e3e6d..fae244b3 100644 --- a/elements/designer-element/designer-element.html +++ b/elements/designer-element/designer-element.html @@ -174,8 +174,10 @@ }, designChange: function(event) { - this.$.inspector.inspected = this.designer.selected; + this.$.inspector.selected = this.designer.selected; this.$.tree.selected = this.designer.selected; + this.$.inspector.forceUpdate(); + this.$.tree.forceUpdate(); this.selectedName = this.makeSelectedName(this.designer.selected); this.recordChange(); },