Ver Fonte

More object serialization and file utils

tentone há 5 anos atrás
pai
commit
9ebbdf19b0

+ 229 - 96
build/escher.js

@@ -1832,101 +1832,6 @@
 		this.fillStyle = data.fillStyle;
 	};
 
-	/**
-	 * Graph object is used to draw simple graph data into the canvas.
-	 *
-	 * Graph data is composed of X, Y values.
-	 *
-	 * @class
-	 * @extends {Object2D}
-	 */
-	function Graph()
-	{
-		Object2D.call(this);
-
-		/**
-		 * Graph object containing the size of the object.
-		 */
-		this.box = new Box2(new Vector2(-50, -35), new Vector2(50, 35));
-
-		/**
-		 * Color of the box border line.
-		 */
-		this.strokeStyle = "rgb(0, 153, 255)";
-
-		/**
-		 * Line width.
-		 */
-		this.lineWidth = 1;
-
-		/**
-		 * Background color of the box.
-		 */
-		this.fillStyle = "rgba(0, 153, 255, 0.3)";
-
-		/**
-		 * Minimum value of the graph.
-		 */
-		this.min = 0;
-
-		/**
-		 * Maximum value of the graph.
-		 */
-		this.max = 10;
-
-		/**
-		 * Data to be presented in the graph.
-		 *
-		 * The array should store numeric values.
-		 */
-		this.data = [];
-	}
-
-	Graph.prototype = Object.create(Object2D.prototype);
-	Graph.prototype.constructor = Graph;
-	Graph.prototype.type = "Graph";
-
-	Graph.prototype.isInside = function(point)
-	{
-		return this.box.containsPoint(point);
-	};
-
-	Graph.prototype.draw = function(context, viewport, canvas)
-	{
-		if(this.data.length === 0)
-		{
-			return;
-		}
-		
-		var width = this.box.max.x - this.box.min.x;
-		var height = this.box.max.y - this.box.min.y;
-
-		context.lineWidth = this.lineWidth;
-		context.strokeStyle = this.strokeStyle;
-		context.beginPath();
-			
-		var step = width / (this.data.length - 1);
-		var gamma = this.max - this.min;
-
-		context.moveTo(this.box.min.x, this.box.max.y - ((this.data[0] - this.min) / gamma) * height);
-		
-		for(var i = 1, s = step; i < this.data.length; s += step, i++)
-		{
-			context.lineTo(this.box.min.x + s, this.box.max.y - ((this.data[i] - this.min) / gamma) * height);
-		}
-
-		context.stroke();
-
-		if(this.fillStyle !== null)
-		{
-			context.fillStyle = this.fillStyle;
-
-			context.lineTo(this.box.max.x, this.box.max.y);
-			context.lineTo(this.box.min.x, this.box.max.y);
-			context.fill();
-		}
-	};
-
 	/**
 	 * Image object is used to draw an image from URL.
 	 *
@@ -1990,6 +1895,24 @@
 		}
 	};
 
+	Image.prototype.serialize = function(recursive)
+	{
+		var data = Object2D.prototype.serialize.call(this, recursive);
+
+		data.box = this.box.toArray();
+		data.image = this.image.src;
+
+		return data;
+	};
+
+	Image.prototype.parse = function(data)
+	{
+		Object2D.prototype.parse.call(this, data);
+
+		this.box.fromArray(data.box);
+		this.image.src = data.image;
+	};
+
 	/**
 	 * Line object draw a line from one point to another without any kind of interpolation.
 	 *
@@ -4005,7 +3928,9 @@
 		this.box = new Box2();
 
 		/**
-		 * Image source DOM element.
+		 * Image source DOM element. Used as a source for the pattern image.
+		 *
+		 * This element can be replaced by one of other type (e.g canvas, video).
 		 *
 		 * @type {Element}
 		 */
@@ -4014,6 +3939,10 @@
 		/**
 		 * Repetition indicates how the pattern image should be repeated.
 		 *
+		 * Possible values are "repeat", "repeat-x", "repeat-y" or "no-repeat".
+		 *
+		 * More information about this attribute here https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern.
+		 *
 		 * @type {string}
 		 */
 		this.repetition = "repeat";
@@ -4066,6 +3995,149 @@
 		}
 	};
 
