dummy edges are destroyed on cancel

bzr revid: fva@openerp.com-20120224130007-9cdj749bpfrdc0ix
This commit is contained in:
Frédéric van der Essen 2012-02-24 14:00:07 +01:00
parent 80f9259b1f
commit ca974ab6c2
2 changed files with 152 additions and 105 deletions

View File

@ -55,7 +55,7 @@ openerp.web.DiagramView = openerp.web.View.extend({
this.do_update_pager(); this.do_update_pager();
// New Node,Edge // New Node,Edge
this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_edit_node(null, self.node);}); this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_node();});
if(this.id) { if(this.id) {
self.get_diagram_info(); self.get_diagram_info();
@ -112,6 +112,7 @@ openerp.web.DiagramView = openerp.web.View.extend({
} }
}, },
// Set-up the drawing elements of the diagram
draw_diagram: function(result) { draw_diagram: function(result) {
var self = this; var self = this;
console.log(result); console.log(result);
@ -135,13 +136,12 @@ openerp.web.DiagramView = openerp.web.View.extend({
$('#dia-canvas *').remove(); // remove previous diagram $('#dia-canvas *').remove(); // remove previous diagram
var r = new Raphael(document.getElementById("dia-canvas"), '100%','100%'); var r = new Raphael(document.getElementById("dia-canvas"), '100%','100%');
$(r.node).css("border","none");
$(r.node).css("padding",0);
var graph = new CuteGraph(r,style); var graph = new CuteGraph(r,style);
_.each(res_nodes, function(node) { _.each(res_nodes, function(node) {
var n = new CuteNode( graph, var n = new CuteNode( graph,
node.x + 50, node.x + 50, //FIXME the +50 should be in the layout algorithm
node.y + 50, node.y + 50,
CuteGraph.wordwrap(node.name, 16), CuteGraph.wordwrap(node.name, 16),
node.shape === 'rectangle' ? 'rect' : 'circle', node.shape === 'rectangle' ? 'rect' : 'circle',
@ -159,114 +159,144 @@ openerp.web.DiagramView = openerp.web.View.extend({
}); });
CuteNode.double_click_callback = function(cutenode){ CuteNode.double_click_callback = function(cutenode){
self.add_edit_node( cutenode.id, self.node ); self.edit_node(cutenode.id);
} };
CuteEdge.double_click_callback = function(cuteedge){ CuteEdge.double_click_callback = function(cuteedge){
self.add_edit_node(cuteedge.id,self.connector); self.edit_connector(cuteedge.id);
} };
CuteEdge.creation_callback = function(node_start, node_end){ CuteEdge.creation_callback = function(node_start, node_end){
console.log("creating edge from:",node_start," to:",node_end); return {label:_t("new transition")};
self.add_edit_node(null, self.connector, { };
act_from: node_start.id, CuteEdge.new_edge_callback = function(cuteedge){
act_to: node_end.id, self.add_connector( cuteedge.get_start().id,
activity_from_id: node_start.id, cuteedge.get_end().id,
activity_to_id: node_end.id, cuteedge);
}); };
return {label:""}; // TODO destroy edge on cancel
}
}, },
add_edit_node: function(id, model, defaults) { // Creates a popup to edit the content of the node with id node_id
defaults = defaults || {}; edit_node: function(node_id){
var self = this; var self = this;
var title = _t('Activity');
var pop = new openerp.web.form.FormOpenPopup(self);
if(!model) pop.show_element(
model = self.node; self.node,
if(id) node_id,
id = parseInt(id, 10); self.context || self.dataset.context,
var pop,
title = model == self.node ? _t('Activity') : _t('Transition');
if(!id) {
pop = new openerp.web.form.SelectCreatePopup(this);
pop.select_element(
model,
{
title: _t("Create:") + title,
initial_view: 'form',
disable_multiple_selection: true
},
this.dataset.domain,
this.context || this.dataset.context
);
pop.on_select_elements.add_last(function(element_ids) {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
});
pop.$element.bind("dialogbeforeclose",function(){
console.log("HAHHAAH");
console.log(self.connectors.attrs);
});
} else {
pop = new openerp.web.form.FormOpenPopup(this);
pop.show_element(
model,
id,
this.context || this.dataset.context,
{ {
title: _t("Open: ") + title title: _t("Open: ") + title
} }
); );
pop.on_write.add(function() {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded); pop.on_write.add(function() {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
}); });
} var form_fields = [self.parent_field];
var form_controller = pop.view_form;
form_controller.on_record_loaded.add_first(function() {
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
field.$input.prop('disabled', true);
field.$drop_down.unbind();
field.$menu_btn.unbind();
});
});
},
// Creates a popup to add a node to the diagram
add_node: function(){
var self = this;
var title = _t('Activity');
var pop = new openerp.web.form.SelectCreatePopup(self);
pop.select_element(
self.node,
{
title: _t("Create:") + title,
initial_view: 'form',
disable_multiple_selection: true
},
self.dataset.domain,
self.context || self.dataset.context
);
pop.on_select_elements.add_last(function(element_ids) {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
});
var form_controller = pop.view_form;
var form_fields = [this.parent_field];
form_controller.on_record_loaded.add_last(function() {
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
field.set_value([self.id,self.active_model]);
field.dirty = true;
});
});
},
// Creates a popup to edit the connector of id connector_id
edit_connector: function(connector_id){
var self = this;
var title = _t('Transition');
var pop = new openerp.web.form.FormOpenPopup(self);
pop.show_element(
self.connector,
parseInt(connector_id,10), //FIXME Isn't connector_id supposed to be an int ?
self.context || self.dataset.context,
{
title: _t("Open: ") + title
}
);
pop.on_write.add(function() {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
});
},
// Creates a popup to add a connector from node_source_id to node_dest_id.
// dummy_cuteedge if not null, will be removed form the graph after the popup is closed.
add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
var self = this;
var title = _t('Transition');
var pop = new openerp.web.form.SelectCreatePopup(self);
pop.select_element(
self.connector,
{
title: _t("Create:") + title,
initial_view: 'form',
disable_multiple_selection: true
},
this.dataset.domain,
this.context || this.dataset.context
);
pop.on_select_elements.add_last(function(element_ids) {
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
});
// We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
// This is not a problem since the diagram is completely redrawn on saved changes.
pop.$element.bind("dialogbeforeclose",function(){
if(dummy_cuteedge){
dummy_cuteedge.remove();
}
});
var form_controller = pop.view_form; var form_controller = pop.view_form;
var form_fields; form_controller.on_record_loaded.add_last(function () {
form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
if (model === self.node) { form_controller.fields[self.connectors.attrs.source].dirty = true;
form_fields = [this.parent_field]; form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
if (!id) { form_controller.fields[self.connectors.attrs.destination].dirty = true;
form_controller.on_record_loaded.add_last(function() { });
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
field.set_value([self.id,self.active_model]);
field.dirty = true;
});
});
} else {
form_controller.on_record_loaded.add_first(function() {
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
field.$input.prop('disabled', true);
field.$drop_down.unbind();
field.$menu_btn.unbind();
});
});
}
} else {
form_fields = [
this.connectors.attrs.source,
this.connectors.attrs.destination];
}
if (!_.isEmpty(defaults)) {
form_controller.on_record_loaded.add_last(function () {
_(form_fields).each(function (field) {
if (!defaults[field]) { return; }
form_controller.fields[field].set_value(defaults[field]);
form_controller.fields[field].dirty = true;
});
});
}
}, },
on_pager_action: function(action) { on_pager_action: function(action) {

View File

@ -63,7 +63,8 @@
if(graph.target_node){ if(graph.target_node){
edge_prop = GraphEdge.creation_callback(node,graph.target_node); edge_prop = GraphEdge.creation_callback(node,graph.target_node);
if(edge_prop){ if(edge_prop){
new GraphEdge(graph,edge_prop.label, node,graph.target_node); var new_edge = new GraphEdge(graph,edge_prop.label, node,graph.target_node);
GraphEdge.new_edge_callback(new_edge);
} }
} }
} }
@ -172,7 +173,7 @@
var n2 = edge.get_end(); var n2 = edge.get_end();
links[n1.uid] = _.without(links[n1.uid],edge); links[n1.uid] = _.without(links[n1.uid],edge);
links[n2.uid] = _.without(links[n2.uid],edge); links[n2.uid] = _.without(links[n2.uid],edge);
graph[n1.uid][n2.uid] = _without(graph[n1.uid][n2.uid],edge); graph[n1.uid][n2.uid] = _.without(graph[n1.uid][n2.uid],edge);
} }
//return the list of edges from n1 to n2 //return the list of edges from n1 to n2
this.get_edge_list = function(n1,n2){ this.get_edge_list = function(n1,n2){
@ -293,7 +294,14 @@
node_label.transform(graph.get_transform()); node_label.transform(graph.get_transform());
$(node_label.node).css('text-shadow',"1px 2px 3px rgba(0,0,0,0.3)"); $(node_label.node).css('text-shadow',"1px 2px 3px rgba(0,0,0,0.3)");
// redraws all edges linked to this node
var update_linked_edges = function(){
var edges = graph.get_linked_edge_list(self);
for(var i = 0; i < edges.length; i++){
edges[i].update();
}
}
// sets the center position of the node // sets the center position of the node
var set_pos = function(pos){ var set_pos = function(pos){
if(type == 'circle'){ if(type == 'circle'){
@ -305,10 +313,7 @@
for(var i = 0; i < self.connectors.length; i++){ for(var i = 0; i < self.connectors.length; i++){
self.connectors[i].update_pos(); self.connectors[i].update_pos();
} }
var edges = graph.get_linked_edge_list(self); update_linked_edges();
for(var i = 0; i < edges.length; i++){
edges[i].update();
}
} }
// returns the figure used to draw the node // returns the figure used to draw the node
var get_fig = function(){ var get_fig = function(){
@ -372,6 +377,7 @@
this.get_fig = get_fig; this.get_fig = get_fig;
this.set_selected = set_selected; this.set_selected = set_selected;
this.set_not_selected = set_not_selected this.set_not_selected = set_not_selected
this.update_linked_edges = update_linked_edges;
//select the node and play an animation when clicked //select the node and play an animation when clicked
@ -594,18 +600,26 @@
edge_label.attr({'x':labelpos.x, 'y':labelpos.y - 14}); edge_label.attr({'x':labelpos.x, 'y':labelpos.y - 14});
} }
} }
//TODO remove from graph // removes the edge from the scene, disconnects it from linked
// nodes, destroy its drawable elements.
function remove(){ function remove(){
edge.remove(); edge.remove();
edge_label.remove(); edge_label.remove();
if(!tmp){ if(!tmp){
graph.remove_edge(self); graph.remove_edge(self);
} }
if(start.update_linked_edges){
start.update_linked_edges();
}
if(start != end && end.update_linked_edges){
end.update_linked_edges();
}
} }
function double_click(){ function double_click(){
GraphEdge.double_click_callback(self); GraphEdge.double_click_callback(self);
} }
edge.dblclick(double_click); edge.dblclick(double_click);
edge_label.dblclick(double_click); edge_label.dblclick(double_click);
@ -630,7 +644,10 @@
var edge_prop = {}; var edge_prop = {};
edge_prop.label = 'new edge!'; edge_prop.label = 'new edge!';
return edge_prop; return edge_prop;
} };
// This is is called after a new edge is created, with the new edge
// as parameter
GraphEdge.new_edge_callback = function(new_edge){};
// returns a new string with the same content as str, but with lines of maximum 'width' characters. // returns a new string with the same content as str, but with lines of maximum 'width' characters.
// lines are broken on words, or into words if a word is longer than 'width' // lines are broken on words, or into words if a word is longer than 'width'