forked from paperjs/paper.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPaperScope.js
More file actions
207 lines (192 loc) · 5.84 KB
/
Copy pathPaperScope.js
File metadata and controls
207 lines (192 loc) · 5.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
/**
* @name PaperScope
*
* @class The {@code PaperScope} class represents the scope associated with a
* Paper context. When working with PaperScript, these scopes are automatically
* created for us, and through clever scoping the properties and methods of the
* active scope seem to become part of the global scope.
*
* When working with normal JavaScript code, {@code PaperScope} objects need to
* be manually created and handled.
*
* Paper classes can only be accessed through {@code PaperScope} objects. Thus
* in PaperScript they are global, while in JavaScript, they are available on
* the global {@link paper} object. For JavaScript you can use
* {@link PaperScope#install(scope) } to install the Paper classes and objects
* on the global scope. Note that when working with more than one scope, this
* still works for classes, but not for objects like {@link PaperScope#project},
* since they are not updated in the injected scope if scopes are switched.
*
* The global {@link paper} object is simply a reference to the currently active
* {@code PaperScope}.
*/
var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
/**
* Creates a PaperScope object.
*
* @name PaperScope#initialize
* @function
*/
initialize: function(script) {
// script is only used internally, when creating scopes for PaperScript.
// Whenever a PaperScope is created, it automatically becomes the active
// one.
paper = this;
this.project = null;
this.projects = [];
this.tools = [];
this.palettes = [];
// Assign an id to this canvas that's either extracted from the script
// or automatically generated.
this._id = script && (script.getAttribute('id') || script.src)
|| ('paperscope-' + (PaperScope._id++));
// Make sure the script tag also has this id now. If it already had an
// id, we're not changing it, since it's the first option we're
// trying to get an id from above.
if (script)
script.setAttribute('id', this._id);
PaperScope._scopes[this._id] = this;
if (!this.support) {
// Set up paper.support, as an object containing properties that
// describe the support of various features.
var ctx = CanvasProvider.getContext(1, 1);
PaperScope.prototype.support = {
nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx
};
CanvasProvider.release(ctx);
}
},
/**
* The version of Paper.js, as a float number.
*
* @type Number
*/
version: /*#=*/ options.version,
/**
* The currently active project.
* @name PaperScope#project
* @type Project
*/
/**
* The list of all open projects within the current Paper.js context.
* @name PaperScope#projects
* @type Project[]
*/
/**
* The reference to the active project's view.
* @type View
* @bean
*/
getView: function() {
return this.project && this.project.view;
},
/**
* The reference to the active tool.
* @type Tool
* @bean
*/
getTool: function() {
// If no tool exists yet but one is requested, produce it now on the fly
// so it can be used in PaperScript.
if (!this._tool)
this._tool = new Tool();
return this._tool;
},
/**
* The list of available tools.
* @name PaperScope#tools
* @type Tool[]
*/
evaluate: function(code) {
var res = PaperScript.evaluate(code, this);
View.updateFocus();
return res;
},
/**
* Injects the paper scope into any other given scope. Can be used for
* examle to inject the currently active PaperScope into the window's global
* scope, to emulate PaperScript-style globally accessible Paper classes and
* objects:
*
* @example
* paper.install(window);
*/
install: function(scope) {
// Define project, view and tool as getters that redirect to these
// values on the PaperScope, so they are kept up to date
var that = this;
Base.each(['project', 'view', 'tool'], function(key) {
Base.define(scope, key, {
configurable: true,
writable: true,
get: function() {
return that[key];
}
});
});
// Copy over all fields from this scope to the destination.
// Do not use Base.each, since we also want to enumerate over
// fields on PaperScope.prototype, e.g. all classes
for (var key in this) {
if (!/^(version|_id)/.test(key) && !(key in scope))
scope[key] = this[key];
}
},
/**
* Sets up an empty project for us. If a canvas is provided, it also creates
* a {@link View} for it, both linked to this scope.
*
* @param {HTMLCanvasElement} canvas The canvas this scope should be
* associated with.
*/
setup: function(canvas) {
// Create an empty project for the scope.
// Make sure this is the active scope, so the created project and view
// are automatically associated with it.
paper = this;
this.project = new Project(canvas);
// This is needed in PaperScript.load().
return this;
},
clear: function() {
// Remove all projects, views and tools.
// This also removes the installed event handlers.
for (var i = this.projects.length - 1; i >= 0; i--)
this.projects[i].remove();
for (var i = this.tools.length - 1; i >= 0; i--)
this.tools[i].remove();
for (var i = this.palettes.length - 1; i >= 0; i--)
this.palettes[i].remove();
},
remove: function() {
this.clear();
delete PaperScope._scopes[this._id];
},
statics: /** @lends PaperScope */{
_scopes: {},
_id: 0,
/**
* Retrieves a PaperScope object with the given id or associated with
* the passed canvas element.
*
* @param id
*/
get: function(id) {
// If a script tag is passed, get the id from it.
if (typeof id === 'object')
id = id.getAttribute('id');
return this._scopes[id] || null;
}
}
});