mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Define Callback code for callback based event handling (#atach() / #detach() #fire()) and start implementing it in View.
This commit is contained in:
parent
6713d6aaa8
commit
256e48b511
4 changed files with 202 additions and 64 deletions
132
src/core/Callback.js
Normal file
132
src/core/Callback.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Paper.js
|
||||
*
|
||||
* This file is part of Paper.js, a JavaScript Vector Graphics Library,
|
||||
* based on Scriptographer.org and designed to be largely API compatible.
|
||||
* http://paperjs.org/
|
||||
* http://scriptographer.org/
|
||||
*
|
||||
* Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
|
||||
* http://lehni.org/ & http://jonathanpuckey.com/
|
||||
*
|
||||
* Distributed under the MIT license. See LICENSE file for details.
|
||||
*
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
var events = {
|
||||
frame: function() {
|
||||
|
||||
},
|
||||
|
||||
resize: function() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
view.attach(events);
|
||||
view.detach(events);
|
||||
|
||||
function handler() {
|
||||
|
||||
}
|
||||
|
||||
view.attach('frame', handler);
|
||||
|
||||
|
||||
view.detach('frame', handler);
|
||||
*/
|
||||
|
||||
var Callback = {
|
||||
attach: function(type, func) {
|
||||
var entry = this._events[type];
|
||||
// If an object literal is passed, attach all callbacks defined in it
|
||||
if (!entry) {
|
||||
return Base.each(type, function(value, key) {
|
||||
this.attach(key, value);
|
||||
}, this);
|
||||
}
|
||||
// Otherwise, attach the event now
|
||||
var handlers = this._handlers = this._handlers || {};
|
||||
handlers = handlers[type] = handlers[type] || [];
|
||||
if (handlers.indexOf(func) == -1) { // Not added yet, add it now
|
||||
// See if this is the first handler that we're attaching, and
|
||||
// call install if defined.
|
||||
if (entry.install && !handlers.length)
|
||||
entry.install.call(this);
|
||||
handlers.push(func);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
detach: function(type, func) {
|
||||
var entry = this._events[type];
|
||||
// If an object literal is passed, detach all callbacks defined in it
|
||||
if (!entry) {
|
||||
return Base.each(type, function(value, key) {
|
||||
this.detach(key, value);
|
||||
}, this);
|
||||
}
|
||||
// Otherwise, detach the event now
|
||||
var handlers = this._handlers && this._handlers[type],
|
||||
index = handlers && handlers.indexOf(func) || -1;
|
||||
if (index != -1) {
|
||||
handlers.splice(index, 1);
|
||||
// See if this is the last handler that we're detaching, and
|
||||
// call uninstall if defined.
|
||||
if (!handlers.length) {
|
||||
delete this._handlers[type];
|
||||
if (entry.uninstall)
|
||||
entry.uninstall.call(this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
detachAll: function(type) {
|
||||
return Base.each(this._handlers && this._handlers[type] || [],
|
||||
function(func) {
|
||||
this.detach(type, func);
|
||||
},
|
||||
this);
|
||||
},
|
||||
|
||||
fire: function(type, param) {
|
||||
// Returns true if fired, false otherwise
|
||||
var handlers = this._handlers && this._handlers[type];
|
||||
if (!handlers)
|
||||
return false;
|
||||
Base.each(handlers, function(func) {
|
||||
func.call(this, param);
|
||||
}, this);
|
||||
return true;
|
||||
},
|
||||
|
||||
statics: {
|
||||
inject: function(/* src, ... */) {
|
||||
for (var i = 0, l = arguments.length; i < l; i++) {
|
||||
var src = arguments[i],
|
||||
events = src._events;
|
||||
if (events) {
|
||||
Base.each(events, function(entry, type) {
|
||||
var part = Base.capitalize(type);
|
||||
src['getOn' + part] = function() {
|
||||
return this['_on' + part];
|
||||
};
|
||||
src['setOn' + part] = function(func) {
|
||||
if (func) {
|
||||
this.attach(type, func);
|
||||
} else {
|
||||
this.detach(type, this['_on' + part]);
|
||||
}
|
||||
this['_on' + part] = func;
|
||||
};
|
||||
});
|
||||
}
|
||||
this.base(src);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -191,7 +191,7 @@ var PaperScript = this.PaperScript = new function() {
|
|||
});
|
||||
}
|
||||
if (view) {
|
||||
view.onResize = onResize;
|
||||
view.setOnResize(onResize);
|
||||
view.setOnFrame(onFrame);
|
||||
// Automatically draw view at the end.
|
||||
view.draw();
|
||||
|
|
|
@ -54,6 +54,7 @@ var paper = new function() {
|
|||
/*#*/ include('core/Base.js');
|
||||
/*#*/ include('core/PaperScope.js');
|
||||
/*#*/ include('core/PaperScopeItem.js');
|
||||
/*#*/ include('core/Callback.js');
|
||||
|
||||
// Include Paper classes, which are later injected into PaperScope by setting
|
||||
// them on the 'this' object, e.g.:
|
||||
|
|
131
src/ui/View.js
131
src/ui/View.js
|
@ -23,9 +23,60 @@
|
|||
* center, both useful for constructing artwork that should appear centered on
|
||||
* screen.
|
||||
*/
|
||||
var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
||||
var View = this.View = PaperScopeItem.extend(Callback, /** @lends View# */{
|
||||
_list: 'views',
|
||||
_reference: 'view',
|
||||
_events: {
|
||||
frame: {
|
||||
install: function() {
|
||||
/*#*/ if (options.browser) {
|
||||
var that = this,
|
||||
requested = false,
|
||||
before,
|
||||
time = 0,
|
||||
count = 0;
|
||||
this._onFrameCallback = function(param, dontRequest) {
|
||||
requested = false;
|
||||
// See if we need to stop due to a call to uninstall()
|
||||
if (!that._onFrameCallback)
|
||||
return;
|
||||
// Set the global paper object to the current scope
|
||||
paper = that._scope;
|
||||
if (!dontRequest) {
|
||||
// Request next frame already
|
||||
requested = true;
|
||||
DomEvent.requestAnimationFrame(that._onFrameCallback,
|
||||
that._canvas);
|
||||
}
|
||||
var now = Date.now() / 1000,
|
||||
delta = before ? now - before : 0;
|
||||
// delta: Time elapsed since last redraw in seconds
|
||||
// time: Time since first call of frame() in seconds
|
||||
// Use Base.merge to convert into a Base object,
|
||||
// for #toString()
|
||||
that.fire('frame', Base.merge({
|
||||
delta: delta,
|
||||
time: time += delta,
|
||||
count: count++
|
||||
}));
|
||||
before = now;
|
||||
// Automatically draw view on each frame.
|
||||
that.draw(true);
|
||||
};
|
||||
// Call the onFrame handler straight away, initializing the
|
||||
// sequence of onFrame calls.
|
||||
if (!requested)
|
||||
this._onFrameCallback();
|
||||
/*#*/ } // options.browser
|
||||
},
|
||||
|
||||
uninstall: function() {
|
||||
delete this._onFrameCallback;
|
||||
}
|
||||
},
|
||||
|
||||
resize: {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a view object
|
||||
|
@ -123,8 +174,8 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
this._zoom = 1;
|
||||
|
||||
/*#*/ if (options.browser) {
|
||||
this._events = this._createEvents();
|
||||
DomEvent.add(this._canvas, this._events);
|
||||
this._domEvents = this._createEvents();
|
||||
DomEvent.add(this._canvas, this._domEvents);
|
||||
// Make sure the first view is focused for keyboard input straight away
|
||||
if (!View._focused)
|
||||
View._focused = this;
|
||||
|
@ -155,9 +206,11 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
View._focused = null;
|
||||
delete View._views[this._id];
|
||||
// Uninstall event handlers again for this view.
|
||||
DomEvent.remove(this._canvas, this._events);
|
||||
// Clearing _onFrame makes the frame handler stop automatically.
|
||||
this._canvas = this._events = this._onFrame = null;
|
||||
DomEvent.remove(this._canvas, this._domEvents);
|
||||
this._canvas = this._domEvents = null;
|
||||
// Removing all onFrame handlers makes the _onFrameCallback handler stop
|
||||
// automatically through its uninstall method.
|
||||
this.detachAll('frame');
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -215,12 +268,10 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
this._bounds = null;
|
||||
this._redrawNeeded = true;
|
||||
// Call onResize handler on any size change
|
||||
if (this.onResize) {
|
||||
this.onResize({
|
||||
size: size,
|
||||
delta: delta
|
||||
});
|
||||
}
|
||||
this.fire('resize', {
|
||||
size: size,
|
||||
delta: delta
|
||||
});
|
||||
this._redraw();
|
||||
},
|
||||
|
||||
|
@ -346,7 +397,7 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
if (!this._inverse)
|
||||
this._inverse = this._matrix.createInverse();
|
||||
return this._inverse;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* {@grouptitle Event Handlers}
|
||||
|
@ -373,57 +424,10 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
* path.rotate(3);
|
||||
* }
|
||||
*
|
||||
* @property
|
||||
* @name View#onFrame
|
||||
* @type Function
|
||||
* @bean
|
||||
*/
|
||||
getOnFrame: function() {
|
||||
return this._onFrame;
|
||||
},
|
||||
|
||||
setOnFrame: function(onFrame) {
|
||||
this._onFrame = onFrame;
|
||||
if (!onFrame) {
|
||||
delete this._onFrameCallback;
|
||||
return;
|
||||
}
|
||||
/*#*/ if (options.browser) {
|
||||
var that = this,
|
||||
requested = false,
|
||||
before,
|
||||
time = 0,
|
||||
count = 0;
|
||||
this._onFrameCallback = function(param, dontRequest) {
|
||||
requested = false;
|
||||
if (!that._onFrame)
|
||||
return;
|
||||
// Set the global paper object to the current scope
|
||||
paper = that._scope;
|
||||
// Request next frame already
|
||||
requested = true;
|
||||
if (!dontRequest) {
|
||||
DomEvent.requestAnimationFrame(that._onFrameCallback,
|
||||
that._canvas);
|
||||
}
|
||||
var now = Date.now() / 1000,
|
||||
delta = before ? now - before : 0;
|
||||
// Use Base.merge to convert into a Base object, for #toString()
|
||||
that._onFrame(Base.merge({
|
||||
delta: delta, // Time elapsed since last redraw in seconds
|
||||
time: time += delta, // Time since first call of frame() in seconds
|
||||
count: count++
|
||||
}));
|
||||
before = now;
|
||||
// Automatically draw view on each frame.
|
||||
that.draw(true);
|
||||
};
|
||||
// Call the onFrame handler straight away, initializing the sequence
|
||||
// of onFrame calls.
|
||||
if (!requested)
|
||||
this._onFrameCallback();
|
||||
/*#*/ } // options.browser
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handler function that is called whenever a view is resized.
|
||||
|
@ -440,9 +444,10 @@ var View = this.View = PaperScopeItem.extend(/** @lends View# */{
|
|||
* path.position = view.center;
|
||||
* }
|
||||
*
|
||||
* @property
|
||||
* @name View#onResize
|
||||
* @type Function
|
||||
*/
|
||||
onResize: null
|
||||
}, {
|
||||
statics: {
|
||||
_views: {},
|
||||
|
|
Loading…
Reference in a new issue