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:
Jürg Lehni 2011-06-14 15:37:25 +01:00
parent e670c262c3
commit a32b687bfd
5 changed files with 43 additions and 51 deletions

View file

@ -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);
} }
}, },

View file

@ -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';

View file

@ -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

View file

@ -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
}; };

View file

@ -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 {