mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Implement segment point selection.
This commit is contained in:
parent
63c3480ef4
commit
73b97dbfba
4 changed files with 168 additions and 19 deletions
|
@ -279,7 +279,7 @@ var Item = this.Item = Base.extend({
|
|||
* Removes the item.
|
||||
*/
|
||||
remove: function() {
|
||||
if(this._selected)
|
||||
if(this.getSelected())
|
||||
this.setSelected(false);
|
||||
return this.removeFromParent();
|
||||
},
|
||||
|
|
|
@ -20,6 +20,7 @@ var Path = this.Path = PathItem.extend({
|
|||
initialize: function(segments) {
|
||||
this.base();
|
||||
this.closed = false;
|
||||
this._selectedSegmentCount = 0;
|
||||
// Support both passing of segments as array or arguments
|
||||
// If it is an array, it can also be a description of a point, so
|
||||
// check its first entry for object as well
|
||||
|
@ -128,6 +129,37 @@ var Path = this.Path = PathItem.extend({
|
|||
}
|
||||
},
|
||||
|
||||
getSelected: function() {
|
||||
return this._selectedSegmentCount > 0;
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
var wasSelected = this.getSelected();
|
||||
var length = this._segments.length;
|
||||
if (wasSelected != selected && length) {
|
||||
var selectedItems = this._document._selectedItems;
|
||||
if (selected) {
|
||||
selectedItems.push(this);
|
||||
} else {
|
||||
// TODO: is there a faster way?
|
||||
var index = selectedItems.indexOf(this);
|
||||
if (index != -1)
|
||||
selectedItems.splice(index, 1);
|
||||
}
|
||||
}
|
||||
this._selectedSegmentCount = selected ? length : 0;
|
||||
for (var i = 0; i < length; i++)
|
||||
this._segments[i]._selectionState = selected ? 'point' : null;
|
||||
},
|
||||
|
||||
isFullySelected: function() {
|
||||
return this._selectedSegmentCount == this._segments.length;
|
||||
},
|
||||
|
||||
setFullySelected: function(selected) {
|
||||
this.setSelected(selected);
|
||||
},
|
||||
|
||||
// TODO: pointsToCurves([tolerance[, threshold[, cornerRadius[, scale]]]])
|
||||
// TODO: curvesToPoints([maxPointDistance[, flatness]])
|
||||
// TODO: reduceSegments([flatness])
|
||||
|
@ -254,23 +286,28 @@ var Path = this.Path = PathItem.extend({
|
|||
function drawHandles(ctx, segments) {
|
||||
for (var i = 0, l = segments.length; i < l; i++) {
|
||||
var segment = segments[i],
|
||||
point = segment._point;
|
||||
point = segment._point,
|
||||
pointSelected = segment._selectionState == 'point';
|
||||
// TODO: draw handles depending on selection state of
|
||||
// segment.point and neighbouring segments.
|
||||
drawHandle(ctx, point, segment._handleIn);
|
||||
drawHandle(ctx, point, segment._handleOut);
|
||||
if (pointSelected || segment.getSelected(segment._handleIn))
|
||||
drawHandle(ctx, point, segment._handleIn);
|
||||
if (pointSelected || segment.getSelected(segment._handleOut))
|
||||
drawHandle(ctx, point, segment._handleOut);
|
||||
// Draw a rectangle at segment.point:
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(point._x - 2, point._y - 2, 4, 4);
|
||||
ctx.fill();
|
||||
// TODO: Only draw white rectangle if point.isSelected()
|
||||
// TODO: Only draw white rectangle if point.getSelected()
|
||||
// is false:
|
||||
ctx.beginPath();
|
||||
ctx.rect(point._x - 1, point._y - 1, 2, 2);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
if (!pointSelected) {
|
||||
ctx.beginPath();
|
||||
ctx.rect(point._x - 1, point._y - 1, 2, 2);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,12 +125,112 @@ var Segment = this.Segment = Base.extend({
|
|||
return this._path && this._path._segments[this.getIndex() - 1] || null;
|
||||
},
|
||||
|
||||
// TODO:
|
||||
// isSelected: function() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// setSelected: function(pt, selected)
|
||||
getSelected: function(/* point */) {
|
||||
var point = arguments.length ? arguments[0] : this.point;
|
||||
var state = this._selectionState;
|
||||
if (point == this.point) {
|
||||
return state == 'point';
|
||||
} else if (point == this.handleIn) {
|
||||
return state == 'handle-in' || state == 'handle-both';
|
||||
} else if (point == this.handleOut) {
|
||||
return state == 'handle-out' || state == 'handle-both';
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
setSelected: function(/* pt, selected */) {
|
||||
var pt, selected;
|
||||
if (arguments.length == 2) {
|
||||
// setSelected(pt, selected)
|
||||
pt = arguments[0];
|
||||
selected = arguments[1];
|
||||
} else {
|
||||
// setSelected(selected)
|
||||
pt = this._point;
|
||||
selected = arguments[0];
|
||||
}
|
||||
if (!this._path)
|
||||
return;
|
||||
var wasSelected = !!this._selectionState;
|
||||
var state = this._selectionState,
|
||||
pointSelected = state == 'point',
|
||||
handleInSelected = state == 'handle-in'
|
||||
|| state == 'handle-both',
|
||||
handleOutSelected = state == 'handle-out'
|
||||
|| state == 'handle-both',
|
||||
previous = this.getPrevious(),
|
||||
next = this.getNext(),
|
||||
closed = this._path.closed,
|
||||
segments = this._path._segments,
|
||||
length = segments.length;
|
||||
if (length > 1 && closed) {
|
||||
if (previous == null)
|
||||
previous = segments[length - 1];
|
||||
if (next == null)
|
||||
next = segments[0];
|
||||
}
|
||||
if (pt == this._point) {
|
||||
if (pointSelected != selected) {
|
||||
if (selected) {
|
||||
handleInSelected = handleOutSelected = false;
|
||||
} else {
|
||||
// When deselecting a point, the handles get selected
|
||||
// instead depending on the selection state of their
|
||||
// neighbors.
|
||||
handleInSelected = previous != null
|
||||
&& (previous._point.getSelected()
|
||||
|| previous._handleOut.getSelected());
|
||||
handleOutSelected = next != null
|
||||
&& (next._point.getSelected()
|
||||
|| next._handleOut.getSelected());
|
||||
}
|
||||
pointSelected = selected;
|
||||
}
|
||||
} else if (pt == this._handleIn) {
|
||||
if (handleInSelected != selected) {
|
||||
// When selecting handles, the point get deselected.
|
||||
if (selected)
|
||||
pointSelected = false;
|
||||
handleInSelected = selected;
|
||||
}
|
||||
} else if (pt == this._handleOut) {
|
||||
if (handleOutSelected != selected) {
|
||||
// When selecting handles, the point get deselected.
|
||||
if (selected)
|
||||
pointSelected = false;
|
||||
handleOutSelected = selected;
|
||||
}
|
||||
}
|
||||
this._selectionState = pointSelected
|
||||
? 'point'
|
||||
: handleInSelected
|
||||
? handleOutSelected
|
||||
? 'handle-both'
|
||||
: 'handle-in'
|
||||
: handleOutSelected
|
||||
? 'handle-out'
|
||||
: null;
|
||||
// If the selection state of the segment has changed, we need to let
|
||||
// it's path know and possibly add or remove it from
|
||||
// document._selectedItems
|
||||
if (wasSelected == !this._selectionState) {
|
||||
var path = this._path,
|
||||
selectedItems = path._document._selectedItems;
|
||||
if (!this._selectionState) {
|
||||
path._selectedSegmentCount--;
|
||||
if (path._selectedSegmentCount == 0) {
|
||||
var index = selectedItems.indexOf(this);
|
||||
selectedItems.slice(index, 1);
|
||||
}
|
||||
} else {
|
||||
path._selectedSegmentCount++;
|
||||
if (path._selectedSegmentCount == 1) {
|
||||
selectedItems.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
return new Segment(this._point, this._handleOut, this._handleIn);
|
||||
|
@ -141,8 +241,12 @@ var Segment = this.Segment = Base.extend({
|
|||
},
|
||||
|
||||
remove: function() {
|
||||
if (this._path && this._path._segments)
|
||||
return !!this._path._segments.splice(this.getIndex(), 1).length;
|
||||
if (this._path) {
|
||||
this._path._segments.splice(this.getIndex(), 1);
|
||||
if (this.getSelected())
|
||||
this._path._selectedSegmentCount--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
|
|
@ -29,7 +29,15 @@ var SegmentPoint = Point.extend({
|
|||
this._y = y;
|
||||
// this._segment._markDirty(DirtyFlags.BOUNDS);
|
||||
},
|
||||
|
||||
|
||||
setSelected: function(selected) {
|
||||
this._segment.setSelected(this, selected);
|
||||
},
|
||||
|
||||
getSelected: function() {
|
||||
return this._segment.getSelected(this);
|
||||
},
|
||||
|
||||
statics: {
|
||||
create: function(segment, arg1, arg2) {
|
||||
var point;
|
||||
|
|
Loading…
Reference in a new issue