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; return this._index1;
}, },
_setIndex: function(index) {
this._index1 = index;
this._updateSegments();
},
getNext: function() { getNext: function() {
// TODO: No need to call getCurves() here? // TODO: No need to call getCurves() here?
var curves = this._path && this._path._curves; 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)); 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. * The curves contained within the path.
*/ */
@ -65,6 +73,15 @@ var Path = this.Path = PathItem.extend({
return this._curves; return this._curves;
}, },
getFirstCurve: function() {
return this.getCurves()[0];
},
getLastCurve: function() {
var curves = this.getCurves();
return curves[curves.length - 1];
},
getClosed: function() { getClosed: function() {
return this._closed; 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 // 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 // path, with the added benefit that b can be < a, and closed looping is
// taken into account. // 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 * 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. * 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) { _add: function(segment, index) {
// If this segment belongs to another path already, clone it before // If this segment belongs to another path already, clone it before
// adding. // adding.
if (segment._path) if (segment._path)
segment = new Segment(segment); segment = new Segment(segment);
segment._path = this;
if (index === undefined) { if (index === undefined) {
this._segments.push(segment); // Insert at the end
index = this._segments.push(segment) - 1;
} else { } else {
// Insert somewhere else
this._segments.splice(index, 0, segment); 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; return segment;
}, },
// TODO: Support multiple segments? // TODO: Add support for adding multiple segments at once
add: function(segment) { add: function(segment) {
segment = Segment.read(arguments); segment = Segment.read(arguments);
return segment ? this._add(segment) : null; return segment ? this._add(segment) : null;
}, },
// TODO: Support multiple segments? // TODO: Add support for adding multiple segments at once
insert: function(index, segment) { insert: function(index, segment) {
segment = Segment.read(arguments, 1); segment = Segment.read(arguments, 1);
return segment ? this._add(segment, index) : null; return segment ? this._add(segment, index) : null;
@ -150,16 +180,28 @@ var Path = this.Path = PathItem.extend({
// TODO: Port back to Sg // TODO: Port back to Sg
removeSegment: function(index) { removeSegment: function(index) {
var segment = this._segments[index] var segments = this.removeSegments(index, index + 1);
return segment && segment.remove() ? segment : null; return segments ? segments[0] : null;
}, },
// TODO: Port back to Sg // TODO: Port back to Sg
removeSegments: function(from, to) { removeSegments: function(from, to) {
var i = Base.pick(to, this._segments.length - 1), from = from || 0;
from = from || 0; to = Base.pick(to, this._segments.length - 1);
while (i >= from) var amount = to - from,
this.removeSegment(i--); 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() { isSelected: function() {

View file

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

View file

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