src_js/iconolab-bundle/src/components/cutout/shape-resizer.js
changeset 146 f912b591e1c1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src_js/iconolab-bundle/src/components/cutout/shape-resizer.js	Fri Aug 19 19:04:26 2016 +0200
@@ -0,0 +1,159 @@
+/* Enabling us to resize a shape width a handler 
+	#http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types
+*/
+import { eventEmitter } from "../utils"
+
+var ShapeResizer = function (paper, shape, vp, vb) {
+	this.paper = paper;
+	this.shape = shape;
+	this.handlers = [];
+	this.viewPort = vp;
+	this.viewBox = vb;
+	this.isResizing = false;
+	this.currentPosition = {};
+	this.HANDLER_SIZE = 8;
+	this.SHAPE_MIN_SIZE = 20;
+	this.states = {};
+	this.noop = function (){}
+	this.init();
+}
+
+var api = ShapeResizer.prototype = {
+
+	init: function () {
+		this.showHandlers();
+
+	},
+	
+	computeHandlerSize: function () {
+		return this.HANDLER_SIZE * (Math.min(this.viewBox[2], this.viewBox[3])) / this.viewPort.width; //w==h
+	},
+
+	showHandlers: function () {
+		/* show handler here */
+		var bbox = this.shape.getBBox();
+		var handleX = bbox.x - (this.computeHandlerSize()/2);
+		var handleY = bbox.y - (this.computeHandlerSize()/2);
+		var handler = this.paper.rect(handleX, handleY, this.computeHandlerSize(), this.computeHandlerSize()).attr({fill: 'red'});
+		handler.addClass("drawingHandler");
+		this.shape.addClass("drawingHandler");
+		var handlerInfos = {position: "t_r", handler: handler};
+		this.handlers.push(handlerInfos);
+		this.shapesGroup = this.paper.g(this.shape, handler);
+		this.attachEvents();
+	},
+
+	/*one handlers */
+	updateShapePositions: function (handlerData, dx, dy) {
+		//start
+		var handlerBBox = handlerData.handler.getBBox();
+		var shapeBBox = this.shape.data("origBbox");
+		var newX = handlerBBox.x + (this.computeHandlerSize() / 2);
+		var newY = handlerBBox.y + (this.computeHandlerSize() / 2);
+
+		/*to the right => reduce the size */
+		var newWidth = (dx > 0) ? shapeBBox.width - dx : shapeBBox.width + Math.abs(dx); 
+		var newHeight = (dy > 0) ? shapeBBox.height - dy : shapeBBox.height + Math.abs(dy);
+		
+		var transformValue = this.shape.data('origTransform') + (this.shape.data('origTransform') ? "T" : "t") + [dx, dy];
+		this.shape.attr({'transform': transformValue, width: newWidth, height: newHeight});
+	},
+
+	dragEvents: {
+		onStart: function (handlerData, dx, dy, e) {
+			this.startPosition = {x: e.clientX, y: e.clientY};
+			this.isResizing = true;
+			this.currentPosition = {};
+			handlerData.handler.data("origTransform", handlerData.handler.transform().local);
+			this.shape.data("origBbox", this.shape.getBBox());
+			this.shape.data("origBounding", this.shape.node.getBoundingClientRect());
+			this.shape.data("origTransform", this.shape.transform().local);
+		},
+
+		onMove: function (handlerData, dx, dy, x, y, e) {
+			
+			var tdx, tdy;
+            var snapInvMatrix = handlerData.handler.transform().diffMatrix.invert();
+            snapInvMatrix.e = snapInvMatrix.f = 0;
+            tdx = snapInvMatrix.x( dx,dy ); 
+            tdy = snapInvMatrix.y( dx,dy );
+
+			this.currentPosition.x = e.clientX;
+			this.currentPosition.y = e.clientY;
+			if (! this.checkBondaries(dx, dy)) { return; }
+
+			handlerData.handler.transform( "t" + [ tdx, tdy ] + handlerData.handler.data("origTransform")  );
+			this.updateShapePositions(handlerData, tdx, tdy);
+		},
+
+		onStop: function () {
+			this.isResizing = false;
+			this.startPosition = {};
+			this.currentPosition = {};
+		}
+	},
+	
+	checkBondaries: function (dx, dy) {
+		var result = true;
+		var origBounding = this.shape.data("origBounding");
+		var getBoundingClientRect = this.shape.node.getBoundingClientRect();
+
+		if (origBounding.width - dx <=  this.SHAPE_MIN_SIZE) {
+			result = false;
+		}
+
+		if (origBounding.height - dy <= this.SHAPE_MIN_SIZE) {
+			result = false;
+		}
+
+		return result;
+	},
+
+	destroy: function () {
+		this.handlers.map(function (handlerData) {
+			handlerData.handler.remove();
+		});
+		delete this;
+	},
+
+	getZoomFactor: function () {
+		return { 
+				x: this.viewPort.width / this.viewBox[2],
+				y: this.viewPort.height / this.viewBox[3]
+		};
+	},
+
+	attachEvents: function () {
+		var self = this;
+		this.handlers.map(function (handlerData) {
+			handlerData.handler.drag(
+				self.dragEvents.onMove.bind(self, handlerData),
+			 	self.dragEvents.onStart.bind(self, handlerData),
+				self.dragEvents.onStop.bind(self, handlerData));
+		});
+
+		eventEmitter.on("cutout:clear", function () {
+			self.destroy();
+		});
+		
+		this.shapesGroup.drag(function (dx, dy) {
+			if (self.isResizing) { return; }
+            var snapInvMatrix = this.transform().diffMatrix.invert();
+            snapInvMatrix.e = snapInvMatrix.f = 0;
+            var tdx = snapInvMatrix.x( dx,dy ); 
+            var tdy = snapInvMatrix.y( dx,dy );
+
+			var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [tdx, tdy];
+			this.transform(transformValue);
+		}, function () {
+			this.data('origTransform', this.transform().local);
+		}, this.noop);
+	},
+}
+
+export default {
+
+	enable_resizer : function (paper, rect, viewPort, cViewbox) {
+		new ShapeResizer(paper, rect, viewPort, cViewbox);
+	}
+}
\ No newline at end of file