~therp-nl/openerp-web/7.0-lp1013636-x2m_honour_required_attribute

« back to all changes in this revision

Viewing changes to addons/web_diagram/static/src/js/diagram.js

[MERGE] from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
        this.do_update_pager();
56
56
 
57
57
        // New Node,Edge
58
 
        this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_edit_node(null, self.node);});
 
58
        this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_node();});
59
59
 
60
60
        if(this.id) {
61
61
            self.get_diagram_info();
111
111
            this.get_diagram_info();
112
112
        }
113
113
    },
114
 
    select_node: function (node, element) {
115
 
        if (!this.selected_node) {
116
 
            this.selected_node = node;
117
 
            element.attr('stroke', 'red');
118
 
            return;
119
 
        }
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');
124
 
            return;
125
 
        }
126
 
        this.add_edit_node(null, this.connector, {
127
 
            act_from: this.selected_node.id,
128
 
            act_to: node.id
129
 
        });
130
 
    },
 
114
 
 
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();
134
 
 
135
 
        this.active_model = result['id_model'];
136
 
 
137
 
        var res_nodes = result['nodes'];
138
 
        var res_connectors = result['conn'];
 
117
        var self = this;
 
118
        var res_nodes  = result['nodes'];
 
119
        var res_edges  = result['conn'];
139
120
        this.parent_field = result.parent_field;
140
 
 
141
 
        //Custom logic
142
 
        var self = this;
143
 
        var renderer = function(r, n) {
144
 
            var shape = (n.node.shape === 'rectangle') ? 'rect' : 'ellipse';
145
 
 
146
 
            var node = r[shape](n.node.x, n.node.y).attr({
147
 
                "fill": n.node.color
148
 
            });
149
 
 
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);
154
 
                })
155
 
                .mousedown(function () { node.moved = false; })
156
 
                .mousemove(function () { node.moved = true; })
157
 
                .click(function () {
158
 
                    // Ignore click from move event
159
 
                    if (node.moved) { return; }
160
 
                    self.select_node(n.node, node);
161
 
                });
162
 
 
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});
166
 
            } else {
167
 
                node.attr({rx: "40", ry: "20"});
168
 
            }
169
 
 
170
 
            return nodes;
171
 
        };
172
 
 
173
 
        _.each(res_nodes, function(res_node) {
174
 
            diagram.addNode(res_node['name'],{node: res_node,render: renderer});
175
 
        });
176
 
 
177
 
        // Id for Path(Edges)
178
 
        var edge_ids = [];
179
 
 
180
 
        _.each(res_connectors, function(connector, index) {
181
 
            edge_ids.push(index);
182
 
            diagram.addEdge(connector['source'], connector['destination'], {directed : true, label: connector['signal']});
183
 
        });
184
 
 
185
 
        self.$element.find('.diagram').empty();
186
 
 
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());
189
 
 
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);
194
 
                });
195
 
            }
196
 
        });
 
121
        this.$element.find('h3.oe_diagram_title').text(result.name);
 
122
 
 
123
        var id_to_node = {};
 
124
 
 
125
 
 
126
        var style = {
 
127
            edge_color: "#A0A0A0",
 
128
            edge_label_color: "#555",
 
129
            edge_label_font_size: 10,
 
130
            edge_width: 2,
 
131
            edge_spacing: 100,
 
132
            edge_loop_radius: 100,
 
133
 
 
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,
 
140
            node_size_x: 110,
 
141
            node_size_y: 80,
 
142
            connector_active_color: "#FFF",
 
143
            connector_radius: 4,
 
144
            
 
145
            close_button_radius: 8,
 
146
            close_button_color: "#333",
 
147
            close_button_x_color: "#FFF",
 
148
 
 
149
            gray: "#DCDCDC",
 
150
            white: "#FFF",
 
151
            
 
152
            viewport_margin: 50
 
153
        };
 
