client/js/paper-renderer.js
changeset 36 d249d36ecc37
parent 35 10e0c23c849e
child 37 db991a757015
--- a/client/js/paper-renderer.js	Mon Sep 03 18:51:32 2012 +0200
+++ b/client/js/paper-renderer.js	Wed Sep 05 14:49:33 2012 +0200
@@ -17,7 +17,10 @@
     _EDITOR_ARROW_WIDTH : 40,
     _EDITOR_MARGIN : 15,
     _EDITOR_PADDING : 10,
-    _EDITOR_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0'])
+    _EDITOR_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0']),
+    _CLICKMODE_ADDNODE : 1,
+    _CLICKMODE_STARTEDGE : 2,
+    _CLICKMODE_ENDEDGE : 3
 }
 
 Rkns.Renderer.Utils = {
@@ -272,6 +275,8 @@
     if (!this.renderer.is_dragging) {
         this.openEditor();
     }
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
 }
 
 Rkns.Renderer.Node.prototype.destroy = function(_event) {
@@ -376,6 +381,8 @@
     if (!this.renderer.is_dragging) {
         this.openEditor();
     }
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
 }
 
 Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
@@ -436,20 +443,31 @@
 }
 
 Rkns.Renderer.TempEdge.prototype.mouseup = function(_event) {
-    var _hitResult = paper.project.hitTest(_event.point);
+    var _hitResult = paper.project.hitTest(_event.point),
+        _model = this.from_representation.model,
+        _endDrag = true;
     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
         var _target = _hitResult.item.__representation;
-        if (_target.type === "Node" && this.from_representation.model !== _target.model) {
+        if (_target.type === "Node" && _model !== _target.model) {
             var _data = {
                 id: Rkns.Utils.getUID('edge'),
                 created_by: this.renderer.renkan.current_user,
-                from: this.from_representation.model.get("_id"),
+                from: _model.get("_id"),
                 to: _target.model.get("_id")
             };
             this.project.addEdge(_data);
         }
+        if (_model === _target.model || (_target.node_representation && _target.node_representation.model === _model)) {
+            _endDrag = false;
+            this.renderer.is_dragging = true;
+        }
     }
-    this.renderer.removeRepresentation(this);
+    if (_endDrag) {
+        this.renderer.click_target = null;
+        this.renderer.is_dragging = false;
+        this.renderer.removeRepresentation(this);
+        paper.view.draw();
+    }
 }
 
 Rkns.Renderer.TempEdge.prototype.destroy = function() {
@@ -679,6 +697,7 @@
 }
 
 Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
+    this.renderer.removeRepresentationsOfType("editor");
     if (confirm('Do you really wish to remove node "' + this.node_representation.model.get("title") + '"?')) {
         this.project.removeNode(this.node_representation.model);
     }
@@ -801,6 +820,7 @@
 }
 
 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
+    this.renderer.removeRepresentationsOfType("editor");
     if (confirm('Do you really wish to remove edge "' + this.edge_representation.model.get("title") + '"?')) {
         this.project.removeEdge(this.edge_representation.model);
     }
@@ -821,6 +841,7 @@
     }))
     this.canvas_$ = this.$.find(".Rk-Canvas");
     this.editor_$ = this.$.find(".Rk-Editor");
+    this.notif_$ = this.$.find(".Rk-Notifications");
     paper.setup(this.canvas_$[0]);
     this.scale = 1;
     this.offset = paper.view.center;
@@ -831,6 +852,7 @@
     this.node_layer = new paper.Layer();
     this.overlay_layer = new paper.Layer();
     this.bundles = [];
+    this.click_mode = false;
     var _tool = new paper.Tool(),
         _this = this;
     _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
@@ -871,11 +893,12 @@
         _this.setScale( _this.scale * Math.SQRT2 );
         _this.redraw();
     });
