111
111
this.get_diagram_info();
114
select_node: function (node, element) {
115
if (!this.selected_node) {
116
this.selected_node = node;
117
element.attr('stroke', 'red');
120
// Re-click selected node, deselect it
121
if (node.id === this.selected_node.id) {
122
this.selected_node = null;
123
element.attr('stroke', 'black');
126
this.add_edit_node(null, this.connector, {
127
act_from: this.selected_node.id,
115
// Set-up the drawing elements of the diagram
131
116
draw_diagram: function(result) {
132
this.selected_node = null;
133
var diagram = new Graph();
135
this.active_model = result['id_model'];
137
var res_nodes = result['nodes'];
138
var res_connectors = result['conn'];
118
var res_nodes = result['nodes'];
119
var res_edges = result['conn'];
139
120
this.parent_field = result.parent_field;
143
var renderer = function(r, n) {
144
var shape = (n.node.shape === 'rectangle') ? 'rect' : 'ellipse';
146
var node = r[shape](n.node.x, n.node.y).attr({
150
var nodes = r.set(node, r.text(n.node.x, n.node.y, (n.label || n.id)))
151
.attr("cursor", "pointer")
152
.dblclick(function() {
153
self.add_edit_node(n.node.id, self.node);
155
.mousedown(function () { node.moved = false; })
156
.mousemove(function () { node.moved = true; })
158
// Ignore click from move event
159
if (node.moved) { return; }
160
self.select_node(n.node, node);
163
if (shape === 'rect') {
164
node.attr({width: "60", height: "44"});
165
node.next.attr({"text-anchor": "middle", x: n.node.x + 20, y: n.node.y + 20});
167
node.attr({rx: "40", ry: "20"});
173
_.each(res_nodes, function(res_node) {
174
diagram.addNode(res_node['name'],{node: res_node,render: renderer});
177
// Id for Path(Edges)
180
_.each(res_connectors, function(connector, index) {
181
edge_ids.push(index);
182
diagram.addEdge(connector['source'], connector['destination'], {directed : true, label: connector['signal']});
185
self.$element.find('.diagram').empty();
187
var layouter = new Graph.Layout.Ordered(diagram);
188
var render_diagram = new Graph.Renderer.Raphael('dia-canvas', diagram, $('div#dia-canvas').width(), $('div#dia-canvas').height());
190
_.each(diagram.edges, function(edge, index) {
191
if(edge.connection) {
192
edge.connection.fg.attr({cursor: "pointer"}).dblclick(function() {
193
self.add_edit_node(edge_ids[index], self.connector);
121
this.$element.find('h3.oe_diagram_title').text(result.name);
127
edge_color: "#A0A0A0",
128
edge_label_color: "#555",
129
edge_label_font_size: 10,
132
edge_loop_radius: 100,
134
node_label_color: "#333",
135
node_label_font_size: 12,
136
node_outline_color: "#333",
137
node_outline_width: 1,
138
node_selected_color: "#0097BE",
139
node_selected_width: 2,
142
connector_active_color: "#FFF",
145
close_button_radius: 8,
146
close_button_color: "#333",
147
close_button_x_color: "#FFF",
155
// remove previous diagram
156
var canvas = self.$element.find('div.oe_diagram_diagram')
159
var r = new Raphael(canvas, '100%','100%');
161
var graph = new CuteGraph(r,style,canvas.parentNode);
163
var confirm_dialog = $('#dialog').dialog({
165
title: _t("Are you sure?") });
168
_.each(res_nodes, function(node) {
169
var n = new CuteNode(
171
node.x + 50, //FIXME the +50 should be in the layout algorithm
173
CuteGraph.wordwrap(node.name, 14),
174
node.shape === 'rectangle' ? 'rect' : 'circle',
175
node.color === 'white' ? style.white : style.gray);
178
id_to_node[node.id] = n;
181
_.each(res_edges, function(edge) {
182
var e = new CuteEdge(
184
CuteGraph.wordwrap(edge.signal, 32),
185
id_to_node[edge.s_id],
186
id_to_node[edge.d_id] || id_to_node[edge.s_id] ); //WORKAROUND
190
CuteNode.double_click_callback = function(cutenode){
191
self.edit_node(cutenode.id);
194
CuteNode.destruction_callback = function(cutenode){
195
if(!confirm(_t("Deleting this node cannot be undone.\nIt will also delete all connected transitions.\n\nAre you sure ?"))){
196
return $.Deferred().reject().promise();
198
return new openerp.web.DataSet(self,self.node).unlink([cutenode.id]);
200
CuteEdge.double_click_callback = function(cuteedge){
201
self.edit_connector(cuteedge.id);
204
CuteEdge.creation_callback = function(node_start, node_end){
205
return {label:_t("")};
207
CuteEdge.new_edge_callback = function(cuteedge){
208
self.add_connector(cuteedge.get_start().id,
209
cuteedge.get_end().id,
212
CuteEdge.destruction_callback = function(cuteedge){
213
if(!confirm(_t("Deleting this transition cannot be undone.\n\nAre you sure ?"))){
214
return $.Deferred().reject().promise();
216
return new openerp.web.DataSet(self,self.connector).unlink([cuteedge.id]);
199
add_edit_node: function(id, model, defaults) {
200
defaults = defaults || {};
221
// Creates a popup to edit the content of the node with id node_id
222
edit_node: function(node_id){
224
var title = _t('Activity');
225
var pop = new openerp.web.form.FormOpenPopup(self);
206
id = parseInt(id, 10);
209
title = model == self.node ? _t('Activity') : _t('Transition');
211
pop = new openerp.web.form.SelectCreatePopup(this);
215
title: _t("Create:") + title,
216
initial_view: 'form',
217
disable_multiple_selection: true
220
this.context || this.dataset.context
222
pop.on_select_elements.add_last(function(element_ids) {
223
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
226
pop = new openerp.web.form.FormOpenPopup(this);
230
this.context || this.dataset.context,
230
self.context || self.dataset.context,
232
232
title: _t("Open: ") + title
235
pop.on_write.add(function() {
236
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
240
var form_controller = pop.view_form;
244
if (model === self.node) {
245
form_fields = [this.parent_field];
247
form_controller.on_record_loaded.add_last(function() {
248
_.each(form_fields, function(fld) {
249
if (!(fld in form_controller.fields)) { return; }
250
var field = form_controller.fields[fld];
251
field.set_value([self.id,self.active_model]);
256
form_controller.on_record_loaded.add_first(function() {
257
_.each(form_fields, function(fld) {
258
if (!(fld in form_controller.fields)) { return; }
259
var field = form_controller.fields[fld];
260
field.$input.prop('disabled', true);
261
field.$drop_down.unbind();
262
field.$menu_btn.unbind();
268
this.connectors.attrs.source,
269
this.connectors.attrs.destination];
272
if (!_.isEmpty(defaults)) {
273
form_controller.on_record_loaded.add_last(function () {
274
_(form_fields).each(function (field) {
275
if (!defaults[field]) { return; }
276
form_controller.fields[field].set_value(defaults[field]);
277
form_controller.fields[field].dirty = true;
236
pop.on_write.add(function() {
237
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
240
var form_fields = [self.parent_field];
241
var form_controller = pop.view_form;
243
form_controller.on_record_loaded.add_first(function() {
244
_.each(form_fields, function(fld) {
245
if (!(fld in form_controller.fields)) { return; }
246
var field = form_controller.fields[fld];
247
field.$input.prop('disabled', true);
248
field.$drop_down.unbind();
249
field.$menu_btn.unbind();
254
// Creates a popup to add a node to the diagram
255
add_node: function(){
257
var title = _t('Activity');
258
var pop = new openerp.web.form.SelectCreatePopup(self);
262
title: _t("Create:") + title,
263
initial_view: 'form',
264
disable_multiple_selection: true
267
self.context || self.dataset.context
269
pop.on_select_elements.add_last(function(element_ids) {
270
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
273
var form_controller = pop.view_form;
274
var form_fields = [this.parent_field];
276
form_controller.on_record_loaded.add_last(function() {
277
_.each(form_fields, function(fld) {
278
if (!(fld in form_controller.fields)) { return; }
279
var field = form_controller.fields[fld];
280
field.set_value(self.id);
286
// Creates a popup to edit the connector of id connector_id
287
edit_connector: function(connector_id){
289
var title = _t('Transition');
290
var pop = new openerp.web.form.FormOpenPopup(self);
293
parseInt(connector_id,10), //FIXME Isn't connector_id supposed to be an int ?
294
self.context || self.dataset.context,
296
title: _t("Open: ") + title
299
pop.on_write.add(function() {
300
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
304
// Creates a popup to add a connector from node_source_id to node_dest_id.
305
// dummy_cuteedge if not null, will be removed form the graph after the popup is closed.
306
add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
308
var title = _t('Transition');
309
var pop = new openerp.web.form.SelectCreatePopup(self);
314
title: _t("Create:") + title,
315
initial_view: 'form',
316
disable_multiple_selection: true
319
this.context || this.dataset.context
322
pop.on_select_elements.add_last(function(element_ids) {
323
self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
325
// We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
326
// This is not a problem since the diagram is completely redrawn on saved changes.
327
pop.$element.bind("dialogbeforeclose",function(){
329
dummy_cuteedge.remove();
333
var form_controller = pop.view_form;
335
form_controller.on_record_loaded.add_last(function () {
336
form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
337
form_controller.fields[self.connectors.attrs.source].dirty = true;
338
form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
339
form_controller.fields[self.connectors.attrs.destination].dirty = true;
285
343
on_pager_action: function(action) {