client/js/paper-renderer.js
changeset 23 70c8af9b44ec
parent 21 b43dd87f7ffa
child 25 b5ada3bb8e53
equal deleted inserted replaced
22:948283342245 23:70c8af9b44ec
    42         return {
    42         return {
    43             left: (this._EDITOR_PADDING + Math.min(_left, _right)),
    43             left: (this._EDITOR_PADDING + Math.min(_left, _right)),
    44             top: (this._EDITOR_PADDING + _top)
    44             top: (this._EDITOR_PADDING + _top)
    45         }
    45         }
    46     },
    46     },
    47     sector : function(_ctrl, _inR, _outR, _startAngle, _endAngle, _padding, _imgsrc) {
    47     sector : function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgsrc) {
    48         var _startRads = _startAngle * Math.PI / 180,
    48         var _startRads = _startAngle * Math.PI / 180,
    49             _endRads = _endAngle * Math.PI / 180,
    49             _endRads = _endAngle * Math.PI / 180,
    50             _img = new Image(),
    50             _img = new Image(),
    51             _span = _endRads - _startRads,
    51             _span = _endRads - _startRads,
    52             _k = .0879 * _span,
    52             _k = .0879 * _span,
    92         var _path = new paper.Path();
    92         var _path = new paper.Path();
    93         _path.add.apply(_path, _segments);
    93         _path.add.apply(_path, _segments);
    94         _path.fillColor = "#333333";
    94         _path.fillColor = "#333333";
    95         _path.opacity = .5;
    95         _path.opacity = .5;
    96         _path.closed = true;
    96         _path.closed = true;
    97         _path.__controller = _ctrl;
    97         _path.__representation = _repr;
    98         var _visible = false,
    98         var _visible = false,
    99             _restPos = new paper.Point(-200, -200),
    99             _restPos = new paper.Point(-200, -200),
   100             _grp = new paper.Group([_path]),
   100             _grp = new paper.Group([_path]),
   101             _delta = _grp.position,
   101             _delta = _grp.position,
   102             _imgdelta = new paper.Point([_centerX, _centerY]),
   102             _imgdelta = new paper.Point([_centerX, _centerY]),
   140         _img.src = _imgsrc;
   140         _img.src = _imgsrc;
   141         return _res
   141         return _res
   142     }
   142     }
   143 }
   143 }
   144 
   144 
   145 Rkns.Renderer._BaseController = function(_renderer, _element) {
   145 Rkns.Renderer._BaseRepresentation = function(_renderer, _model) {
   146     if (typeof _renderer !== "undefined") {
   146     if (typeof _renderer !== "undefined") {
   147         this.id = Rkns.Utils.getUID('controller');
   147         this.renderer = _renderer;
   148         this._renderer = _renderer;
   148         this.project = _renderer.renkan.project;
   149         this._project = _renderer._project;
   149         this.model = _model;
   150         this._element = _element;
   150     }
   151         this._element.__controller = this;
   151 }
   152     }
   152 
   153 }
   153 Rkns.Renderer._BaseRepresentation.prototype.select = function() {}
   154 
   154 
   155 Rkns.Renderer._BaseController.prototype.select = function() {}
   155 Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {}
   156 
   156 
   157 Rkns.Renderer._BaseController.prototype.unselect = function() {}
   157 Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {}
   158 
   158 
   159 Rkns.Renderer._BaseController.prototype.mouseup = function() {}
   159 Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {}
   160 
   160 
   161 Rkns.Renderer._BaseController.prototype.destroy = function() {}
   161 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   162 
       
   163 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
       
   164 
   162 
   165 Rkns.Renderer.Node.prototype._init = function() {
   163 Rkns.Renderer.Node.prototype._init = function() {
   166     this._renderer.node_layer.activate();
   164     this.renderer.node_layer.activate();
   167     this.type = "Node";
   165     this.type = "Node";
   168     this.circle = new paper.Path.Circle([0, 0], Rkns._NODE_RADIUS);
   166     this.circle = new paper.Path.Circle([0, 0], Rkns._NODE_RADIUS);
   169     this.circle.fillColor = '#ffffff';
   167     this.circle.fillColor = '#ffffff';
   170     this.circle.__controller = this;
   168     this.circle.__representation = this;
   171     this.title = new paper.PointText([0,0]);
   169     this.title = new paper.PointText([0,0]);
   172     this.title.characterStyle = {
   170     this.title.characterStyle = {
   173         fontSize: Rkns._NODE_FONT_SIZE,
   171         fontSize: Rkns._NODE_FONT_SIZE,
   174         fillColor: 'black'
   172         fillColor: 'black'
   175     };
   173     };
   176     this.edit_button = new Rkns.Renderer.NodeEditButton(this._renderer, {});
   174     this.edit_button = new Rkns.Renderer.NodeEditButton(this.renderer, {});
   177     this.edit_button.node_controller = this;
   175     this.edit_button.node_representation = this;
   178     this.remove_button = new Rkns.Renderer.NodeRemoveButton(this._renderer, {});
   176     this.remove_button = new Rkns.Renderer.NodeRemoveButton(this.renderer, {});
   179     this.remove_button.node_controller = this;
   177     this.remove_button.node_representation = this;
   180     this.link_button = new Rkns.Renderer.NodeLinkButton(this._renderer, {});
   178     this.link_button = new Rkns.Renderer.NodeLinkButton(this.renderer, {});
   181     this.link_button.node_controller = this;
   179     this.link_button.node_representation = this;
   182     this.title.paragraphStyle.justification = 'center';
   180     this.title.paragraphStyle.justification = 'center';
   183     this.title.__controller = this;
   181     this.title.__representation = this;
   184 }
   182 }
   185 
   183 
   186 Rkns.Renderer.Node.prototype.redraw = function() {
   184 Rkns.Renderer.Node.prototype.redraw = function() {
   187     var _model_coords = new paper.Point(this._element.position);
   185     var _model_coords = new paper.Point(this.model.get("position"));
   188     this.paper_coords = this._renderer.toPaperCoords(_model_coords);
   186     this.paper_coords = this.renderer.toPaperCoords(_model_coords);
   189     this.circle.position = this.paper_coords;
   187     this.circle.position = this.paper_coords;
   190     this.title.content = this._element.title;
   188     this.title.content = this.model.get("title");
   191     this.title.position = this.paper_coords.add([0, 2 * Rkns._NODE_RADIUS]);
   189     this.title.position = this.paper_coords.add([0, 2 * Rkns._NODE_RADIUS]);
   192     this.circle.strokeColor = this._element.created_by.color;
   190     this.circle.strokeColor = this.model.get("created_by").get("color");
   193     this.edit_button.moveTo(this.paper_coords);
   191     this.edit_button.moveTo(this.paper_coords);
   194     this.remove_button.moveTo(this.paper_coords);
   192     this.remove_button.moveTo(this.paper_coords);
   195     this.link_button.moveTo(this.paper_coords);
   193     this.link_button.moveTo(this.paper_coords);
   196 }
   194 }
   197 
   195 
   198 Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
   196 Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
   199     var _coords = this._renderer.toModelCoords(this.paper_coords.add(_delta)),
   197     var _coords = this.renderer.toModelCoords(this.paper_coords.add(_delta)),
   200         _data = {
   198         _data = {
   201             position: {
   199             position: {
   202                 x: _coords.x,
   200                 x: _coords.x,
   203                 y: _coords.y
   201                 y: _coords.y
   204             }
   202             }
   205         };
   203         };
   206     this._project.updateElement(this.type, this._element, _data, Rkns._SAVE);
   204     this.model.set(_data);
   207     this._renderer.redraw();
   205     this.renderer.redraw();
   208 }
   206 }
   209 
   207 
   210 Rkns.Renderer.Node.prototype.openEditor = function() {
   208 Rkns.Renderer.Node.prototype.openEditor = function() {
   211     this._renderer.removeControllersOfType("editor");
   209     this.renderer.removeRepresentationsOfType("editor");
   212     var _editor = this._renderer.addController("NodeEditor",{});
   210     var _editor = this.renderer.addRepresentation("NodeEditor",null);
   213     _editor.node_controller = this;
   211     _editor.node_representation = this;
   214     _editor.redraw();
   212     _editor.redraw();
   215 }
   213 }
   216 
   214 
   217 Rkns.Renderer.Node.prototype.select = function() {
   215 Rkns.Renderer.Node.prototype.select = function() {
   218     this.circle.strokeWidth = 3;
   216     this.circle.strokeWidth = 3;
   229     }
   227     }
   230     this.circle.strokeWidth = 1;
   228     this.circle.strokeWidth = 1;
   231 }
   229 }
   232 
   230 
   233 Rkns.Renderer.Node.prototype.mouseup = function(_event) {
   231 Rkns.Renderer.Node.prototype.mouseup = function(_event) {
   234     if (!this._renderer.is_dragging) {
   232     if (!this.renderer.is_dragging) {
   235         this.openEditor();
   233         this.openEditor();
   236     }
   234     }
   237 }
   235 }
   238 
   236 
   239 Rkns.Renderer.Node.prototype.destroy = function(_event) {
   237 Rkns.Renderer.Node.prototype.destroy = function(_event) {
   243     this.title.remove();
   241     this.title.remove();
   244 }
   242 }
   245 
   243 
   246 /* */
   244 /* */
   247 
   245 
   248 Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   246 Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   249 
   247 
   250 Rkns.Renderer.Edge.prototype._init = function() {
   248 Rkns.Renderer.Edge.prototype._init = function() {
   251     this._renderer.edge_layer.activate();
   249     this.renderer.edge_layer.activate();
   252     this.type = "Edge";
   250     this.type = "Edge";
   253     this.from_controller = this._element.from.__controller;
   251     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
   254     this.to_node_controller = this._element.to.__controller;
   252     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
   255     this.line = new paper.Path();
   253     this.line = new paper.Path();
   256     this.line.add([0,0],[0,0]);
   254     this.line.add([0,0],[0,0]);
   257     this.line.__controller = this;
   255     this.line.__representation = this;
   258     this.arrow = new paper.Path();
   256     this.arrow = new paper.Path();
   259     this.arrow.add([0,0],[Rkns._ARROW_LENGTH,Rkns._ARROW_WIDTH / 2],[0,Rkns._ARROW_WIDTH]);
   257     this.arrow.add([0,0],[Rkns._ARROW_LENGTH,Rkns._ARROW_WIDTH / 2],[0,Rkns._ARROW_WIDTH]);
   260     this.arrow.__controller = this;
   258     this.arrow.__representation = this;
   261     this.text = new paper.PointText();
   259     this.text = new paper.PointText();
   262     this.text.characterStyle = {
   260     this.text.characterStyle = {
   263         fontSize: Rkns._EDGE_FONT_SIZE,
   261         fontSize: Rkns._EDGE_FONT_SIZE,
   264         fillColor: 'black'
   262         fillColor: 'black'
   265     };
   263     };
   266     this.text.paragraphStyle.justification = 'center';
   264     this.text.paragraphStyle.justification = 'center';
   267     this.text.__controller = this;
   265     this.text.__representation = this;
   268     this.text_angle = 0;
   266     this.text_angle = 0;
   269     this.arrow_angle = 0;
   267     this.arrow_angle = 0;
   270     this.edit_button = new Rkns.Renderer.EdgeEditButton(this._renderer, {});
   268     this.edit_button = new Rkns.Renderer.EdgeEditButton(this.renderer, {});
   271     this.edit_button.edge_controller = this;
   269     this.edit_button.edge_representation = this;
   272     this.remove_button = new Rkns.Renderer.EdgeRemoveButton(this._renderer, {});
   270     this.remove_button = new Rkns.Renderer.EdgeRemoveButton(this.renderer, {});
   273     this.remove_button.edge_controller = this;
   271     this.remove_button.edge_representation = this;
   274 }
   272 }
   275 
   273 
   276 Rkns.Renderer.Edge.prototype.redraw = function() {
   274 Rkns.Renderer.Edge.prototype.redraw = function() {
   277     var _p0o = this.from_controller.paper_coords,
   275     var _p0o = this.from_representation.paper_coords,
   278         _p1o = this.to_node_controller.paper_coords,
   276         _p1o = this.to_representation.paper_coords,
   279         _v = _p1o.subtract(_p0o),
   277         _v = _p1o.subtract(_p0o),
   280         _r = _v.length,
   278         _r = _v.length,
   281         _u = _v.divide(_r),
   279         _u = _v.divide(_r),
   282         _delta = new paper.Point([- _u.y, _u.x]).multiply( 4 ),
   280         _delta = new paper.Point([- _u.y, _u.x]).multiply( 4 ),
   283         _p0 = _p0o.add(_delta), /* Adding a 4 px difference */
   281         _p0 = _p0o.add(_delta), /* Adding a 4 px difference */
   284         _p1 = _p1o.add(_delta), /* to differentiate inbound and outbound links */
   282         _p1 = _p1o.add(_delta), /* to differentiate inbound and outbound links */
   285         _a = _v.angle,
   283         _a = _v.angle,
   286         _color = this._element.created_by.color;
   284         _color = this.model.get("created_by").get("color");
   287     this.paper_coords = _p0.add(_p1).divide(2);
   285     this.paper_coords = _p0.add(_p1).divide(2);
   288     this.line.strokeColor = _color;
   286     this.line.strokeColor = _color;
   289     this.line.segments[0].point = _p0;
   287     this.line.segments[0].point = _p0;
   290     this.line.segments[1].point = _p1;
   288     this.line.segments[1].point = _p1;
   291     this.arrow.rotate(_a - this.arrow_angle);
   289     this.arrow.rotate(_a - this.arrow_angle);
   297     }
   295     }
   298     if (_a < -90) {
   296     if (_a < -90) {
   299         _a += 180;
   297         _a += 180;
   300     }
   298     }
   301     this.text.rotate(_a - this.text_angle);
   299     this.text.rotate(_a - this.text_angle);
   302     this.text.content = this._element.title;
   300     this.text.content = this.model.get("title");
   303     this.text.position = this.paper_coords;
   301     this.text.position = this.paper_coords;
   304     this.text_angle = _a;
   302     this.text_angle = _a;
   305     this.edit_button.moveTo(this.paper_coords);
   303     this.edit_button.moveTo(this.paper_coords);
   306     this.remove_button.moveTo(this.paper_coords);
   304     this.remove_button.moveTo(this.paper_coords);
   307 }
   305 }
   308 
   306 
   309 Rkns.Renderer.Edge.prototype.openEditor = function() {
   307 Rkns.Renderer.Edge.prototype.openEditor = function() {
   310     this._renderer.removeControllersOfType("editor");
   308     this.renderer.removeRepresentationsOfType("editor");
   311     var _editor = this._renderer.addController("EdgeEditor",{});
   309     var _editor = this.renderer.addRepresentation("EdgeEditor",null);
   312     _editor.edge_controller = this;
   310     _editor.edge_representation = this;
   313     _editor.redraw();
   311     _editor.redraw();
   314 }
   312 }
   315 
   313 
   316 Rkns.Renderer.Edge.prototype.select = function() {
   314 Rkns.Renderer.Edge.prototype.select = function() {
   317     this.line.strokeWidth = 3;
   315     this.line.strokeWidth = 3;
   326     }
   324     }
   327     this.line.strokeWidth = 1;
   325     this.line.strokeWidth = 1;
   328 }
   326 }
   329 
   327 
   330 Rkns.Renderer.Edge.prototype.mouseup = function(_event) {
   328 Rkns.Renderer.Edge.prototype.mouseup = function(_event) {
   331     if (!this._renderer.is_dragging) {
   329     if (!this.renderer.is_dragging) {
   332         this.openEditor();
   330         this.openEditor();
   333     }
   331     }
   334 }
   332 }
   335 
   333 
   336 Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
   334 Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
   337     this.from_controller.paperShift(_delta);
   335     this.from_representation.paperShift(_delta);
   338     this.to_node_controller.paperShift(_delta);
   336     this.to_representation.paperShift(_delta);
   339     this._renderer.redraw();
   337     this.renderer.redraw();
   340 }
   338 }
   341 
   339 
   342 Rkns.Renderer.Edge.prototype.destroy = function() {
   340 Rkns.Renderer.Edge.prototype.destroy = function() {
   343     this.line.remove();
   341     this.line.remove();
   344     this.arrow.remove();
   342     this.arrow.remove();
   347     this.remove_button.destroy();
   345     this.remove_button.destroy();
   348 }
   346 }
   349 
   347 
   350 /* */
   348 /* */
   351 
   349 
   352 Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   350 Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   353 
   351 
   354 Rkns.Renderer.TempEdge.prototype._init = function() {
   352 Rkns.Renderer.TempEdge.prototype._init = function() {
   355     this._renderer.edge_layer.activate();
   353     this.renderer.edge_layer.activate();
   356     this.type = "temp-edge";
   354     this.type = "temp-edge";
   357     var _color = this._project.current_user.color;
   355     
       
   356     var _color = this.project.get("users").get(this.renderer.renkan.current_user).get("color");
   358     this.line = new paper.Path();
   357     this.line = new paper.Path();
   359     this.line.strokeColor = _color;
   358     this.line.strokeColor = _color;
   360     this.line.add([0,0],[0,0]);
   359     this.line.add([0,0],[0,0]);
   361     this.line.__controller = this;
   360     this.line.__representation = this;
   362     this.arrow = new paper.Path();
   361     this.arrow = new paper.Path();
   363     this.arrow.fillColor = _color;
   362     this.arrow.fillColor = _color;
   364     this.arrow.add([0,0],[Rkns._ARROW_LENGTH,Rkns._ARROW_WIDTH / 2],[0,Rkns._ARROW_WIDTH]);
   363     this.arrow.add([0,0],[Rkns._ARROW_LENGTH,Rkns._ARROW_WIDTH / 2],[0,Rkns._ARROW_WIDTH]);
   365     this.arrow.__controller = this;
   364     this.arrow.__representation = this;
   366     this.arrow_angle = 0;
   365     this.arrow_angle = 0;
   367 }
   366 }
   368 
   367 
   369 Rkns.Renderer.TempEdge.prototype.redraw = function() {
   368 Rkns.Renderer.TempEdge.prototype.redraw = function() {
   370     var _p0 = this.from_controller.paper_coords,
   369     var _p0 = this.from_representation.paper_coords,
   371         _p1 = this.end_pos,
   370         _p1 = this.end_pos,
   372         _a = _p1.subtract(_p0).angle,
   371         _a = _p1.subtract(_p0).angle,
   373         _c = _p0.add(_p1).divide(2);
   372         _c = _p0.add(_p1).divide(2);
   374     this.line.segments[0].point = _p0;
   373     this.line.segments[0].point = _p0;
   375     this.line.segments[1].point = _p1;
   374     this.line.segments[1].point = _p1;
   379 }
   378 }
   380 
   379 
   381 Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
   380 Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
   382     this.end_pos = this.end_pos.add(_delta);
   381     this.end_pos = this.end_pos.add(_delta);
   383     var _hitResult = paper.project.hitTest(this.end_pos);
   382     var _hitResult = paper.project.hitTest(this.end_pos);
   384     this._renderer.findTarget(_hitResult);
   383     this.renderer.findTarget(_hitResult);
   385     this.redraw();
   384     this.redraw();
   386 }
   385 }
   387 
   386 
   388 Rkns.Renderer.TempEdge.prototype.mouseup = function(_event) {
   387 Rkns.Renderer.TempEdge.prototype.mouseup = function(_event) {
   389     var _hitResult = paper.project.hitTest(_event.point);
   388     var _hitResult = paper.project.hitTest(_event.point);
   390     if (_hitResult && typeof _hitResult.item.__controller !== "undefined") {
   389     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
   391         var _target = _hitResult.item.__controller;
   390         var _target = _hitResult.item.__representation;
   392         if (_target.type === "Node" && this.from_controller._element.id !== _target._element.id) {
   391         if (_target.type === "Node" && this.from_representation.model !== _target.model) {
   393             this._project.addEdge({
   392             var _data = {
   394                 from: this.from_controller._element.id,
   393                 id: Rkns.Utils.getUID('edge'),
   395                 to: _target._element.id
   394                 created_by: this.renderer.renkan.current_user,
   396             }, Rkns._RENDER_AND_SAVE)
   395                 from: this.from_representation.model.get("id"),
   397         }
   396                 to: _target.model.get("id")
   398     }
   397             };
   399     this._renderer.removeController(this);
   398             this.project.addEdge(_data);
       
   399         }
       
   400     }
       
   401     this.renderer.removeRepresentation(this);
   400 }
   402 }
   401 
   403 
   402 Rkns.Renderer.TempEdge.prototype.destroy = function() {
   404 Rkns.Renderer.TempEdge.prototype.destroy = function() {
   403     this.arrow.remove();
   405     this.arrow.remove();
   404     this.line.remove();
   406     this.line.remove();
   405 }
   407 }
   406 
   408 
   407 /* */
   409 /* */
   408 
   410 
   409 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   411 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   410 
   412 
   411 Rkns.Renderer.NodeEditor.prototype._init = function() {
   413 Rkns.Renderer.NodeEditor.prototype._init = function() {
   412     this._renderer.overlay_layer.activate();
   414     this.renderer.overlay_layer.activate();
   413     this.type = "editor";
   415     this.type = "editor";
   414     this.editor_block = new paper.Path();
   416     this.editor_block = new paper.Path();
   415     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   417     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   416     this.editor_block.add.apply(this.editor_block, _pts);
   418     this.editor_block.add.apply(this.editor_block, _pts);
   417     this.editor_block.strokeWidth = 2;
   419     this.editor_block.strokeWidth = 2;
   418     this.editor_block.strokeColor = "#999999";
   420     this.editor_block.strokeColor = "#999999";
   419     this.editor_block.fillColor = "#e0e0e0";
   421     this.editor_block.fillColor = "#e0e0e0";
   420     this.editor_block.opacity = .8;
   422     this.editor_block.opacity = .8;
   421     this.editor_$ = Rkns.$('<div>')
   423     this.editor_$ = Rkns.$('<div>')
   422         .appendTo(this._renderer.editor_$)
   424         .appendTo(this.renderer.editor_$)
   423         .css({
   425         .css({
   424             position: "absolute",
   426             position: "absolute",
   425             opacity: .8
   427             opacity: .8
   426         })
   428         })
   427         .hide();
   429         .hide();
   434     + '<p><label><%=l10n.edit_description%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
   436     + '<p><label><%=l10n.edit_description%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
   435     + '<p><label><%=l10n.created_by%></label> <span class="Rk-UserColor" style="background:<%=node.created_by.color%>;"></span> <%=node.created_by.title%></p>'
   437     + '<p><label><%=l10n.created_by%></label> <span class="Rk-UserColor" style="background:<%=node.created_by.color%>;"></span> <%=node.created_by.title%></p>'
   436 );
   438 );
   437 
   439 
   438 Rkns.Renderer.NodeEditor.prototype.redraw = function() {
   440 Rkns.Renderer.NodeEditor.prototype.redraw = function() {
   439     var _coords = this.node_controller.paper_coords,
   441     var _coords = this.node_representation.paper_coords,
   440         _element = this.node_controller._element,
   442         _model = this.node_representation.model,
   441         _css = Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 300);
   443         _css = Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 300);
   442     this.editor_$
   444     this.editor_$
   443         .html(this.template({
   445         .html(this.template({
   444             node: _element,
   446             node: {
   445             l10n: this._project.l10n
   447                 title: _model.get("title"),
       
   448                 uri: _model.get("uri"),
       
   449                 description: _model.get("description"),
       
   450                 created_by: {
       
   451                     color: _model.get("created_by").get("color"),
       
   452                     title: _model.get("created_by").get("title")
       
   453                 }
       
   454             },
       
   455             l10n: this.renderer.renkan.l10n
   446         }))
   456         }))
   447         .show()
   457         .show()
   448         .css(_css);
   458         .css(_css);
   449     var _this = this;
   459     var _this = this;
   450     this.editor_$.find(".Rk-CloseX").click(function() {
   460     this.editor_$.find(".Rk-CloseX").click(function() {
   451         _this._renderer.removeController(_this);
   461         _this.renderer.removeRepresentation(_this);
   452         paper.view.draw();
   462         paper.view.draw();
   453     });
   463     });
   454     this.editor_$.find("input, textarea").bind("keyup change", function() {
   464     this.editor_$.find("input, textarea").bind("keyup change", function() {
   455         var _data = {
   465         var _data = {
   456             title: _this.editor_$.find(".Rk-Edit-Title").val(),
   466             title: _this.editor_$.find(".Rk-Edit-Title").val(),
   457             description: _this.editor_$.find(".Rk-Edit-Description").val(),
   467             description: _this.editor_$.find(".Rk-Edit-Description").val(),
   458             uri: _this.editor_$.find(".Rk-Edit-URI").val()
   468             uri: _this.editor_$.find(".Rk-Edit-URI").val()
   459         }
   469         }
   460         _this._project.updateNode(
   470         _model.set(_data);
   461             _element,
       
   462             _data,
       
   463             Rkns._SAVE
       
   464         );
       
   465         _this.node_controller.redraw();
       
   466         paper.view.draw();
   471         paper.view.draw();
   467     });
   472     });
   468     this.editor_$.find(".Rk-Edit-Title")[0].focus();
   473     this.editor_$.find(".Rk-Edit-Title")[0].focus();
       
   474     paper.view.draw();
   469 }
   475 }
   470 
   476 
   471 Rkns.Renderer.NodeEditor.prototype.destroy = function() {
   477 Rkns.Renderer.NodeEditor.prototype.destroy = function() {
   472     this.editor_block.remove();
   478     this.editor_block.remove();
   473     this.editor_$.detach();
   479     this.editor_$.detach();
   474 }
   480 }
   475 
   481 
   476 /* */
   482 /* */
   477 
   483 
   478 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   484 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   479 
   485 
   480 Rkns.Renderer.EdgeEditor.prototype._init = function() {
   486 Rkns.Renderer.EdgeEditor.prototype._init = function() {
   481     this._renderer.overlay_layer.activate();
   487     this.renderer.overlay_layer.activate();
   482     this.type = "editor";
   488     this.type = "editor";
   483     this.editor_block = new paper.Path();
   489     this.editor_block = new paper.Path();
   484     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   490     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
   485     this.editor_block.add.apply(this.editor_block, _pts);
   491     this.editor_block.add.apply(this.editor_block, _pts);
   486     this.editor_block.strokeWidth = 2;
   492     this.editor_block.strokeWidth = 2;
   487     this.editor_block.strokeColor = "#999999";
   493     this.editor_block.strokeColor = "#999999";
   488     this.editor_block.fillColor = "#e0e0e0";
   494     this.editor_block.fillColor = "#e0e0e0";
   489     this.editor_block.opacity = .8;
   495     this.editor_block.opacity = .8;
   490     this.editor_$ = Rkns.$('<div>')
   496     this.editor_$ = Rkns.$('<div>')
   491         .appendTo(this._renderer.editor_$)
   497         .appendTo(this.renderer.editor_$)
   492         .css({
   498         .css({
   493             position: "absolute",
   499             position: "absolute",
   494             opacity: .8
   500             opacity: .8
   495         })
   501         })
   496         .hide();
   502         .hide();
   504     + '<p><label><%=l10n.edit_to%></label><span class="Rk-UserColor" style="background:<%=edge.to.created_by.color%>;"></span><%=edge.to.title%></p>'
   510     + '<p><label><%=l10n.edit_to%></label><span class="Rk-UserColor" style="background:<%=edge.to.created_by.color%>;"></span><%=edge.to.title%></p>'
   505     + '<p><label><%=l10n.created_by%> </label><span class="Rk-UserColor" style="background:<%=edge.created_by.color%>;"></span> <%=edge.created_by.title%></p>'
   511     + '<p><label><%=l10n.created_by%> </label><span class="Rk-UserColor" style="background:<%=edge.created_by.color%>;"></span> <%=edge.created_by.title%></p>'
   506 );
   512 );
   507 
   513 
   508 Rkns.Renderer.EdgeEditor.prototype.redraw = function() {
   514 Rkns.Renderer.EdgeEditor.prototype.redraw = function() {
   509     var _coords = this.edge_controller.paper_coords,
   515     var _coords = this.edge_representation.paper_coords,
   510         _element = this.edge_controller._element,
   516         _model = this.edge_representation.model,
   511         _css = Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 200);
   517         _css = Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 200);
   512     this.editor_$
   518     this.editor_$
   513         .html(this.template({
   519         .html(this.template({
   514             edge: _element,
   520             edge: _model,
   515             l10n: this._project.l10n
   521             l10n: this.renderer.renkan.l10n
   516         }))
   522         }))
   517         .show()
   523         .show()
   518         .css(_css);
   524         .css(_css);
   519     var _this = this;
   525     var _this = this;
   520     this.editor_$.find(".Rk-CloseX").click(function() {
   526     this.editor_$.find(".Rk-CloseX").click(function() {
   521         _this._renderer.removeController(_this);
   527         _this.renderer.removeRepresentation(_this);
   522         paper.view.draw();
   528         paper.view.draw();
   523     });
   529     });
   524     this.editor_$.find("input, textarea").bind("keyup change", function() {
   530     this.editor_$.find("input, textarea").bind("keyup change", function() {
   525         var _data = {
   531         var _data = {
   526             title: _this.editor_$.find(".Rk-Edit-Title").val(),
   532             title: _this.editor_$.find(".Rk-Edit-Title").val(),
   527             uri: _this.editor_$.find(".Rk-Edit-URI").val()
   533             uri: _this.editor_$.find(".Rk-Edit-URI").val()
   528         }
   534         }
   529         _this._project.updateEdge(
   535         _model.set(_data);
   530             _element,
       
   531             _data,
       
   532             Rkns._SAVE
       
   533         );
       
   534         _this.edge_controller.redraw();
       
   535         paper.view.draw();
   536         paper.view.draw();
   536     });
   537     });
       
   538     paper.view.draw();
   537 }
   539 }
   538 
   540 
   539 Rkns.Renderer.EdgeEditor.prototype.destroy = function() {
   541 Rkns.Renderer.EdgeEditor.prototype.destroy = function() {
   540     this.editor_block.remove();
   542     this.editor_block.remove();
   541     this.editor_$.detach();
   543     this.editor_$.detach();
   542 }
   544 }
   543 
   545 
   544 /* */
   546 /* */
   545 
   547 
   546 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   548 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   547 
   549 
   548 Rkns.Renderer.NodeEditButton.prototype._init = function() {
   550 Rkns.Renderer.NodeEditButton.prototype._init = function() {
   549     this._renderer.node_layer.activate();
   551     this.renderer.node_layer.activate();
   550     this.type = "Node-edit-button";
   552     this.type = "Node-edit-button";
   551     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS, 3 * Rkns._NODE_RADIUS, - 90, 30, 2, 'img/edit.png');
   553     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS, 3 * Rkns._NODE_RADIUS, - 90, 30, 2, 'img/edit.png');
   552 }
   554 }
   553 
   555 
   554 Rkns.Renderer.NodeEditButton.prototype.moveTo = function(_pos) {
   556 Rkns.Renderer.NodeEditButton.prototype.moveTo = function(_pos) {
   568 }
   570 }
   569 
   571 
   570 Rkns.Renderer.NodeEditButton.prototype.unselect = function() {
   572 Rkns.Renderer.NodeEditButton.prototype.unselect = function() {
   571     this.sector.unselect();
   573     this.sector.unselect();
   572     this.hide();
   574     this.hide();
   573     this.node_controller.remove_button.hide();
   575     this.node_representation.remove_button.hide();
   574     this.node_controller.link_button.hide();
   576     this.node_representation.link_button.hide();
   575 }
   577 }
   576 
   578 
   577 Rkns.Renderer.NodeEditButton.prototype.mouseup = function() {
   579 Rkns.Renderer.NodeEditButton.prototype.mouseup = function() {
   578     if (!this._renderer.is_dragging) {
   580     if (!this.renderer.is_dragging) {
   579         this.node_controller.openEditor();
   581         this.node_representation.openEditor();
   580     }
   582     }
   581 }
   583 }
   582 
   584 
   583 Rkns.Renderer.NodeEditButton.prototype.destroy = function() {
   585 Rkns.Renderer.NodeEditButton.prototype.destroy = function() {
   584     this.sector.destroy();
   586     this.sector.destroy();
   585 }
   587 }
   586 
   588 
   587 /* */
   589 /* */
   588 
   590 
   589 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   591 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   590 
   592 
   591 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
   593 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
   592     this._renderer.node_layer.activate();
   594     this.renderer.node_layer.activate();
   593     this.type = "Node-remove-button";
   595     this.type = "Node-remove-button";
   594     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS, 3 * Rkns._NODE_RADIUS, -210, -90, 2, 'img/remove.png');
   596     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS, 3 * Rkns._NODE_RADIUS, -210, -90, 2, 'img/remove.png');
   595 }
   597 }
   596 
   598 
   597 Rkns.Renderer.NodeRemoveButton.prototype.moveTo = function(_pos) {
   599 Rkns.Renderer.NodeRemoveButton.prototype.moveTo = function(_pos) {
   611 }
   613 }
   612 
   614 
   613 Rkns.Renderer.NodeRemoveButton.prototype.unselect = function() {
   615 Rkns.Renderer.NodeRemoveButton.prototype.unselect = function() {
   614     this.sector.unselect();
   616     this.sector.unselect();
   615     this.hide();
   617     this.hide();
   616     this.node_controller.edit_button.hide();
   618     this.node_representation.edit_button.hide();
   617     this.node_controller.link_button.hide();
   619     this.node_representation.link_button.hide();
   618 }
   620 }
   619 
   621 
   620 Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
   622 Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
   621     if (confirm('Do you really wish to remove node "' + this.node_controller._element.title + '"?')) {
   623     if (confirm('Do you really wish to remove node "' + this.node_representation.model.get("title") + '"?')) {
   622         this._renderer._project.removeNode(this.node_controller._element, Rkns._RENDER_AND_SAVE);
   624         this.project.removeNode(this.node_representation.model);
   623     }
   625     }
   624 }
   626 }
   625 
   627 
   626 Rkns.Renderer.NodeRemoveButton.prototype.destroy = function() {
   628 Rkns.Renderer.NodeRemoveButton.prototype.destroy = function() {
   627     this.sector.destroy();
   629     this.sector.destroy();
   628 }
   630 }
   629 
   631 
   630 /* */
   632 /* */
   631 
   633 
   632 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   634 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   633 
   635 
   634 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
   636 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
   635     this._renderer.node_layer.activate();
   637     this.renderer.node_layer.activate();
   636     this.type = "Node-link-button";
   638     this.type = "Node-link-button";
   637     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS , 3 * Rkns._NODE_RADIUS, 30, 150, 2, 'img/link.png');
   639     this.sector = Rkns.Renderer.Utils.sector(this, 1 + Rkns._NODE_RADIUS , 3 * Rkns._NODE_RADIUS, 30, 150, 2, 'img/link.png');
   638 }
   640 }
   639 
   641 
   640 Rkns.Renderer.NodeLinkButton.prototype.moveTo = function(_pos) {
   642 Rkns.Renderer.NodeLinkButton.prototype.moveTo = function(_pos) {
   654 }
   656 }
   655 
   657 
   656 Rkns.Renderer.NodeLinkButton.prototype.unselect = function() {
   658 Rkns.Renderer.NodeLinkButton.prototype.unselect = function() {
   657     this.sector.unselect();
   659     this.sector.unselect();
   658     this.hide();
   660     this.hide();
   659     this.node_controller.edit_button.hide();
   661     this.node_representation.edit_button.hide();
   660     this.node_controller.remove_button.hide();
   662     this.node_representation.remove_button.hide();
   661 }
   663 }
   662 
   664 
   663 Rkns.Renderer.NodeLinkButton.prototype.destroy = function() {
   665 Rkns.Renderer.NodeLinkButton.prototype.destroy = function() {
   664     this.sector.destroy();
   666     this.sector.destroy();
   665 }
   667 }
   666 
   668 
   667 /* */
   669 /* */
   668 
   670 
   669 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   671 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   670 
   672 
   671 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
   673 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
   672     this._renderer.edge_layer.activate();
   674     this.renderer.edge_layer.activate();
   673     this.type = "Edge-edit-button";
   675     this.type = "Edge-edit-button";
   674     this.sector = Rkns.Renderer.Utils.sector(this, 5 , 2 * Rkns._NODE_RADIUS, - 60, 60, 2, 'img/edit.png');
   676     this.sector = Rkns.Renderer.Utils.sector(this, 5 , 2 * Rkns._NODE_RADIUS, - 60, 60, 2, 'img/edit.png');
   675 }
   677 }
   676 
   678 
   677 Rkns.Renderer.EdgeEditButton.prototype.moveTo = function(_pos) {
   679 Rkns.Renderer.EdgeEditButton.prototype.moveTo = function(_pos) {
   691 }
   693 }
   692 
   694 
   693 Rkns.Renderer.EdgeEditButton.prototype.unselect = function() {
   695 Rkns.Renderer.EdgeEditButton.prototype.unselect = function() {
   694     this.sector.unselect();
   696     this.sector.unselect();
   695     this.hide();
   697     this.hide();
   696     this.edge_controller.remove_button.hide();
   698     this.edge_representation.remove_button.hide();
   697 }
   699 }
   698 
   700 
   699 Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() {
   701 Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() {
   700     if (!this._renderer.is_dragging) {
   702     if (!this.renderer.is_dragging) {
   701         this.edge_controller.openEditor();
   703         this.edge_representation.openEditor();
   702     }
   704     }
   703 }
   705 }
   704 
   706 
   705 Rkns.Renderer.EdgeEditButton.prototype.destroy = function() {
   707 Rkns.Renderer.EdgeEditButton.prototype.destroy = function() {
   706     this.sector.destroy();
   708     this.sector.destroy();
   707 }
   709 }
   708 
   710 
   709 /* */
   711 /* */
   710 
   712 
   711 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseController);
   713 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
   712 
   714 
   713 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
   715 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
   714     this._renderer.edge_layer.activate();
   716     this.renderer.edge_layer.activate();
   715     this.type = "Edge-remove-button";
   717     this.type = "Edge-remove-button";
   716     this.sector = Rkns.Renderer.Utils.sector(this, 5, 2 * Rkns._NODE_RADIUS, - 240, -120, 2, 'img/remove.png');
   718     this.sector = Rkns.Renderer.Utils.sector(this, 5, 2 * Rkns._NODE_RADIUS, - 240, -120, 2, 'img/remove.png');
   717 }
   719 }
   718 Rkns.Renderer.EdgeRemoveButton.prototype.moveTo = function(_pos) {
   720 Rkns.Renderer.EdgeRemoveButton.prototype.moveTo = function(_pos) {
   719     this.sector.moveTo(_pos);
   721     this.sector.moveTo(_pos);
   732 }
   734 }
   733 
   735 
   734 Rkns.Renderer.EdgeRemoveButton.prototype.unselect = function() {
   736 Rkns.Renderer.EdgeRemoveButton.prototype.unselect = function() {
   735     this.sector.unselect();
   737     this.sector.unselect();
   736     this.hide();
   738     this.hide();
   737     this.edge_controller.edit_button.hide();
   739     this.edge_representation.edit_button.hide();
   738 }
   740 }
   739 
   741 
   740 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
   742 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
   741     if (confirm('Do you really wish to remove edge "' + this.edge_controller._element.title + '"?')) {
   743     if (confirm('Do you really wish to remove edge "' + this.edge_representation.model.get("title") + '"?')) {
   742         this._renderer._project.removeEdge(this.edge_controller._element, Rkns._RENDER_AND_SAVE);
   744         this.project.removeEdge(this.edge_representation.model);
   743     }
   745     }
   744 }
   746 }
   745 
   747 
   746 Rkns.Renderer.EdgeRemoveButton.prototype.destroy = function() {
   748 Rkns.Renderer.EdgeRemoveButton.prototype.destroy = function() {
   747     this.sector.destroy();
   749     this.sector.destroy();
   748 }
   750 }
   749 
   751 
   750 /* */
   752 /* */
   751 
   753 
   752 Rkns.Renderer.Scene = function(_project) {
   754 Rkns.Renderer.Scene = function(_renkan) {
   753     this._project = _project;
   755     this.renkan = _renkan;
   754     this._MARGIN_X = 80;
   756     this._MARGIN_X = 80;
   755     this._MARGIN_Y = 50;
   757     this._MARGIN_Y = 50;
   756     this.$ = Rkns.$(".Rk-Render");
   758     this.$ = Rkns.$(".Rk-Render");
       
   759     this.representations = [];
   757     this.$.html(this.template({
   760     this.$.html(this.template({
   758         l10n: this._project.l10n
   761         l10n: _renkan.l10n
   759     }))
   762     }))
   760     this.canvas_$ = this.$.find(".Rk-Canvas");
   763     this.canvas_$ = this.$.find(".Rk-Canvas");
   761     this.editor_$ = this.$.find(".Rk-Editor");
   764     this.editor_$ = this.$.find(".Rk-Editor");
   762     paper.setup(this.canvas_$[0]);
   765     paper.setup(this.canvas_$[0]);
   763     this.scale = 1;
   766     this.scale = 1;
   810     });
   813     });
   811     paper.view.onResize = function(_event) {
   814     paper.view.onResize = function(_event) {
   812         _this.offset = _this.offset.add(_event.delta.divide(2));
   815         _this.offset = _this.offset.add(_event.delta.divide(2));
   813         _this.redraw();
   816         _this.redraw();
   814     }
   817     }
       
   818     
       
   819     var _thRedraw = Rkns._.throttle(function() {
       
   820         _this.redraw();
       
   821     },50);
       
   822     
       
   823     this.addRepresentations("Node", this.renkan.project.get("nodes"));
       
   824     this.addRepresentations("Edge", this.renkan.project.get("edges"));
       
   825     
       
   826     this.renkan.project.on("add:nodes", function(_node) {
       
   827         _this.addRepresentation("Node", _node);
       
   828         _thRedraw();
       
   829     });
       
   830     this.renkan.project.on("add:edges", function(_edge) {
       
   831         _this.addRepresentation("Edge", _edge);
       
   832         _thRedraw();
       
   833     });
       
   834     
       
   835     this.redraw();
   815 }
   836 }
   816 
   837 
   817 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
   838 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
   818     '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor">'
   839     '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor">'
   819     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%=l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%=l10n.zoom_out%>"></div></div>'
   840     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%=l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%=l10n.zoom_out%>"></div></div>'
   827 
   848 
   828 Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
   849 Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
   829     return _point.subtract(this.offset).divide(this.scale);
   850     return _point.subtract(this.offset).divide(this.scale);
   830 }
   851 }
   831 
   852 
   832 Rkns.Renderer.Scene.prototype.draw = function() {
   853 Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) {
   833     var _this = this,
   854     var _repr = new Rkns.Renderer[_type](this, _model);
   834         _xx = this._project.nodes.map(function(_node) { return _node.position.x }),
   855     this.representations.push(_repr);
   835         _yy = this._project.nodes.map(function(_node) { return _node.position.y }),
   856     if (_model) {
   836         _minx = Math.min.apply(Math, _xx),
   857         var _this = this;
   837         _miny = Math.min.apply(Math, _yy),
   858         _model.on("change", function() {
   838         _maxx = Math.max.apply(Math, _xx),
   859             _repr.redraw();
   839         _maxy = Math.max.apply(Math, _yy);
   860         });
   840     this.scale = Math.min((paper.view.size.width - 2 * this._MARGIN_X) / (_maxx - _minx), (paper.view.size.height - 2 * this._MARGIN_Y) / (_maxy - _miny));
   861         _model.on("remove", function() {
   841     this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(this.scale));
   862             _this.removeRepresentation(_repr);
   842     this.controllers = new Rkns.ViewModel.List();
   863             _this.redraw();
   843     this._project.nodes.forEach(function(_node) {
   864         });
   844         _this.addController("Node", _node);
   865     }
   845     });
   866     return _repr;
   846     this._project.edges.forEach(function(_edge) {
   867 }
   847         _this.addController("Edge", _edge);
   868 
   848     });
   869 Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) {
   849     
   870     var _this = this;
   850     this.redraw();
   871     _collection.forEach(function(_model) {
   851 }
   872         _this.addRepresentation(_type, _model);
   852 
   873     });
   853 Rkns.Renderer.Scene.prototype.addController = function(_type, _controller) {
   874 }
   854     var _el = new Rkns.Renderer[_type](this, _controller);
   875 
   855     this.controllers.push(_el);
   876 Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) {
   856     return _el;
   877     _representation.destroy();
   857 }
   878     this.representations = Rkns._(this.representations).reject(
   858 
   879         function(_repr) {
   859 Rkns.Renderer.Scene.prototype.removeController = function(_controller) {
   880             return _repr == _representation
   860     _controller.destroy();
   881         }
   861     this.controllers.removeId(_controller.id);
   882     );
   862 }
   883 }
   863 
   884 
   864 Rkns.Renderer.Scene.prototype.removeControllersOfType = function(_type) {
   885 Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) {
   865     var _controllers = this.controllers.filter(function(_ctrl) {
   886     return Rkns._(this.representations).find(function(_repr) {
   866             return _ctrl.type == _type;
   887         return _repr.model === _model;
       
   888     });
       
   889 }
       
   890 
       
   891 Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) {
       
   892     var _representations = Rkns._(this.representations).filter(function(_repr) {
       
   893             return _repr.type == _type;
   867         }),
   894         }),
   868         _this = this;
   895         _this = this;
   869     _controllers.forEach(function(_ctrl) {
   896     Rkns._(_representations).each(function(_repr) {
   870         _this.removeController(_ctrl);
   897         _this.removeRepresentation(_repr);
   871     });
   898     });
   872 }
   899 }
   873 
   900 
   874 Rkns.Renderer.Scene.prototype.redraw = function() {
   901 Rkns.Renderer.Scene.prototype.redraw = function() {
   875     this.controllers.forEach(function(_controller) {
   902     Rkns._(this.representations).each(function(_representation) {
   876         _controller.redraw();
   903         _representation.redraw();
   877     });
   904     });
   878     paper.view.draw();
   905     paper.view.draw();
   879 }
   906 }
   880 
   907 
   881 Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
   908 Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
   882     var _tmpEdge = this.addController("TempEdge",{});
   909     var _tmpEdge = this.addRepresentation("TempEdge",null);
   883     _tmpEdge.end_pos = _point;
   910     _tmpEdge.end_pos = _point;
   884     _tmpEdge.from_controller = _from;
   911     _tmpEdge.from_representation = _from;
   885     _tmpEdge.redraw();
   912     _tmpEdge.redraw();
   886     this.click_target = _tmpEdge;
   913     this.click_target = _tmpEdge;
   887 }
   914 }
   888 
   915 
   889 Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
   916 Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
   890     if (_hitResult && typeof _hitResult.item.__controller !== "undefined") {
   917     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
   891         var _newTarget = _hitResult.item.__controller;
   918         var _newTarget = _hitResult.item.__representation;
   892         if (this.selected_target !== _hitResult.item.__controller) {
   919         if (this.selected_target !== _hitResult.item.__representation) {
   893             if (this.selected_target) {
   920             if (this.selected_target) {
   894                 this.selected_target.unselect(_newTarget);
   921                 this.selected_target.unselect(_newTarget);
   895             }
   922             }
   896             _newTarget.select(this.selected_target);
   923             _newTarget.select(this.selected_target);
   897             this.selected_target = _newTarget;
   924             this.selected_target = _newTarget;
   919 }
   946 }
   920 
   947 
   921 Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
   948 Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
   922     this.is_dragging = false;
   949     this.is_dragging = false;
   923     var _hitResult = paper.project.hitTest(_event.point);
   950     var _hitResult = paper.project.hitTest(_event.point);
   924     if (_hitResult && typeof _hitResult.item.__controller !== "undefined") {
   951     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
   925         this.click_target = _hitResult.item.__controller;
   952         this.click_target = _hitResult.item.__representation;
   926         if (this.click_target.type === "Node" && _hitResult.type === "stroke") {
   953         if (this.click_target.type === "Node" && _hitResult.type === "stroke") {
   927             this.addTempEdge(this.click_target, _event.point);
   954             this.addTempEdge(this.click_target, _event.point);
   928         }
   955         }
   929         if (this.click_target.type === "Node-link-button") {
   956         if (this.click_target.type === "Node-link-button") {
   930             this.addTempEdge(this.click_target.node_controller, _event.point);
   957             this.addTempEdge(this.click_target.node_representation, _event.point);
   931         }
   958         }
   932     } else {
   959     } else {
   933         this.click_target = null;
   960         this.click_target = null;
   934     }
   961     }
   935 }
   962 }
   980         _point = new paper.Point([
  1007         _point = new paper.Point([
   981             _event.pageX - _off.left,
  1008             _event.pageX - _off.left,
   982             _event.pageY - _off.top
  1009             _event.pageY - _off.top
   983         ]);
  1010         ]);
   984     var _hitResult = paper.project.hitTest(_point);
  1011     var _hitResult = paper.project.hitTest(_point);
   985     if (!_hitResult || typeof _hitResult.item.__controller === "undefined") {
  1012     if (!_hitResult || typeof _hitResult.item.__representation === "undefined") {
   986         var _coords = this.toModelCoords(_point),
  1013         var _coords = this.toModelCoords(_point),
   987             _node = this._project.addNode({
  1014             _data = {
       
  1015                 id: Rkns.Utils.getUID('node'),
       
  1016                 created_by: this.renkan.current_user,
   988                 position: {
  1017                 position: {
   989                     x: _coords.x,
  1018                     x: _coords.x,
   990                     y: _coords.y
  1019                     y: _coords.y
   991                 }
  1020                 }
   992             }, Rkns._RENDER_AND_SAVE);
  1021             };
   993         _node.__controller.openEditor();
  1022             _node = this.renkan.project.addNode(_data);
       
  1023             this.getRepresentationByModel(_node).openEditor();
   994     }
  1024     }
   995     paper.view.draw();
  1025     paper.view.draw();
   996 }
  1026 }
   997 
  1027 
   998 Rkns.Renderer.Scene.prototype.onMouseEnter = function(_event) {
  1028 Rkns.Renderer.Scene.prototype.onMouseEnter = function(_event) {
  1002             _point = new paper.Point([
  1032             _point = new paper.Point([
  1003                 _event.pageX - _off.left,
  1033                 _event.pageX - _off.left,
  1004                 _event.pageY - _off.top
  1034                 _event.pageY - _off.top
  1005             ]),
  1035             ]),
  1006             _coords = this.toModelCoords(_point),
  1036             _coords = this.toModelCoords(_point),
  1007             _node = this._project.addNode({
  1037             _data = {
       
  1038                 id: Rkns.Utils.getUID('node'),
       
  1039                 created_by: this.renkan.current_user,
  1008                 uri: _newEl.uri,
  1040                 uri: _newEl.uri,
  1009                 title: _newEl.title,
  1041                 title: _newEl.title,
  1010                 description: _newEl.description,
  1042                 description: _newEl.description,
  1011                 position: {
  1043                 position: {
  1012                     x: _coords.x,
  1044                     x: _coords.x,
  1013                     y: _coords.y
  1045                     y: _coords.y
  1014                 }
  1046                 }
  1015             }, Rkns._RENDER_AND_SAVE);
  1047             };
       
  1048         var _node = this.renkan.project.addNode(_data);
       
  1049         this.renkan.selected_bin_item = null;
  1016         this.is_dragging = true;
  1050         this.is_dragging = true;
  1017         this.click_target = _node.__controller;
  1051         this.click_target = this.getRepresentationByModel(_node);
  1018     }
  1052     }
  1019 }
  1053 }