+	Image.prototype.serialize = function(recursive)
+	{
+		var data = Object2D.prototype.serialize.call(this, recursive);
+
+		data.box = this.box.toArray();
+		data.image = this.image.src;
+		data.repetition = this.repetition;
+
+		return data;
+	};
+
+	Image.prototype.parse = function(data)
+	{
+		Object2D.prototype.parse.call(this, data);
+
+		this.box.fromArray(data.box);
+		this.image.src = data.image;
+		this.repetition = data.repetition;
+	};
+
+	/**
+	 * Graph object is used to draw simple graph data into the canvas.
+	 *
+	 * Graph data is composed of X, Y values.
+	 *
+	 * @class
+	 * @extends {Object2D}
+	 */
+	function Graph()
+	{
+		Object2D.call(this);
+
+		/**
+		 * Graph object containing the size of the object.
+		 */
+		this.box = new Box2(new Vector2(-50, -35), new Vector2(50, 35));
+
+		/**
+		 * Color of the box border line.
+		 */
+		this.strokeStyle = "rgb(0, 153, 255)";
+
+		/**
+		 * Line width.
+		 */
+		this.lineWidth = 1;
+
+		/**
+		 * Background color of the box.
+		 */
+		this.fillStyle = "rgba(0, 153, 255, 0.3)";
+
+		/**
+		 * Minimum value of the graph.
+		 */
+		this.min = 0;
+
+		/**
+		 * Maximum value of the graph.
+		 */
+		this.max = 10;
+
+		/**
+		 * Data to be presented in the graph.
+		 *
+		 * The array should store numeric values.
+		 */
+		this.data = [];
+	}
+
+	Graph.prototype = Object.create(Object2D.prototype);
+	Graph.prototype.constructor = Graph;
+	Graph.prototype.type = "Graph";
+
+	Graph.prototype.isInside = function(point)
+	{
+		return this.box.containsPoint(point);
+	};
+
+	Graph.prototype.draw = function(context, viewport, canvas)
+	{
+		if(this.data.length === 0)
+		{
+			return;
+		}
+		
+		var width = this.box.max.x - this.box.min.x;
+		var height = this.box.max.y - this.box.min.y;
+
+		context.lineWidth = this.lineWidth;
+		context.strokeStyle = this.strokeStyle;
+		context.beginPath();
+			
+		var step = width / (this.data.length - 1);
+		var gamma = this.max - this.min;
+
+		context.moveTo(this.box.min.x, this.box.max.y - ((this.data[0] - this.min) / gamma) * height);
+		
+		for(var i = 1, s = step; i < this.data.length; s += step, i++)
+		{
+			context.lineTo(this.box.min.x + s, this.box.max.y - ((this.data[i] - this.min) / gamma) * height);
+		}
+
+		context.stroke();
+
+		if(this.fillStyle !== null)
+		{
+			context.fillStyle = this.fillStyle;
+
+			context.lineTo(this.box.max.x, this.box.max.y);
+			context.lineTo(this.box.min.x, this.box.max.y);
+			context.fill();
+		}
+	};
+
+	Graph.prototype.serialize = function(recursive)
+	{
+		var data = Object2D.prototype.serialize.call(this, recursive);
+
+		data.box = this.box.toArray();
+		data.strokeStyle = this.strokeStyle;
+		data.lineWidth = this.lineWidth;
+		data.fillStyle = this.fillStyle;
+		data.min = this.min;
+		data.max = this.max;
+		data.data = this.data;
+
+		return data;
+	};
+
+	Graph.prototype.parse = function(data)
+	{
+		Object2D.prototype.parse.call(this, data);
+
+		this.box.fromArray(data.box);
+		this.strokeStyle = data.strokeStyle;
+		this.lineWidth = data.lineWidth;
+		this.fillStyle = data.fillStyle;
+		this.min = data.min;
+		this.max = data.max;
+		this.data = data.data;
+	};
+
 	/**
 	 * Node connector is used to connect a output of a node to a input of another node.
 	 *
@@ -4710,6 +4782,66 @@
 		updateHelpers();
 	};
 
+	/**
+	 * File utils is used to read and write files.
+	 *
+	 * Can be used alongside with object serialization to store and load objects from file.
+	 *
+	 * @class
+	 * @static
+	 */
+	function FileUtils(){}
+
+	/**
+	 * Read a local or remote file as text data.
+	 *
+	 * @param {string} fname Path or URL of the file being read.
+	 * @param {Function} onLoad onLoad callback receives the read data as parameter.
+	 * @param {Function} onError onError call is called when a error occurs while reading the file.
+	 */
+	FileUtils.read = function(fname, onLoad, onError)
+	{
+		var file = new XMLHttpRequest();
+		file.overrideMimeType("text/plain");
+		file.open("GET", fname, true);
+		if(onLoad !== undefined)
+		{
+			file.onload = function()
+			{
+				onLoad(file.response);
+			};
+		}
+
+		if(onError !== undefined)
+		{
+			file.onerror = onError;
+		}
+
+		file.send(null);
+	};
+
+	/**
+	 * Write text to a file and automatically download it from blob storage.
+	 *
+	 * @method writeFile
+	 * @param {string} fname Path of the file to write.
+	 * @param {string} data Text data to be written to the file.
+	 */
+	FileUtils.write = function(fname, data)
+	{
+		var blob = new Blob([data], {type:"octet/stream"});
+		var download = document.createElement("a");
+		download.download = fname;
+		download.href = window.URL.createObjectURL(blob);
+		download.style.display = "none";
+		download.onclick = function()
+		{
+			document.body.removeChild(this);
+		};
+		document.body.appendChild(download);
+		download.click();
+	};
+
 	exports.BezierCurve = BezierCurve;
 	exports.Box = Box;
 	exports.Box2 = Box2;
