1 /*---------------------------------------------------------
2 * OpenERP diagram library
3 *---------------------------------------------------------*/
5 openerp.web_diagram = function (openerp) {
6 var QWeb = openerp.web.qweb,
9 openerp.web.views.add('diagram', 'openerp.web.DiagramView');
10 openerp.web.DiagramView = openerp.web.View.extend({
11 display_name: _lt('Diagram'),
13 init: function(parent, dataset, view_id, options) {
15 this.set_default_options(options);
16 this.view_manager = parent;
17 this.dataset = dataset;
18 this.model = this.dataset.model;
19 this.view_id = view_id;
20 this.domain = this.dataset._domain || [];
22 this.ids = this.dataset.ids;
26 return this.rpc("/web_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
29 toTitleCase: function(str) {
30 return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
33 on_loaded: function(result) {
36 if(this.ids && this.ids.length) {
37 this.id = this.ids[self.dataset.index || 0];
40 this.fields_view = result.fields_view,
41 this.view_id = this.fields_view.view_id,
42 this.fields = this.fields_view.fields,
43 this.nodes = this.fields_view.arch.children[0],
44 this.connectors = this.fields_view.arch.children[1],
45 this.node = this.nodes.attrs.object,
46 this.connector = this.connectors.attrs.object;
48 this.$element.html(QWeb.render("DiagramView", this));
50 this.$element.find('div.oe_diagram_pager button[data-pager-action]').click(function() {
51 var action = $(this).data('pager-action');
52 self.on_pager_action(action);
55 this.do_update_pager();
58 this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_node();});
61 self.get_diagram_info();
66 get_diagram_info: function() {
72 'connector': this.connector,
73 'bgcolor': this.nodes.attrs.bgcolor,
74 'shape': this.nodes.attrs.shape,
75 'src_node': this.connectors.attrs.source,
76 'des_node': this.connectors.attrs.destination,
77 'label': this.connectors.attrs.label || false,
79 'invisible_nodes': [],
82 'connectors_fields': []
85 _.each(this.nodes.children, function(child) {
86 if(child.attrs.invisible == '1')
87 params['invisible_nodes'].push(child.attrs.name);
89 params['visible_nodes'].push(child.attrs.name);
90 params['node_fields'].push(self.fields[child.attrs.name]['string']|| this.toTitleCase(child.attrs.name));
94 _.each(this.connectors.children, function(conn) {
95 params['connectors_fields'].push(self.fields[conn.attrs.name]['string']|| this.toTitleCase(conn.attrs.name));
96 params['connectors'].push(conn.attrs.name);
100 '/web_diagram/diagram/get_diagram_info',params,
102 self.draw_diagram(result);
107 on_diagram_loaded: function(record) {
108 var id_record = record['id'];
111 this.get_diagram_info();
115 // Set-up the drawing elements of the diagram
116 draw_diagram: function(result) {
118 var res_nodes = result['nodes'];
119 var res_edges = result['conn'];
120 this.parent_field = result.parent_field;
125 var style = { "edge_color" : "#A0A0A0",
126 "edge_label_color" : "#555",
127 "edge_label_font_size" : 10,
129 "edge_spacing" : 100,
130 "edge_loop_radius" : 100,
132 "node_label_color" : "#333",
133 "node_label_font_size" : 12,
134 "node_outline_color" : "#333",
135 "node_outline_width" : 1,
136 "node_selected_color" : "#0097BE",
137 "node_selected_width" : 2,
140 "connector_active_color" : "#FFF",
141 "connector_radius" : 4,
147 $('#dia-canvas').empty(); // remove previous diagram
149 var r = new Raphael(document.getElementById("dia-canvas"), '100%','100%');
151 var graph = new CuteGraph(r,style);
153 _.each(res_nodes, function(node) {
154 var n = new CuteNode( graph,
155 node.x + 50, //FIXME the +50 should be in the layout algorithm
157 CuteGraph.wordwrap(node.name, 14),
158 node.shape === 'rectangle' ? 'rect' : 'circle',
159 node.color === 'white' ? style.white : style.gray );
161 id_to_node[node.id] = n;
164 _.each(res_edges, function(edge) {
165 var e = new CuteEdge( graph,
166 CuteGraph.wordwrap(edge.signal, 32),
167 id_to_node[edge.s_id],
168 id_to_node[edge.d_id] || id_to_node[edge.s_id] ); //WORKAROUND
172 CuteNode.double_click_callback = function(cutenode){
173 self.edit_node(cutenode.id);
176 CuteEdge.double_click_callback = function(cuteedge){
177 self.edit_connector(cuteedge.id);
180 CuteEdge.creation_callback = function(node_start, node_end){
181 return {label:_t("")};
183 CuteEdge.new_edge_callback = function(cuteedge){
184 self.add_connector( cuteedge.get_start().id,
185 cuteedge.get_end().id,
191 // Creates a popup to edit the content of the node with id node_id
192 edit_node: function(node_id){
194 var title = _t('Activity');
195 var pop = new openerp.web.form.FormOpenPopup(self);
200 self.context || self.dataset.context,
202 title: _t("Open: ") + title
206 pop.on_write.add(function() {
207 self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
210 var form_fields = [self.parent_field];
211 var form_controller = pop.view_form;
213 form_controller.on_record_loaded.add_first(function() {
214 _.each(form_fields, function(fld) {
215 if (!(fld in form_controller.fields)) { return; }
216 var field = form_controller.fields[fld];
217 field.$input.prop('disabled', true);
218 field.$drop_down.unbind();
219 field.$menu_btn.unbind();
224 // Creates a popup to add a node to the diagram
225 add_node: function(){
227 var title = _t('Activity');
228 var pop = new openerp.web.form.SelectCreatePopup(self);
232 title: _t("Create:") + title,
233 initial_view: 'form',
234 disable_multiple_selection: true
237 self.context || self.dataset.context
239 pop.on_select_elements.add_last(function(element_ids) {
240 self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
243 var form_controller = pop.view_form;
244 var form_fields = [this.parent_field];
246 form_controller.on_record_loaded.add_last(function() {
247 _.each(form_fields, function(fld) {
248 if (!(fld in form_controller.fields)) { return; }
249 var field = form_controller.fields[fld];
250 field.set_value(self.id);
256 // Creates a popup to edit the connector of id connector_id
257 edit_connector: function(connector_id){
259 var title = _t('Transition');
260 var pop = new openerp.web.form.FormOpenPopup(self);
263 parseInt(connector_id,10), //FIXME Isn't connector_id supposed to be an int ?
264 self.context || self.dataset.context,
266 title: _t("Open: ") + title
269 pop.on_write.add(function() {
270 self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
274 // Creates a popup to add a connector from node_source_id to node_dest_id.
275 // dummy_cuteedge if not null, will be removed form the graph after the popup is closed.
276 add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
278 var title = _t('Transition');
279 var pop = new openerp.web.form.SelectCreatePopup(self);
284 title: _t("Create:") + title,
285 initial_view: 'form',
286 disable_multiple_selection: true
289 this.context || this.dataset.context
292 pop.on_select_elements.add_last(function(element_ids) {
293 self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_diagram_loaded);
295 // We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
296 // This is not a problem since the diagram is completely redrawn on saved changes.
297 pop.$element.bind("dialogbeforeclose",function(){
299 dummy_cuteedge.remove();
303 var form_controller = pop.view_form;
305 form_controller.on_record_loaded.add_last(function () {
306 form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
307 form_controller.fields[self.connectors.attrs.source].dirty = true;
308 form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
309 form_controller.fields[self.connectors.attrs.destination].dirty = true;
313 on_pager_action: function(action) {
316 this.dataset.index = 0;
319 this.dataset.previous();
325 this.dataset.index = this.dataset.ids.length - 1;
328 this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_diagram_loaded);
329 this.do_update_pager();
332 do_update_pager: function(hide_index) {
333 var $pager = this.$element.find('div.oe_diagram_pager');
334 var index = hide_index ? '-' : this.dataset.index + 1;
335 if(!this.dataset.count) {
336 this.dataset.count = this.dataset.ids.length;
338 $pager.find('span.oe_pager_index').html(index);
339 $pager.find('span.oe_pager_count').html(this.dataset.count);
342 do_show: function() {
343 this.do_push_state({});
344 return this._super();
349 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: