mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Merge remote branch 'origin/master'
This commit is contained in:
commit
241d98a1cf
24 changed files with 208 additions and 211 deletions
|
@ -71,7 +71,7 @@ var GradientColor = this.GradientColor = Color.extend({
|
|||
var gradient;
|
||||
if (this.gradient.type === 'linear') {
|
||||
gradient = ctx.createLinearGradient(this._origin.x, this._origin.y,
|
||||
this.destination.x, this.destination.y);
|
||||
this._destination.x, this._destination.y);
|
||||
} else {
|
||||
var origin = this._hilite || this._origin;
|
||||
gradient = ctx.createRadialGradient(origin.x, origin.y,
|
||||
|
@ -79,7 +79,7 @@ var GradientColor = this.GradientColor = Color.extend({
|
|||
}
|
||||
for (var i = 0, l = this.gradient._stops.length; i < l; i++) {
|
||||
var stop = this.gradient._stops[i];
|
||||
gradient.addColorStop(stop._rampPoint, stop.color.toCssString());
|
||||
gradient.addColorStop(stop._rampPoint, stop._color.toCssString());
|
||||
}
|
||||
return gradient;
|
||||
},
|
||||
|
@ -92,12 +92,10 @@ var GradientColor = this.GradientColor = Color.extend({
|
|||
* @return true if the GrayColor is the same, false otherwise.
|
||||
*/
|
||||
equals: function(color) {
|
||||
if (color && color._colorType === this._colorType) {
|
||||
return this.gradient.equals(color.gradient)
|
||||
&& this._origin.equals(color._origin)
|
||||
&& this._destination.equals(color._destination);
|
||||
}
|
||||
return false;
|
||||
return color == this || color && color._colorType === this._colorType
|
||||
&& this.gradient.equals(color.gradient)
|
||||
&& this._origin.equals(color._origin)
|
||||
&& this._destination.equals(color._destination);
|
||||
},
|
||||
|
||||
transform: function(matrix) {
|
||||
|
|
|
@ -28,7 +28,7 @@ var GradientStop = this.GradientStop = Base.extend({
|
|||
},
|
||||
|
||||
setRampPoint: function(rampPoint) {
|
||||
this._rampPoint = rampPoint !== null ? rampPoint : 0;
|
||||
this._rampPoint = rampPoint || 0;
|
||||
},
|
||||
|
||||
getColor: function() {
|
||||
|
@ -38,14 +38,10 @@ var GradientStop = this.GradientStop = Base.extend({
|
|||
setColor: function(color) {
|
||||
this._color = Color.read(arguments);
|
||||
},
|
||||
|
||||
|
||||
equals: function(stop) {
|
||||
if (stop == this) {
|
||||
return true;
|
||||
} else if (stop instanceof GradientStop) {
|
||||
return this._color.equals(stop._color)
|
||||
&& rampPoint == stop.rampPoint;
|
||||
}
|
||||
return false;
|
||||
return stop == this || stop instanceof GradientStop
|
||||
&& this._color.equals(stop._color)
|
||||
&& rampPoint == stop._rampPoint;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -43,6 +43,14 @@ Base.inject({
|
|||
return res;
|
||||
},
|
||||
|
||||
initialize: function(object, values, defaults) {
|
||||
if (!values)
|
||||
values = defaults;
|
||||
return Base.each(defaults, function(value, key) {
|
||||
this[key] = values[key] || value;
|
||||
}, object);
|
||||
},
|
||||
|
||||
/**
|
||||
* Utility function for adding and removing items from a list of which
|
||||
* each entry keeps a reference to its index in the list in the private
|
||||
|
|
|
@ -19,27 +19,18 @@
|
|||
* global paper object, which simply is a pointer to the currently active scope.
|
||||
*/
|
||||
var PaperScope = this.PaperScope = Base.extend({
|
||||
beans: true,
|
||||
|
||||
initialize: function(id) {
|
||||
this.project = null;
|
||||
this.projects = [];
|
||||
this.view = null;
|
||||
this.views = [];
|
||||
this.tool = null;
|
||||
this.tools = [];
|
||||
this.id = id;
|
||||
PaperScope._scopes[id] = this;
|
||||
},
|
||||
|
||||
/**
|
||||
* A short-cut to the currently active view of the active project.
|
||||
*/
|
||||
getView: function() {
|
||||
return this.project.activeView;
|
||||
},
|
||||
|
||||
getViews: function() {
|
||||
return this.project.views;
|
||||
},
|
||||
|
||||
evaluate: function(code) {
|
||||
return PaperScript.evaluate(code, this);
|
||||
},
|
||||
|
@ -60,9 +51,12 @@ var PaperScope = this.PaperScope = Base.extend({
|
|||
},
|
||||
|
||||
clear: function() {
|
||||
// Remove all projects and tools.
|
||||
// Remove all projects, views and tools.
|
||||
for (var i = this.projects.length - 1; i >= 0; i--)
|
||||
this.projects[i].remove();
|
||||
// This also removes the installed event handlers.
|
||||
for (var i = this.views.length - 1; i >= 0; i--)
|
||||
this.views[i].remove();
|
||||
for (var i = this.tools.length - 1; i >= 0; i--)
|
||||
this.tools[i].remove();
|
||||
},
|
||||
|
|
|
@ -137,11 +137,12 @@ var PaperScript = this.PaperScript = new function() {
|
|||
// so the active project is defined.
|
||||
var canvas = code.getAttribute('canvas');
|
||||
if (canvas = canvas && document.getElementById(canvas)) {
|
||||
// Create a Project for this canvas, using the right scope
|
||||
// Create an empty Project for this scope, and a view for the
|
||||
// canvas, both using the right paper scope
|
||||
paper = scope;
|
||||
// XXX: Do not pass canvas to Project.
|
||||
// Create ProjectView here instead.
|
||||
new Project(canvas);
|
||||
new Project();
|
||||
// Activate the newly created view straight away
|
||||
new View(canvas).activate();
|
||||
}
|
||||
if (code.src) {
|
||||
// If we're loading from a source, request that first and then
|
||||
|
@ -154,7 +155,7 @@ var PaperScript = this.PaperScript = new function() {
|
|||
}
|
||||
//#endif // BROWSER
|
||||
var proj = scope.project,
|
||||
view = proj.activeView,
|
||||
view = scope.view,
|
||||
// TODO: Add support for multiple tools
|
||||
tool = scope.tool = /on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code)
|
||||
&& new Tool(null, scope),
|
||||
|
|
|
@ -21,12 +21,9 @@ var Group = this.Group = Item.extend({
|
|||
this.base();
|
||||
this._children = [];
|
||||
this._namedChildren = {};
|
||||
if (items) {
|
||||
for (var i = 0, l = items.length; i < l; i++) {
|
||||
this.appendTop(items[i]);
|
||||
}
|
||||
}
|
||||
this._clipped = false;
|
||||
this.setChildren(!items || !Array.isArray(items)
|
||||
|| typeof items[0] !== 'object' ? arguments : items);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
135
src/item/Item.js
135
src/item/Item.js
|
@ -19,6 +19,7 @@ var Item = this.Item = Base.extend({
|
|||
|
||||
initialize: function() {
|
||||
paper.project.activeLayer.appendTop(this);
|
||||
this._style = PathStyle.create(this);
|
||||
this.setStyle(this._project.getCurrentStyle());
|
||||
},
|
||||
|
||||
|
@ -38,29 +39,10 @@ var Item = this.Item = Base.extend({
|
|||
* The unique id of the item.
|
||||
*/
|
||||
getId: function() {
|
||||
if (this._id == null) {
|
||||
if (this._id == null)
|
||||
this._id = Item._id = (Item._id || 0) + 1;
|
||||
}
|
||||
return this._id;
|
||||
},
|
||||
|
||||
_removeFromNamed: function() {
|
||||
var children = this._parent._children,
|
||||
namedChildren = this._parent._namedChildren,
|
||||
name = this._name,
|
||||
namedArray = namedChildren[name];
|
||||
if (children[name] = this)
|
||||
delete children[name];
|
||||
namedArray.splice(namedArray.indexOf(this), 1);
|
||||
// If there are any items left in the named array, set
|
||||
// the last of them to be this.parent.children[this.name]
|
||||
if (namedArray.length) {
|
||||
children[name] = namedArray[namedArray.length - 1];
|
||||
} else {
|
||||
// Otherwise delete the empty array
|
||||
delete namedChildren[name];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The name of the item.
|
||||
|
@ -86,6 +68,47 @@ var Item = this.Item = Base.extend({
|
|||
delete children[name];
|
||||
}
|
||||
},
|
||||
|
||||
_removeFromNamed: function() {
|
||||
var children = this._parent._children,
|
||||
namedChildren = this._parent._namedChildren,
|
||||
name = this._name,
|
||||
namedArray = namedChildren[name];
|
||||
if (children[name] = this)
|
||||
delete children[name];
|
||||
namedArray.splice(namedArray.indexOf(this), 1);
|
||||
// If there are any items left in the named array, set
|
||||
// the last of them to be this.parent.children[this.name]
|
||||
if (namedArray.length) {
|
||||
children[name] = namedArray[namedArray.length - 1];
|
||||
} else {
|
||||
// Otherwise delete the empty array
|
||||
delete namedChildren[name];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the item from its parent's children list.
|
||||
*/
|
||||
_removeFromParent: function() {
|
||||
if (this._parent) {
|
||||
if (this._name)
|
||||
this._removeFromNamed();
|
||||
var res = Base.splice(this._parent._children, null, this._index, 1);
|
||||
this._parent = null;
|
||||
return !!res.length;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the item.
|
||||
*/
|
||||
remove: function() {
|
||||
if (this.isSelected())
|
||||
this.setSelected(false);
|
||||
return this._removeFromParent();
|
||||
},
|
||||
|
||||
/**
|
||||
* When passed a project, copies the item to the project,
|
||||
|
@ -238,7 +261,20 @@ var Item = this.Item = Base.extend({
|
|||
return this._children;
|
||||
},
|
||||
|
||||
// TODO: #setChildren()
|
||||
setChildren: function(items) {
|
||||
this.removeChildren();
|
||||
for (var i = 0, l = items && items.length; i < l; i++)
|
||||
this.appendTop(items[i]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the item contains any children items.
|
||||
*
|
||||
* @return true if it has one or more children, false otherwise.
|
||||
*/
|
||||
hasChildren: function() {
|
||||
return this._children && this._children.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Reverses the order of this item's children
|
||||
|
@ -252,6 +288,18 @@ var Item = this.Item = Base.extend({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all of the item's children, if it has any
|
||||
*/
|
||||
removeChildren: function() {
|
||||
var removed = false;
|
||||
if (this._children) {
|
||||
for (var i = this._children.length - 1; i >= 0; i--)
|
||||
removed = this._children[i].remove() || removed;
|
||||
}
|
||||
return removed;
|
||||
},
|
||||
|
||||
/**
|
||||
* The first item contained within this item.
|
||||
*/
|
||||
|
@ -281,38 +329,6 @@ var Item = this.Item = Base.extend({
|
|||
return this._parent && this._parent._children[this._index - 1] || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the item from its parent's children list.
|
||||
*/
|
||||
_removeFromParent: function() {
|
||||
if (this._parent) {
|
||||
if (this._name)
|
||||
this._removeFromNamed();
|
||||
var res = Base.splice(this._parent._children, null, this._index, 1);
|
||||
this._parent = null;
|
||||
return !!res.length;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the item.
|
||||
*/
|
||||
remove: function() {
|
||||
if (this.isSelected())
|
||||
this.setSelected(false);
|
||||
return this._removeFromParent();
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the item contains any children items.
|
||||
*
|
||||
* @return true if it has one or more children, false otherwise.
|
||||
*/
|
||||
hasChildren: function() {
|
||||
return this._children && this._children.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether the item is editable.
|
||||
*
|
||||
|
@ -629,7 +645,7 @@ var Item = this.Item = Base.extend({
|
|||
},
|
||||
|
||||
setStyle: function(style) {
|
||||
this._style = PathStyle.create(this, style);
|
||||
this._style.initialize(style);
|
||||
},
|
||||
|
||||
// TODO: toString
|
||||
|
@ -649,7 +665,7 @@ var Item = this.Item = Base.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// TODO: Implement ProjectView into the drawing
|
||||
// TODO: Implement View into the drawing
|
||||
// TODO: Optimize temporary canvas drawing to ignore parts that are
|
||||
// outside of the visible view.
|
||||
draw: function(item, ctx, param) {
|
||||
|
@ -781,15 +797,6 @@ var Item = this.Item = Base.extend({
|
|||
*/
|
||||
appendBottom: append(false),
|
||||
|
||||
/**
|
||||
* A link to {@link #appendTop}
|
||||
*
|
||||
* @deprecated use {@link #appendTop} or {@link #appendBottom} instead.
|
||||
*/
|
||||
appendChild: function(item) {
|
||||
return this.appendTop(item);
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves this item above the specified item.
|
||||
*
|
||||
|
|
|
@ -18,6 +18,8 @@ var Layer = this.Layer = Group.extend({
|
|||
beans: true,
|
||||
|
||||
initialize: function() {
|
||||
// TODO: Isn't there a way to call this.base() here and then move the
|
||||
// layer into layers instead?
|
||||
this._children = [];
|
||||
this._namedChildren = {};
|
||||
this._project = paper.project;
|
||||
|
|
|
@ -29,13 +29,13 @@ var PathStyle = this.PathStyle = Base.extend(new function() {
|
|||
beans: true,
|
||||
|
||||
initialize: function(style) {
|
||||
if (style) {
|
||||
for (var i = 0, l = keys.length; i < l; i++) {
|
||||
var key = keys[i],
|
||||
value = style[key];
|
||||
if (value !== undefined)
|
||||
this[key] = value;
|
||||
}
|
||||
// Note: This relies on bean setters that get implicetly
|
||||
// called when setting values on this[key].
|
||||
for (var i = 0, l = style && keys.length; i < l; i++) {
|
||||
var key = keys[i],
|
||||
value = style[key];
|
||||
if (value !== undefined)
|
||||
this[key] = value;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -44,10 +44,9 @@ var PathStyle = this.PathStyle = Base.extend(new function() {
|
|||
},
|
||||
|
||||
statics: {
|
||||
create: function(item, other) {
|
||||
create: function(item) {
|
||||
var style = new PathStyle(PathStyle.dont);
|
||||
style._item = item;
|
||||
style.initialize(other);
|
||||
return style;
|
||||
}
|
||||
}
|
||||
|
@ -101,8 +100,8 @@ var PathStyle = this.PathStyle = Base.extend(new function() {
|
|||
}
|
||||
};
|
||||
|
||||
// 'this' = the Base.each() side-car = the object that is injected into
|
||||
// Item above:
|
||||
// 'this' = the Base.each() side-car = the object that is returned from
|
||||
// Base.each and injected into Item above:
|
||||
this[set] = function(value) {
|
||||
this._style[set](value);
|
||||
return this;
|
||||
|
|
|
@ -35,7 +35,6 @@ var sources = [
|
|||
'src/basic/Matrix.js',
|
||||
'src/basic/Line.js',
|
||||
|
||||
'src/project/ProjectView.js',
|
||||
'src/project/Project.js',
|
||||
'src/project/Symbol.js',
|
||||
|
||||
|
@ -73,6 +72,7 @@ var sources = [
|
|||
'src/browser/DomElement.js',
|
||||
'src/browser/DomEvent.js',
|
||||
|
||||
'src/ui/View.js',
|
||||
'src/ui/Event.js',
|
||||
'src/ui/KeyEvent.js',
|
||||
'src/ui/Key.js',
|
||||
|
|
|
@ -52,7 +52,6 @@ var paper = new function() {
|
|||
//#include "basic/Matrix.js"
|
||||
//#include "basic/Line.js"
|
||||
|
||||
//#include "project/ProjectView.js"
|
||||
//#include "project/Project.js"
|
||||
//#include "project/Symbol.js"
|
||||
|
||||
|
@ -92,8 +91,8 @@ var paper = new function() {
|
|||
|
||||
//#include "browser/DomElement.js"
|
||||
//#include "browser/DomEvent.js"
|
||||
//#include "browser/Request.js"
|
||||
|
||||
//#include "ui/View.js"
|
||||
//#include "ui/Event.js"
|
||||
//#include "ui/KeyEvent.js"
|
||||
//#include "ui/Key.js"
|
||||
|
|
|
@ -28,6 +28,7 @@ var CompoundPath = this.CompoundPath = PathItem.extend({
|
|||
// clockwise orientation when creating a compound path, so that they
|
||||
// appear as holes, but only if their orientation was not already
|
||||
// specified before (= _clockwise is defined).
|
||||
// TODO: This should really be handled in appendTop / Bottom, right?
|
||||
if (path._clockwise === undefined)
|
||||
path.setClockwise(i < l - 1);
|
||||
this.appendTop(path);
|
||||
|
|
|
@ -643,8 +643,14 @@ var Path = this.Path = PathItem.extend({
|
|||
};
|
||||
|
||||
return {
|
||||
beans: true,
|
||||
|
||||
_setStyles: function(ctx) {
|
||||
for (var i in styles) {
|
||||
var style = this._style[i]();
|
||||
if (style)
|
||||
ctx[styles[i]] = style;
|
||||
}
|
||||
},
|
||||
|
||||
smooth: function() {
|
||||
// This code is based on the work by Oleg V. Polikarpotchkin,
|
||||
// http://ov-p.spaces.live.com/blog/cns!39D56F0C7A08D703!147.entry
|
||||
|
@ -742,14 +748,6 @@ var Path = this.Path = PathItem.extend({
|
|||
var segment = this._segments[0];
|
||||
segment.setHandleIn(handleIn.subtract(segment._point));
|
||||
}
|
||||
},
|
||||
|
||||
_setStyles: function(ctx) {
|
||||
for (var i in styles) {
|
||||
var style = this[i]();
|
||||
if (style)
|
||||
ctx[styles[i]] = style;
|
||||
}
|
||||
}
|
||||
};
|
||||
}, new function() { // PostScript-style drawing commands
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
var Project = this.Project = Base.extend({
|
||||
beans: true,
|
||||
|
||||
// XXX: Add arguments to define pages, but do not pass canvas here
|
||||
initialize: function(canvas) {
|
||||
// TODO: Add arguments to define pages
|
||||
initialize: function() {
|
||||
// Store reference to the currently active global paper scope:
|
||||
this._scope = paper;
|
||||
// Push it onto this._scope.projects and set index:
|
||||
|
@ -27,13 +27,11 @@ var Project = this.Project = Base.extend({
|
|||
// Layer and DoumentView constructors.
|
||||
this.activate();
|
||||
this.layers = [];
|
||||
this.views = [];
|
||||
this.symbols = [];
|
||||
this.activeLayer = new Layer();
|
||||
this.activeView = canvas ? new ProjectView(canvas) : null;
|
||||
this._selectedItems = {};
|
||||
this._selectedItemCount = 0;
|
||||
this.setCurrentStyle(null);
|
||||
this._currentStyle = PathStyle.create(null);
|
||||
},
|
||||
|
||||
getCurrentStyle: function() {
|
||||
|
@ -41,7 +39,7 @@ var Project = this.Project = Base.extend({
|
|||
},
|
||||
|
||||
setCurrentStyle: function(style) {
|
||||
this._currentStyle = PathStyle.create(null, style);
|
||||
this._currentStyle.initialize(style);
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
|
@ -55,9 +53,6 @@ var Project = this.Project = Base.extend({
|
|||
remove: function() {
|
||||
var res = Base.splice(this._scope.projects, null, this._index, 1);
|
||||
this._scope = null;
|
||||
// Remove all views. This also removes the installed event handlers.
|
||||
for (var i = this.views.length - 1; i >= 0; i--)
|
||||
this.views[i].remove();
|
||||
return !!res.length;
|
||||
},
|
||||
|
||||
|
@ -130,8 +125,10 @@ var Project = this.Project = Base.extend({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
redraw: function() {
|
||||
for (var i = 0, l = this.views.length; i < l; i++)
|
||||
this.views[i].draw();
|
||||
this._scope.view.draw();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,16 +16,17 @@
|
|||
|
||||
var CharacterStyle = this.CharacterStyle = PathStyle.extend({
|
||||
initialize: function(style) {
|
||||
this.fontSize = style.fontSize || 10;
|
||||
this.font = style.font || 'sans-serif';
|
||||
Base.initialize(this, style, {
|
||||
fontSize: 10,
|
||||
font: 'sans-serif'
|
||||
});
|
||||
this.base(style);
|
||||
},
|
||||
|
||||
|
||||
statics: {
|
||||
create: function(item, other) {
|
||||
create: function(item) {
|
||||
var style = new CharacterStyle(CharacterStyle.dont);
|
||||
style._item = item;
|
||||
style.initialize(other);
|
||||
return style;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,21 +15,16 @@
|
|||
*/
|
||||
|
||||
var ParagraphStyle = this.ParagraphStyle = Base.extend({
|
||||
beans: true,
|
||||
|
||||
initialize: function(style) {
|
||||
this.justification = (style && style.justification) || 'left';
|
||||
},
|
||||
|
||||
clone: function() {
|
||||
return new PathStyle(this);
|
||||
Base.initialize(this, style, {
|
||||
justification: 'left'
|
||||
});
|
||||
},
|
||||
|
||||
statics: {
|
||||
create: function(item, other) {
|
||||
var style = new ParagraphStyle(PathStyle.dont);
|
||||
create: function(item) {
|
||||
var style = new CharacterStyle(CharacterStyle.dont);
|
||||
style._item = item;
|
||||
style.initialize(other);
|
||||
return style;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@ var PointText = this.PointText = TextItem.extend({
|
|||
|
||||
initialize: function(point) {
|
||||
this.base();
|
||||
point = Point.read(arguments, 0, 1);
|
||||
this._point = point || new Point();
|
||||
this._point = Point.read(arguments, 0);
|
||||
this.matrix = new Matrix().translate(this._point);
|
||||
},
|
||||
|
||||
|
@ -37,13 +36,13 @@ var PointText = this.PointText = TextItem.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// TODO: position should be the center point of the bounds
|
||||
// but we currently don't support bounds for PointText.
|
||||
getPosition: function() {
|
||||
return this._point;
|
||||
},
|
||||
|
||||
setPosition: function(point) {
|
||||
// TODO: position should be the center point of the bounds
|
||||
// but we currently don't support bounds for PointText.
|
||||
this.setPoint.apply(this, arguments);
|
||||
},
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ var TextItem = this.TextItem = Item.extend({
|
|||
|
||||
initialize: function() {
|
||||
this.base();
|
||||
point = Point.read(arguments, 0, 1);
|
||||
this.content = null;
|
||||
this._characterStyle = CharacterStyle.create(this);
|
||||
this.setCharacterStyle(this._project.getCurrentStyle());
|
||||
this._paragraphStyle = ParagraphStyle.create(this);
|
||||
this.setParagraphStyle();
|
||||
},
|
||||
|
||||
|
@ -30,7 +31,7 @@ var TextItem = this.TextItem = Item.extend({
|
|||
},
|
||||
|
||||
setCharacterStyle: function(style) {
|
||||
this._characterStyle = CharacterStyle.create(this, style);
|
||||
this._characterStyle.initialize(style);
|
||||
},
|
||||
|
||||
getParagraphStyle: function() {
|
||||
|
@ -38,6 +39,6 @@ var TextItem = this.TextItem = Item.extend({
|
|||
},
|
||||
|
||||
setParagraphStyle: function(style) {
|
||||
this._paragraphStyle = ParagraphStyle.create(this, style);
|
||||
this._paragraphStyle.initialize(style);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -65,7 +65,7 @@ var Key = this.Key = new function() {
|
|||
var character = String.fromCharCode(charCode),
|
||||
key = keys[keyCode] || character.toLowerCase(),
|
||||
handler = down ? 'onKeyDown' : 'onKeyUp',
|
||||
scope = ProjectView.focused && ProjectView.focused._scope,
|
||||
scope = View.focused && View.focused._scope,
|
||||
tool = scope && scope.tool;
|
||||
keyMap[key] = down;
|
||||
if (tool && tool[handler]) {
|
||||
|
|
|
@ -14,19 +14,17 @@
|
|||
* All rights reserved.
|
||||
*/
|
||||
|
||||
var ProjectView = this.ProjectView = Base.extend({
|
||||
var View = this.View = Base.extend({
|
||||
beans: true,
|
||||
|
||||
// TODO: Add bounds parameter that defines position within canvas?
|
||||
// Find a good name for these bounds, since #bounds is already the artboard
|
||||
// bounds of the visible area.
|
||||
initialize: function(canvas) {
|
||||
// To go with the convention of never passing project to constructors,
|
||||
// in all items, associate the view with the currently active project.
|
||||
this._project = paper.project;
|
||||
this._scope = this._project._scope;
|
||||
// Associate this view with the active paper scope.
|
||||
this._scope = paper;
|
||||
// Push it onto project.views and set index:
|
||||
this._index = this._project.views.push(this) - 1;
|
||||
this._index = this._scope.views.push(this) - 1;
|
||||
// Handle canvas argument
|
||||
var size;
|
||||
if (canvas && canvas instanceof HTMLCanvasElement) {
|
||||
|
@ -86,12 +84,8 @@ var ProjectView = this.ProjectView = Base.extend({
|
|||
this._events = this._createEvents();
|
||||
DomEvent.add(this._canvas, this._events);
|
||||
// Make sure the first view is focused for keyboard input straight away
|
||||
if (!ProjectView.focused)
|
||||
ProjectView.focused = this;
|
||||
},
|
||||
|
||||
getProject: function() {
|
||||
return this._project;
|
||||
if (!View.focused)
|
||||
View.focused = this;
|
||||
},
|
||||
|
||||
getViewBounds: function() {
|
||||
|
@ -150,14 +144,19 @@ var ProjectView = this.ProjectView = Base.extend({
|
|||
|
||||
setZoom: function(zoom) {
|
||||
// TODO: Clamp the view between 1/32 and 64, just like Illustrator?
|
||||
var mx = new Matrix();
|
||||
mx.scale(zoom / this._zoom, this._center);
|
||||
this.transform(mx);
|
||||
this._transform(new Matrix().scale(zoom / this._zoom, this.getCenter()));
|
||||
this._zoom = zoom;
|
||||
},
|
||||
|
||||
scrollBy: function(point) {
|
||||
this.transform(new Matrix().translate(Point.read(arguments).negate()));
|
||||
this._transform(new Matrix().translate(Point.read(arguments).negate()));
|
||||
},
|
||||
|
||||
_transform: function(matrix, flags) {
|
||||
this._matrix.preConcatenate(matrix);
|
||||
// Force recalculation of these values next time they are requested.
|
||||
this._bounds = null;
|
||||
this._inverse = null;
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
|
@ -166,46 +165,40 @@ var ProjectView = this.ProjectView = Base.extend({
|
|||
// Initial tests conclude that clearing the canvas using clearRect
|
||||
// is always faster than setting canvas.width = canvas.width
|
||||
// http://jsperf.com/clearrect-vs-setting-width/7
|
||||
var bounds = this._viewBounds;
|
||||
this._context.clearRect(bounds._x, bounds._y,
|
||||
var ctx =this._context,
|
||||
bounds = this._viewBounds;
|
||||
ctx.clearRect(bounds._x, bounds._y,
|
||||
// TODO: +1... what if we have multiple views in one canvas?
|
||||
bounds._width + 1, bounds._height + 1);
|
||||
this._project.draw(this._context);
|
||||
|
||||
ctx.save();
|
||||
this._matrix.applyToContext(ctx);
|
||||
// Just draw the active project for now
|
||||
this._scope.project.draw(ctx);
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this._project.activeView = this;
|
||||
this._scope.view = this;
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
var res = Base.splice(this._project.views, null, this._index, 1);
|
||||
var res = Base.splice(this._scope.views, null, this._index, 1);
|
||||
// Uninstall event handlers again for this view.
|
||||
DomEvent.remove(this._canvas, this._events);
|
||||
this._project = this._scope = this._canvas = this._events = null;
|
||||
// Clearing _onFrame makes the frame handler stop automatically.
|
||||
this._onFrame = null;
|
||||
this._scope = this._canvas = this._events = this._onFrame = null;
|
||||
return !!res.length;
|
||||
},
|
||||
|
||||
transform: function(matrix, flags) {
|
||||
this._matrix.preConcatenate(matrix);
|
||||
// Force recalculation of these values next time they are requested.
|
||||
this._bounds = null;
|
||||
this._inverse = null;
|
||||
},
|
||||
|
||||
_getInverse: function() {
|
||||
if (!this._inverse)
|
||||
this._inverse = this._matrix.createInverse();
|
||||
return this._inverse;
|
||||
},
|
||||
|
||||
// TODO: getInvalidBounds
|
||||
// TODO: invalidate(rect)
|
||||
// TODO: style: artwork / preview / raster / opaque / ink
|
||||
// TODO: getShowGrid
|
||||
// TODO: getMousePoint
|
||||
// TODO: artworkToView(rect)
|
||||
|
||||
// TODO: Consider naming these projectToView, viewToProject
|
||||
artworkToView: function(point) {
|
||||
return this._matrix._transformPoint(Point.read(arguments));
|
||||
},
|
||||
|
@ -214,6 +207,12 @@ var ProjectView = this.ProjectView = Base.extend({
|
|||
return this._getInverse()._transformPoint(Point.read(arguments));
|
||||
},
|
||||
|
||||
_getInverse: function() {
|
||||
if (!this._inverse)
|
||||
this._inverse = this._matrix.createInverse();
|
||||
return this._inverse;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler to be called whenever a view gets resized.
|
||||
*/
|
||||
|
@ -279,7 +278,7 @@ var ProjectView = this.ProjectView = Base.extend({
|
|||
|
||||
function mousedown(event) {
|
||||
// Tell the Key class which view should receive keyboard input.
|
||||
ProjectView.focused = that;
|
||||
View.focused = that;
|
||||
if (!(tool = that._scope.tool))
|
||||
return;
|
||||
curPoint = viewToArtwork(event);
|
|
@ -37,10 +37,14 @@ test('clockwise', function() {
|
|||
return path3.clockwise;
|
||||
}, true);
|
||||
|
||||
new CompoundPath([
|
||||
path1, path2, path3
|
||||
]);
|
||||
var compound = new CompoundPath(path1, path2, path3);
|
||||
|
||||
equals(function() {
|
||||
return compound.lastChild == path3;
|
||||
}, true);
|
||||
equals(function() {
|
||||
return compound.firstChild == path1;
|
||||
}, true);
|
||||
equals(function() {
|
||||
return path1.clockwise;
|
||||
}, true);
|
||||
|
|
|
@ -23,16 +23,17 @@ test('Group bounds', function() {
|
|||
strokeWidth: 5,
|
||||
strokeColor: 'black'
|
||||
};
|
||||
|
||||
var path = new Path.Circle([150, 150], 60);
|
||||
var secondPath = new Path.Circle([175, 175], 85);
|
||||
var group = new Group([path, secondPath]);
|
||||
compareRectangles(group.bounds, { x: 90, y: 90, width: 170, height: 170 });
|
||||
compareRectangles(group.strokeBounds, { x: 87.5, y: 87.5, width: 175, height: 175 });
|
||||
compareRectangles(group.bounds, { x: 90, y: 90, width: 170, height: 170 }, 'group.bounds');
|
||||
compareRectangles(group.strokeBounds, { x: 87.5, y: 87.5, width: 175, height: 175 }, 'group.strokeBounds');
|
||||
|
||||
group.rotate(20);
|
||||
compareRectangles(group.bounds, { x: 89.97681, y: 82.94095, width: 170.04639, height: 177.08224 });
|
||||
compareRectangles(group.strokeBounds, { x: 87.47681, y: 80.44095, width: 175.04639, height: 182.08224 });
|
||||
compareRectangles(group.bounds, { x: 89.97681, y: 82.94095, width: 170.04639, height: 177.08224 }, 'group.bounds');
|
||||
compareRectangles(group.strokeBounds, { x: 87.47681, y: 80.44095, width: 175.04639, height: 182.08224 }, 'group.strokeBounds');
|
||||
group.rotate(20, new Point(50, 50));
|
||||
compareRectangles(group.bounds, { x: 39.70692, y: 114.99196, width: 170.00412, height: 180.22401 });
|
||||
compareRectangles(group.strokeBounds, { x: 37.20692, y: 112.49196, width: 175.00412, height: 185.22401 });
|
||||
compareRectangles(group.bounds, { x: 39.70692, y: 114.99196, width: 170.00412, height: 180.22401 }, 'group.bounds');
|
||||
compareRectangles(group.strokeBounds, { x: 37.20692, y: 112.49196, width: 175.00412, height: 185.22401 }, 'group.strokeBounds');
|
||||
});
|
|
@ -42,10 +42,10 @@ test('clone()', function() {
|
|||
}, true);
|
||||
});
|
||||
|
||||
test('appendChild(item)', function() {
|
||||
test('appendTop(item)', function() {
|
||||
var proj = paper.project;
|
||||
var path = new Path();
|
||||
proj.activeLayer.appendChild(path);
|
||||
proj.activeLayer.appendTop(path);
|
||||
equals(function() {
|
||||
return proj.activeLayer.children.length;
|
||||
}, 1);
|
||||
|
@ -55,7 +55,7 @@ test('item.parent / item.isChild / item.isParent', function() {
|
|||
var proj = paper.project;
|
||||
var secondDoc = new Project();
|
||||
var path = new Path();
|
||||
proj.activeLayer.appendChild(path);
|
||||
proj.activeLayer.appendTop(path);
|
||||
equals(function() {
|
||||
return proj.activeLayer.children.indexOf(path) != -1;
|
||||
}, true);
|
||||
|
|
Loading…
Reference in a new issue