client/js/paper-renderer.js
changeset 67 d341117f9370
parent 66 9b459e41e2df
child 68 803dbeb7c919
equal deleted inserted replaced
66:9b459e41e2df 67:d341117f9370
     1 Rkns.Renderer = {
     1 Rkns.Renderer = {
     2     _MARGIN_X: 80,
     2     _MARGIN_X: 80,
     3     _MARGIN_Y: 50,
     3     _MARGIN_Y: 50,
     4     _MIN_DRAG_DISTANCE: 2,
     4     _MIN_DRAG_DISTANCE: 2,
     5     _NODE_RADIUS: 25,
     5     _NODE_SIZE_BASE: 25,
     6     _NODE_BUTTON_INNER: 26,
     6     _NODE_BUTTON_WIDTH: 40,
     7     _NODE_BUTTON_OUTER: 60,
     7     _EDGE_BUTTON_INNER: 2,
     8     _EDGE_BUTTON_INNER: 1,
       
     9     _EDGE_BUTTON_OUTER: 40,
     8     _EDGE_BUTTON_OUTER: 40,
    10     _NODE_FONT_SIZE: 10,
     9     _NODE_FONT_SIZE: 10,
    11     _EDGE_FONT_SIZE: 9,
    10     _EDGE_FONT_SIZE: 9,
    12     _NODE_MAX_CHAR: 50,
    11     _NODE_MAX_CHAR: 50,
    13     _EDGE_MAX_CHAR: 40,
    12     _EDGE_MAX_CHAR: 40,
    20     _EDITOR_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0']),
    19     _EDITOR_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0']),
    21     _CLICKMODE_ADDNODE : 1,
    20     _CLICKMODE_ADDNODE : 1,
    22     _CLICKMODE_STARTEDGE : 2,
    21     _CLICKMODE_STARTEDGE : 2,
    23     _CLICKMODE_ENDEDGE : 3,
    22     _CLICKMODE_ENDEDGE : 3,
    24     _IMAGE_MAX_KB : 500,
    23     _IMAGE_MAX_KB : 500,
       
    24     _NODE_SIZE_STEP: Math.LN2/4,
    25     _USER_PLACEHOLDER : {
    25     _USER_PLACEHOLDER : {
    26         color: "#000000",
    26         color: "#000000",
    27         title: "(unknown user)",
    27         title: "(unknown user)",
    28         get: function(attr) {
    28         get: function(attr) {
    29             return this[attr] || false;
    29             return this[attr] || false;
    97             _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy,
    97             _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy,
    98             _centerR = (_inR + _outR)/2,
    98             _centerR = (_inR + _outR)/2,
    99             _centerRads = (_startRads + _endRads) / 2,
    99             _centerRads = (_startRads + _endRads) / 2,
   100             _centerX = Math.cos(_centerRads) * _centerR,
   100             _centerX = Math.cos(_centerRads) * _centerR,
   101             _centerY = Math.sin(_centerRads) * _centerR,
   101             _centerY = Math.sin(_centerRads) * _centerR,
       
   102             _centerXIn = Math.cos(_centerRads) * _inR,
       
   103             _centerXOut = Math.cos(_centerRads) * _outR,
       
   104             _centerYIn = Math.sin(_centerRads) * _inR,
       
   105             _centerYOut = Math.sin(_centerRads) * _outR,
   102             _textX = Math.cos(_centerRads) * (_outR + 3),
   106             _textX = Math.cos(_centerRads) * (_outR + 3),
   103             _textY = Math.sin(_centerRads) * (_outR + 3),
   107             _textY = Math.sin(_centerRads) * (_outR + 3),
   104             _segments = [];
   108             _segments = [];
   105         _segments.push([[_startXIn, _startYIn], [0, 0], [ _kin * _startdx, _kin * _startdy ]]);
       
   106         for (var i = 1; i < 4; i++) {
       
   107             var _rads = i * _span / 4 + _startRads,
       
   108                 _dx = - Math.sin(_rads),
       
   109                 _dy = Math.cos(_rads),
       
   110                 _x = Math.cos(_rads) * _inR,
       
   111                 _y = Math.sin(_rads) * _inR;
       
   112             _segments.push([[_x, _y], [ - _kin * _dx, - _kin * _dy], [ _kin * _dx, _kin * _dy ]]);
       
   113         }
       
   114         _segments.push([[_endXIn, _endYIn], [ - _kin * _enddx, - _kin * _enddy ], [0,0]]);
       
   115         _segments.push([[_endXOut, _endYOut], [ 0,0 ], [ - _kout * _enddx, - _kout * _enddy ]]);
       
   116         for (var i = 3; i > 0; i--) {
       
   117             var _rads = i * _span / 4 + _startRads,
       
   118                 _dx = - Math.sin(_rads),
       
   119                 _dy = Math.cos(_rads),
       
   120                 _x = Math.cos(_rads) * _outR,
       
   121                 _y = Math.sin(_rads) * _outR;
       
   122             _segments.push([[_x, _y], [ _kout * _dx, _kout * _dy], [ - _kout * _dx, - _kout * _dy ]]);
       
   123         }
       
   124         _segments.push([[_startXOut, _startYOut], [ _kout * _startdx, _kout * _startdy ], [0, 0]]);
       
   125         var _path = new paper.Path();
   109         var _path = new paper.Path();
   126         _path.add.apply(_path, _segments);
   110         _path.add([_startXIn, _startYIn]);
       
   111         _path.arcTo([_centerXIn, _centerYIn], [_endXIn, _endYIn]);
       
   112         _path.lineTo([_endXOut,  _endYOut]);
       
   113         _path.arcTo([_centerXOut, _centerYOut], [_startXOut, _startYOut]);
   127         _path.fillColor = "#333333";
   114         _path.fillColor = "#333333";
   128         _path.opacity = .5;
   115         _path.opacity = .5;
   129         _path.closed = true;
   116         _path.closed = true;
   130         _path.__representation = _repr;
   117         _path.__representation = _repr;
   131         if (_textX >= -2 && _textX <= 2) {
   118         if (_textX >= -2 && _textX <= 2) {
   249 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   236 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   250 
   237 
   251 Rkns.Renderer.Node.prototype._init = function() {
   238 Rkns.Renderer.Node.prototype._init = function() {
   252     this.renderer.node_layer.activate();
   239     this.renderer.node_layer.activate();
   253     this.type = "Node";
   240     this.type = "Node";
   254     this.circle = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
   241     this.circle = new paper.Path.Circle([0, 0], 1);
   255     this.circle.fillColor = '#ffffff';
   242     this.circle.fillColor = '#ffffff';
   256     this.circle.__representation = this;
   243     this.circle.__representation = this;
   257     this.circle.strokeWidth = 2;
   244     this.circle.strokeWidth = 2;
   258     this.title = new paper.PointText([0,0]);
   245     this.title = new paper.PointText([0,0]);
   259     this.title.characterStyle = {
   246     this.title.characterStyle = {
   270         this.remove_button = new Rkns.Renderer.NodeRemoveButton(this.renderer, null);
   257         this.remove_button = new Rkns.Renderer.NodeRemoveButton(this.renderer, null);
   271         this.remove_button.node_representation = this;
   258         this.remove_button.node_representation = this;
   272         this.link_button = new Rkns.Renderer.NodeLinkButton(this.renderer, null);
   259         this.link_button = new Rkns.Renderer.NodeLinkButton(this.renderer, null);
   273         this.link_button.node_representation = this;
   260         this.link_button.node_representation = this;
   274     }
   261     }
   275     
   262     this.last_circle_radius = 1;
   276     this.title.paragraphStyle.justification = 'center';
   263     this.title.paragraphStyle.justification = 'center';
   277 }
   264 }
   278 
   265 
   279 Rkns.Renderer.Node.prototype.redraw = function() {
   266 Rkns.Renderer.Node.prototype.redraw = function() {
   280     if (!this.paper_coords) {
   267     if (!this.paper_coords) {
   281         var _model_coords = new paper.Point(this.model.get("position"));
   268         var _model_coords = new paper.Point(this.model.get("position"));
   282         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
   269         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
   283     }
   270     }
   284     this.circle.position = this.paper_coords;
   271     this.circle_radius = Rkns.Renderer._NODE_SIZE_BASE * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP) * this.renderer.scale;
       
   272     if (this.last_circle_radius !== this.circle_radius) {
       
   273     	if (!this.renderer.renkan.read_only) {
       
   274 	    	this.edit_button.setSectorSize();
       
   275 	    	this.remove_button.setSectorSize();
       
   276 	    	this.link_button.setSectorSize();
       
   277 	    }
       
   278 	    var square = new paper.Size(this.circle_radius, this.circle_radius),
       
   279 	    	topleft = this.paper_coords.subtract(square),
       
   280 	    	bounds = new paper.Rectangle(topleft, square.multiply(2));
       
   281 	    this.circle.fitBounds(bounds);
       
   282 	    if (this.node_image) {
       
   283 	    	this.node_image.fitBounds(bounds);
       
   284 	    }
       
   285     } else {
       
   286     	this.circle.position = this.paper_coords;
       
   287     	if (this.node_image) {
       
   288             this.node_image.position = this.paper_coords;
       
   289         }
       
   290     }
       
   291     
   285     this.title.content = this.model.get("title");
   292     this.title.content = this.model.get("title");
   286     this.title.position = this.paper_coords.add([0, Rkns.Renderer._NODE_RADIUS + 1.5 *Rkns.Renderer._NODE_FONT_SIZE]);
   293     this.title.position = this.paper_coords.add([0, this.circle_radius + 1.5 *Rkns.Renderer._NODE_FONT_SIZE]);
   287     this.circle.strokeColor = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color");
   294     this.circle.strokeColor = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color");
   288     this.edit_button.moveTo(this.paper_coords);
   295     this.edit_button.moveTo(this.paper_coords);
   289     this.remove_button.moveTo(this.paper_coords);
   296     this.remove_button.moveTo(this.paper_coords);
   290     this.link_button.moveTo(this.paper_coords);
   297     this.link_button.moveTo(this.paper_coords);
   291     var _img = this.model.get("image");
   298     var _img = this.model.get("image");
   295         _image.onload = function() {
   302         _image.onload = function() {
   296             if (_this.node_image) {
   303             if (_this.node_image) {
   297                 _this.node_image.remove();
   304                 _this.node_image.remove();
   298             }
   305             }
   299             _this.renderer.node_layer.activate();
   306             _this.renderer.node_layer.activate();
   300             var _ratio = Math.min(1, 2 * Rkns.Renderer._NODE_RADIUS / _image.width, 2 * Rkns.Renderer._NODE_RADIUS / _image.height );
   307             var _ratio = Math.min(1, 2 * _this.circle_radius / _image.width, 2 * _this.circle_radius / _image.height );
   301             var _raster = new paper.Raster(_image);
   308             var _raster = new paper.Raster(_image);
   302             var _clip = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
   309             var _clip = new paper.Path.Circle([0, 0], _this.circle_radius);
   303             _raster.scale(_ratio);
   310             _raster.scale(_ratio);
   304             _this.node_image = new paper.Group(_clip, _raster);
   311             _this.node_image = new paper.Group(_clip, _raster);
   305             _this.node_image.opacity = .9;
   312             _this.node_image.opacity = .9;
   306             /* This is a workaround to allow clipping at group level
   313             /* This is a workaround to allow clipping at group level
   307              * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug).
   314              * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug).
   313             paper.view.draw();
   320             paper.view.draw();
   314         }
   321         }
   315         _image.src = _img;
   322         _image.src = _img;
   316     }
   323     }
   317     this.img = _img;
   324     this.img = _img;
   318     if (this.node_image) {
   325     if (this.node_image && !this.img) {
   319         if (!this.img) {
   326         this.node_image.remove();
   320             this.node_image.remove();
   327         delete this.node_image;
   321             delete this.node_image;
       
   322         } else {
       
   323             this.node_image.position = this.paper_coords;
       
   324         }
       
   325     }
   328     }
   326         
   329         
   327     Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){
   330     Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){
   328         var repr = this.renderer.getRepresentationByModel(edge);
   331         var repr = this.renderer.getRepresentationByModel(edge);
   329     	if(repr != null && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
   332     	if(repr != null && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
   625 /* */
   628 /* */
   626 
   629 
   627 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   630 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   628 
   631 
   629 Rkns.Renderer.NodeEditor.prototype._init = function() {
   632 Rkns.Renderer.NodeEditor.prototype._init = function() {
   630     this.renderer.overlay_layer.activate();
   633     this.renderer.buttons_layer.activate();
   631     this.type = "editor";
   634     this.type = "editor";
   632     this.editor_block = new paper.Path();
   635     this.editor_block = new paper.Path();
   633     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   636     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   634     this.editor_block.add.apply(this.editor_block, _pts);
   637     this.editor_block.add.apply(this.editor_block, _pts);
   635     this.editor_block.strokeWidth = 2;
   638     this.editor_block.strokeWidth = 2;
   648 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
   651 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
   649     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Node")%></span></h2>'
   652     '<h2><span class="Rk-CloseX">&times;</span><%-translate("Edit Node")%></span></h2>'
   650     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%=node.title%>"/></p>'
   653     + '<p><label><%-translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%=node.title%>"/></p>'
   651     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%=node.uri%>"/><a class="Rk-Edit-Goto" href="<%=node.uri%>" target="_blank"></a></p>'
   654     + '<p><label><%-translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%=node.uri%>"/><a class="Rk-Edit-Goto" href="<%=node.uri%>" target="_blank"></a></p>'
   652     + '<p><label><%-translate("Description:")%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
   655     + '<p><label><%-translate("Description:")%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
       
   656     + '<p><span class="Rk-Editor-Label"><%-translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%=node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p>'
   653     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%=node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   657     + '<div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%=node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
   654     + '<% print(Rkns.pickerColors.reduce(function(m,c) { return m + "<li data-color=\'" + c + "\' style=\'background: " + c + "\'></li>"},"")); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   658     + '<% print(Rkns.pickerColors.reduce(function(m,c) { return m + "<li data-color=\'" + c + "\' style=\'background: " + c + "\'></li>"},"")); %></ul><span class="Rk-Edit-ColorPicker-Text">Choose color</span></div></div>'
   655     + '<img class="Rk-Edit-ImgPreview" src="<%=node.image || node.image_placeholder%>" />'
   659     + '<img class="Rk-Edit-ImgPreview" src="<%=node.image || node.image_placeholder%>" />'
   656     + '<p><label><%-translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%=node.image%>"/></p>'
   660     + '<p><label><%-translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%=node.image%>"/></p>'
   657     + '<p><label><%-translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file"/></p>'    
   661     + '<p><label><%-translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file"/></p>'    
   660 
   664 
   661 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
   665 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
   662     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%=node.color%>;"></span><%-node.title%></span></h2>'
   666     '<h2><span class="Rk-CloseX">&times;</span><span class="Rk-UserColor" style="background:<%=node.color%>;"></span><%-node.title%></span></h2>'
   663     + '<p><a href="<%-node.uri%>" target="_blank"><%-node.uri%></a></p>'
   667     + '<p><a href="<%-node.uri%>" target="_blank"><%-node.uri%></a></p>'
   664     + '<p><%-node.description%></p>'
   668     + '<p><%-node.description%></p>'
   665     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%> </span><span class="Rk-UserColor" style="background:<%=node.created_by_color%>;"></span><%=node.created_by_title%></p>'
   669     + '<p><span class="Rk-Editor-Label"><%-translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%=node.created_by_color%>;"></span><%=node.created_by_title%></p>'
   666 );
   670 );
   667 
   671 
   668 Rkns.Renderer.NodeEditor.prototype.draw = function() {
   672 Rkns.Renderer.NodeEditor.prototype.draw = function() {
   669     var _model = this.node_representation.model,
   673     var _model = this.node_representation.model,
   670         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER,
   674         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER,
   671         _template = (this.renderer.renkan.read_only ? this.readOnlyTemplate : this.template);
   675         _template = (this.renderer.renkan.read_only ? this.readOnlyTemplate : this.template),
       
   676         _image_placeholder = this.renderer.renkan.static_url + "img/image-placeholder.png",
       
   677         _size = (_model.get("size") || 0);
   672     this.editor_$
   678     this.editor_$
   673         .html(_template({
   679         .html(_template({
   674             node: {
   680             node: {
   675                 title: _model.get("title"),
   681                 title: _model.get("title"),
   676                 uri: _model.get("uri"),
   682                 uri: _model.get("uri"),
   677                 description: _model.get("description"),
   683                 description: _model.get("description"),
   678                 image: _model.get("image") || "",
   684                 image: _model.get("image") || "",
   679                 image_placeholder: this.renderer.renkan.static_url + "img/image-placeholder.png",
   685                 image_placeholder: _image_placeholder,
   680                 color: _model.get("color") || _created_by.get("color"),
   686                 color: _model.get("color") || _created_by.get("color"),
   681                 created_by_color: _created_by.get("color"),
   687                 created_by_color: _created_by.get("color"),
   682                 created_by_title: _created_by.get("title")
   688                 created_by_title: _created_by.get("title"),
       
   689                 size: (_size > 0 ? "+" : "") + _size
   683             },
   690             },
   684             translate: this.renderer.renkan.translate
   691             translate: this.renderer.renkan.translate
   685         }));
   692         }));
   686     this.redraw();
   693     this.redraw();
   687     var _this = this;
   694     var _this = this;
   693     	
   700     	
   694     	var onFieldChange = Rkns._(function() {
   701     	var onFieldChange = Rkns._(function() {
   695     		Rkns._(function() {
   702     		Rkns._(function() {
   696 	            var _uri = _this.editor_$.find(".Rk-Edit-URI").val(),
   703 	            var _uri = _this.editor_$.find(".Rk-Edit-URI").val(),
   697 	                _image = _this.editor_$.find(".Rk-Edit-Image").val();
   704 	                _image = _this.editor_$.find(".Rk-Edit-Image").val();
   698 	            _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _image);
   705 	            _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _image || _image_placeholder);
   699 	            _this.editor_$.find(".Rk-Edit-Goto").attr("href",_uri);
   706 	            _this.editor_$.find(".Rk-Edit-Goto").attr("href",_uri);
   700 	            var _data = {
   707 	            var _data = {
   701 	                title: _this.editor_$.find(".Rk-Edit-Title").val(),
   708 	                title: _this.editor_$.find(".Rk-Edit-Title").val(),
   702 	                description: _this.editor_$.find(".Rk-Edit-Description").val(),
   709 	                description: _this.editor_$.find(".Rk-Edit-Description").val(),
   703 	                uri: _uri,
   710 	                uri: _uri,
   737         this.editor_$.find(".Rk-Edit-ColorPicker li").hover(
   744         this.editor_$.find(".Rk-Edit-ColorPicker li").hover(
   738             function() { _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color")); },
   745             function() { _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color")); },
   739             function() { _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color")) }
   746             function() { _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER).get("color")) }
   740         ).click(function() {
   747         ).click(function() {
   741             _model.set("color", $(this).attr("data-color"));
   748             _model.set("color", $(this).attr("data-color"));
   742             _this.redraw();
   749         });
       
   750         
       
   751         function shiftSize(n) {
       
   752         	var _newsize = n+(_model.get("size") || 0);
       
   753         	_this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
       
   754         	_model.set("size", _newsize);
       
   755         }
       
   756         
       
   757         this.editor_$.find(".Rk-Edit-Size-Down").click(function() {
       
   758         	shiftSize(-1);
       
   759         	return false;
       
   760         });
       
   761         this.editor_$.find(".Rk-Edit-Size-Up").click(function() {
       
   762         	shiftSize(1);
       
   763         	return false;
   743         });
   764         });
   744     }
   765     }
   745     this.editor_$.find("img").load(function() {
   766     this.editor_$.find("img").load(function() {
   746         _this.redraw();
   767         _this.redraw();
   747     });
   768     });
   762 /* */
   783 /* */
   763 
   784 
   764 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   785 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   765 
   786 
   766 Rkns.Renderer.EdgeEditor.prototype._init = function() {
   787 Rkns.Renderer.EdgeEditor.prototype._init = function() {
   767     this.renderer.overlay_layer.activate();
   788     this.renderer.buttons_layer.activate();
   768     this.type = "editor";
   789     this.type = "editor";
   769     this.editor_block = new paper.Path();
   790     this.editor_block = new paper.Path();
   770     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   791     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   771     this.editor_block.add.apply(this.editor_block, _pts);
   792     this.editor_block.add.apply(this.editor_block, _pts);
   772     this.editor_block.strokeWidth = 2;
   793     this.editor_block.strokeWidth = 2;
   874 /* */
   895 /* */
   875 
   896 
   876 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   897 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   877 
   898 
   878 Rkns.Renderer.NodeEditButton.prototype._init = function() {
   899 Rkns.Renderer.NodeEditButton.prototype._init = function() {
   879     this.renderer.overlay_layer.activate();
   900     this.renderer.buttons_layer.activate();
   880     this.type = "Node-edit-button";
   901     this.type = "Node-edit-button";
   881     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, - 90, 30, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.translate("Edit"));
   902     this.lastSectorInner = 0;
       
   903 }
       
   904 
       
   905 Rkns.Renderer.NodeEditButton.prototype.setSectorSize = function() {
       
   906 	var sectorInner = this.node_representation.circle_radius;
       
   907 	if (sectorInner !== this.lastSectorInner) {
       
   908 		if (this.sector) {
       
   909 			this.sector.destroy();
       
   910 		}
       
   911 		this.sector = Rkns.Renderer.Utils.sector(this, 1 + sectorInner, Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner, - 90, 30, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.translate("Edit"));
       
   912 		this.lastSectorInner = sectorInner;
       
   913 	}
   882 }
   914 }
   883 
   915 
   884 Rkns.Renderer.NodeEditButton.prototype.moveTo = function(_pos) {
   916 Rkns.Renderer.NodeEditButton.prototype.moveTo = function(_pos) {
   885     this.sector.moveTo(_pos);
   917     this.sector.moveTo(_pos);
   886 }
   918 }
   917 /* */
   949 /* */
   918 
   950 
   919 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   951 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   920 
   952 
   921 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
   953 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
   922     this.renderer.overlay_layer.activate();
   954     this.renderer.buttons_layer.activate();
   923     this.type = "Node-remove-button";
   955     this.type = "Node-remove-button";
   924     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, -210, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.translate("Remove"));
   956     this.lastSectorInner = 0;
       
   957 }
       
   958 
       
   959 Rkns.Renderer.NodeRemoveButton.prototype.setSectorSize = function() {
       
   960 	var sectorInner = this.node_representation.circle_radius;
       
   961 	if (sectorInner !== this.lastSectorInner) {
       
   962 		if (this.sector) {
       
   963 			this.sector.destroy();
       
   964 		}
       
   965 		this.sector = Rkns.Renderer.Utils.sector(this, 1 + sectorInner, Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner, - 210, - 90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.translate("Remove"));
       
   966 		this.lastSectorInner = sectorInner;
       
   967 	}
   925 }
   968 }
   926 
   969 
   927 Rkns.Renderer.NodeRemoveButton.prototype.moveTo = function(_pos) {
   970 Rkns.Renderer.NodeRemoveButton.prototype.moveTo = function(_pos) {
   928     this.sector.moveTo(_pos);
   971     this.sector.moveTo(_pos);
   929 }
   972 }
   961 /* */
  1004 /* */
   962 
  1005 
   963 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1006 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   964 
  1007 
   965 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
  1008 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
   966     this.renderer.overlay_layer.activate();
  1009     this.renderer.buttons_layer.activate();
   967     this.type = "Node-link-button";
  1010     this.type = "Node-link-button";
   968     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, 30, 150, 1, this.renderer.renkan.static_url+'img/link.png', this.renderer.renkan.translate("Link to another node"));
  1011     this.lastSectorInner = 0;
       
  1012 }
       
  1013 
       
  1014 Rkns.Renderer.NodeLinkButton.prototype.setSectorSize = function() {
       
  1015 	var sectorInner = this.node_representation.circle_radius;
       
  1016 	if (sectorInner !== this.lastSectorInner) {
       
  1017 		if (this.sector) {
       
  1018 			this.sector.destroy();
       
  1019 		}
       
  1020 		this.sector = Rkns.Renderer.Utils.sector(this, 1 + sectorInner, Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner, 30, 150, 1, this.renderer.renkan.static_url+'img/link.png', this.renderer.renkan.translate("Link to another node"));
       
  1021 		this.lastSectorInner = sectorInner;
       
  1022 	}
   969 }
  1023 }
   970 
  1024 
   971 Rkns.Renderer.NodeLinkButton.prototype.moveTo = function(_pos) {
  1025 Rkns.Renderer.NodeLinkButton.prototype.moveTo = function(_pos) {
   972     this.sector.moveTo(_pos);
  1026     this.sector.moveTo(_pos);
   973 }
  1027 }
   998 /* */
  1052 /* */
   999 
  1053 
  1000 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1054 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1001 
  1055 
  1002 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
  1056 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
  1003     this.renderer.overlay_layer.activate();
  1057     this.renderer.buttons_layer.activate();
  1004     this.type = "Edge-edit-button";
  1058     this.type = "Edge-edit-button";
  1005     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 90, 90, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.translate("Edit"));
  1059     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 90, 90, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.translate("Edit"));
  1006 }
  1060 }
  1007 
  1061 
  1008 Rkns.Renderer.EdgeEditButton.prototype.moveTo = function(_pos) {
  1062 Rkns.Renderer.EdgeEditButton.prototype.moveTo = function(_pos) {
  1041 /* */
  1095 /* */
  1042 
  1096 
  1043 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1097 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1044 
  1098 
  1045 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
  1099 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
  1046     this.renderer.overlay_layer.activate();
  1100     this.renderer.buttons_layer.activate();
  1047     this.type = "Edge-remove-button";
  1101     this.type = "Edge-remove-button";
  1048     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 270, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.translate("Remove"));
  1102     this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 270, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.translate("Remove"));
  1049 }
  1103 }
  1050 Rkns.Renderer.EdgeRemoveButton.prototype.moveTo = function(_pos) {
  1104 Rkns.Renderer.EdgeRemoveButton.prototype.moveTo = function(_pos) {
  1051     this.sector.moveTo(_pos);
  1105     this.sector.moveTo(_pos);
  1097     this.totalScroll = 0;
  1151     this.totalScroll = 0;
  1098     this.click_target = null;
  1152     this.click_target = null;
  1099     this.selected_target = null;
  1153     this.selected_target = null;
  1100     this.edge_layer = new paper.Layer();
  1154     this.edge_layer = new paper.Layer();
  1101     this.node_layer = new paper.Layer();
  1155     this.node_layer = new paper.Layer();
  1102     this.overlay_layer = new paper.Layer();
  1156     this.buttons_layer = new paper.Layer();
  1103     this.bundles = [];
  1157     this.bundles = [];
  1104     this.click_mode = false;
  1158     this.click_mode = false;
  1105     var _tool = new paper.Tool(),
  1159     var _tool = new paper.Tool(),
  1106         _this = this;
  1160         _this = this;
  1107     _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
  1161     _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
  1338 Rkns.Renderer.Scene.prototype.setScale = function(_newScale) {
  1392 Rkns.Renderer.Scene.prototype.setScale = function(_newScale) {
  1339     this.scale = _newScale;
  1393     this.scale = _newScale;
  1340     this.resetCoords();
  1394     this.resetCoords();
  1341     this.redraw();
  1395     this.redraw();
  1342 }
  1396 }
  1343 
  1397 /*
  1344 Rkns.Renderer.Scene.prototype.autoScale = function() {
  1398 Rkns.Renderer.Scene.prototype.autoScale = function() {
  1345     var nodes = this.renkan.project.get("nodes")
  1399     var nodes = this.renkan.project.get("nodes")
  1346     if (nodes.length > 1) {
  1400     if (nodes.length > 1) {
  1347         var _xx = nodes.map(function(_node) { return _node.get("position").x }),
  1401         var _xx = nodes.map(function(_node) { return _node.get("position").x }),
  1348             _yy = nodes.map(function(_node) { return _node.get("position").y }),
  1402             _yy = nodes.map(function(_node) { return _node.get("position").y }),
  1357     if (nodes.length === 1) {
  1411     if (nodes.length === 1) {
  1358         this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
  1412         this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
  1359         this.setScale(1);
  1413         this.setScale(1);
  1360     }
  1414     }
  1361 }
  1415 }
  1362 
  1416 */
  1363 Rkns.Renderer.Scene.prototype.resetCoords = function(_point) {
  1417 Rkns.Renderer.Scene.prototype.resetCoords = function(_point) {
  1364     _(this.representations).each(function(r) {
  1418     _(this.representations).each(function(r) {
  1365         r.resetCoords();
  1419         r.resetCoords();
  1366     });
  1420     });
  1367 }
  1421 }