-    this.$.find(".Rk-Users").mouseenter(function() {
-        _this.$.find(".Rk-UserList").slideDown();
-    }).mouseleave(function() {
-        _this.$.find(".Rk-UserList").slideUp();
-    });
+    this.$.find(".Rk-CurrentUser").mouseenter(
+        function() { _this.$.find(".Rk-UserList").slideDown() }
+    );
+    this.$.find(".Rk-Users").mouseleave(
+        function() { _this.$.find(".Rk-UserList").slideUp(); }
+    );
     this.$.find(".Rk-FullScreen-Button").click(function() {
         var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,
             _el = _this.renkan.$[0],
@@ -898,17 +921,22 @@
         }
     });
     this.$.find(".Rk-AddNode-Button").click(function() {
-        var _coords = _this.toModelCoords(paper.view.center),
-            _data = {
-                id: Rkns.Utils.getUID('node'),
-                created_by: _this.renkan.current_user,
-                position: {
-                    x: _coords.x,
-                    y: _coords.y
-                }
-            };
-            _node = _this.renkan.project.addNode(_data);
-        _this.getRepresentationByModel(_node).openEditor();
+        if (_this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
+            _this.click_mode = false;
+            _this.notif_$.hide();
+        } else {
+            _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE;
+            _this.notif_$.html(_renkan.l10n.notif_add_node).fadeIn();
+        }
+    });
+    this.$.find(".Rk-AddEdge-Button").click(function() {
+        if (_this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE || _this.click_mode === Rkns.Renderer._CLICKMODE_ENDEDGE) {
+            _this.click_mode = false;
+            _this.notif_$.hide();
+        } else {
+            _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
+            _this.notif_$.html(_renkan.l10n.notif_start_edge).fadeIn();
+        }
     });
     this.$.find(".Rk-TopBar-Button").mouseover(function() {
         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
@@ -947,12 +975,13 @@
 }
 
 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
-    '<div class="Rk-TopBar"><h3 class="Rk-PadTitle">Untitled Project</h3>'
+    '<div class="Rk-TopBar"><h3 class="Rk-PadTitle"><%=l10n.untitled_project%></h3>'
     + '<div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.full_screen%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_node%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_edge%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div></div>'
-    + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor">'
+    + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%=l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%=l10n.zoom_out%>"></div></div>'
     + '</div>'
 );
@@ -1138,18 +1167,44 @@
 }
 
 Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
-    this.is_dragging = false;
-    var _hitResult = paper.project.hitTest(_event.point);
-    if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
-        this.click_target = _hitResult.item.__representation;
-        if (this.click_target.type === "Node" && _hitResult.type === "stroke") {
+    if (!this.click_target || this.click_target.type !== "temp-edge") {
+        this.is_dragging = false;
+        var _hitResult = paper.project.hitTest(_event.point);
+        if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+            this.click_target = _hitResult.item.__representation;
+            if (this.click_target.type === "Node-link-button") {
+                this.removeRepresentationsOfType("editor");
+                this.addTempEdge(this.click_target.node_representation, _event.point);
+            }
+        } else {
+            this.click_target = null;
+            if (this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
+                var _coords = this.toModelCoords(_event.point),
+                    _data = {
+                        id: Rkns.Utils.getUID('node'),
+                        created_by: this.renkan.current_user,
+                        position: {
+                            x: _coords.x,
+                            y: _coords.y
+                        }
+                    };
+                    _node = this.renkan.project.addNode(_data);
+                this.getRepresentationByModel(_node).openEditor();
+            }
+        }
+    }
+    if (this.click_mode) {
+        if (this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
+            this.removeRepresentationsOfType("editor");
             this.addTempEdge(this.click_target, _event.point);
+            this.click_mode = Rkns.Renderer._CLICKMODE_ENDEDGE;
+            this.notif_$.fadeOut(function() {
+                Rkns.$(this).html(_renkan.l10n.notif_end_edge).fadeIn();
+            });
+        } else {
+            this.notif_$.hide();
+            this.click_mode = false;
         }
-        if (this.click_target.type === "Node-link-button") {
-            this.addTempEdge(this.click_target.node_representation, _event.point);
-        }
-    } else {
-        this.click_target = null;
     }
 }
 
@@ -1169,9 +1224,10 @@
                 ])
             }
         );
+    } else {
+        this.click_target = null;
+        this.is_dragging = false;
     }
-    this.is_dragging = false;
-    this.click_target = null;
 }
 
 Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {