Gitlab CSE Unil

Commit cf474af6 authored by Julien Furrer's avatar Julien Furrer
Browse files

Changed drag handling for Shapes

Possible to drag and resize with both shape and
select tool. Shift-Drag handles to resize and 
preserve shape ratio
parent 23f1bc47
......@@ -2,10 +2,17 @@ define(["paper"],
function () {
// ----- Returned Class Module ------------------------------
return function(shapeType, events){
var c;
var drawing = false;
var startPoint, endPoint;
return function(shapeType, _events){
var _creatingShape,
_drawing = false,
_startPoint, _endPoint,
_dragMode = null, _dragOpts = {}, _dragModified = false;
var DRAG_MODES = {
FULL_DRAG: 1,
DRAG_HANDLE: 4
};
var defaultProperties = {
comment: "",
confidence: 3,
......@@ -24,12 +31,43 @@ function () {
}
};
function exportJSON(param) {
var json = this.exportJSON({asString:false});
// // There is no apparent reason why we would nullify strokeWidth ?
// // @TODO: remove this part of code when we are sure there are no side effect
// if (!json[1].strokeColor) {
// json[1].strokeWidth = 0;
// }
delete(json[1].fontFamily);
delete(json[1].font);
delete(json[1].fontSize);
delete(json[1].leading);
return (param && param.asString) ? JSON.stringify(json) : json;
}
function importJSON(itemDef, layer, listening) {
var item = layer.importJSON(itemDef);
attachListeners(item);
return item;
}
function _isItemShapeType(item) {
var types = ['ellipse', 'rectangle'];
return !!item && item.data && item.data.type &&
types.indexOf(item.data.type) > -1;
}
function drawShape(event, style) {
var s;
if (event.modifiers.shift) {
var w = startPoint.subtract(endPoint).length / 1.414213;
var q = endPoint.subtract(startPoint).quadrant;
var w = _startPoint.subtract(_endPoint).length / 1.414213;
var q = _endPoint.subtract(_startPoint).quadrant;
var xw = (q===2 || q===3) ? -w : w;
var yw = (q===3 || q===4) ? -w : w;
}
......@@ -37,21 +75,21 @@ function () {
switch (shapeType) {
case 'circle':
s = new paper.Shape.Circle({
center: startPoint,
radius: startPoint.subtract(endPoint).length
center: _startPoint,
radius: _startPoint.subtract(_endPoint).length
});
break;
case 'ellipse':
if (event.modifiers.shift) {
s = new paper.Shape.Ellipse({
point: startPoint,
point: _startPoint,
size: [xw, yw]
});
} else {
s = new paper.Shape.Ellipse({
from: startPoint,
to: endPoint
from: _startPoint,
to: _endPoint
});
}
break;
......@@ -59,13 +97,13 @@ function () {
case 'rectangle':
if (event.modifiers.shift) {
s = new paper.Shape.Rectangle({
point: startPoint,
point: _startPoint,
size: [xw, yw]
});
} else {
s = new paper.Shape.Rectangle({
from: startPoint,
to: endPoint
from: _startPoint,
to: _endPoint
});
}
}
......@@ -75,31 +113,10 @@ function () {
}
function updateDash(event) {
if (c) { c.remove(); }
if (drawing) { c = drawShape(event); }
if (_creatingShape) { _creatingShape.remove(); }
if (_drawing) { _creatingShape = drawShape(event); }
}
function exportJSON(param) {
var json = this.exportJSON({asString:false});
// // There is no apparent reason why we would nullify strokeWidth ?
// // @TODO: remove this part of code when we are sure there are no side effect
// if (!json[1].strokeColor) {
// json[1].strokeWidth = 0;
// }
delete(json[1].fontFamily);
delete(json[1].font);
delete(json[1].fontSize);
delete(json[1].leading);
return (param && param.asString) ? JSON.stringify(json) : json;
}
function importJSON(itemDef, layer, listening) {
var item = layer.importJSON(itemDef);
attachListeners(item);
return item;
}
function attachListeners(item) {
// Extend item properties with default values
......@@ -117,6 +134,10 @@ function () {
return exportJSON.call(self, param);
}
})(item);
// add other handlers to data
item.data.setDragMode = _setDragMode;
item.data.itemMouseDrag = _itemMouseDrag;
}
function itemPropertyChange(property, value) {
......@@ -126,13 +147,106 @@ function () {
}
}
function _hitOnShapeTest(point) {
var hitResult, hitShape;
// Check if hit on a selected arrow or on its bounds
hitResult = paper.project.activeLayer.hitTest(point,{
tolerance: 7,
fill: true,
stroke: true,
bounds: true,
selected: true
});
// If nothing found, check if hit on a not yet selected arrow
if (!hitResult) {
hitResult = paper.project.activeLayer.hitTest(point, {
fill: true,
stroke: true
});
}
if (!hitResult || !_isItemShapeType(hitResult.item)) {
return false;
} else {
hitShape = hitResult.item;
if (!hitShape.selected) {
paper.project.deselectAll();
hitShape.selected = true;
_events.annotationSelected.dispatch(hitShape);
}
if (hitResult.type === 'bounds' && hitResult.name.split('-')[1] !== 'center') {
var p = hitResult.name.split('-');
var fixedLoc = (p[0] === 'bottom') ? 'top' : 'bottom' ;
fixedLoc += (p[1] === 'left') ? 'Right' : 'Left';
var resizeDir = [
(p[1] === 'right') ? 1 : -1,
(p[0] === 'bottom') ? 1 : -1
];
_setDragMode('DRAG_HANDLE', {
nameStr: hitResult.name,
nameParts: p,
item: hitResult.item,
fixedPt: hitResult.item.bounds[fixedLoc],
resizeDir: resizeDir
} );
} else {
_setDragMode('FULL_DRAG', {
item: hitShape
});
}
}
return true;
}
function _dragResize(event) {
var dstSize, dstMove, ratio;
dstSize = new paper.Rectangle({from: _dragOpts.fixedPt, to: event.point}).size;
if (event.event.shiftKey) {
ratio = _dragOpts.item.bounds.size.width / _dragOpts.item.bounds.size.height;
dstSize.height = dstSize.width / ratio;
}
dstMove = dstSize.subtract(_dragOpts.item.bounds.size).multiply(_dragOpts.resizeDir).divide(2);
_dragOpts.item.size = dstSize;
_dragOpts.item.translate(dstMove.width, dstMove.height);
}
function _setDragMode(mode, opts) {
if (! mode in DRAG_MODES) {
_dragMode = null;
_dragOpts = {};
_dragModified = false;
} else {
_dragMode = DRAG_MODES[mode];
_dragOpts = opts;
}
}
function _itemMouseDrag(event) {
_dragModified = true;
switch(_dragMode) {
case DRAG_MODES.FULL_DRAG:
this.translate(event.delta);
break;
case DRAG_MODES.DRAG_HANDLE:
_dragResize(event);
break;
}
}
// The Tool returned as a Class instence
return {
exportJSON: exportJSON,
importJSON: importJSON,
onKeyDown: function(event) {
if (c) { updateDash(event); }
if (_creatingShape) { updateDash(event); }
},
onKeyUp: function(event) {
......@@ -140,34 +254,57 @@ function () {
},
onMouseDown: function(event) {
paper.project.deselectAll();
drawing = true;
startPoint = event.point;
endPoint = startPoint;
_drawing = _dragModified = false;
if (!_hitOnShapeTest(event.point)) {
paper.project.deselectAll();
_events.annotationSelected.dispatch(null);
// lets create a new shape
paper.project.deselectAll();
_drawing = true;
_startPoint = event.point;
_endPoint = _startPoint;
}
//
// paper.project.deselectAll();
// drawing = true;
// startPoint = event.point;
// endPoint = startPoint;
},
onMouseDrag: function(event) {
endPoint = event.point;
updateDash(event);
if (_drawing) {
_endPoint = event.point;
updateDash(event);
} else if (_dragMode && _dragOpts.item) {
_itemMouseDrag.call(_dragOpts.item, event);
}
},
onMouseUp: function(event) {
endPoint = event.point;
updateDash(event);
drawing = false;
if (c) { c.remove(); }
c = null;
if (event.delta.length > 5) {
var newObj = drawShape(event);
newObj.data.tId = "a" + newObj._id;
newObj.selected = true;
attachListeners(newObj);
if (events && typeof events.annotationAdded.dispatch === 'function') {
events.annotationAdded.dispatch(newObj);
if (_drawing) {
_endPoint = event.point;
updateDash(event);
_drawing = false;
if (_creatingShape) {
_creatingShape.remove();
}
_creatingShape = null;
if (event.delta.length > 5) {
var newObj = drawShape(event);
newObj.data.tId = "a" + newObj._id;
newObj.selected = true;
attachListeners(newObj);
if (_events && typeof _events.annotationAdded.dispatch === 'function') {
_events.annotationAdded.dispatch(newObj);
}
}
paper.view.draw();
} else if (_dragModified && _dragOpts.item) {
_events.annotationChanged.dispatch(_dragOpts.item);
_dragModified = false;
}
paper.view.draw();
}
}
......
......@@ -86,13 +86,13 @@ define(["paper"], function (paper) {
var defPath = new paper.Path({
segments: [
[0, -2],
[0 , 2],
new paper.Segment([20, 5]), //, [-40, 0]),
[0, -5],
[0 , 5],
new paper.Segment([20, 5]),
[10, 30],
new paper.Segment([50, 0]), //, [-15, 0], [-15, 0]),
new paper.Segment([50, 0]),
[10, -30],
new paper.Segment([20, -5]) //, [0,0], [-40, 0]),
new paper.Segment([20, -5])
],
strokeJoin: 'round',
strokeScaling: false,
......
......@@ -50,11 +50,13 @@ define([
var _selectedHandle;
var _selectedShape = null;
var _selectedShapeBound = null;
var _selectedShapeResizeDir = [1,1];
var _selectedArrowBound = null;
function itemMouseDown(item, event) {
var itemHitResult = item.hitTest(event.point, itemHitOptions);
_selectedSegment = _selectedMove = _selectedHandle = _selectedShape = _selectedShapeBound = _selectedArrowBound = null;
_selectedSegment = _selectedMove = _selectedHandle = null;
_selectedShape = _selectedShapeBound = _selectedShapeResizeDir = _selectedArrowBound = null;
switch (itemHitResult.type) {
case 'handle-in':
case 'handle-out':
......@@ -78,7 +80,11 @@ define([
_selectedSegment = item.insert(location.index + 1, event.point);
*/
} else {
_selectedMove = true;
if (item.data && typeof item.data.setDragMode === 'function') {
item.data.setDragMode('FULL_DRAG', {item: itemHitResult.item} );
} else {
_selectedMove = true;
}
}
break;
......@@ -86,12 +92,27 @@ define([
var p = itemHitResult.name.split('-');
if (['shape', 'ellipse', 'rectangle', 'circle'].indexOf(itemHitResult.item.type) > -1) {
if (p[0] === 'center' || p[1] === 'center') {
_selectedMove = true;
item.data.setDragMode('FULL_DRAG', {item: item} );
// _selectedMove = true;
} else {
var fixedLoc = (p[0] === 'bottom') ? 'top' : 'bottom' ;
fixedLoc += (p[1] === 'left') ? 'Right' : 'Left';
_selectedShapeBound = itemHitResult.item.bounds[fixedLoc];
_selectedShape = itemHitResult.item;
var resizeDir = [
(p[1] === 'right') ? 1 : -1,
(p[0] === 'bottom') ? 1 : -1
];
_selectedShapeResizeDir = resizeDir;
// _selectedShapeBound = itemHitResult.item.bounds[fixedLoc];
// _selectedShape = itemHitResult.item;
itemHitResult.item.data.setDragMode.call(itemHitResult.item, 'DRAG_HANDLE', {
nameStr: itemHitResult.name,
nameParts: p,
item: itemHitResult.item,
fixedPt: itemHitResult.item.bounds[fixedLoc],
resizeDir: resizeDir
} );
}
}
else if (itemHitResult.item.data.type === 'arrow' && p[1] === 'right') {
......@@ -129,19 +150,31 @@ define([
}
function _resizeShape(event) {
var constructorName = _selectedShape.data.type.charAt(0).toUpperCase() + _selectedShape.data.type.slice(1);
var shapeStyle = _selectedShape.style;
var shapeData = _selectedShape.data;
var tmpShape = new paper.Shape[constructorName]({
from: _selectedShapeBound,
to: event.point,
style: shapeStyle,
data: shapeData
}).insertAbove(_selectedShape);
_selectedShape.remove();
_selectedShape = tmpShape;
_selectedShape.selected = true;
var dstSize, dstMove, ratio;
dstSize = new paper.Rectangle({from: _selectedShapeBound, to: event.point}).size;
if (event.event.shiftKey) {
ratio = _selectedShape.bounds.size.width / _selectedShape.bounds.size.height;
dstSize.height = dstSize.width / ratio;
}
dstMove = dstSize.subtract(_selectedShape.bounds.size).multiply(_selectedShapeResizeDir).divide(2);
_selectedShape.size = dstSize;
_selectedShape.translate(dstMove.width, dstMove.height);
// var constructorName = _selectedShape.data.type.charAt(0).toUpperCase() + _selectedShape.data.type.slice(1);
// var shapeStyle = _selectedShape.style;
// var opacity = _selectedShape.opacity;
// var shapeData = _selectedShape.data;
// var tmpShape = new paper.Shape[constructorName]({
// from: _selectedShapeBound,
// to: event.point,
// style: shapeStyle,
// data: shapeData,
// opacity: opacity
// }).insertAbove(_selectedShape);
// _selectedShape.remove();
// _selectedShape = tmpShape;
// _selectedShape.selected = true;
}
function itemMouseDrag(item, event) {
......@@ -268,7 +301,7 @@ define([
} else {
// click on an item already selected
itemModified = false;
if (keepExistingSelection) {
if (keepExistingSelection && toolHitResult.type !== 'bounds') {
hitItem.fullySelected = false;
}
else if (!hitItem.responds('mousedown') || toolHitResult.type === 'bounds') {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment