/***** * * ResizableSelection.es * * Author: Antoine Quint * *****/ ResizableSelection.VERSION = 0.1; ResizableSelection.prototype = new EventTarget(false) ResizableSelection.prototype.Class = ResizableSelection; ResizableSelection.Super = EventTarget.prototype; ResizableSelection.Directions = { TOP_LEFT: 1, TOP_RIGHT: 2, BOTTOM_LEFT: 3, BOTTOM_RIGHT: 4 }; function ResizableSelection () { this.Target = null; this.Bounds = null; this.OrignalBounds = null; this.Container = null; this.BoundingRect = null; this.Interactors = {}; this.Built = false; this.Drawn = false; this.Display = false; this.DragTarget = null; this.Dragger = null; this.Direction = this.Class.Directions.TOP_LEFT; this.Init(); }; ResizableSelection.prototype.toString = function () { return '[ResizableSelection]'; }; /***** Core Methods *****/ ResizableSelection.prototype.Init = function () { this.Class.Super.Init.call(this); this.Build(); }; ResizableSelection.prototype.Build = function () { this.BuildContainer(); this.BuildBoundingRect(); this.BuildInteractors(); this.Built = true; }; ResizableSelection.prototype.BuildContainer = function () { var attributes = { css: [ ['display', 'inline'], ['fill', 'white'], ['stroke', '#4f80ff'], ['stroke-width', '1px'], ['shape-rendering', 'optimizeSpeed'] ] }; this.Container = SVGUtil.CreateElement('g', attributes); }; ResizableSelection.prototype.BuildBoundingRect = function () { var attributes = { css: [ ['fill', 'none'] ] }; this.BoundingRect = this.Container.appendChild( SVGUtil.CreateElement('rect', attributes) ); }; ResizableSelection.prototype.BuildInteractors = function () { var attributes = { xml: [ ['width', 16], ['height', 16] ] }; this.Interactors.TopLeft = this.Container.appendChild( SVGUtil.CreateElement('rect', attributes) ); this.Interactors.TopRight = this.Container.appendChild( SVGUtil.CreateElement('rect', attributes) ); this.Interactors.BottomLeft = this.Container.appendChild( SVGUtil.CreateElement('rect', attributes) ); this.Interactors.BottomRight = this.Container.appendChild( SVGUtil.CreateElement('rect', attributes) ); }; ResizableSelection.prototype.Refresh = function () { this.RefreshBoundingRect(); this.RefreshInteractors(); }; ResizableSelection.prototype.RefreshBoundingRect = function () { var b = this.Bounds; var x = b.x; var y = b.y; var dirX = 'LEFT'; var dirY = 'TOP'; if (b.x > b.x + b.width) { x = b.x + b.width; dirX = 'RIGHT'; } if (b.y > b.y + b.height) { y = b.y + b.height; dirY = 'BOTTOM'; } this.BoundingRect.setAttribute('x', x); this.BoundingRect.setAttribute('y', y); this.BoundingRect.setAttribute('width', Math.abs(b.width)); this.BoundingRect.setAttribute('height', Math.abs(b.height)); var dir = this.Class.Directions[dirY + '_' + dirX]; if (dir != this.Direction) { this.Direction = dir; this.DispatchEvent({type: 'directionChange', direction: this.Direction}); } }; ResizableSelection.prototype.RefreshInteractors = function () { var b = this.Bounds; var leftX = b.x - this.Interactors.TopLeft.width.baseVal.value/2; var rightX = b.x + b.width - this.Interactors.TopLeft.width.baseVal.value/2; var topY = b.y - this.Interactors.TopLeft.height.baseVal.value/2; var bottomY = b.y + b.height - this.Interactors.TopLeft.height.baseVal.value/2; this.Interactors.TopLeft.setAttribute('x', leftX); this.Interactors.TopLeft.setAttribute('y', topY); this.Interactors.TopRight.setAttribute('x', rightX); this.Interactors.TopRight.setAttribute('y', topY); this.Interactors.BottomLeft.setAttribute('x', leftX); this.Interactors.BottomLeft.setAttribute('y', bottomY); this.Interactors.BottomRight.setAttribute('x', rightX); this.Interactors.BottomRight.setAttribute('y', bottomY); }; ResizableSelection.prototype.EnableInteractors = function () { for (var i in this.Interactors) { this.Interactors[i].addEventListener('mousedown', this, false); } }; ResizableSelection.prototype.DisableInteractors = function () { for (var i in this.Interactors) { this.Interactors[i].removeEventListener('mousedown', this, false); } }; ResizableSelection.prototype.EnableDragger = function (dragTarget, e) { this.DragTarget = dragTarget; this.Dragger = new Dragger(); this.Dragger.AddEventListener("dragbegin", this, false); this.Dragger.AddEventListener("drag", this, false); this.Dragger.AddEventListener("dragend", this, false); this.Dragger.SetContext(this.Target); this.Dragger.Drag(e); }; ResizableSelection.prototype.DisableDragger = function () { this.Dragger = null; this.DragTarget = null; }; /***** Events *****/ ResizableSelection.prototype.MakeEvent = function(type) { return new ResizeEvent( type, this.GetUserBounds() ); } ResizableSelection.prototype.Onmousedown = function (e) { var target = e.target; for (var i in this.Interactors) { if (this.Interactors[i] === target) { this.EnableDragger(this.Interactors[i], e); this.DisableInteractors(); } } }; ResizableSelection.prototype.Ondragbegin = function(e) { this.OriginalBounds = SVGUtil.CreateSVGRect( this.Bounds.x, this.Bounds.y, this.Bounds.width, this.Bounds.height ); this.DispatchEvent(this.MakeEvent(ResizeEvent.Events.RESIZEBEGIN)); }; ResizableSelection.prototype.Ondrag = function(e) { var x, y, w, h; var d = SVGUtil.CreateSVGPoint(e.Last.x - e.Start.x, e.Last.y - e.Start.y); if (this.DragTarget === this.Interactors.TopLeft) { x = this.OriginalBounds.x + d.x; y = this.OriginalBounds.y + d.y; w = this.OriginalBounds.width - d.x; h = this.OriginalBounds.height - d.y; } else if (this.DragTarget === this.Interactors.TopRight) { x = this.Bounds.x; y = this.OriginalBounds.y + d.y; w = this.OriginalBounds.width + d.x; h = this.OriginalBounds.height - d.y; } else if (this.DragTarget === this.Interactors.BottomLeft) { x = this.OriginalBounds.x + d.x; y = this.Bounds.y; w = this.OriginalBounds.width - d.x; h = this.OriginalBounds.height + d.y; } else if (this.DragTarget === this.Interactors.BottomRight) { x = this.Bounds.x; y = this.Bounds.y; w = this.OriginalBounds.width + d.x; h = this.OriginalBounds.height + d.y; } this.Bounds.x = x; this.Bounds.y = y; this.Bounds.width = w; this.Bounds.height = h; this.Refresh(); this.DispatchEvent(this.MakeEvent(ResizeEvent.Events.RESIZE)); }; ResizableSelection.prototype.Ondragend = function(e) { this.DisableDragger(); this.DispatchEvent(this.MakeEvent(ResizeEvent.Events.RESIZEEND)); this.EnableInteractors(); }; ResizableSelection.prototype.Draw = function () { SVGUtil.InsertAfter(this.Container, this.Target); this.Drawn = true; this.Refresh(); }; ResizableSelection.prototype.GetUserBounds = function () { return this.BoundingRect.getBBox(); }; /***** Public Methods *****/ ResizableSelection.prototype.SetTarget = function (target) { if (this.Target != target) { this.Target = target; this.Draw(); } }; ResizableSelection.prototype.SetBounds = function (bounds) { this.Bounds = bounds; this.Refresh(); }; ResizableSelection.prototype.Show = function () { if (!this.Display) { this.Container.style.setProperty('display', 'inline', null); this.EnableInteractors(); this.Display = true; } }; ResizableSelection.prototype.Hide = function () { if (this.Display) { this.Container.style.setProperty('display', 'none', null); this.Display = false; } }; /***** * * ResizeEvent.es * * Author: Antoine Quint * *****/ ResizeEvent.VERSION = 0.1; ResizeEvent.Events = { RESIZEBEGIN : "resizebegin", RESIZE : "resize", RESIZEEND : "resizeend" }; function ResizeEvent(type, b) { this.Init(type, b); } ResizeEvent.prototype.toString = function () { return '[ResizeEvent]'; }; ResizeEvent.prototype.Init = function (type, b) { this.type = type; this.X = b.x; this.Y = b.y; this.Width = b.width; this.Height = b.height; };