Implement a first version of drawing path selection.

This commit is contained in:
Jonathan Puckey 2011-04-17 18:46:35 +02:00
parent 74cee4abef
commit be9f312110
3 changed files with 176 additions and 70 deletions

View file

@ -56,6 +56,17 @@ var Document = this.Document = Base.extend({
return false;
},
getSelectionContext: function(param) {
var context = this._selectionContext;
if (!context) {
var canvas = CanvasProvider.getCanvas(this.size);
context = this._selectionContext = canvas.getContext('2d');
context.strokeWidth = 1;
}
context.strokeStyle = context.fillStyle = param.layerColor;
return context;
},
draw: function() {
if (this.canvas) {
// Initial tests conclude that clearing the canvas using clearRect
@ -66,9 +77,21 @@ var Document = this.Document = Base.extend({
this.context.save();
var param = { offset: new Point(0, 0) };
for (var i = 0, l = this.layers.length; i < l; i++) {
// TODO: use Layer#color:
param.layerColor = '#4f7aff';
Item.draw(this.layers[i], this.context, param);
}
this.context.restore();
// If, during drawing, one of the paths was selected, there will
// be a selectionContext which needs to be composited onto the
// canvas:
if (this._selectionContext) {
var canvas = this._selectionContext.canvas;
this.context.drawImage(canvas, 0, 0);
CanvasProvider.returnCanvas(canvas);
this._selectionContext = null;
}
}
},

View file

@ -53,7 +53,29 @@ var Item = this.Item = Base.extend({
return copy;
},
// TODO: isSelected / setSelected
setSelected: function(selected) {
if (this._children) {
for (var i = 0, l = this.children.length; i < l; i++) {
var child = this._children[i];
child.setSelected(selected);
}
} else {
this._selected = selected;
}
},
getSelected: function() {
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++) {
var child = this._children[i];
if (child.getSelected())
return true;
}
} else {
return !!this._selected;
}
},
// TODO: isFullySelected / setFullySelected
/**
@ -650,11 +672,14 @@ var Item = this.Item = Base.extend({
// on the temporary canvas.
context.translate(-itemOffset.x, -itemOffset.y);
}
item.draw(context, {
offset: itemOffset || param.offset,
compound: param.compound
});
var savedOffset;
if (itemOffset) {
savedOffset = param.offset;
param.offset = itemOffset;
}
item.draw(context, param);
if (itemOffset)
param.offset = savedOffset;
// If we created a temporary canvas before, composite it onto the
// parent canvas:

View file

@ -99,13 +99,13 @@ var Path = this.Path = PathItem.extend({
return segment;
},
add: function() {
var segment = Segment.read(arguments);
add: function(segment) {
segment = Segment.read(arguments);
return segment ? this._add(segment) : null;
},
insert: function(index, segment) {
var segment = Segment.read(arguments, 1);
segment = Segment.read(arguments, 1);
return segment ? this._add(segment, index) : null;
},
@ -248,8 +248,50 @@ var Path = this.Path = PathItem.extend({
return loc
? loc.getCurve().getNormal(loc.getParameter())
: null;
},
}
}, new function() { // Scope for drawing
function drawHandles(ctx, segments) {
for (var i = 0, l = segments.length; i < l; i++) {
var segment = segments[i],
handleIn = segment.handleIn,
handleOut = segment.handleOut,
point = segment.point,
rounded = point.round();
// TODO: draw handles depending on selection state of
// segment.point and neighbouring segments.
drawHandle(ctx, point, handleIn);
drawHandle(ctx, point, handleOut);
// Draw a rectangle at segment.point:
ctx.save();
ctx.beginPath();
ctx.rect(rounded.x - 2, rounded.y - 2, 4, 4);
ctx.fill();
// TODO: Only draw white rectangle if point.isSelected()
// is false:
ctx.beginPath();
ctx.rect(rounded.x - 1, rounded.y - 1, 2, 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.restore();
}
}
function drawHandle(ctx, point, handle) {
if (!handle.isZero()) {
handle = handle.add(point);
ctx.beginPath();
ctx.moveTo(point.x, point.y);
ctx.lineTo(handle.x, handle.y);
ctx.stroke();
ctx.beginPath();
var rounded = handle.round();
ctx.rect(rounded.x - 1, rounded.y - 1, 2, 2);
ctx.stroke();
}
}
return {
draw: function(ctx, param) {
if (!param.compound)
ctx.beginPath();
@ -292,6 +334,12 @@ var Path = this.Path = PathItem.extend({
// stroke, there is no need to continue.
var fillColor = this.getFillColor(),
strokeColor = this.getStrokeColor();
// If we are drawing onto the selection canvas, stroke the
// path and draw its handles.
if (param.selection) {
ctx.stroke();
drawHandles(ctx, this.segments);
} else {
if (!param.compound && (fillColor || strokeColor)) {
this.setContextStyles(ctx);
ctx.save();
@ -310,7 +358,17 @@ var Path = this.Path = PathItem.extend({
}
ctx.restore();
}
// If the path is selected, draw it again on the separate
// selection canvas, which will be composited onto the canvas
// after drawing of the document is complete.
if (this.getSelected()) {
param.selection = true;
this.draw(this.document.getSelectionContext(param), param);
param.selection = false;
}
}
}
};
}, new function() { // Scope for segments list change detection
var segmentsFields = Base.each(