mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Implement ChangeFlag.INSERTION notification to know when an item was inserted in a new parent inside the DOM.
This commit is contained in:
parent
946e0d5b2c
commit
aeeba4d58d
3 changed files with 43 additions and 21 deletions
|
@ -14,25 +14,27 @@ var ChangeFlag = {
|
||||||
// Anything affecting the appearance of an item, including GEOMETRY,
|
// Anything affecting the appearance of an item, including GEOMETRY,
|
||||||
// STROKE, STYLE and ATTRIBUTE (except for the invisible ones: locked, name)
|
// STROKE, STYLE and ATTRIBUTE (except for the invisible ones: locked, name)
|
||||||
APPEARANCE: 0x1,
|
APPEARANCE: 0x1,
|
||||||
// Change in item hierarchy
|
// A change in the item's children
|
||||||
CHILDREN: 0x2,
|
CHILDREN: 0x2,
|
||||||
|
// A change in the item's place in the DOM (removed, inserted, moved).
|
||||||
|
INSERTION: 0x4,
|
||||||
// Item geometry (path, bounds)
|
// Item geometry (path, bounds)
|
||||||
GEOMETRY: 0x4,
|
GEOMETRY: 0x8,
|
||||||
// Only segment(s) have changed, and affected curves have alredy been
|
// Only segment(s) have changed, and affected curves have already been
|
||||||
// notified. This is to implement an optimization in _changed() calls.
|
// notified. This is to implement an optimization in _changed() calls.
|
||||||
SEGMENTS: 0x8,
|
SEGMENTS: 0x10,
|
||||||
// Stroke geometry (excluding color)
|
// Stroke geometry (excluding color)
|
||||||
STROKE: 0x10,
|
STROKE: 0x20,
|
||||||
// Fill style or stroke color / dash
|
// Fill style or stroke color / dash
|
||||||
STYLE: 0x20,
|
STYLE: 0x40,
|
||||||
// Item attributes: visible, blendMode, locked, name, opacity, clipMask ...
|
// Item attributes: visible, blendMode, locked, name, opacity, clipMask ...
|
||||||
ATTRIBUTE: 0x40,
|
ATTRIBUTE: 0x80,
|
||||||
// Text content
|
// Text content
|
||||||
CONTENT: 0x80,
|
CONTENT: 0x100,
|
||||||
// Raster pixels
|
// Raster pixels
|
||||||
PIXELS: 0x100,
|
PIXELS: 0x200,
|
||||||
// Clipping in one of the child items
|
// Clipping in one of the child items
|
||||||
CLIPPING: 0x200
|
CLIPPING: 0x400
|
||||||
};
|
};
|
||||||
|
|
||||||
// Shortcuts to often used ChangeFlag values including APPEARANCE
|
// Shortcuts to often used ChangeFlag values including APPEARANCE
|
||||||
|
@ -40,6 +42,8 @@ var Change = {
|
||||||
// CHILDREN also changes GEOMETRY, since removing children from groups
|
// CHILDREN also changes GEOMETRY, since removing children from groups
|
||||||
// changes bounds.
|
// changes bounds.
|
||||||
CHILDREN: ChangeFlag.CHILDREN | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
CHILDREN: ChangeFlag.CHILDREN | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
||||||
|
// Changing the insertion can change the appearance through parent's matrix.
|
||||||
|
INSERTION: ChangeFlag.INSERTION | ChangeFlag.APPEARANCE,
|
||||||
GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
||||||
SEGMENTS: ChangeFlag.SEGMENTS | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
SEGMENTS: ChangeFlag.SEGMENTS | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
||||||
STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
|
STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
|
||||||
|
|
|
@ -2006,10 +2006,15 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
if (_proto && !(item instanceof _proto)) {
|
if (_proto && !(item instanceof _proto)) {
|
||||||
items.splice(i, 1);
|
items.splice(i, 1);
|
||||||
} else {
|
} else {
|
||||||
item._remove(true);
|
// Notify parent of change. Don't notify item itself yet,
|
||||||
|
// as we're doing so when adding it to the new parent below.
|
||||||
|
item._remove(false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Base.splice(children, items, index, 0);
|
Base.splice(children, items, index, 0);
|
||||||
|
var project = this._project,
|
||||||
|
// See #_remove() for an explanation of this:
|
||||||
|
notifySelf = project && project._changes;
|
||||||
for (var i = 0, l = items.length; i < l; i++) {
|
for (var i = 0, l = items.length; i < l; i++) {
|
||||||
var item = items[i];
|
var item = items[i];
|
||||||
item._parent = this;
|
item._parent = this;
|
||||||
|
@ -2018,6 +2023,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// are kept in sync.
|
// are kept in sync.
|
||||||
if (item._name)
|
if (item._name)
|
||||||
item.setName(item._name);
|
item.setName(item._name);
|
||||||
|
if (notifySelf)
|
||||||
|
this._changed(/*#=*/ Change.INSERTION);
|
||||||
}
|
}
|
||||||
this._changed(/*#=*/ Change.CHILDREN);
|
this._changed(/*#=*/ Change.CHILDREN);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2164,16 +2171,24 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
/**
|
/**
|
||||||
* Removes the item from its parent's children list.
|
* Removes the item from its parent's children list.
|
||||||
*/
|
*/
|
||||||
_remove: function(notify) {
|
_remove: function(notifySelf, notifyParent) {
|
||||||
if (this._parent) {
|
var parent = this._parent;
|
||||||
|
if (parent) {
|
||||||
if (this._name)
|
if (this._name)
|
||||||
this._removeNamed();
|
this._removeNamed();
|
||||||
if (this._index != null)
|
if (this._index != null)
|
||||||
Base.splice(this._parent._children, null, this._index, 1);
|
Base.splice(parent._children, null, this._index, 1);
|
||||||
this._installEvents(false);
|
this._installEvents(false);
|
||||||
// Notify parent of changed hierarchy
|
// Notify self of the insertion change. We only need this
|
||||||
if (notify)
|
// notification if we're tracking changes for now.
|
||||||
this._parent._changed(/*#=*/ Change.CHILDREN);
|
if (notifySelf) {
|
||||||
|
var project = this._project;
|
||||||
|
if (project && project._changes)
|
||||||
|
this._changed(/*#=*/ Change.INSERTION);
|
||||||
|
}
|
||||||
|
// Notify parent of changed children
|
||||||
|
if (notifyParent)
|
||||||
|
parent._changed(/*#=*/ Change.CHILDREN);
|
||||||
this._parent = null;
|
this._parent = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2187,7 +2202,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
* @return {Boolean} {@true if the item was removed}
|
* @return {Boolean} {@true if the item was removed}
|
||||||
*/
|
*/
|
||||||
remove: function() {
|
remove: function() {
|
||||||
return this._remove(true);
|
// Notify self and parent of change:
|
||||||
|
return this._remove(true, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2217,8 +2233,10 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// deletes it for the removed items. Calling #_remove() afterwards is
|
// deletes it for the removed items. Calling #_remove() afterwards is
|
||||||
// fine, since it only calls Base.splice() if #_index is set.
|
// fine, since it only calls Base.splice() if #_index is set.
|
||||||
var removed = Base.splice(this._children, null, from, to - from);
|
var removed = Base.splice(this._children, null, from, to - from);
|
||||||
for (var i = removed.length - 1; i >= 0; i--)
|
for (var i = removed.length - 1; i >= 0; i--) {
|
||||||
removed[i]._remove(false);
|
// Don't notify parent each time, notify it separately after.
|
||||||
|
removed[i]._remove(true, false);
|
||||||
|
}
|
||||||
if (removed.length > 0)
|
if (removed.length > 0)
|
||||||
this._changed(/*#=*/ Change.CHILDREN);
|
this._changed(/*#=*/ Change.CHILDREN);
|
||||||
return removed;
|
return removed;
|
||||||
|
|
|
@ -131,7 +131,7 @@ var Layer = Group.extend(/** @lends Layer# */{
|
||||||
// If the item is a layer and contained within Project#layers, use
|
// If the item is a layer and contained within Project#layers, use
|
||||||
// our own version of move().
|
// our own version of move().
|
||||||
if (item instanceof Layer && !item._parent) {
|
if (item instanceof Layer && !item._parent) {
|
||||||
this._remove(true);
|
this._remove(true, true);
|
||||||
Base.splice(item._project.layers, [this],
|
Base.splice(item._project.layers, [this],
|
||||||
item._index + (above ? 1 : 0), 0);
|
item._index + (above ? 1 : 0), 0);
|
||||||
this._setProject(item._project, true);
|
this._setProject(item._project, true);
|
||||||
|
|
Loading…
Reference in a new issue