154
 
 
155
        // remove previous diagram
 
156
        var canvas = self.$element.find('div.oe_diagram_diagram')
 
157
                             .empty().get(0);
 
158
 
 
159
        var r  = new Raphael(canvas, '100%','100%');
 
160
 
 
161
        var graph  = new CuteGraph(r,style,canvas.parentNode);
 
162
        
 
163
        var confirm_dialog = $('#dialog').dialog({ 
 
164
            autoOpen: false,
 
165
            title: _t("Are you sure?") });
 
166
        
 
167
 
 
168
        _.each(res_nodes, function(node) {
 
169
            var n = new CuteNode(
 
170
                graph,
 
171
                node.x + 50,  //FIXME the +50 should be in the layout algorithm
 
172
                node.y + 50,
 
173
                CuteGraph.wordwrap(node.name, 14),
 
174
                node.shape === 'rectangle' ? 'rect' : 'circle',
 
175
                node.color === 'white' ? style.white : style.gray);
 
176
 
 
177
            n.id = node.id;
 
178
            id_to_node[node.id] = n;
 
179
        });
 
180
 
 
181
        _.each(res_edges, function(edge) {
 
182
            var e =  new CuteEdge(
 
183
                graph,
 
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
 
187
            e.id = edge.id;
 
188
        });
 
189
 
 
190
        CuteNode.double_click_callback = function(cutenode){
 
191
            self.edit_node(cutenode.id);
 
192
        };
 
193
        var i = 0;
 
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();
 
197
            }
 
198
            return new openerp.web.DataSet(self,self.node).unlink([cutenode.id]);
 
199
        };
 
200
        CuteEdge.double_click_callback = function(cuteedge){
 
201
            self.edit_connector(cuteedge.id);
 
202
        };
 
203
 
 
204
        CuteEdge.creation_callback = function(node_start, node_end){
 
205
            return {label:_t("")};
 
206
        };
 
207
        CuteEdge.new_edge_callback = function(cuteedge){
 
208
            self.add_connector(cuteedge.get_start().id,
 
209
                               cuteedge.get_end().id,
 
210
                               cuteedge);
 
211
        };
 
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();
 
215
            }
 
216
            return new openerp.web.DataSet(self,self.connector).unlink([cuteedge.id]);
 
217
        };
 
218
 
197
219
    },
198
220
 
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){
201
223
        var self = this;
 
224
        var title = _t('Activity');
 
225
        var pop = new openerp.web.form.FormOpenPopup(self);
202
226
 
203
 
        if(!model)
204
 
            model = self.node;
205
 
        if(id)
206
 
            id = parseInt(id, 10);
207
 
        
208
 
        var pop,
209
 
            title = model == self.node ? _t('Activity') : _t('Transition');
210
 
        if(!id) {
211
 
            pop = new openerp.web.form.SelectCreatePopup(this);
212
 
            pop.select_element(
213
 
                model,
214
 
                {
215
 
                    title: _t("Create:") + title,
216
 
                    initial_view: 'form',
217
 
                    disable_multiple_selection: true
218
 
                },
219
 
                this.dataset.domain,
220
 
                this.context || this.dataset.context
221
 
            );
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);
224
 
            });
225
 
        } else {
226
 
            pop = new openerp.web.form.FormOpenPopup(this);
227
 
            pop.show_element(
228
 
                model,
229
 
                id,
230
 
                this.context || this.dataset.context,
 
227
        pop.show_element(
 
228
                self.node,
 
229
                node_id,
 
230
                self.context || self.dataset.context,
231
231
                {
232
232
                    title: _t("Open: ") + title
233
233
                }
234
234
            );
235
 
            pop.on_write.add(function() {
236
 
                self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
237
 
            });
238
 
        }
239
 
 
240
 
        var form_controller = pop.view_form;
241
 
 
242
 
        var form_fields;
243
 
 
244
 
        if (model === self.node) {
245
 
            form_fields = [this.parent_field];
246
 
            if (!id) {
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]);
252
 
                        field.dirty = true;
253
 
                    });
