client/js/paper-renderer.js
changeset 161 c7a503c80ef4
parent 160 408da84d4dc0
child 163 fca0475da9a7
--- a/client/js/paper-renderer.js	Fri Apr 19 15:31:56 2013 +0200
+++ b/client/js/paper-renderer.js	Mon Apr 22 19:51:12 2013 +0200
@@ -173,31 +173,33 @@
     this.type = "Node";
     this.circle = new paper.Path.Circle([0, 0], 1);
     this.circle.__representation = this;
-    this.circle.fillColor = this.options.node_fill_color;
     if (this.options.show_node_circles) {
         this.circle.strokeWidth = this.options.node_stroke_width;
         this.h_ratio = 1;
     } else {
-        this.circle.opacity = .01;
         this.h_ratio = 0;
     }
     this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
     if (this.options.editor_mode) {
-        this.buttons = [
+        this.normal_buttons = [
             new Rkns.Renderer.NodeEditButton(this.renderer, null),
             new Rkns.Renderer.NodeRemoveButton(this.renderer, null),
             new Rkns.Renderer.NodeLinkButton(this.renderer, null),
             new Rkns.Renderer.NodeEnlargeButton(this.renderer, null),
             new Rkns.Renderer.NodeShrinkButton(this.renderer, null)
         ];
-        for (var i = 0; i < this.buttons.length; i++) {
-            this.buttons[i].source_representation = this;
+        this.pending_delete_buttons = [
+            new Rkns.Renderer.NodeRevertButton(this.renderer, null)
+        ];
+        this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons)
+        for (var i = 0; i < this.all_buttons.length; i++) {
+            this.all_buttons[i].source_representation = this;
         }
+        this.active_buttons = [];
     } else {
-        this.buttons = [];
+        this.active_buttons = this.all_buttons = [];
     }
     this.last_circle_radius = 1;
-//    this.title.paragraphStyle.justification = 'center';
     
     if (this.renderer.minimap) {
         this.renderer.minimap.node_layer.activate();
@@ -215,7 +217,7 @@
     }
     this.circle_radius = _baseRadius * this.renderer.scale;
     if (this.last_circle_radius !== this.circle_radius) {
-        this.buttons.forEach(function(b) {
+        this.all_buttons.forEach(function(b) {
             b.setSectorSize();
         });
         var square = new paper.Size(this.circle_radius, this.circle_radius),
@@ -233,17 +235,45 @@
     }
     this.last_circle_radius = this.circle_radius;
     
+    var old_act_btn = this.active_buttons;
+    
+    if (this.model.get("delete_scheduled")) {
+        var opacity = .33;
+        this.active_buttons = this.pending_delete_buttons;
+    } else {
+        var opacity = 1;
+        this.active_buttons = this.normal_buttons;
+    }
+    
+    if (this.selected && this.renderer.isEditable() && old_act_btn !== this.active_buttons) {
+        old_act_btn.forEach(function(b) {
+            b.hide();
+        });
+        this.active_buttons.forEach(function(b) {
+            b.show();
+        });
+    }
+    
+    if (this.node_image) {
+        this.node_image.opacity = this.highlighted ? opacity * .5 : (opacity - .01);
+    }
+    
+    this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
+    
+    this.circle.opacity = this.options.show_node_circles ? opacity : .01;
+    
     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
     _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length);
     this.title.text(_text);
     this.title.css({
         left: this.paper_coords.x,
-        top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance
+        top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
+        opacity: opacity
     })
     var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
     this.circle.strokeColor = _color;
     var _pc = this.paper_coords;
-    this.buttons.forEach(function(b) {
+    this.all_buttons.forEach(function(b) {
         b.moveTo(_pc);
     });
     var _img = this.model.get("image");
@@ -331,7 +361,7 @@
     this.selected = true;
     this.circle.strokeWidth = this.options.selected_node_stroke_width;
     if (this.renderer.isEditable()) {
-        this.buttons.forEach(function(b) {
+        this.active_buttons.forEach(function(b) {
             b.show();
         });
     }
@@ -355,9 +385,9 @@
 }
 
 Rkns.Renderer.Node.prototype.unselect = function(_newTarget) {
-    this.selected = false;
     if (!_newTarget || _newTarget.source_representation !== this) {
-        this.buttons.forEach(function(b) {
+        this.selected = false;
+        this.all_buttons.forEach(function(b) {
             b.hide();
         });
         this.circle.strokeWidth = this.options.node_stroke_width;
@@ -369,17 +399,21 @@
 }
     
 Rkns.Renderer.Node.prototype.highlight = function() {
-    this.circle.fillColor = this.options.highlighted_node_fill_color;
-    if (this.node_image) {
-        this.node_image.opacity = .5;
+    if (this.highlighted) {
+        return;
     }
+    this.highlighted = true;
+    this.redraw();
+    this.renderer.throttledPaperDraw();
 }
 
-Rkns.Renderer.Node.prototype.unhighlight = function(_newTarget) {
-    this.circle.fillColor = this.options.node_fill_color;
-    if (this.node_image) {
-        this.node_image.opacity = .99;
+Rkns.Renderer.Node.prototype.unhighlight = function() {
+    if (!this.highlighted) {
+        return;
     }
+    this.highlighted = false;
+    this.redraw();
+    this.renderer.throttledPaperDraw();
 }
 
 Rkns.Renderer.Node.prototype.saveCoords = function() {
@@ -403,10 +437,10 @@
 }
 
 Rkns.Renderer.Node.prototype.mouseup = function(_event, _isTouch) {
-    if (this.renderer.isEditable() && this.renderer.is_dragging) {
+    if (this.renderer.is_dragging && this.renderer.isEditable()) {
         this.saveCoords();
     } else {
-        if (!_isTouch) {
+        if (!_isTouch && !this.model.get("delete_scheduled")) {
             this.openEditor();
         }
     }
@@ -417,7 +451,7 @@
 
 Rkns.Renderer.Node.prototype.destroy = function(_event) {
     this.super("destroy");
-    this.buttons.forEach(function(b) {
+    this.all_buttons.forEach(function(b) {
         b.destroy();
     });
     this.circle.remove();
@@ -454,10 +488,20 @@
     this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
     this.arrow_angle = 0;
     if (this.options.editor_mode) {
-        this.edit_button = new Rkns.Renderer.EdgeEditButton(this.renderer, null);
-        this.edit_button.source_representation = this;
-        this.remove_button = new Rkns.Renderer.EdgeRemoveButton(this.renderer, null);
-        this.remove_button.source_representation = this;
+        this.normal_buttons = [
+            new Rkns.Renderer.EdgeEditButton(this.renderer, null),
+            new Rkns.Renderer.EdgeRemoveButton(this.renderer, null),
+        ];
+        this.pending_delete_buttons = [
+            new Rkns.Renderer.EdgeRevertButton(this.renderer, null)
+        ];
+        this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons)
+        for (var i = 0; i < this.all_buttons.length; i++) {
+            this.all_buttons[i].source_representation = this;
+        }
+        this.active_buttons = [];
+    } else {
+        this.active_buttons = this.all_buttons = [];
     }
     
     if (this.renderer.minimap) {
@@ -489,8 +533,25 @@
         _textdelta = _ortho.multiply(this.options.edge_label_distance),
         _handle = _v.divide(3),
         _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
+    
+    var opacity = (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) ? .33 : 1;
+    
+    var old_act_btn = this.active_buttons;
+    
+    this.active_buttons = this.model.get("delete_scheduled") ? this.pending_delete_buttons : this.normal_buttons;
+    
+    if (this.selected && this.renderer.isEditable() && old_act_btn !== this.active_buttons) {
+        old_act_btn.forEach(function(b) {
+            b.hide();
+        });
+        this.active_buttons.forEach(function(b) {
+            b.show();
+        });
+    }
+    
     this.paper_coords = _p0b.add(_p1b).divide(2);
     this.line.strokeColor = _color;
+    this.line.opacity = opacity;
     this.line.segments[0].point = _p0a;
     this.line.segments[1].point = this.paper_coords;
     this.line.segments[1].handleIn = _handle.multiply(-1);
@@ -498,6 +559,7 @@
     this.line.segments[2].point = _p1a;
     this.arrow.rotate(_a - this.arrow_angle);
     this.arrow.fillColor = _color;
+    this.arrow.opacity = opacity;
     this.arrow.position = this.paper_coords;
     this.arrow_angle = _a;
     if (_a > 90) {
@@ -517,13 +579,15 @@
         top: _textpos.y,
         transform: "rotate(" + _a + "deg)",
         "-moz-transform": "rotate(" + _a + "deg)",
-        "-webkit-transform": "rotate(" + _a + "deg)"
+        "-webkit-transform": "rotate(" + _a + "deg)",
+        opacity: opacity
     });
     this.text_angle = _a;
-    if (this.options.editor_mode) {
-        this.edit_button.moveTo(this.paper_coords);
-        this.remove_button.moveTo(this.paper_coords);
-    }
+    
+    var _pc = this.paper_coords;
+    this.all_buttons.forEach(function(b) {
+        b.moveTo(_pc);
+    });
     
     if (this.renderer.minimap) {
         this.minimap_line.strokeColor = _color;
@@ -543,20 +607,22 @@
     this.selected = true;
     this.line.strokeWidth = this.options.selected_edge_stroke_width;
     if (this.renderer.isEditable()) {
-        this.edit_button.show();
-        this.remove_button.show();
-       }
+        this.active_buttons.forEach(function(b) {
+            b.show();
+        });
+    }
     if (!this.options.editor_mode) {
         this.openEditor();
     }
 }
 
 Rkns.Renderer.Edge.prototype.unselect = function(_newTarget) {
-    this.selected = false;
     if (!_newTarget || _newTarget.source_representation !== this) {
+        this.selected = false;
         if (this.options.editor_mode) {
-            this.edit_button.hide();
-            this.remove_button.hide();
+            this.all_buttons.forEach(function(b) {
+                b.hide();
+            });
         }
         this.line.strokeWidth = this.options.edge_stroke_width;
     }
@@ -603,10 +669,9 @@
     if (this.renderer.minimap) {
         this.minimap_line.remove();
     }
-    if (this.options.editor_mode) {
-        this.edit_button.destroy();
-        this.remove_button.destroy();
-    }
+    this.all_buttons.forEach(function(b) {
+        b.destroy();
+    });
     var _this = this;
     this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
         return _edge === _this;
@@ -1138,8 +1203,34 @@
     this.renderer.click_target = null;
     this.renderer.is_dragging = false;
     this.renderer.removeRepresentationsOfType("editor");
-    if (this.renderer.isEditable() && confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
-        this.project.removeNode(this.source_representation.model);
+    if (this.renderer.isEditable()) {
+        var delid = Rkns.Utils.getUID("delete");
+        this.renderer.delete_list.push({
+            id: delid,
+            time: new Date().valueOf() + this.options.element_delete_delay
+        });
+        this.source_representation.model.set("delete_scheduled", delid);
+    }
+}
+
+/* */
+
+Rkns.Renderer.NodeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
+
+Rkns.Renderer.NodeRevertButton.prototype._init = function() {
+    this.type = "Node-revert-button";
+    this.lastSectorInner = 0;
+    this.startAngle = -135;
+    this.endAngle = 135;
+    this.imageName = "revert";
+    this.text = "Cancel deletion";
+}
+
+Rkns.Renderer.NodeRevertButton.prototype.mouseup = function() {
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
+    if (this.renderer.isEditable()) {
+        this.source_representation.model.unset("delete_scheduled");
     }
 }
 
@@ -1239,8 +1330,30 @@
     this.renderer.click_target = null;
     this.renderer.is_dragging = false;
     this.renderer.removeRepresentationsOfType("editor");
-    if (this.renderer.isEditable() && confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
-        this.project.removeEdge(this.source_representation.model);
+    if (this.renderer.isEditable()) {
+        var delid = Rkns.Utils.getUID("delete");
+        this.renderer.delete_list.push({
+            id: delid,
+            time: new Date().valueOf() + this.options.element_delete_delay
+        });
+        this.source_representation.model.set("delete_scheduled", delid);
+    }
+}
+
+/* */
+
+Rkns.Renderer.EdgeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
+
+Rkns.Renderer.EdgeRevertButton.prototype._init = function() {
+    this.type = "Edge-revert-button";
+    this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
+}
+
+Rkns.Renderer.EdgeRevertButton.prototype.mouseup = function() {
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
+    if (this.renderer.isEditable()) {
+        this.source_representation.model.unset("delete_scheduled");
     }
 }
 
@@ -1280,6 +1393,7 @@
     this.edge_layer = new paper.Layer();
     this.node_layer = new paper.Layer();
     this.buttons_layer = new paper.Layer();
+    this.delete_list = [];
     
     if (_renkan.options.show_minimap) {
         this.minimap = {
@@ -1329,7 +1443,7 @@
     
     this.imageCache = {};
     
-    ['edit', 'remove', 'link', 'enlarge', 'shrink'].forEach(function(imgname) {
+    ['edit', 'remove', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) {
         var img = new Image();
         img.src = _renkan.options.static_url + 'img/' + imgname + '.png';
         _this.imageCache[imgname] = img;
@@ -1637,6 +1751,25 @@
     
     this.redraw();
     
+    window.setInterval(function() {
+        var _now = new Date().valueOf();
+        _this.delete_list.forEach(function(d) {
+            if (_now >= d.time) {
+                var el = _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id});
+                if (el) {
+                    project.removeNode(el);
+                }
+                el = _renkan.project.get("edges").findWhere({"delete_scheduled":d.id});
+                if (el) {
+                    project.removeEdge(el);
+                }
+            }
+        });
+        _this.delete_list = _this.delete_list.filter(function(d) {
+            return _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id}) || _renkan.project.get("edges").findWhere({"delete_scheduled":d.id})
+        });
+    }, 500);
+    
     if (this.minimap) {
         window.setInterval(function() {
             _this.rescaleMinimap()