/**
* @fileoverview A class representing an engine-independent
* hoverable, selectable, modifiable and creatable poly-line shape.
*/
goog.provide('xrx.shape.Polyline');
goog.provide('xrx.shape.PolylineCreatable');
goog.provide('xrx.shape.PolylineHoverable');
goog.provide('xrx.shape.PolylineModifiable');
goog.provide('xrx.shape.PolylineSelectable');
goog.require('goog.array');
goog.require('xrx.geometry.Polyline');
goog.require('xrx.shape.PathLike');
goog.require('xrx.shape.Hoverable');
goog.require('xrx.shape.Modifiable');
goog.require('xrx.shape.PathLike');
goog.require('xrx.shape.Selectable');
/**
* A class representing an engine-independent poly-line shape.
* @param {xrx.drawing.Drawing} drawing The parent drawing canvas.
* @extends {xrx.shape.Style}
* @constructor
*/
xrx.shape.Polyline = function(drawing) {
goog.base(this, drawing, new xrx.geometry.Polyline());
/**
* The engine element.
* @type {(xrx.canvas.Polyline|xrx.svg.Polyline|xrx.vml.Polyline)}
* @private
*/
this.engineElement_ = this.drawing_.getEngine().createPolyline();
};
goog.inherits(xrx.shape.Polyline, xrx.shape.PathLike);
/**
* Draws this poly-line shape.
* @private
*/
xrx.shape.Polyline.prototype.draw = function() {
this.startDrawing_();
this.engineElement_.draw(this.getCoords(), this.getRenderingFillColor(),
0, this.getRenderingStrokeColor(), this.getRenderingStrokeWidth());
this.finishDrawing_();
};
/**
* Returns a helper shape that makes this shape hoverable.
* @return {xrx.shape.PolylineHoverable} The hoverable poly-line shape.
*/
xrx.shape.Polyline.prototype.getHoverable = function() {
if (!this.hoverable_) this.hoverable_ = new xrx.shape.PolylineHoverable(this);
return this.hoverable_;
};
/**
* Returns a helper shape that makes this shape selectable.
* @return {xrx.shape.PolylineSelectable} The selectable poly-line shape.
*/
xrx.shape.Polyline.prototype.getSelectable = function() {
if (!this.selectable_) this.selectable_ = new xrx.shape.PolylineSelectable(this);
return this.selectable_;
};
/**
* Returns a helper shape that makes this shape modifiable.
* @return {xrx.shape.PolylineModifiable} The modifiable poly-line shape.
*/
xrx.shape.Polyline.prototype.getModifiable = function(drawing) {
if (!this.modifiable_) this.modifiable_ = new xrx.shape.PolylineModifiable(this);
return this.modifiable_;
};
/**
* Returns a helper shape that makes this shape creatable.
* @return {xrx.shape.PolylineCreatable} The creatable poly-line shape.
*/
xrx.shape.Polyline.prototype.getCreatable = function() {
if (!this.creatable_) this.creatable_ = new xrx.shape.PolylineCreatable(this);
return this.creatable_;
};
/**
* Disposes this poly-line shape.
*/
xrx.shape.Polyline.prototype.disposeInternal = function() {
goog.base(this, 'disposeInternal');
};
/**
* A class representing a hoverable poly-line shape.
* @param {xrx.shape.Polyline} poly-line The parent poly-line shape.
* @constructor
* @private
*/
xrx.shape.PolylineHoverable = function(polyline) {
goog.base(this, polyline);
};
goog.inherits(xrx.shape.PolylineHoverable, xrx.shape.Hoverable);
/**
* Disposes this hoverable poly-line shape.
*/
xrx.shape.PolylineHoverable.prototype.disposeInternal = function() {
goog.base(this, 'disposeInternal');
};
/**
* A class representing a selectable poly-line shape.
* @param {xrx.shape.Polyline} poly-line The parent poly-line shape.
* @constructor
* @private
*/
xrx.shape.PolylineSelectable = function(polyline) {
goog.base(this, polyline);
};
goog.inherits(xrx.shape.PolylineSelectable, xrx.shape.Selectable);
/**
* Disposes this selectable poly-line shape.
*/
xrx.shape.PolylineSelectable.prototype.disposeInternal = function() {
goog.base(this, 'disposeInternal');
};
/**
* A class representing a modifiable poly-line shape.
* @param {xrx.shape.Polyline} poly-line The parent poly-line shape.
* @constructor
* @private
*/
xrx.shape.PolylineModifiable = function(polyline, helper) {
goog.base(this, polyline, helper);
this.init_();
};
goog.inherits(xrx.shape.PolylineModifiable, xrx.shape.Modifiable);
/**
* @private
*/
xrx.shape.PolylineModifiable.prototype.setCoords = function(coords, position) {
for(var i = 0, len = this.dragger_.length; i < len; i++) {
if (i !== position) {
this.dragger_[i].setCoordX(coords[i][0]);
this.dragger_[i].setCoordY(coords[i][1]);
}
}
this.shape_.setCoords(coords);
};
/**
* @private
*/
xrx.shape.PolylineModifiable.prototype.setCoordAt = function(pos, coord) {
this.dragger_[pos].setCoordX(coord[0]);
this.dragger_[pos].setCoordY(coord[1]);
this.shape_.setCoordXAt(pos, coord[0]);
this.shape_.setCoordYAt(pos, coord[1]);
};
/**
* @private
*/
xrx.shape.PolylineModifiable.prototype.init_ = function() {
var coords = this.shape_.getCoords();
var draggers = [];
var dragger;
for(var i = 0, len = coords.length; i < len; i++) {
dragger = new xrx.shape.Dragger(this, i);
dragger.setCoords([coords[i]]);
draggers.push(dragger);
}
this.setDragger(draggers);
};
/**
* Disposes this modifiable poly-line shape.
*/
xrx.shape.PolylineModifiable.prototype.disposeInternal = function() {
goog.base(this, 'disposeInternal');
};
/**
* @private
*/
xrx.shape.PolylineModifiable.prototype.move = function(distX, distY) {
var coords = this.shape_.getCoordsCopy();
for (var i = 0, len = coords.length; i < len; i++) {
coords[i][0] += distX;
coords[i][1] += distY;
}
this.setCoords(coords);
};
/**
* A class representing a creatable poly-line shape.
* @param {xrx.shape.Polyline} poly-line The parent poly-line shape.
* @constructor
* @private
*/
xrx.shape.PolylineCreatable = function(polyline) {
goog.base(this, polyline, new xrx.shape.Polyline(polyline.getDrawing()));
/**
* The last point created by the user, which closes the poly-line when clicked.
* @type {xrx.shape.Dragger}
* @private
*/
this.close_;
/**
* Number of points the user has created so far.
* @type {number}
* @private
*/
this.count_ = 0;
};
goog.inherits(xrx.shape.PolylineCreatable, xrx.shape.Creatable);
/**
* Returns the coordinates of the poly-line created so far.
* @return Array<number> The coordinates.
* @private
*/
xrx.shape.PolylineCreatable.prototype.getCoords = function() {
return this.preview_.getCoords();
};
/**
* @private
*/
xrx.shape.PolylineCreatable.prototype.handleDown = function(e, cursor) {
var shape = cursor.getShape();
var point = cursor.getPointTransformed();
if (this.count_ === 0) { // user creates the first point
// update the poly-line preview
this.preview_.setCoords([point, goog.array.clone(point)]);
this.count_ += 1;
this.target_.getDrawing().eventShapeCreate([this.preview_]);
} else if (this.close_ && shape === this.close_ && this.count_ === 1) {
// Do nothing if the user tries to close the path at the time
// when there is only one point yet
} else { // user touches down to move to the next point or end point
this.preview_.setLastCoord(point);
}
};
/**
* @private
*/
xrx.shape.PolylineCreatable.prototype.handleMove = function(e, cursor) {
var shape = cursor.getShape();
var point = cursor.getPointTransformed();
if (this.count_ === 0) {
return;
} else {
this.preview_.setLastCoord(point);
}
if (this.close_ && shape === this.close_) {
this.close_.setStrokeColor('red');
this.close_.setStrokeWidth(3);
} else if (this.close_) {
this.close_.setStrokeColor('black');
this.close_.setStrokeWidth(1);
} else {}
};
/**
* @private
*/
xrx.shape.PolylineCreatable.prototype.handleUp = function(e, cursor) {
var shape = cursor.getShape();
var point = cursor.getPointTransformed();
if (this.close_ && shape === this.close_) { // user closes the poly-line
// create a poly-line
var polyline = new xrx.shape.Polyline(this.target_.getDrawing());
polyline.setStyle(this.target_);
polyline.setCoords(this.preview_.getCoordsCopy().splice(0, this.count_));
this.target_.getDrawing().eventShapeCreated(polyline);
// reset for next drawing
this.close_ = null;
this.count_ = 0;
} else { // user creates another point
// extend the poly-line
this.preview_.appendCoord(point);
// create the closing point as soon as the user creates the second point
if (this.count_ === 1) {
this.close_ = new xrx.shape.Dragger(this.target_.getModifiable(), 0);
this.target_.getDrawing().eventShapeCreate([this.close_]);
}
this.close_.setCoords([point]);
this.count_ += 1;
}
};
/**
* Disposes this creatable poly-line shape.
*/
xrx.shape.PolylineCreatable.prototype.disposeInternal = function() {
this.close_.dispose();
this.close_ = null;
goog.base(this, 'disposeInternal');
};