254
 
                });
255
 
            } else {
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();
263
 
                    });
264
 
                });
265
 
            }
266
 
        } else {
267
 
            form_fields = [
268
 
                this.connectors.attrs.source,
269
 
                this.connectors.attrs.destination];
270
 
        }
271
 
 
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;
278
 
                });
279
 
            });
280
 
        }
281
 
        
282
 
        
 
235
 
 
236
        pop.on_write.add(function() {
 
237
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
 
238
            });
 
239
 
 
240
        var form_fields = [self.parent_field];
 
241
        var form_controller = pop.view_form;
 
242
 
 
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();
 
250
            });
 
251
        });
 
252
    },
 
253
 
 
254
    // Creates a popup to add a node to the diagram
 
255
    add_node: function(){
 
256
        var self = this;
 
257
        var title = _t('Activity');
 
258
        var pop = new openerp.web.form.SelectCreatePopup(self);
 
259
        pop.select_element(
 
260
            self.node,
 
261
            {
 
262
                title: _t("Create:") + title,
 
263
                initial_view: 'form',
 
264
                disable_multiple_selection: true
 
265
            },
 
266
            self.dataset.domain,
 
267
            self.context || self.dataset.context
 
268
        );
 
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);
 
271
        });
 
272
 
 
273
        var form_controller = pop.view_form;
 
274
        var form_fields = [this.parent_field];
 
275
 
 
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);
 
281
                field.dirty = true;
 
282
            });
 
283
        });
 
284
    },
 
285
 
 
286
    // Creates a popup to edit the connector of id connector_id
 
287
    edit_connector: function(connector_id){
 
288
        var self = this;
 
289
        var title = _t('Transition');
 
290
        var pop = new openerp.web.form.FormOpenPopup(self);
 
291
        pop.show_element(
 
292
            self.connector,
 
293
            parseInt(connector_id,10),      //FIXME Isn't connector_id supposed to be an int ?
 
294
            self.context || self.dataset.context,
 
295
            {
 
296
                title: _t("Open: ") + title
 
297
            }
 
298
        );
 
299
        pop.on_write.add(function() {
 
300
            self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
 
301
        });
 
302
    },
 
303
 
 
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){
 
307
        var self = this;
 
308
        var title = _t('Transition');
 
309
        var pop = new openerp.web.form.SelectCreatePopup(self);
 
310
 
 
311
        pop.select_element(
 
312
            self.connector,
 
313
            {
 
314
                title: _t("Create:") + title,
 
315
                initial_view: 'form',
 
316
                disable_multiple_selection: true
 
317
            },
 
318
            this.dataset.domain,
 
319
            this.context || this.dataset.context
 
320
        );
 
321
 
 
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);
 
324
        });
 
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(){
 
328
            if(dummy_cuteedge){
 
329
                dummy_cuteedge.remove();
 
330
            }
 
331
        });
 
332
 
 
333
        var form_controller = pop.view_form;
 
334
 
 
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;
 
340
        });
283
341
    },
284
342
 
285
343
    on_pager_action: function(action) {
297
355
                this.dataset.index = this.dataset.ids.length - 1;
298
356
                break;
299
357
        }
300
 
        this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_diagram_loaded);
 
358
        var loaded = this.dataset.read_index(_.keys(this.fields_view.fields))
 
359
                .pipe(this.on_diagram_loaded);
301
360
        this.do_update_pager();
 
361
        return loaded;
302
362
    },
303
363
 
304
364
    do_update_pager: function(hide_index) {
313
373
 
314
374
    do_show: function() {
315
375
        this.do_push_state({});
316
 
        return this._super();
 
376
        return $.when(this._super(), this.on_pager_action('reload'));
317
377
    }
318
378
});
319
379
};