@@ -4717,6 +4849,7 @@
 	exports.Circle = Circle;
 	exports.DOM = DOM;
 	exports.EventManager = EventManager;
+	exports.FileUtils = FileUtils;
 	exports.Graph = Graph;
 	exports.Helpers = Helpers;
 	exports.Image = Image;

+ 1 - 0
source/Escher.js

@@ -36,3 +36,4 @@ export {NodeGraph} from "./objects/node/NodeGraph.js";
 export {ViewportControls} from "./controls/ViewportControls.js";
 
 export {Helpers} from "./utils/Helpers.js";
+export {FileUtils} from "./utils/FileUtils.js";

+ 0 - 1
source/objects/BezierCurve.js

@@ -2,7 +2,6 @@ import {Object2D} from "../Object2D.js";
 import {Vector2} from "../math/Vector2.js";
 import {Circle} from "./Circle.js";
 import {Line} from "./Line.js";
-import {QuadraticCurve} from "./QuadraticCurve";
 
 /**
  * Bezier curve object draw as bezier curve between two points.

+ 0 - 2
source/objects/Box.js

@@ -1,8 +1,6 @@
 import {Object2D} from "../Object2D.js";
 import {Vector2} from "../math/Vector2.js";
 import {Box2} from "../math/Box2.js";
-import {BezierCurve} from "./BezierCurve";
-import {Text} from "./Text";
 
 /**
  * Box object draw a rectangular object.

+ 0 - 1
source/objects/Circle.js

@@ -1,5 +1,4 @@
 import {Object2D} from "../Object2D.js";
-import {Box} from "./Box";
 
 /**
  * Circle object draw a circular object, into the canvas.

+ 29 - 0
source/objects/Graph.js

@@ -97,4 +97,33 @@ Graph.prototype.draw = function(context, viewport, canvas)
 	}
 };
 
+Graph.prototype.serialize = function(recursive)
+{
+	var data = Object2D.prototype.serialize.call(this, recursive);
+
+	data.box = this.box.toArray();
+	data.strokeStyle = this.strokeStyle;
+	data.lineWidth = this.lineWidth;
+	data.fillStyle = this.fillStyle;
+	data.min = this.min;
+	data.max = this.max;
+	data.data = this.data;
+
+	return data;
+};
+
+Graph.prototype.parse = function(data)
+{
+	Object2D.prototype.parse.call(this, data);
+
+	this.box.fromArray(data.box);
+	this.strokeStyle = data.strokeStyle;
+	this.lineWidth = data.lineWidth;
+	this.fillStyle = data.fillStyle;
+	this.min = data.min;
+	this.max = data.max;
+	this.data = data.data;
+};
+
+
 export {Graph};

+ 18 - 1
source/objects/Image.js

@@ -1,6 +1,5 @@
 import {Object2D} from "../Object2D.js";
 import {Box2} from "../math/Box2.js";
-import {Graph} from "./Graph";
 
 /**
  * Image object is used to draw an image from URL.
@@ -65,4 +64,22 @@ Image.prototype.draw = function(context, viewport, canvas)
 	}
 };
 
+Image.prototype.serialize = function(recursive)
+{
+	var data = Object2D.prototype.serialize.call(this, recursive);
+
+	data.box = this.box.toArray();
+	data.image = this.image.src;
+
+	return data;
+};
+
+Image.prototype.parse = function(data)
+{
+	Object2D.prototype.parse.call(this, data);
+
+	this.box.fromArray(data.box);
+	this.image.src = data.image;
+};
+
 export {Image};

+ 0 - 2
source/objects/MultiLineText.js

@@ -1,6 +1,4 @@
 import {Text} from "./Text.js";
-import {Line} from "./Line";
-import {Object2D} from "../Object2D";
 
 /**
  * Multiple line text drawing directly into the canvas.

+ 28 - 1
source/objects/Pattern.js

@@ -1,5 +1,6 @@
 import {Object2D} from "../Object2D.js";
 import {Box2} from "../math/Box2.js";
+import {Image} from "./Image";
 
 /**
  * Pattern object draw a image repeated as a pattern.
@@ -22,7 +23,9 @@ function Pattern(src)
 	this.box = new Box2();
 
 	/**
-	 * Image source DOM element.
+	 * Image source DOM element. Used as a source for the pattern image.
+	 *
+	 * This element can be replaced by one of other type (e.g canvas, video).
 	 *
 	 * @type {Element}
 	 */
