123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- /*
- Spacedeck Whiteboard Directive
- This module registers a custom Vue directive that handles Whiteboard sections.
- */
- function setup_whiteboard_directives() {
- if ('ontouchstart' in window) {
- var edown = "touchstart";
- var emove = "touchmove";
- var eup = "touchend";
- } else {
- var edown = "mousedown";
- var emove = "mousemove";
- var eup = "mouseup";
- }
- Vue.directive('sd-whiteboard', {
- bind: function () {
- var el = this.el;
- $(el).on(edown, ".artifact", this.handle_mouse_down_artifact.bind(this));
- $(el).on("dblclick", ".artifact", this.handle_double_click_artifact.bind(this));
- $(el).on("keyup", ".artifact", this.handle_key_up_artifact.bind(this));
- $(el).on("keydown", ".artifact", this.handle_key_down_artifact.bind(this));
- $(el).bind(edown, this.handle_mouse_down_space.bind(this));
- $(el).bind(emove, this.handle_mouse_move.bind(this));
- $(el).bind(eup, this.handle_mouse_up_space.bind(this));
-
- $(el).bind("wheel", this.handle_wheel_space.bind(this));
- $(document.body).bind("mouseleave", this.handle_mouse_leave.bind(this));
- $(el).find(".handle.resize-nw").bind(edown, function(e){this.handle_transform_mouse_down(e,1,1)}.bind(this));
- $(el).find(".handle.resize-n").bind(edown, function(e){this.handle_transform_mouse_down(e,0.5,1)}.bind(this));
- $(el).find(".handle.resize-ne").bind(edown, function(e){this.handle_transform_mouse_down(e,0,1)}.bind(this));
- $(el).find(".handle.resize-e").bind(edown, function(e){this.handle_transform_mouse_down(e,0,0.5)}.bind(this));
- $(el).find(".handle.resize-se").bind(edown, function(e){this.handle_transform_mouse_down(e,0,0)}.bind(this));
- $(el).find(".handle.resize-s").bind(edown, function(e){this.handle_transform_mouse_down(e,0.5,0)}.bind(this));
- $(el).find(".handle.resize-sw").bind(edown, function(e){this.handle_transform_mouse_down(e,1,0)}.bind(this));
- $(el).find(".handle.resize-w").bind(edown, function(e){this.handle_transform_mouse_down(e,1,0.5)}.bind(this));
- $(el).find(".edge-handle.resize-n").bind(edown, function(e){this.handle_transform_mouse_down(e,0.5,1)}.bind(this));
- $(el).find(".edge-handle.resize-s").bind(edown, function(e){this.handle_transform_mouse_down(e,0.5,0)}.bind(this));
- $(el).find(".edge-handle.resize-e").bind(edown, function(e){this.handle_transform_mouse_down(e,0,0.5)}.bind(this));
- $(el).find(".edge-handle.resize-w").bind(edown, function(e){this.handle_transform_mouse_down(e,1,0.5)}.bind(this));
- $(el).on(edown, ".vector-handle", function(e){this.handle_vector_transform_mouse_down(e)}.bind(this));
- var $scope = this.vm.$root;
- this.space_zoom = 1;
- this.artifacts_before_transaction = [];
- $scope.active_tool = "pointer";
- },
- update: function () {
- },
- unbind: function () {
- // do clean up work
- // e.g. remove event listeners added in bind()
- var el = this.el;
- $(el).off(edown+" "+emove+" "+eup+" "+"keyup keydown mouseleave");
- $(document.body).unbind("mouseleave");
- },
- handle_key_down_artifact: function(evt) {
- var $scope = this.vm.$root;
- },
- handle_key_up_artifact: function(evt) {
- var $scope = this.vm.$root;
- },
- handle_mouse_down_artifact: function(evt) {
- var $scope = this.vm.$root;
- if (!$scope.editing_artifact_id) {
- evt.preventDefault();
- evt.stopPropagation();
- }
- var a = $scope.find_artifact_by_id(evt.currentTarget.id.replace("artifact-",""));
- if ($scope.active_tool == "zoom") return;
- if ($scope.active_tool == "eyedrop") {
- var arts = $scope.selected_artifacts();
- if (!$scope.is_selected(a) && arts.length > 0) {
- // copy style from clicked artifact to selected artifacts
- $scope.begin_transaction();
- $scope.update_selected_artifacts(function(selected_artifact) {
- selected_artifact.style = _.clone(a.style);
- });
- $scope.active_tool = "pointer";
- return;
- }
- }
- if ($scope.active_tool == "pan") {
- this.start_pan(evt);
- return;
- }
- if ($scope.active_tool == "pointer") {
- if (!$scope.is_selected(a) || evt.shiftKey) {
- this.select(evt,a);
- }
- // copy via alt+move
- if (evt.altKey) {
- a = $scope.clone_artifact(a);
- this.select(evt,a);
- }
- }
- $scope.begin_transaction();
- var cursor = this.cursor_point_to_space(evt);
- $scope.mouse_ox = cursor.x;
- $scope.mouse_oy = cursor.y;
- $scope.mouse_moved = false;
- this.mouse_state = "move";
- evt.stopPropagation();
- },
- handle_double_click_artifact: function(evt) {
- var $scope = this.vm.$root;
- var a = $scope.find_artifact_by_id(evt.currentTarget.id.replace("artifact-",""));
- if (!a) return;
-
- if (a.payload_uri) {
- $scope.download_selected_artifacts();
- }
- $scope.toggle_selected_artifact_editing(true);
- },
- handle_transform_mouse_down: function(evt,origin_x,origin_y) {
- evt.stopPropagation();
- evt.preventDefault();
- var $scope = this.vm.$root;
- $scope.begin_transaction();
- var cursor = this.cursor_point_to_space(evt);
- this.mouse_state = "transform";
- $scope.mouse_ox = cursor.x;
- $scope.mouse_oy = cursor.y;
- $scope.transform_ox = origin_x;
- $scope.transform_oy = origin_y;
- },
- handle_vector_transform_mouse_down: function(evt) {
- evt.stopPropagation();
- evt.preventDefault();
- var $scope = this.vm.$root;
- var idx = parseInt($(evt.currentTarget).attr("data-idx"));
- $scope.selected_control_point_idx = idx;
- $scope.begin_transaction();
- var cursor = this.cursor_point_to_space(evt);
- this.mouse_state = "vector_transform";
- $scope.mouse_ox = cursor.x;
- $scope.mouse_oy = cursor.y;
- //$scope.transform_ox = origin_x;
- //$scope.transform_oy = origin_y;
- },
- handle_wheel_space: function(evt) {
- var $scope = this.vm.$root;
- if (!evt.ctrlKey && !evt.shiftKey) return;
-
- evt.preventDefault();
- evt.stopPropagation();
-
- var amount = 1;
- var dy = evt.originalEvent.deltaY;
- if (dy>0) {
- amount=1.2;
- if ($scope.viewport_zoom<=0.05) return false;
- } else if (dy<0) {
- amount=0.9;
- if ($scope.viewport_zoom>=2) return false;
- } else {
- return false;
- }
- $scope.zoom_to_cursor(evt,amount);
- },
- handle_mouse_down_space: function(evt) {
- if (evt.target != evt.currentTarget && !_.include(["wrapper"],evt.target.className)) return;
- var $scope = this.vm.$root;
- $scope.opened_dialog="none";
- var cursor = this.cursor_point_to_space(evt);
- $scope.mouse_ox = cursor.x;
- $scope.mouse_oy = cursor.y;
- if (evt.which == 2 || evt.buttons == 4) {
- $scope.active_tool = "pan";
- }
-
- if ($scope.active_tool=="note") {
- this.deselect();
- this.mouse_state = "transform";
- $scope.mouse_state = this.mouse_state;
- this.start_adding_note(evt);
- return;
- } else if ($scope.active_tool=="arrow") {
- this.deselect();
- this.mouse_state = "vector_transform";
- $scope.mouse_state = this.mouse_state;
- this.start_drawing_arrow(evt);
- return;
- } else if ($scope.active_tool=="line") {
- this.deselect();
- this.mouse_state = "vector_transform";
- $scope.mouse_state = this.mouse_state;
- this.start_drawing_line(evt);
- return;
- } else if ($scope.active_tool=="scribble") {
- this.deselect();
- this.mouse_state = "scribble";
- $scope.mouse_state = this.mouse_state;
- this.start_drawing_scribble(evt);
- return;
- } else if ($scope.active_tool=="zoom") {
- if (evt.altKey) {
- $scope.zoom_out();
- } else {
- $scope.zoom_in();
- }
- return;
- } else if ($scope.active_tool=="pointer") {
- this.mouse_state = "lasso";
- this.start_lasso(evt);
- } else if ($scope.active_tool=="zone") {
- this.deselect();
- this.mouse_state = "transform";
- $scope.start_adding_zone(evt);
- return;
- } else if ($scope.active_tool=="image") {
- this.deselect();
- this.mouse_state = "transform";
- $scope.start_adding_placeholder(evt);
- return;
- } else if ($scope.active_tool=="pan") {
- this.start_pan(evt);
- return;
- }
- if ($scope.selection_metrics.count>0) {
- this._no_artifact_toolbar_this_round = true;
- }
- this.deselect();
- },
- start_pan: function(evt) {
- var $scope = this.vm.$root;
- el = $("#space")[0];
- if (el) {
- this.mouse_state = "pan";
- this.old_panx = el.scrollLeft;
- this.old_pany = el.scrollTop;
- }
-
- var cursor = this.cursor_point_to_space(evt);
- $scope.mouse_ox = cursor.x;
- $scope.mouse_oy = cursor.y;
- $scope.mouse_moved = false;
- },
- deselect: function() {
- var $scope = this.vm.$root;
-
- $scope.deselect();
- },
- select: function(evt, a) {
- var $scope = this.vm.$root;
- $scope.select(evt, a);
- },
- multi_select: function(arts) {
- var $scope = this.vm.$root;
- $scope.multi_select(arts);
- },
- start_lasso: function(evt) {
- var point = this.cursor_point_to_space(evt);
- this.lasso = {
- x: point.x,
- y: point.y,
- w: 0,
- h: 0
- }
- },
- rects_intersecting: function(r1,r2) {
- if (!r1 || !r2) return false;
-
- if ( (r1.x+r1.w < r2.x)
- || (r1.x > r2.x+r2.w)
- || (r1.y+r1.h < r2.y)
- || (r1.y > r2.y+r2.h) ) return false;
- return true;
- },
- artifacts_in_rect: function(rect) {
- if (!rect) return [];
-
- var $scope = this.vm.$root;
- return _.filter($scope.active_space_artifacts, function(a) {
- return this.rects_intersecting(a, rect);
- }.bind(this));
- },
- abs_rect: function(rect) {
- var res = {
- x: rect.x,
- y: rect.y,
- w: Math.abs(rect.w),
- h: Math.abs(rect.h)
- }
- if (rect.w<0) res.x+=rect.w;
- if (rect.h<0) res.y+=rect.h;
- return res;
- },
- lasso_style: function() {
- var $scope = this.vm.$root;
- if (!this.lasso) return "";
- var lasso_scaled = {
- x:this.lasso.x,
- y:this.lasso.y,
- w:this.lasso.w*$scope.viewport_zoom,
- h:this.lasso.h*$scope.viewport_zoom
- }
- lasso_scaled = this.abs_rect(lasso_scaled);
- lasso_scaled.x += $scope.bounds_margin_horiz;
- lasso_scaled.y += $scope.bounds_margin_vert;
- var s = "left:" +lasso_scaled.x+"px;";
- s += "top:" +lasso_scaled.y+"px;";
- s += "width:" +lasso_scaled.w+"px;";
- s += "height:"+lasso_scaled.h+"px;";
- s += "opacity: 1;";
- return s;
- },
- render_lasso: function() {
- if (!this.lasso) {
- $("#lasso").hide();
- return;
- }
- $("#lasso").attr("style", this.lasso_style());
- $("#lasso").show();
- },
- cursor_point_to_space: function(evt) {
- var $scope = this.vm.$root;
- var offset = {left: 0, top: 0};
- evt = fixup_touches(evt);
- return {
- x: (parseInt(evt.pageX) - parseInt(offset.left) - $scope.bounds_margin_horiz) / this.space_zoom,
- y: (parseInt(evt.pageY) - parseInt(offset.top) - $scope.bounds_margin_vert) / this.space_zoom
- };
- },
- rect_to_points: function(rect) {
- return [
- {x:rect.x,y:rect.y},
- {x:rect.x+rect.w,y:rect.y},
- {x:rect.x,y:rect.y+rect.h},
- {x:rect.x+rect.w,y:rect.y+rect.h}
- ];
- },
- old_selection_rect: function() {
- var $scope = this.vm.$root;
- var selected = $scope.selected_artifacts().map(function(a){
- return $scope.find_artifact_before_transaction(a);
- }.bind(this));
- return $scope.enclosing_rect(selected);
- },
- snap_point: function(x,y,snap_middle) {
- var $scope = this.vm.$root;
- var TOL = 8;
- var dists = [];
- if (snap_middle) {
- dists.push([[x-window.innerWidth/2,Math.abs(y-window.innerHeight/2)],[x-window.innerWidth/2,Math.abs(y-window.innerHeight/2)]]);
- }
- if ($scope.grid_active) {
- // snap to grid
- var gw = $scope.grid.spacing/$scope.grid.subdivisions;
- var gh = $scope.grid.spacing/$scope.grid.subdivisions;
- var sx1 = parseInt(x/gw)*gw;
- var sy1 = parseInt(y/gh)*gh;
- var sx2 = (parseInt(x/gw)+1)*gw;
- var sy2 = (parseInt(y/gh)+1)*gh;
- dists = [[[Math.abs(sx1-x),sx1], [Math.abs(sy1-y),sy1]],
- [[Math.abs(sx2-x),sx2], [Math.abs(sy2-y),sy2]]];
- } else {
- // snap to other artifacts
- dists = $scope.unselected_artifacts().map(function(a){
- var r = this.rect_to_points(a);
- var xd1 = Math.abs(r[0].x-x);
- var xd2 = Math.abs(r[1].x-x);
- var xd3 = Math.abs(r[0].x+a.w/2 - x);
- var yd1 = Math.abs(r[0].y-y);
- var yd2 = Math.abs(r[2].y-y);
- var yd3 = Math.abs(r[0].y+a.h/2 - y);
- if (!snap_middle) {
- if (xd2<xd1) {
- var xd = xd2;
- var sx = r[1].x;
- } else {
- var xd = xd1;
- var sx = r[0].x;
- }
- if (yd2<yd1) {
- var yd = yd2;
- var sy = r[2].y;
- } else {
- var yd = yd1;
- var sy = r[0].y;
- }
- }
- if (snap_middle) {
- var xd = xd3;
- var sx = r[0].x+a.w/2;
- var yd = yd3;
- var sy = r[0].y+a.h/2;
- }
- return [[xd,sx],[yd,sy]];
- }.bind(this));
- }
- // snap to space edges
- dists.push([[Math.abs(x),0],[Math.abs(y),0]]);
- //dists.push([[Math.abs(dims.width-x),dims.width],[Math.abs(dims.height-y),dims.height]]);
- var unzipped = _.unzip(dists);
- var xdists = _.sortBy(unzipped[0], function(pair) {return pair[0];});
- var ydists = _.sortBy(unzipped[1], function(pair) {return pair[0];});
- var results = {snapx:xdists[0], snapy:ydists[0]};
- if (!xdists[0] || xdists[0][0]>TOL) {
- results.snapx = [0,x]; // distance, coordinate
- } else {
- //$scope.snap_ruler_x = xdists[0][1];
- }
- if (!ydists[0] || ydists[0][0]>TOL) {
- results.snapy = [0,y];
- } else {
- //$scope.snap_ruler_y = ydists[0][1];
- }
- return results;
- },
- offset_point_in_wrapper: function(point) {
- var $scope = this.vm.$root;
- var section_el = $(this.el)[0];
- var z = $scope.viewport_zoom;
- var pt = parseInt($("#space").css("padding-top"));
- point.y=(point.y+section_el.scrollTop-pt)/z;
- point.x=(point.x+section_el.scrollLeft)/z;
- return point;
- },
- start_drawing_scribble: function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- var $scope = this.vm.$root;
- var point = this.offset_point_in_wrapper(this.cursor_point_to_space(evt));
- var z = $scope.highest_z()+1;
- $scope.deselect();
- var a = {
- space_id: $scope.active_space._id,
- mime: "x-spacedeck/vector",
- description: "",
- control_points: [{dx:0,dy:0}],
- x: point.x,
- y: point.y,
- z: z,
- w: 64,
- h: 64,
- stroke_color: "#000000",
- stroke: 2,
- shape: "scribble"
- };
- $scope.save_artifact(a, function(saved_a) {
- $scope.update_board_artifact_viewmodel(saved_a);
- $scope.active_space_artifacts.push(saved_a);
- this.select(evt,saved_a);
- //$scope.tool_artifact = a;
- $scope.transform_ox = 0;
- $scope.transform_oy = 0;
- $scope.begin_transaction();
- }.bind(this));
- },
- start_drawing_arrow: function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- var $scope = this.vm.$root;
- var point = this.cursor_point_to_space(evt);
- this.offset_point_in_wrapper(point);
- var z = $scope.highest_z()+1;
- var a = {
- space_id: $scope.active_space._id,
- mime: "x-spacedeck/vector",
- description: "",
- control_points: [{dx:0,dy:0},{dx:0,dy:0},{dx:0,dy:0}],
- x: point.x,
- y: point.y,
- z: z,
- w: 64,
- h: 64,
- stroke_color: "#000000",
- stroke: 2,
- shape: "arrow"
- };
- $scope.save_artifact(a, function(saved_a) {
- $scope.update_board_artifact_viewmodel(saved_a);
- $scope.active_space_artifacts.push(saved_a);
- $scope.select(evt,a);
- $scope.selected_control_point_idx = 1;
- $scope.transform_ox = 0;
- $scope.transform_oy = 0;
- $scope.begin_transaction();
- }.bind(this));
- },
- // FIXME: consolidate with arrow drawing?
- start_drawing_line: function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- var $scope = this.vm.$root;
- var point = this.cursor_point_to_space(evt);
- this.offset_point_in_wrapper(point);
- var z = $scope.highest_z()+1;
- var a = {
- space_id: $scope.active_space._id,
- mime: "x-spacedeck/vector",
- description: "",
- control_points: [{dx:0,dy:0},{dx:0,dy:0}],
- x: point.x,
- y: point.y,
- z: z,
- w: 64,
- h: 64,
- stroke_color: "#000000",
- stroke: 2,
- shape: "line"
- };
- $scope.save_artifact(a, function(saved_a) {
- $scope.update_board_artifact_viewmodel(saved_a);
- $scope.active_space_artifacts.push(saved_a);
- $scope.select(evt,a);
- $scope.selected_control_point_idx = 1;
- $scope.transform_ox = 0;
- $scope.transform_oy = 0;
- $scope.begin_transaction();
- }.bind(this));
- },
- snap_point_simple: function(point) {
- var snapped = this.snap_point(point.x, point.y);
- return {
- x: snapped.snapx[1],
- y: snapped.snapy[1]
- }
- },
- handle_mouse_up_space: function(evt) {
- var $scope = this.vm.$root;
- evt.preventDefault();
-
- if (this.mouse_state == "lasso") {
- var lasso_rect = this.abs_rect(this.offset_point_in_wrapper(this.lasso));
- // convert to space coordinates
- if (lasso_rect.w>0 && lasso_rect.h>0) {
- var arts = this.artifacts_in_rect(lasso_rect);
- this.multi_select(arts);
- } else {
-
- if (this._no_artifact_toolbar_this_round) {
- this._no_artifact_toolbar_this_round = false;
- } else {
- $scope.start_adding_artifact(evt);
- }
- }
- this.lasso = null;
- this.render_lasso();
- }
- else if (_.include(["transform","move","vector_transform","scribble"],this.mouse_state)) {
- var ars = $scope.selected_artifacts();
-
- for (var i=0; i<ars.length; i++) {
- if (_.include(["text","placeholder"],$scope.artifact_major_type(ars[i]))) {
- // some types of artifact need a minimum size
- if (ars[i].w<10) {
- ars[i].w = 10;
- }
- if (ars[i].h<10) {
- ars[i].h = 10;
- }
- }
- //save_artifact(ars[i], null, $scope.display_saving_error);
- }
- }
- if (this.mouse_state == "text_editor") {
- return;
- }
- if (_.include(["zoom"], $scope.active_tool)) {
- // tools that stay active after use
- this.mouse_state = "idle";
- $scope.mouse_state = this.mouse_state;
- $scope.end_transaction();
- $scope.deselect();
- return;
- }
- this.mouse_state = "idle";
- $scope.mouse_state = this.mouse_state;
- this.lasso = null;
- $scope.active_tool = "pointer";
- $scope.end_transaction();
- $scope.show_toolbar_props();
- },
- handle_mouse_leave: function(evt) {
- var $scope = this.vm.$root;
- this.mouse_state = "idle";
- this.lasso = null;
- $scope.active_tool = "pointer";
- $scope.end_transaction();
- this.render_lasso();
- },
- handle_mouse_move: function(evt) {
- var $scope = this.vm.$root;
- if (!$scope.active_space) return;
- if (!$scope.editing_artifact_id) {
- evt.preventDefault();
- evt.stopPropagation();
- }
- $scope.handle_scroll();
- var cursor = this.cursor_point_to_space(evt);
- var dx = cursor.x - $scope.mouse_ox;
- var dy = cursor.y - $scope.mouse_oy;
- var dt = (new Date()).getTime() - this.last_mouse_move_time;
- this.last_mouse_move_time = (new Date()).getTime();
- var zoom = $scope.viewport_zoom||1;
- if (zoom) {
- dx/=zoom;
- dy/=zoom;
- }
- // send cursor
- if (dx>10 || dy>10 || dt>100) {
- var name = "anonymous";
- if ($scope.logged_in) {
- name = $scope.user.nickname || $scope.user.email;
- } else {
- name = $scope.guest_nickname || "anonymous";
- }
- var cursor_msg = {
- action: "cursor",
- x: cursor.x/zoom,
- y: cursor.y/zoom,
- name: name,
- id: $scope.user._id||name
- };
- $scope.websocket_send(cursor_msg);
- }
-
- // side effects ftw!
- $scope.snap_ruler_x = -1000;
- $scope.snap_ruler_y = -1000;
- $scope.mouse_moved = true;
- $scope.transform_lock = evt.shiftKey;
- if ($scope.transform_lock) {
- if (this.mouse_state == "transform") {
- // lock aspect is done in transform
- } else {
- // lock axis
- if (Math.abs(dy)>Math.abs(dx)) {
- dx = 0;
- } else {
- dy = 0;
- }
- }
- }
- if (this.mouse_state == "move") {
- $scope.hide_toolbar_props();
-
- var snap_dx = 0;
- var snap_dy = 0;
- var selected = $scope.selected_artifacts();
- var snap_edges = this.old_selection_rect();
- if (selected.length && selected[0]._id==$scope.editing_artifact_id) {
- // bail out of moving editable artifact
- return;
- }
- if (snap_edges) {
- var mx = snap_edges.x1 + (snap_edges.x2-snap_edges.x1)/2;
- var my = snap_edges.y1 + (snap_edges.y2-snap_edges.y1)/2;
- var snapped1 = this.snap_point(snap_edges.x1 + dx, snap_edges.y1 + dy, false);
- var snapped2 = this.snap_point(snap_edges.x2 + dx, snap_edges.y2 + dy, false);
- var snapped3 = this.snap_point(mx + dx, my + dy, true);
- if (snapped3.snapx[0]>0) {
- snap_dx = mx + dx - snapped3.snapx[1];
- } else if (snapped2.snapx[0]>0) {
- snap_dx = snap_edges.x2 + dx - snapped2.snapx[1];
- } else {
- snap_dx = snap_edges.x1 + dx - snapped1.snapx[1];
- }
- if (snapped3.snapy[0]>0) {
- snap_dy = my + dy - snapped3.snapy[1];
- } else if (snapped2.snapy[0]>0) {
- snap_dy = snap_edges.y2 + dy - snapped2.snapy[1];
- } else {
- snap_dy = snap_edges.y1 + dy - snapped1.snapy[1];
- }
- }
- $scope.update_selected_artifacts(function(a) {
- var old_a = $scope.find_artifact_before_transaction(a);
- if (old_a) {
- return {
- x: old_a.x + dx - snap_dx,
- y: old_a.y + dy - snap_dy
- };
- } else {
- // deleted?
- return {};
- }
- }.bind(this));
- } else if (this.mouse_state == "transform") {
- var selected = $scope.selected_artifacts();
- var edges = this.old_selection_rect();
- if (!edges) {
- this.mouse_state = "idle";
- return;
- }
- $scope.hide_toolbar_props();
-
- var ew = (edges.x2-edges.x1);
- var eh = (edges.y2-edges.y1);
- var origin_x = edges.x1 + ew * $scope.transform_ox;
- var origin_y = edges.y1 + eh * $scope.transform_oy;
- // "leading point"
- var lead_x = edges.x1 + ew * (1-$scope.transform_ox) - origin_x;
- var lead_y = edges.y1 + eh * (1-$scope.transform_oy) - origin_y;
- var lead_snapped = this.snap_point(origin_x + lead_x + dx, origin_y + lead_y + dy);
- var moved_x = (lead_snapped.snapx[1] - origin_x);
- var moved_y = (lead_snapped.snapy[1] - origin_y);
- var scale_x = lead_x ? (moved_x)/lead_x : 1;
- var scale_y = lead_y ? (moved_y)/lead_y : 1;
- if (!$scope.transform_lock) scale_y = scale_x;
- $scope.update_selected_artifacts(function(a) {
- var old_a = $scope.find_artifact_before_transaction(a);
- var x1 = origin_x + ((old_a.x - origin_x) * scale_x);
- var y1 = origin_y + ((old_a.y - origin_y) * scale_y);
- var x2 = origin_x + (((old_a.x + old_a.w) - origin_x) * scale_x);
- var y2 = origin_y + (((old_a.y + old_a.h) - origin_y) * scale_y);
- if (x1>x2) { var t = x1; x1 = x2; x2 = t; }
- if (y1>y2) { var t = y1; y1 = y2; y2 = t; }
- return {
- x: x1,
- y: y1,
- w: x2 - x1,
- h: y2 - y1
- };
- }.bind(this));
- } else if (this.mouse_state == "lasso") {
- this.lasso.w = dx;
- this.lasso.h = dy;
- this.render_lasso();
- } else if (this.mouse_state == "vector_transform") {
- $scope.hide_toolbar_props();
-
- var _this = this;
- $scope.update_selected_artifacts(function(a) {
- var old_a = $scope.find_artifact_before_transaction(a);
- var control_points = _.cloneDeep(old_a.control_points);
- var cp = control_points[$scope.selected_control_point_idx];
- var snapped = _this.snap_point(old_a.x+cp.dx+dx, old_a.y+cp.dy+dy);
- dx = snapped.snapx[1]-(old_a.x+cp.dx);
- dy = snapped.snapy[1]-(old_a.y+cp.dy);
- cp.dx += dx;
- cp.dy += dy;
- // special case for arrow's 3rd point
- if (a.shape == "arrow" && $scope.selected_control_point_idx!=2) {
- /*control_points[2].dx += dx/2;
- control_points[2].dy += dy/2; */
- control_points[2].dx = (control_points[0].dx+control_points[1].dx)/2;
- control_points[2].dy = (control_points[0].dy+control_points[1].dy)/2;
- }
- return _this.normalize_control_points(control_points, old_a);
- });
- } else if (this.mouse_state == "scribble") {
- $scope.update_selected_artifacts(function(a) {
- var old_a = a;
- var control_points = _.cloneDeep(old_a.control_points);
- var offset = this.offset_point_in_wrapper({x:cursor.x,y:cursor.y});
- control_points.push({
- dx: offset.x-old_a.x,
- dy: offset.y-old_a.y
- });
- return this.normalize_control_points(simplify_scribble_points(control_points), old_a);
- }.bind(this));
- var arts = $scope.selected_artifacts();
- if (arts.length) {
- $scope.update_board_artifact_viewmodel(arts[0]);
- }
- }
- else if (this.mouse_state == "pan") {
- if (!$("#space").length) return;
- el = $("#space")[0];
- el.scrollLeft = this.old_panx - dx*$scope.viewport_zoom;
- el.scrollTop = this.old_pany - dy*$scope.viewport_zoom;
- $scope.handle_scroll();
- }
- },
- normalize_control_points: function(control_points, artifact) {
- var x1 = _.min(control_points,"dx").dx;
- var y1 = _.min(control_points,"dy").dy;
- var x2 = _.max(control_points,"dx").dx;
- var y2 = _.max(control_points,"dy").dy;
- var shiftx = -x1;
- var shifty = -y1;
- var shifted_cps = control_points.map(function(cp) {
- return {
- dx: cp.dx + shiftx,
- dy: cp.dy + shifty
- };
- });
- var w = Math.abs(x2 - x1);
- var h = Math.abs(y2 - y1);
- var bshiftx = 0;
- var bshifty = 0;
- if (artifact.w < 0) bshiftx = -artifact.w;
- if (artifact.h < 0) bshifty = -artifact.h;
- return {
- x: artifact.x + bshiftx - shiftx,
- y: artifact.y + bshifty - shifty,
- w: w,
- h: h,
- z: artifact.z,
- control_points: shifted_cps
- };
- }
- });
- }
|