Change Segment to be aware of its index in the segment list and have the curves list update automatically on each change to segments.

This commit is contained in:
Jürg Lehni 2011-05-01 13:27:53 +01:00
parent 0680a50fd2
commit b0282b9bd4
4 changed files with 80 additions and 53 deletions

View file

@ -117,11 +117,6 @@ var Curve = this.Curve = Base.extend({
return this._index1;
},
_setIndex: function(index) {
this._index1 = index;
this._updateSegments();
},
getNext: function() {
// TODO: No need to call getCurves() here?
var curves = this._path && this._path._curves;

View file

@ -49,6 +49,14 @@ var Path = this.Path = PathItem.extend({
this._add(Segment.read(segments, i, 1));
},
getFirstSegment: function() {
return this._segments[0];
},
getLastSegment: function() {
return this._segments[this._segments.length - 1];
},
/**
* The curves contained within the path.
*/
@ -65,6 +73,15 @@ var Path = this.Path = PathItem.extend({
return this._curves;
},
getFirstCurve: function() {
return this.getCurves()[0];
},
getLastCurve: function() {
var curves = this.getCurves();
return curves[curves.length - 1];
},
getClosed: function() {
return this._closed;
},
@ -88,23 +105,6 @@ var Path = this.Path = PathItem.extend({
}
},
getFirstSegment: function() {
return this._segments[0];
},
getLastSegment: function() {
return this._segments[this._segments.length - 1];
},
getFirstCurve: function() {
return this.getCurves()[0];
},
getLastCurve: function() {
var curves = this.getCurves();
return curves[curves.length - 1];
},
// TODO: Consider adding getSubPath(a, b), returning a part of the current
// path, with the added benefit that b can be < a, and closed looping is
// taken into account.
@ -121,28 +121,58 @@ var Path = this.Path = PathItem.extend({
/**
* Private method that adds a segment to the segment list. It assumes that
* the passed object is a segment already and does not perform any checks.
* If a curves list was requested, it will kept in sync with the segments
* list automatically.
*/
// TODO: Add support for adding multiple segments at once
_add: function(segment, index) {
// If this segment belongs to another path already, clone it before
// adding.
if (segment._path)
segment = new Segment(segment);
segment._path = this;
if (index === undefined) {
this._segments.push(segment);
// Insert at the end
index = this._segments.push(segment) - 1;
} else {
// Insert somewhere else
this._segments.splice(index, 0, segment);
// Adjust the indices of the segments above.
for (var i = index + 1, l = this._segments.length; i < l; i++)
this._segments[i]._index = i;
}
segment._path = this;
segment._index = index;
// Keep the curves list in sync all the time in case it as requested
// already. We need to step one index down from the inserted segment to
// get its curve:
if (this._curves && --index >= 0) {
// Insert a new curve as well and update the curves above
this._curves.splice(index, 0, Curve.create(this, index));
// Adjust indices now for the curves above this one.
for (var i = index + 1, l = this._curves.length; i < l; i++) {
var curve = this._curves[i];
curve._index1 = i;
// This is wrong for the last closing curve but it will be
// corrected further down.
curve._index2 = i + 1;
}
// The curve that comes right after will has changed beyond a simple
// shift in indices, so it needs an update:
this._curves[index + 1]._updateSegments();
// If this is a closed path, also update the closing curve
if (this._closed)
this._curves[l - 1]._updateSegments();
}
return segment;
},
// TODO: Support multiple segments?
// TODO: Add support for adding multiple segments at once
add: function(segment) {
segment = Segment.read(arguments);
return segment ? this._add(segment) : null;
},
// TODO: Support multiple segments?
// TODO: Add support for adding multiple segments at once
insert: function(index, segment) {
segment = Segment.read(arguments, 1);
return segment ? this._add(segment, index) : null;
@ -150,16 +180,28 @@ var Path = this.Path = PathItem.extend({
// TODO: Port back to Sg
removeSegment: function(index) {
var segment = this._segments[index]
return segment && segment.remove() ? segment : null;
var segments = this.removeSegments(index, index + 1);
return segments ? segments[0] : null;
},
// TODO: Port back to Sg
removeSegments: function(from, to) {
var i = Base.pick(to, this._segments.length - 1),
from = from || 0;
while (i >= from)
this.removeSegment(i--);
from = from || 0;
to = Base.pick(to, this._segments.length - 1);
var amount = to - from,
segments = this._segments.splice(from, amount);
if (segments.length == amount) {
// TODO: Keep _curves in sync
for (var i = 0; i < amount; i++) {
var segment = segments[0];
if (segment._selectionState) {
this._selectedSegmentCount--;
segment._selectionState = 0;
}
}
return segments;
}
return null;
},
isSelected: function() {

View file

@ -21,8 +21,8 @@ var Segment = this.Segment = Base.extend({
if (arguments.length == 0) {
this._point = SegmentPoint.create(this, 0, 0);
} else if (arguments.length == 1) {
// TODO: If beans are not activated, this won't copy from
// an existing segment. OK?
// TODO: If beans are not activated, this won't copy from n existing
// segment. OK?
if (arg0.point) {
this._point = SegmentPoint.create(this, arg0.point);
this._handleIn = SegmentPoint.create(this, arg0.handleIn);
@ -96,19 +96,17 @@ var Segment = this.Segment = Base.extend({
? null : this._handleOut;
},
getIndex: function() {
// TODO: Cache and update indices instead of searching?
// TODO: Return null instead of -1?
return this._path ? this._path._segments.indexOf(this) : -1;
},
getPath: function() {
return this._path;
},
getIndex: function() {
return this._index;
},
getCurve: function() {
if (this._path != null) {
var index = this.getIndex();
var index = this._index;
// The last segment of an open path belongs to the last curve
if (!this._path._closed && index == this._path._segments.length - 1)
index--;
@ -119,13 +117,13 @@ var Segment = this.Segment = Base.extend({
getNext: function() {
var segments = this._path && this._path._segments;
return segments && (segments[this.getIndex() + 1]
return segments && (segments[this._index + 1]
|| this._path._closed && segments[0]) || null;
},
getPrevious: function() {
var segments = this._path && this._path._segments;
return segments && (segments[this.getIndex() - 1]
return segments && (segments[this._index - 1]
|| this._path._closed && segments[segments.length - 1]) || null;
},
@ -206,15 +204,7 @@ var Segment = this.Segment = Base.extend({
},
remove: function() {
if (this._path) {
this._path._segments.splice(this.getIndex(), 1);
if (this._selectionState) {
this._path._selectedSegmentCount--;
this._selectionState = 0;
}
return true;
}
return false;
return this._path ? !!this._path.removeSegment(this._index) : false;
},
toString: function() {

View file

@ -69,7 +69,7 @@ test('path.remove()', function() {
path.removeSegment(0);
equals(path.segments.length, 2);
path.removeSegments(0, 1);
path.removeSegments(0, 2);
equals(path.segments.length, 0);
path.remove();