@@ -31,6 +34,10 @@ function Pattern(src)
 	/**
 	 * Repetition indicates how the pattern image should be repeated.
 	 *
+	 * Possible values are "repeat", "repeat-x", "repeat-y" or "no-repeat".
+	 *
+	 * More information about this attribute here https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern.
+	 *
 	 * @type {string}
 	 */
 	this.repetition = "repeat"
@@ -83,4 +90,24 @@ Pattern.prototype.draw = function(context, viewport, canvas)
 	}
 };
 
+Pattern.prototype.serialize = function(recursive)
+{
+	var data = Object2D.prototype.serialize.call(this, recursive);
+
+	data.box = this.box.toArray();
+	data.image = this.image.src;
+	data.repetition = this.repetition;
+
+	return data;
+};
+
+Pattern.prototype.parse = function(data)
+{
+	Object2D.prototype.parse.call(this, data);
+
+	this.box.fromArray(data.box);
+	this.image.src = data.image;
+	this.repetition = data.repetition;
+};
+
 export {Pattern};

+ 0 - 1
source/objects/RoundedBox.js

@@ -84,5 +84,4 @@ RoundedBox.prototype.parse = function(data)
 	this.radius = data.radius;
 };
 
-
 export {RoundedBox};

+ 0 - 1
source/objects/Text.js

@@ -1,5 +1,4 @@
 import {Object2D} from "../Object2D.js";
-import {RoundedBox} from "./RoundedBox";
 
 /**
  * Text element, used to draw single line text into the canvas.

+ 0 - 1
source/objects/mask/BoxMask.js

@@ -1,7 +1,6 @@
 import {Mask} from "./Mask.js";
 import {Vector2} from "../../math/Vector2.js";
 import {Box2} from "../../math/Box2.js";
-import {Text} from "../Text";
 
 /**
  * Box mask can be used to clear a box mask region.

+ 5 - 2
source/objects/mask/Mask.js

@@ -1,5 +1,4 @@
 import {Object2D} from "../../Object2D.js";
-import {BoxMask} from "./BoxMask";
 
 /**
  * A mask can be used to set the drawing region.
@@ -24,7 +23,11 @@ Mask.prototype.type = "Mask";
 Mask.prototype.isMask = true;
 
 /**
- * Clip the canvas context, to ensure that next objects being drawn are cliped to the path stored here.
+ * Clip the canvas context. Define a clipping path and set the clip using the context.clip() method.
+ *
+ * Ensures that next objects being drawn are clipped to the path stored here.
+ *
+ * More information about canvas clipping https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip.
  *
  * @param {CanvasRenderingContext2D} context Canvas 2d drawing context.
  * @param {Viewport} viewport Viewport applied to the canvas.

+ 0 - 1
source/objects/node/NodeSocket.js

@@ -2,7 +2,6 @@ import {Circle} from "../Circle";
 import {Node} from "./Node";
 import {NodeConnector} from "./NodeConnector";
 import {Text} from "../Text";
-import {NodeGraph} from "./NodeGraph";
 
 /**
  * Represents a node hook point. Is attached to the node element and represented visually.

+ 61 - 0
source/utils/FileUtils.js

@@ -0,0 +1,61 @@
+/**
+ * File utils is used to read and write files.
+ *
+ * Can be used alongside with object serialization to store and load objects from file.
+ *
+ * @class
+ * @static
+ */
+function FileUtils(){}
+
+/**
+ * Read a local or remote file as text data.
+ *
+ * @param {string} fname Path or URL of the file being read.
+ * @param {Function} onLoad onLoad callback receives the read data as parameter.
+ * @param {Function} onError onError call is called when a error occurs while reading the file.
+ */
+FileUtils.read = function(fname, onLoad, onError)
+{
+	var file = new XMLHttpRequest();
+	file.overrideMimeType("text/plain");
+	file.open("GET", fname, true);
+	if(onLoad !== undefined)
+	{
+		file.onload = function()
+		{
+			onLoad(file.response);
+		};
+	}
+
+	if(onError !== undefined)
+	{
+		file.onerror = onError;
+	}
+
+	file.send(null);
+};
+
+/**
+ * Write text to a file and automatically download it from blob storage.
+ *
+ * @method writeFile
+ * @param {string} fname Path of the file to write.
+ * @param {string} data Text data to be written to the file.
+ */
+FileUtils.write = function(fname, data)
+{
+	var blob = new Blob([data], {type:"octet/stream"});
+	var download = document.createElement("a");
+	download.download = fname;
+	download.href = window.URL.createObjectURL(blob);
+	download.style.display = "none";
+	download.onclick = function()
+	{
+		document.body.removeChild(this);
+	};
+	document.body.appendChild(download);
+	download.click();
+};
+
+export {FileUtils};