mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -05:00
Bigger refactoring of handling of segment selection: Have Path#_selectedSegmentState be the summed up value of all Segment's states, and compare it to segments.length * SelectionState.POINT in #fullySelected.
This commit is contained in:
parent
e670c262c3
commit
a32b687bfd
5 changed files with 43 additions and 51 deletions
|
@ -231,7 +231,7 @@ var Item = this.Item = Base.extend({
|
||||||
}
|
}
|
||||||
} else if ((selected = !!selected) != this._selected) {
|
} else if ((selected = !!selected) != this._selected) {
|
||||||
this._selected = selected;
|
this._selected = selected;
|
||||||
this._project._selectItem(this, selected);
|
this._project._updateSelection(this);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ var Path = this.Path = PathItem.extend({
|
||||||
initialize: function(segments) {
|
initialize: function(segments) {
|
||||||
this.base();
|
this.base();
|
||||||
this._closed = false;
|
this._closed = false;
|
||||||
this._selectedSegmentCount = 0;
|
this._selectedSegmentState = 0;
|
||||||
// Support both passing of segments as array or arguments
|
// Support both passing of segments as array or arguments
|
||||||
// If it is an array, it can also be a description of a point, so
|
// If it is an array, it can also be a description of a point, so
|
||||||
// check its first entry for object as well
|
// check its first entry for object as well
|
||||||
|
@ -248,9 +248,9 @@ var Path = this.Path = PathItem.extend({
|
||||||
segment._path = this;
|
segment._path = this;
|
||||||
segment._index = index + i;
|
segment._index = index + i;
|
||||||
// If parts of this segment are selected, adjust the internal
|
// If parts of this segment are selected, adjust the internal
|
||||||
// _selectedSegmentCount now
|
// _selectedSegmentState now
|
||||||
if (segment._selectionState)
|
if (segment._selectionState)
|
||||||
this._updateSelection(segment);
|
this._updateSelection(segment, 0, segment._selectionState);
|
||||||
}
|
}
|
||||||
if (append) {
|
if (append) {
|
||||||
// Append them all at the end by using push
|
// Append them all at the end by using push
|
||||||
|
@ -280,13 +280,6 @@ var Path = this.Path = PathItem.extend({
|
||||||
return segs;
|
return segs;
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateSelection: function(segment) {
|
|
||||||
var count = this._selectedSegmentCount +=
|
|
||||||
segment._selectionState ? 1 : -1;
|
|
||||||
if (count <= 1)
|
|
||||||
this._project._selectItem(this, count == 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
// PORT: Add support for adding multiple segments at once to Scriptographer
|
// PORT: Add support for adding multiple segments at once to Scriptographer
|
||||||
// DOCS: find a way to document the variable segment parameters of Path#add
|
// DOCS: find a way to document the variable segment parameters of Path#add
|
||||||
/**
|
/**
|
||||||
|
@ -537,10 +530,8 @@ var Path = this.Path = PathItem.extend({
|
||||||
// Update selection state accordingly
|
// Update selection state accordingly
|
||||||
for (var i = 0; i < amount; i++) {
|
for (var i = 0; i < amount; i++) {
|
||||||
var segment = removed[i];
|
var segment = removed[i];
|
||||||
if (segment._selectionState) {
|
if (segment._selectionState)
|
||||||
segment._selectionState = 0;
|
this._updateSelection(segment, segment._selectionState, 0);
|
||||||
this._updateSelection(segment);
|
|
||||||
}
|
|
||||||
// Clear the indices and path references of the removed segments
|
// Clear the indices and path references of the removed segments
|
||||||
removed._index = removed._path = undefined;
|
removed._index = removed._path = undefined;
|
||||||
}
|
}
|
||||||
|
@ -599,23 +590,8 @@ var Path = this.Path = PathItem.extend({
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
isSelected: function() {
|
|
||||||
return this._selectedSegmentCount > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
setSelected: function(selected) {
|
|
||||||
var wasSelected = this.isSelected(),
|
|
||||||
length = this._segments.length;
|
|
||||||
if (!wasSelected != !selected && length)
|
|
||||||
this._project._selectItem(this, selected);
|
|
||||||
this._selectedSegmentCount = selected ? length : 0;
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
this._segments[i]._selectionState = selected
|
|
||||||
? SelectionState.POINT : 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether all segments of the path are selected.
|
* Specifies whether the path and all its segments are selected.
|
||||||
*
|
*
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
* @bean
|
* @bean
|
||||||
|
@ -623,10 +599,10 @@ var Path = this.Path = PathItem.extend({
|
||||||
* @example {@paperscript}
|
* @example {@paperscript}
|
||||||
* // A path is fully selected, if all of its segments are selected:
|
* // A path is fully selected, if all of its segments are selected:
|
||||||
* var path = new Path.Circle(new Size(80, 50), 35);
|
* var path = new Path.Circle(new Size(80, 50), 35);
|
||||||
* path.selected = true;
|
* path.fullySelected = true;
|
||||||
*
|
*
|
||||||
* var path2 = new Path.Circle(new Size(180, 50), 35);
|
* var path2 = new Path.Circle(new Size(180, 50), 35);
|
||||||
* path2.selected = true;
|
* path2.fullySelected = true;
|
||||||
*
|
*
|
||||||
* // Deselect the second segment of the second path:
|
* // Deselect the second segment of the second path:
|
||||||
* path2.segments[1].selected = false;
|
* path2.segments[1].selected = false;
|
||||||
|
@ -645,13 +621,26 @@ var Path = this.Path = PathItem.extend({
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
isFullySelected: function() {
|
isFullySelected: function() {
|
||||||
return this._selectedSegmentCount == this._segments.length;
|
return this._selected && this._selectedSegmentState
|
||||||
|
== this._segments.length * SelectionState.POINT;
|
||||||
},
|
},
|
||||||
|
|
||||||
setFullySelected: function(selected) {
|
setFullySelected: function(selected) {
|
||||||
|
var length = this._segments.length;
|
||||||
|
this._selectedSegmentState = selected
|
||||||
|
? length * SelectionState.POINT : 0;
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
this._segments[i]._selectionState = selected
|
||||||
|
? SelectionState.POINT : 0;
|
||||||
this.setSelected(selected);
|
this.setSelected(selected);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_updateSelection: function(segment, oldState, newState) {
|
||||||
|
segment._selectionState = newState;
|
||||||
|
this.setSelected(
|
||||||
|
(this._selectedSegmentState += newState - oldState) > 0);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the curves in the path to straight lines.
|
* Converts the curves in the path to straight lines.
|
||||||
*
|
*
|
||||||
|
@ -1166,13 +1155,12 @@ var Path = this.Path = PathItem.extend({
|
||||||
for (var i = 0, l = segments.length; i < l; i++) {
|
for (var i = 0, l = segments.length; i < l; i++) {
|
||||||
var segment = segments[i],
|
var segment = segments[i],
|
||||||
point = segment._point,
|
point = segment._point,
|
||||||
pointSelected = segment._selectionState == SelectionState.POINT;
|
state = segment._selectionState,
|
||||||
// TODO: draw handles depending on selection state of
|
selected = state & SelectionState.POINT;
|
||||||
// segment.point and neighbouring segments.
|
if (selected || (state & SelectionState.HANDLE_IN))
|
||||||
if (pointSelected || segment._isSelected(segment._handleIn))
|
drawHandle(ctx, point, segment._handleIn);
|
||||||
drawHandle(ctx, point, segment._handleIn);
|
if (selected || (state & SelectionState.HANDLE_OUT))
|
||||||
if (pointSelected || segment._isSelected(segment._handleOut))
|
drawHandle(ctx, point, segment._handleOut);
|
||||||
drawHandle(ctx, point, segment._handleOut);
|
|
||||||
// Draw a rectangle at segment.point:
|
// Draw a rectangle at segment.point:
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
@ -1180,7 +1168,7 @@ var Path = this.Path = PathItem.extend({
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
// If the point is not selected, draw a white square that is 1 px
|
// If the point is not selected, draw a white square that is 1 px
|
||||||
// smaller on all sides:
|
// smaller on all sides:
|
||||||
if (!pointSelected) {
|
if (!selected) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.rect(point._x - 1, point._y - 1, 2, 2);
|
ctx.rect(point._x - 1, point._y - 1, 2, 2);
|
||||||
ctx.fillStyle = '#ffffff';
|
ctx.fillStyle = '#ffffff';
|
||||||
|
|
|
@ -182,7 +182,6 @@ var Segment = this.Segment = Base.extend({
|
||||||
var path = this._path,
|
var path = this._path,
|
||||||
selected = !!selected, // convert to boolean
|
selected = !!selected, // convert to boolean
|
||||||
state = this._selectionState,
|
state = this._selectionState,
|
||||||
wasSelected = !!state,
|
|
||||||
// For performance reasons use array indices to access the various
|
// For performance reasons use array indices to access the various
|
||||||
// selection states: 0 = point, 1 = handleIn, 2 = handleOut
|
// selection states: 0 = point, 1 = handleIn, 2 = handleOut
|
||||||
selection = [
|
selection = [
|
||||||
|
@ -220,10 +219,12 @@ var Segment = this.Segment = Base.extend({
|
||||||
// If the selection state of the segment has changed, we need to let
|
// If the selection state of the segment has changed, we need to let
|
||||||
// it's path know and possibly add or remove it from
|
// it's path know and possibly add or remove it from
|
||||||
// project._selectedItems
|
// project._selectedItems
|
||||||
if (path && wasSelected != !!this._selectionState)
|
if (path && state != this._selectionState)
|
||||||
path._updateSelection(this);
|
path._updateSelection(this, state, this._selectionState);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the {@link #point} of the segment is selected.
|
* Specifies whether the {@link #point} of the segment is selected.
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
|
|
|
@ -14,9 +14,12 @@
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// These values are ordered so that SelectionState.POINT has the highest value.
|
||||||
|
// As Path#_selectedSegmentState is the addition of all segment's states, and is
|
||||||
|
// used to see if all segments are fully selected, meaning they are set to
|
||||||
|
// SelectionState.POINT.
|
||||||
var SelectionState = {
|
var SelectionState = {
|
||||||
POINT: 1,
|
HANDLE_IN: 1,
|
||||||
HANDLE_IN: 2,
|
HANDLE_OUT: 2,
|
||||||
HANDLE_OUT: 4,
|
POINT: 4
|
||||||
HANDLE_BOTH: 6
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,8 +142,8 @@ var Project = this.Project = Base.extend({
|
||||||
|
|
||||||
// TODO: Implement setSelectedItems?
|
// TODO: Implement setSelectedItems?
|
||||||
|
|
||||||
_selectItem: function(item, select) {
|
_updateSelection: function(item) {
|
||||||
if (select) {
|
if (item._selected) {
|
||||||
this._selectedItemCount++;
|
this._selectedItemCount++;
|
||||||
this._selectedItems[item.getId()] = item;
|
this._selectedItems[item.getId()] = item;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue