From b0282b9bd41e4966b8a6740daaf3b7b058618ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 1 May 2011 13:27:53 +0100 Subject: [PATCH] Change Segment to be aware of its index in the segment list and have the curves list update automatically on each change to segments. --- src/path/Curve.js | 5 --- src/path/Path.js | 96 ++++++++++++++++++++++++++++++++------------- src/path/Segment.js | 30 +++++--------- test/tests/Path.js | 2 +- 4 files changed, 80 insertions(+), 53 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 8326145a..19586fde 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -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; diff --git a/src/path/Path.js b/src/path/Path.js index c634f7ae..2b0a677a 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -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() { diff --git a/src/path/Segment.js b/src/path/Segment.js index 6207a12f..ca917c85 100644 --- a/src/path/Segment.js +++ b/src/path/Segment.js @@ -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() { diff --git a/test/tests/Path.js b/test/tests/Path.js index 8a308ca5..83ad7093 100644 --- a/test/tests/Path.js +++ b/test/tests/Path.js @@ -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();