ruote-kit 2.2.0.3 → 2.3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/CHANGELOG.txt +28 -1
  2. data/CREDITS.txt +8 -2
  3. data/LICENSE.txt +1 -1
  4. data/Rakefile +21 -9
  5. data/lib/ruote-kit.rb +13 -4
  6. data/lib/ruote-kit/core_ext.rb +15 -0
  7. data/lib/ruote-kit/helpers/json_helpers.rb +22 -7
  8. data/lib/ruote-kit/helpers/link_helpers.rb +9 -7
  9. data/lib/ruote-kit/helpers/pagination_helpers.rb +1 -2
  10. data/lib/ruote-kit/helpers/render_helpers.rb +1 -1
  11. data/lib/ruote-kit/public/_ruote/images/favicon.png +0 -0
  12. data/lib/ruote-kit/public/_ruote/images/{ruote_buttons.png → ruote-buttons.png} +0 -0
  13. data/lib/ruote-kit/public/_ruote/images/ruote.png +0 -0
  14. data/lib/ruote-kit/public/_ruote/javascripts/foolbox-all.min.js +3 -0
  15. data/lib/ruote-kit/public/_ruote/javascripts/jquery-1.9.1.min.js +5 -0
  16. data/lib/ruote-kit/public/_ruote/javascripts/rk.js +68 -17
  17. data/lib/ruote-kit/public/_ruote/javascripts/ruote-fluo-all.min.js +3 -0
  18. data/lib/ruote-kit/public/_ruote/stylesheets/rk.css +82 -12
  19. data/lib/ruote-kit/public/_ruote/stylesheets/ruote-buttons.png +0 -0
  20. data/lib/ruote-kit/public/_ruote/stylesheets/ruote-fluo-editor.css +9 -6
  21. data/lib/ruote-kit/public/_ruote/stylesheets/ruote-fluo.css +62 -0
  22. data/lib/ruote-kit/resources/errors.rb +8 -3
  23. data/lib/ruote-kit/resources/expressions.rb +38 -35
  24. data/lib/ruote-kit/resources/participants.rb +1 -1
  25. data/lib/ruote-kit/resources/processes.rb +61 -4
  26. data/lib/ruote-kit/resources/workitems.rb +4 -4
  27. data/lib/ruote-kit/version.rb +1 -1
  28. data/lib/ruote-kit/views/_pagination.html.haml +2 -2
  29. data/lib/ruote-kit/views/_tree_editor.html.haml +63 -30
  30. data/lib/ruote-kit/views/error.html.haml +50 -9
  31. data/lib/ruote-kit/views/errors.html.haml +1 -1
  32. data/lib/ruote-kit/views/expression.html.haml +83 -33
  33. data/lib/ruote-kit/views/expressions.html.haml +23 -8
  34. data/lib/ruote-kit/views/http_error.html.haml +9 -2
  35. data/lib/ruote-kit/views/layout.html.haml +14 -13
  36. data/lib/ruote-kit/views/process.html.haml +75 -20
  37. data/lib/ruote-kit/views/processes.html.haml +9 -3
  38. data/lib/ruote-kit/views/processes_new.html.haml +19 -2
  39. data/lib/ruote-kit/views/schedules.html.haml +2 -2
  40. data/lib/ruote-kit/views/workitem.html.haml +17 -6
  41. data/ruote-kit.gemspec +9 -7
  42. data/spec/cases/orphan_workitem_spec.rb +141 -0
  43. data/spec/core_ext_spec.rb +19 -0
  44. data/spec/resources/errors_spec.rb +182 -156
  45. data/spec/resources/expressions_spec.rb +497 -379
  46. data/spec/resources/index_spec.rb +5 -5
  47. data/spec/resources/participants_spec.rb +64 -75
  48. data/spec/resources/processes_spec.rb +396 -277
  49. data/spec/resources/schedules_spec.rb +92 -76
  50. data/spec/resources/workitems_spec.rb +352 -343
  51. data/spec/ruote-kit_configure_spec.rb +41 -13
  52. data/spec/spec_helper.rb +6 -8
  53. data/spec/support/link_helper.rb +11 -0
  54. data/spec/webapp_helpers_spec.rb +29 -23
  55. metadata +161 -180
  56. data/README.rdoc +0 -313
  57. data/lib/ruote-kit/public/_ruote/images/favicon.ico +0 -0
  58. data/lib/ruote-kit/public/_ruote/javascripts/jquery-1.4.2.min.js +0 -154
  59. data/lib/ruote-kit/public/_ruote/javascripts/ruote-fluo-editor.js +0 -548
  60. data/lib/ruote-kit/public/_ruote/javascripts/ruote-fluo.js +0 -1118
@@ -1,1118 +0,0 @@
1
-
2
- /*
3
- * Ruote - open source ruby workflow engine
4
- * (c) 2005-2010 jmettraux@gmail.com
5
- *
6
- * Ruote is freely distributable under the terms of the MIT license.
7
- * For details, see the ruote web site: http://ruote.rubyforge.org
8
- *
9
- * Made in Japan
10
- *
11
- * John Mettraux
12
- * Juan-Pedro Paredes
13
- */
14
-
15
- //function dinspect (o) {
16
- // var s = "[\n";
17
- // for (var k in o) {
18
- // s += ("" + k + ": " + o[k]);
19
- // s += ",\n";
20
- // }
21
- // s += "]";
22
- // return s;
23
- //}
24
-
25
- var FluoConstants = {
26
-
27
- WHITE: 'rgb(255, 255, 255)',
28
- HIGHLIGHT: 'rgb(220, 220, 220)',
29
- LINE_HEIGHT: 20,
30
- MIN_ACTIVITY_WIDTH: 110,
31
- FONT: '12px Helvetica Neue'
32
- }
33
-
34
- var FluoCanvas = function () {
35
-
36
- //
37
- // draws centered text
38
- //
39
- function drawText (c, text, bwidth, bheight, symbolFuncName) {
40
-
41
- var SW = 17; // symbol width
42
-
43
- c.save();
44
-
45
- if (c.canvas.horizontal == true) {
46
- c.translate(bwidth/2, bheight/2);
47
- c.rotate(Math.PI/2);
48
- }
49
- var w1 = c.measure(text);
50
- var w0 = 0;
51
- if (symbolFuncName) w0 = SW;
52
- var w = w0 + w1;
53
- c.translate(-(w/2), 17);
54
- if (symbolFuncName) {
55
- c.translate(0, -4);
56
- FluoCanvas[symbolFuncName](c, SW);
57
- c.translate(0, 4);
58
- }
59
- c.translate(w0, 0);
60
- c.write(text);
61
- c.translate(+(w/2-w0), -17);
62
-
63
- c.restore();
64
- }
65
-
66
- function drawArrow (c, length) {
67
- var w = 3;
68
- c.beginPath();
69
- c.moveTo(0, 0);
70
- c.lineTo(0, length);
71
- c.stroke();
72
- c.beginPath();
73
- c.moveTo(0, length);
74
- c.lineTo(-w, length-w*2);
75
- c.lineTo(w, length-w*2);
76
- c.lineTo(0, length);
77
- c.fill();
78
- }
79
-
80
- function drawVerticalLine (c, x, height) {
81
- c.beginPath();
82
- c.moveTo(x, 0);
83
- c.lineTo(x, height);
84
- c.stroke();
85
- }
86
-
87
- function drawRoundedRect (c, width, height, radius) {
88
- var w2 = width / 2;
89
- c.beginPath();
90
- c.moveTo(0, 0);
91
- c.lineTo(w2 - radius, 0);
92
- c.quadraticCurveTo(w2, 0, w2, radius);
93
- c.lineTo(w2, height - radius);
94
- c.quadraticCurveTo(w2, height, w2 - radius, height);
95
- c.lineTo(-w2 + radius, height);
96
- c.quadraticCurveTo(-w2, height, -w2, height - radius);
97
- c.lineTo(-w2, radius);
98
- c.quadraticCurveTo(-w2, 0, -w2 + radius, 0);
99
- c.lineTo(0, 0);
100
- c.stroke();
101
- }
102
-
103
- function drawQuadraticPath (c, x, y, radius) {
104
- var xradius = radius;
105
- if (x < 0) xradius = -radius;
106
- var yradius = radius;
107
- if (y < 0) yradius = -radius;
108
- c.beginPath();
109
- c.moveTo(0, 0);
110
- c.lineTo(x - xradius, 0);
111
- c.quadraticCurveTo(x, 0, x, yradius);
112
- c.lineTo(x, y);
113
- c.stroke();
114
- }
115
-
116
- function drawDiamond (c, height) {
117
- var h = height / 2;
118
- for (var i = 0; i < 2; i++) {
119
- c.beginPath();
120
- c.moveTo(0, 0);
121
- c.lineTo(h, h);
122
- c.lineTo(0, height);
123
- c.lineTo(-h, h);
124
- c.lineTo(0, 0);
125
- if (i == 0) {
126
- c.save();
127
- c.fillStyle = FluoConstants.WHITE;
128
- c.fill();
129
- c.restore();
130
- }
131
- else {
132
- c.stroke();
133
- }
134
- }
135
- }
136
-
137
- function drawThickCircle (c, height) {
138
- c.save();
139
- c.beginPath();
140
- c.lineWidth = 1.4;
141
- c.fillStyle = FluoConstants.WHITE;
142
- c.arc(0, 0, height / 2 - 1, 0, Math.PI * 2, true);
143
- c.arc(0, 0, height / 2 - 2.3, 0, Math.PI * 2, true);
144
- c.stroke();
145
- c.restore();
146
- }
147
-
148
- function drawDoubleCircle (c, height, arrow) {
149
- c.save();
150
- c.beginPath();
151
- c.lineWidth = 0.5;
152
- c.fillStyle = FluoConstants.WHITE;
153
- c.arc(0, 0, height / 2, 0, Math.PI * 2, true);
154
- c.arc(0, 0, height / 2 - 2.3, 0, Math.PI * 2, true);
155
- c.stroke();
156
- c.restore();
157
- if (arrow) {
158
- c.save();
159
- c.translate(height/2, 0);
160
- c.rotate(-Math.PI/2);
161
- drawArrow(c, 8);
162
- c.restore();
163
- }
164
- }
165
-
166
- function drawError (c, height, sym) { // the flash
167
- if (sym) drawThickCircle(c, height);
168
- else drawDoubleCircle(c, height, true);
169
- var h = height / 2 * 0.8;
170
- var o = Math.cos(Math.PI / 4) * h;
171
- var h2 = h / 2 * 0.5;
172
- var d = h2 * 0.7;
173
- c.beginPath();
174
- c.moveTo(o, -o);
175
- c.lineTo(h2 + d, h2 + d);
176
- c.lineTo(-h2, -h2 + d);
177
- c.lineTo(-o, o);
178
- c.lineTo(-h2 - d, -h2 - d);
179
- c.lineTo(h2, h2 - d);
180
- c.lineTo(o, -o);
181
- c.fill();
182
- }
183
- function drawErrorSymbol (c, height) {
184
- drawError(c, height, true);
185
- }
186
-
187
- function drawCancel (c, height) { // the 'dame'
188
- drawDoubleCircle(c, height, true);
189
- var h = height / 5;
190
- c.beginPath();
191
- c.lineWidth = 2;
192
- c.moveTo(h, h);
193
- c.lineTo(-h, -h);
194
- c.moveTo(-h, h);
195
- c.lineTo(h, -h);
196
- c.stroke();
197
- }
198
-
199
- function pointOnCircle (angle, radius) {
200
- return [ Math.cos(angle) * radius, Math.sin(angle) * radius ];
201
- }
202
- function lineInCircle (c, angle, farRadius, closeRadius) {
203
- var far = pointOnCircle(angle, farRadius);
204
- var close = pointOnCircle(angle, closeRadius);
205
- c.moveTo(far[0], far[1]); c.lineTo(close[0], close[1]);
206
- }
207
-
208
- function drawWaitSymbol (c, height) { // the 'clock'
209
- drawDoubleCircle(c, height, false);
210
- c.save();
211
- c.beginPath();
212
- c.lineWidth = 0.5;
213
- var radius = height / 2 - 4.3;
214
- c.arc(0, 0, radius, 0, Math.PI * 2, true);
215
- for (var i = 0; i < 12; i++) {
216
- lineInCircle(c, Math.PI / 6 * i, radius, radius - 2);
217
- }
218
- lineInCircle(c, Math.PI / 6 * 9.5, radius - 1, 0); // minutes
219
- lineInCircle(c, Math.PI / 6 * 0, radius - 3, 0); // hours
220
- c.stroke();
221
- c.restore();
222
- }
223
-
224
- function drawParaDiamond (c, height) {
225
- drawDiamond(c, height);
226
- c.save();
227
- c.lineWidth = 2.5;
228
- var l = height / 4;
229
- c.beginPath();
230
- c.moveTo(0, l); c.lineTo(0, l * 3);
231
- c.moveTo(-l, l * 2); c.lineTo(l, l * 2);
232
- c.stroke();
233
- c.restore();
234
- }
235
-
236
- function drawCrossInABox (c, h) {
237
- c.save();
238
- c.beginPath();
239
- c.moveTo(-6, h);
240
- c.lineTo(-6, h - 12);
241
- c.lineTo(6, h - 12);
242
- c.lineTo(6, h);
243
- c.moveTo(0, h - 10);
244
- c.lineTo(0, h - 2);
245
- c.moveTo(-4, h - 6);
246
- c.lineTo(4, h - 6);
247
- c.stroke();
248
- c.restore();
249
- }
250
-
251
- function drawLoopSymbol (c, h) {
252
- var r = 5;
253
- c.save();
254
- c.lineWidth = 0.9;
255
- c.translate(0, h - r - 4);
256
- c.beginPath();
257
- var a = Math.PI / 2;
258
- c.arc(0, 0, r, a - 0.5, a, true);
259
- var l = r * 0.8;
260
- c.moveTo(0, r + 1);
261
- c.lineTo(-l, r + 1);
262
- c.moveTo(0, r + 1);
263
- c.lineTo(0, r - l);
264
- c.stroke();
265
- c.restore();
266
- }
267
-
268
- function drawParaSymbol (c, h) {
269
- c.save();
270
- c.translate(0, h - 10);
271
- c.lineWidth = 1.5;
272
- c.beginPath();
273
- c.moveTo(-2, 0); c.lineTo(-2, 8);
274
- c.moveTo(2, 0); c.lineTo(2, 8);
275
- c.stroke();
276
- c.restore();
277
- }
278
-
279
- return {
280
- drawText: drawText,
281
- drawArrow: drawArrow,
282
- drawVerticalLine: drawVerticalLine,
283
- drawRoundedRect: drawRoundedRect,
284
- drawQuadraticPath: drawQuadraticPath,
285
- drawDiamond: drawDiamond,
286
- drawParaDiamond: drawParaDiamond,
287
- drawError: drawError,
288
- drawCancel: drawCancel,
289
- drawCrossInABox: drawCrossInABox,
290
- drawLoopSymbol: drawLoopSymbol,
291
- drawParaSymbol: drawParaSymbol,
292
- draw_error_symbol: drawErrorSymbol,
293
- draw_sleep_symbol: drawWaitSymbol,
294
- draw_wait_symbol: drawWaitSymbol
295
- };
296
- }();
297
-
298
- var Fluo = function () {
299
-
300
- //
301
- // MISC METHODS
302
-
303
- function childrenMax (c, exp, funcname) {
304
- var children = getChildren(c, exp);
305
- var max = 0;
306
- for (var i = 0; i < children.length; i++) {
307
- var val = Fluo[funcname](c, children[i]);
308
- if (val > max) max = val;
309
- }
310
- return max;
311
- }
312
-
313
- function childrenSum (c, exp, funcname) {
314
- var children = getChildren(c, exp);
315
- var sum = 0;
316
- for (var i = 0; i < children.length; i++) {
317
- sum += Fluo[funcname](c, children[i]);
318
- }
319
- return sum;
320
- }
321
-
322
- function attributeMaxWidth (c, exp, title) {
323
- var max = 0;
324
- if (title) max = c.measure(title);
325
- for (var attname in exp[1]) {
326
- var text = '' + attname + ': ' + JSON.stringify(exp[1][attname]);
327
- var l = c.measure(text);
328
- //if (attname.match(/^on[-\_](error|cancel)$/)) l += 30;
329
- if (l > max) max = l;
330
- }
331
- return max;
332
- }
333
-
334
- // returns the list of attribute names (sorted)
335
- //
336
- function attributeNames (exp) {
337
- var an = [];
338
- for (var k in exp[1]) { an.push(k); }
339
- return an.sort();
340
- }
341
-
342
- function attributeCount (exp) {
343
- //var l = attributeNames(exp).length;
344
- //var ct = strchild && childText(exp);
345
- //return l + (ct ? 1 : 0);
346
- return attributeNames(exp).length;
347
- }
348
-
349
- function carriageReturn (c) {
350
- if (c.canvas.horizontal == true) {
351
- c.translate(-FluoConstants.LINE_HEIGHT, 0);
352
- }
353
- else c.translate(0, FluoConstants.LINE_HEIGHT);
354
- }
355
-
356
- function drawAttributes (c, exp, expname, namePlus, width, height) {
357
-
358
- if (expname) {
359
- FluoCanvas.drawText(c, exp[0], width, height);
360
- carriageReturn(c);
361
- }
362
-
363
- var attname;
364
- var attnames = attributeNames(exp, expname);
365
-
366
- while (attname = attnames.shift()) {
367
-
368
- var v = JSON.stringify(exp[1][attname]);
369
-
370
- if (attname.match(/^on[-\_]error$/)) {
371
- FluoCanvas.drawText(c, v, width, height, 'drawError');
372
- carriageReturn(c);
373
- }
374
- else if (attname.match(/^on[-\_]cancel$/)) {
375
- FluoCanvas.drawText(c, v, width, height, 'drawCancel');
376
- carriageReturn(c);
377
- }
378
- else {
379
- var t = attname;
380
- if (v != 'null') t = t + ': ' + v;
381
- FluoCanvas.drawText(c, t, width, height);
382
- carriageReturn(c);
383
- }
384
- }
385
- }
386
-
387
- //
388
- // the methods (and fields) shared by all handler are here
389
- //
390
- var Handler = {};
391
- Handler.getHeight = function (c, exp) {
392
- if (c.canvas.horizontal == true) return this.getRealWidth(c, exp);
393
- return this.getRealHeight(c, exp);
394
- };
395
- Handler.getWidth = function (c, exp) {
396
- if (c.canvas.horizontal == true) return this.getRealHeight(c, exp);
397
- return this.getRealWidth(c, exp);
398
- };
399
-
400
- //
401
- // creates a new Handler (a copy of Handler), if the parentHandler is
402
- // given, will spawn a copy of it instead of a copy of Handler.
403
- // (dead simple inheritance).
404
- //
405
- function newHandler (parentHandler) {
406
- if ( ! parentHandler) parentHandler = Handler;
407
- var result = {};
408
- for (var k in parentHandler) result[k] = parentHandler[k];
409
- for (var k in parentHandler) result['super_'+k] = parentHandler[k];
410
- return result;
411
- }
412
-
413
- function getChildren (c, exp) {
414
- var cs = exp[2];
415
- if ( ! c.canvas.hideMinor) return cs;
416
- if (exp.majorChildren) return exp.majorChildren;
417
- var r = [];
418
- for (var i = 0; i < cs.length; i++) {
419
- var c = cs[i];
420
- if (MINORS.indexOf(c[0]) < 0) r.push(c);
421
- }
422
- exp.majorChildren = r; // caching the result
423
- return r;
424
- }
425
-
426
- //
427
- // EXPRESSION HANDLERS
428
-
429
- var GenericHandler = newHandler();
430
- GenericHandler.adjust = function (exp) {
431
- //var ct = childText(exp);
432
- //if (ct) exp[0] = exp[0] + ' ' + ct;
433
- }
434
- GenericHandler.render = function (c, exp) {
435
- var width = this.getWidth(c, exp);
436
- var height = this.getHeight(c, exp);
437
- FluoCanvas.drawRoundedRect(c, width, height, 8);
438
- c.save();
439
- drawAttributes(c, exp, true, false, width, height);
440
- c.restore();
441
- };
442
- GenericHandler.getRealHeight = function (c, exp) {
443
- return 7 + (1 + attributeCount(exp)) * FluoConstants.LINE_HEIGHT;
444
- };
445
- GenericHandler.getRealWidth = function (c, exp) {
446
- return Math.max(10 + attributeMaxWidth(c, exp, exp[0]), FluoConstants.MIN_ACTIVITY_WIDTH);
447
- };
448
-
449
- var AttributeOnlyHandler = newHandler();
450
- AttributeOnlyHandler.adjust = function (exp) {
451
- //var ct = childText(exp);
452
- //if (ct) exp[0] = exp[0] + ' ' + ct;
453
- }
454
- AttributeOnlyHandler.render = function (c, exp) {
455
- var width = this.getWidth(c, exp);
456
- var height = this.getHeight(c, exp);
457
- c.save();
458
- drawAttributes(c, exp, false, false, width, height);
459
- c.restore();
460
- };
461
- AttributeOnlyHandler.getRealHeight = function (c, exp) {
462
- return 7 + attributeCount(exp) * FluoConstants.LINE_HEIGHT;
463
- };
464
- AttributeOnlyHandler.getRealWidth = function (c, exp) {
465
- return attributeMaxWidth(c, exp, exp[0]);
466
- };
467
-
468
- var SubprocessHandler = newHandler(GenericHandler);
469
- SubprocessHandler.adjust = function (exp) {
470
- if (exp[2].length == 1) exp[1]['ref'] = exp[2][0];
471
- }
472
- SubprocessHandler.render = function (c, exp) {
473
- var width = this.getWidth(c, exp);
474
- var height = this.getHeight(c, exp);
475
- FluoCanvas.drawRoundedRect(c, width, height, 8);
476
- c.save();
477
- drawAttributes(c, exp, true, false, width, height);
478
- c.restore();
479
- FluoCanvas.drawCrossInABox(c, height);
480
- };
481
- SubprocessHandler.getRealHeight = function (c, exp) {
482
- return 12 + 7 + (1 + attributeCount(exp)) * FluoConstants.LINE_HEIGHT;
483
- };
484
-
485
-
486
- // TODO : fix rotated mode
487
- //
488
- var GenericWithChildrenHandler = newHandler();
489
- GenericWithChildrenHandler.render = function (c, exp) {
490
- var width = this.getWidth(c, exp);
491
- var height = this.getHeight(c, exp);
492
- var attWidth = attributeMaxWidth(c, exp, exp[0]) + 7;
493
- var attHeight = attributeCount(exp) * FluoConstants.LINE_HEIGHT;
494
- var children = getChildren(c, exp);
495
- if (c.canvas.horizontal == true) {
496
- var w = attWidth;
497
- attWidth = attHeight;
498
- attHeight = w;
499
- }
500
- if ((c.canvas.noOuterBorder != true) || (exp.expid != "0")) {
501
- FluoCanvas.drawRoundedRect(c, width, height, 8);
502
- }
503
- c.save();
504
- c.translate(-width/2 + attWidth/2 + 5 , 7);
505
- if (c.canvas.horizontal == true) c.translate(attHeight/2, 0);
506
- drawAttributes(c, exp, true, false, attWidth, attHeight);
507
- c.restore();
508
- c.save();
509
- c.translate(width/2 - childrenMax(c, exp, 'getWidth')/2 - 7, 8);
510
- for (var i = 0; i < children.length; i++) {
511
- var child = children[i];
512
- renderExp(c, child);
513
- c.translate(0, Fluo.getHeight(c, child));
514
- if (this.drawArrow && i < children.length -1) FluoCanvas.drawArrow(c, 10);
515
- c.translate(0, 10);
516
- }
517
- c.restore();
518
- };
519
- GenericWithChildrenHandler.drawArrow = false;
520
- GenericWithChildrenHandler.getHeight = function (c, exp) {
521
- var rightHeight =
522
- (getChildren(c, exp).length + 1) * 9 + childrenSum(c, exp, 'getHeight');
523
- var leftHeight =
524
- GenericHandler.getHeight(c, exp);
525
- return (rightHeight > leftHeight) ? rightHeight : leftHeight;
526
- };
527
- GenericWithChildrenHandler.getWidth = function (c, exp) {
528
- return(
529
- attributeMaxWidth(c, exp, exp[0]) +
530
- 28 +
531
- childrenMax(c, exp, 'getWidth'));
532
- };
533
-
534
- var LoopHandler = newHandler(GenericWithChildrenHandler);
535
- LoopHandler.drawArrow = true;
536
- LoopHandler.render = function (c, exp) {
537
- this.super_render(c, exp);
538
- FluoCanvas.drawLoopSymbol(c, this.getHeight(c, exp));
539
- }
540
- LoopHandler.getHeight = function (c, exp) {
541
- return 12 + this.super_getHeight(c, exp);
542
- }
543
-
544
- var ConcurrentIteratorHandler = newHandler(GenericWithChildrenHandler);
545
- ConcurrentIteratorHandler.render = function (c, exp) {
546
- this.super_render(c, exp);
547
- FluoCanvas.drawParaSymbol(c, this.getHeight(c, exp));
548
- }
549
- ConcurrentIteratorHandler.getHeight = function (c, exp) {
550
- return 12 + this.super_getHeight(c, exp);
551
- }
552
-
553
-
554
- // TODO : fix in rotated mode
555
- //
556
- var TextHandler = newHandler();
557
- TextHandler.render = function (c, exp) {
558
- var h = getHeight(c, exp);
559
- var w = getWidth(c, exp);
560
- FluoCanvas.drawText(c, this.getText(exp), h, w);
561
- };
562
- TextHandler.getText = function (exp) {
563
- var t = exp[0];
564
- //var ct = childText(exp); if (ct) t += (' ' + ct);
565
- for (var attname in exp[1]) {
566
- var v = exp[1][attname];
567
- t += (' ' + attname + ': "' + v + '"');
568
- }
569
- return t;
570
- };
571
- TextHandler.getRealHeight = function (c, exp) {
572
- return FluoConstants.LINE_HEIGHT;
573
- };
574
- TextHandler.getRealWidth = function (c, exp) {
575
- return c.measure(this.getText(exp));
576
- };
577
-
578
- // TODO : fix rotated mode
579
- //
580
- var SymbolHandler = newHandler();
581
- SymbolHandler.SYMBOL_HEIGHT = 22;
582
- SymbolHandler.render = function (c, exp) {
583
- var w = this.getWidth(c, exp);
584
- var h = this.getHeight(c, exp);
585
- c.save();
586
- if (c.canvas.horizontal == true) {
587
- c.translate(w/2, h/2);
588
- c.rotate(-Math.PI/2);
589
- }
590
- c.translate(0, 12);
591
- FluoCanvas['draw_'+exp[0]+'_symbol'](c, SymbolHandler.SYMBOL_HEIGHT);
592
- c.translate(0, 12);
593
- drawAttributes(c, exp, false, true, this.getWidth(c, exp), this.getHeight(c, exp));
594
- c.restore();
595
- };
596
- SymbolHandler.getRealHeight = function (c, exp) {
597
- return attributeCount(exp) * FluoConstants.LINE_HEIGHT + SymbolHandler.SYMBOL_HEIGHT;
598
- };
599
- SymbolHandler.getRealWidth = function (c, exp) {
600
- return attributeMaxWidth(c, exp, exp[0]);
601
- };
602
-
603
- var StringHandler = newHandler(TextHandler);
604
- StringHandler.getText = function (exp) {
605
- return exp;
606
- };
607
-
608
- var VerticalHandler = newHandler();
609
- VerticalHandler.adjust = function (exp) {
610
- //if (attributeCount(exp) > 0) exp[2].unshift([ '_atts_', exp[1], [] ]);
611
- }
612
- VerticalHandler.render = function (c, exp) {
613
- c.save();
614
- var children = getChildren(c, exp);
615
- for (var i = 0; i < children.length; i++) {
616
- var child = children[i];
617
- renderExp(c, child);
618
- c.translate(0, Fluo.getHeight(c, child));
619
- if (i < children.length - 1) {
620
- FluoCanvas.drawArrow(c, 14);
621
- c.translate(0, 14);
622
- }
623
- }
624
- c.restore();
625
- };
626
- VerticalHandler.getHeight = function (c, exp) {
627
- return (getChildren(c, exp).length - 1) * 14 + childrenSum(c, exp, 'getHeight');
628
- };
629
- VerticalHandler.getWidth = function (c, exp) {
630
- return childrenMax(c, exp, 'getWidth');
631
- };
632
-
633
- var HorizontalHandler = newHandler();
634
- HorizontalHandler.render = function (c, exp) {
635
- var children = getChildren(c, exp);
636
- var dist = this.computeDistribution(c, exp);
637
- var childrenHeight = this.getChildrenHeight(c, exp);
638
- this.renderHeader(c, exp, dist);
639
- c.save();
640
- c.translate(0, this.getHeaderHeight(c, exp));
641
- for (var i=0; i < children.length; i++) {
642
- var child = children[i];
643
- c.save();
644
- c.translate(dist[i], 0);
645
- this.renderChild(c, child, childrenHeight);
646
- c.restore();
647
- }
648
- c.restore();
649
- this.renderFooter(c, exp, dist, childrenHeight);
650
- };
651
- HorizontalHandler.getHeaderHeight = function (c, exp) {
652
- if (c.canvas.horizontal == true) return 23 + attributeMaxWidth(c, exp);
653
- return 23 + attributeCount(exp) * FluoConstants.LINE_HEIGHT;
654
- };
655
- HorizontalHandler.getChildrenHeight = function (c, exp) {
656
- return childrenMax(c, exp, 'getHeight');
657
- };
658
- HorizontalHandler.getHeight = function (c, exp) {
659
- return this.getHeaderHeight(c, exp) + this.getChildrenHeight(c, exp) + 10;
660
- };
661
- HorizontalHandler.getWidth = function (c, exp) {
662
- return (getChildren(c, exp).length - 1) * 3 + childrenSum(c, exp, 'getWidth');
663
- //return Math.max(
664
- // attributeMaxWidth(c, exp),
665
- // (getChildren(c, exp).length - 1) * 3 + childrenSum(c, exp, 'getWidth'));
666
- };
667
- HorizontalHandler.computeDistribution = function (c, exp) {
668
- var children = getChildren(c, exp);
669
- var totalWidth = this.getWidth(c, exp);
670
- var offset = -totalWidth/2;
671
- var dist = new Array(children.length);
672
- for (var i = 0; i < children.length; i++) {
673
- var cWidth = Fluo.getWidth(c, children[i]);
674
- dist[i] = offset + cWidth / 2;
675
- offset += (cWidth + 3);
676
- }
677
- return dist;
678
- };
679
- HorizontalHandler.renderHeader = function (c, exp, distribution) {
680
- var hheight = this.getHeaderHeight(c, exp) - 10;
681
- c.save();
682
- c.translate(0, 10);
683
- FluoCanvas.drawQuadraticPath(
684
- c, distribution[0], hheight, 8);
685
- FluoCanvas.drawQuadraticPath(
686
- c, distribution[distribution.length-1], hheight, 8);
687
- for (var i = 1; i < distribution.length - 1; i++) {
688
- FluoCanvas.drawVerticalLine(c, distribution[i], hheight);
689
- }
690
- c.restore();
691
- this.renderHeaderSymbol(c);
692
- this.renderHeaderLabel(c, exp);
693
- };
694
- HorizontalHandler.renderHeaderSymbol = function (c) {
695
- FluoCanvas.drawDiamond(c, FluoConstants.LINE_HEIGHT);
696
- };
697
- HorizontalHandler.renderHeaderLabel = function (c, exp) {
698
- var width = attributeMaxWidth(c, exp);
699
- var height = attributeCount(exp) * FluoConstants.LINE_HEIGHT;
700
- if (c.canvas.horizontal == true) {
701
- var w = width;
702
- width = height;
703
- height = w;
704
- }
705
- c.save();
706
- c.translate(0, FluoConstants.LINE_HEIGHT);
707
- c.save();
708
- c.fillStyle = FluoConstants.WHITE;
709
- c.fillRect(-width/2, 0, width, height);
710
- c.restore();
711
- drawAttributes(c, exp, false, false, width, height);
712
- c.restore();
713
- };
714
- HorizontalHandler.renderChild = function (c, exp, childrenHeight) {
715
- var cheight = Fluo.getHeight(c, exp);
716
- renderExp(c, exp);
717
- c.beginPath();
718
- c.moveTo(0, cheight); c.lineTo(0, childrenHeight);
719
- c.stroke();
720
- };
721
- HorizontalHandler.renderFooter = function (c, exp, distribution) {
722
- var childrenHeight = this.getChildrenHeight(c, exp);
723
- c.save();
724
- c.translate(
725
- 0, this.getHeaderHeight(c, exp) + this.getChildrenHeight(c, exp) + 10);
726
- if (distribution.length == 1) {
727
- FluoCanvas.drawVerticalLine(c, distribution[0], -10);
728
- }
729
- else {
730
- FluoCanvas.drawQuadraticPath(
731
- c, distribution[0], -10, 8);
732
- FluoCanvas.drawQuadraticPath(
733
- c, distribution[distribution.length-1], -10, 8);
734
- for (var i = 1; i < distribution.length - 1; i++) {
735
- FluoCanvas.drawVerticalLine(c, distribution[i], -10);
736
- }
737
- }
738
- c.restore();
739
- };
740
- HorizontalHandler.renderFooterDiamond = function (c) {
741
- };
742
-
743
- var ConcurrenceHandler = newHandler(HorizontalHandler);
744
- ConcurrenceHandler.renderHeaderSymbol = function (c) {
745
- FluoCanvas.drawParaDiamond(c, 20);
746
- };
747
-
748
- function hasNoCondition (attributes) {
749
- if (attributes['test']) return false;
750
- if (attributes['not']) return false;
751
- for (k in attributes) {
752
- if (attributes[k] == null) return false;
753
- }
754
- return true;
755
- }
756
-
757
- var IfHandler = newHandler(HorizontalHandler);
758
- IfHandler.adjust = function (exp) {
759
- //
760
- // all the crazy legwork to adapt to the 'if' expression
761
- //
762
- if (hasNoCondition(exp[1])) {
763
- // ok, steal first exp
764
- var cond = exp[2].shift();
765
- if (cond) {
766
- exp[1] = cond[1];
767
- exp[1]['condition'] = cond[0];
768
- }
769
- }
770
- for (var i = 0; i < 2 - exp[2].length; i++) exp[2].push([ '_', {}, [] ]);
771
- // adding ghost expressions
772
- };
773
-
774
- //
775
- // used for empty else clause
776
- //
777
- var GhostHandler = newHandler();
778
- GhostHandler.render = function (c, exp) {
779
- };
780
- GhostHandler.getHeight = function (c, exp) {
781
- return 0;
782
- };
783
- GhostHandler.getWidth = function (c, exp) {
784
- return 35;
785
- };
786
-
787
- var HANDLERS = {
788
-
789
- //'participant': ParticipantHandler
790
-
791
- 'sequence': VerticalHandler,
792
- 'concurrence': ConcurrenceHandler,
793
- 'if': IfHandler,
794
- 'set': TextHandler,
795
- 'unset': TextHandler,
796
- 'sleep': SymbolHandler,
797
- 'wait': SymbolHandler,
798
- 'error': SymbolHandler,
799
- 'subprocess': SubprocessHandler,
800
- 'loop': LoopHandler,
801
- 'repeat': LoopHandler,
802
- 'cursor': LoopHandler,
803
- 'concurrent-iterator': ConcurrentIteratorHandler,
804
-
805
- 'rewind': TextHandler,
806
- 'continue': TextHandler,
807
- 'back': TextHandler,
808
- 'break': TextHandler,
809
- 'stop': TextHandler,
810
- 'cancel': TextHandler,
811
- 'skip': TextHandler,
812
- 'jump': TextHandler,
813
- // 'commands'
814
-
815
- //'_atts_': AttributeOnlyHandler,
816
- '_': GhostHandler
817
- };
818
-
819
- var MINORS = [ 'set', 'set-fields', 'unset', 'description' ];
820
-
821
- var DEFINERS = [ 'process-definition', 'workflow-definition', 'define' ];
822
-
823
- function identifyExpressions (exp, expid) {
824
- if (exp.expid) return; // identify only once
825
- if ( ! expid) expid = '0';
826
- exp.expid = expid;
827
- if ((typeof exp) == 'string') return;
828
- for (var i = 0; i < exp[2].length; i++) {
829
- identifyExpressions(exp[2][i], expid + '_' + i);
830
- }
831
- }
832
-
833
- function setOption (context, options, optname, defval) {
834
- var v = options[optname];
835
- if (v) {
836
- context.canvas[optname] = v;
837
- }
838
- else if (optname in options) { // v is null
839
- context.canvas[optname] = null;
840
- }
841
- else if (defval && ! (context.canvas[optname])) {
842
- context.canvas[optname] = defval;
843
- }
844
- }
845
-
846
- function renderFlow (context, flow, options) {
847
-
848
- if ( ! options) options = {};
849
-
850
- identifyExpressions(flow);
851
-
852
- context = resolveContext(context);
853
- neutralizeContext(context);
854
-
855
- context.canvas.flow = flow;
856
-
857
- setOption(context, options, 'workitems', []);
858
- setOption(context, options, 'highlight');
859
- setOption(context, options, 'hideMinor');
860
- setOption(context, options, 'horizontal');
861
-
862
- context.save();
863
-
864
- if (context.canvas.horizontal == true) {
865
- context.translate(0, flow.width + 2);
866
- context.rotate(-Math.PI/2);
867
- }
868
-
869
- context.mozTextStyle = FluoConstants.FONT;
870
- context.font = FluoConstants.FONT;
871
-
872
- var fs = context.fillStyle;
873
- context.fillStyle = FluoConstants.WHITE;
874
- context.fillRect(0, 0, context.canvas.width, context.canvas.height);
875
- context.fillStyle = fs;
876
-
877
- var w = getWidth(context, flow);
878
- context.translate(w/2 + 1, 1); // aligning left
879
-
880
- renderExp(context, flow);
881
-
882
- context.restore();
883
-
884
- getWidth(context, flow);
885
- getHeight(context, flow);
886
- }
887
-
888
- function highlight (c, highlight) {
889
- canvas = resolveCanvas(c);
890
- renderFlow(canvas, canvas.flow, { 'highlight': highlight });
891
- }
892
-
893
- function drawWorkitem (c, exp) {
894
- var ww = c.measure('wi');
895
- c.save();
896
- if (c.canvas.horizontal == true) {
897
- c.rotate(Math.PI/2);
898
- c.translate(5, -14);
899
- }
900
- else {
901
- c.translate(49, 2);
902
- }
903
- c.fillStyle = '#F4D850';
904
- c.moveTo(0, 0);
905
- c.beginPath();
906
- c.arc(0, 0, 10, Math.PI, 0, false);
907
- c.lineTo(0, 20);
908
- c.lineTo(-10, 0);
909
- c.fill();
910
- c.fillStyle = 'black';
911
- c.moveTo(0, 0);
912
- c.beginPath();
913
- c.arc(0, 0, 10, Math.PI, 0, false);
914
- c.lineTo(0, 20);
915
- c.lineTo(-10, 0);
916
- c.stroke();
917
- c.translate(-ww/2, 3);
918
- c.write('wi');
919
- c.restore();
920
- }
921
-
922
- function renderExp (c, exp) {
923
-
924
- var handler = getHandler(c, exp);
925
-
926
- if (handler.adjust && ! exp.adjusted) {
927
- handler.adjust(exp);
928
- exp.adjusted = true;
929
- }
930
-
931
- if (c.canvas.highlight && exp.expid == c.canvas.highlight) { // highlight
932
- var w = getWidth(c, exp);
933
- var h = getHeight(c, exp);
934
- var t = 7;
935
- c.save();
936
- c.fillStyle = FluoConstants.HIGHLIGHT;
937
- c.fillRect(-w/2, 0, w, h);
938
- c.fillStyle = FluoConstants.WHITE;
939
- c.fillRect(-w/2 + t, 0 + t , w - 2 * t, h - 2 * t);
940
- c.restore();
941
- }
942
-
943
- handler.render(c, exp);
944
-
945
- if (c.canvas.workitems.indexOf(exp.expid) > -1) { // workitem
946
- drawWorkitem(c, exp);
947
- }
948
- }
949
-
950
- /*
951
- function clear (c) {
952
- c = resolveContext(c);
953
- c.clearRect(0, 0, c.canvas.width, c.canvas.height);
954
- }
955
- */
956
-
957
- function resolveCanvas (c) {
958
- if (c.getContext != null) return c;
959
- if (c.canvas != null) return c.canvas;
960
- return document.getElementById(c);
961
- }
962
-
963
- function resolveContext (c) {
964
- if (c.translate != null) return c;
965
- return resolveCanvas(c).getContext('2d');
966
- }
967
-
968
- // replaces the canvas element with a new, cropped, one
969
- //
970
- function crop (canvas) {
971
-
972
- canvas = resolveCanvas(canvas);
973
- var nc = document.createElement("canvas");
974
-
975
- nc.id = canvas.id;
976
-
977
- var w = canvas.flow.width + 2;
978
- var h = canvas.flow.height + 2;
979
-
980
- if (canvas.horizontal == true) {
981
- var x = w; w = h; h = x;
982
- }
983
-
984
- nc.setAttribute('width', w);
985
- nc.setAttribute('height', h);
986
-
987
- nc.hideMinor = canvas.hideMinor;
988
- nc.horizontal = canvas.horizontal;
989
- nc.workitems = canvas.workitems;
990
- nc.noOuterBorder = canvas.noOuterBorder;
991
-
992
- renderFlow(nc, canvas.flow);
993
- canvas.parentNode.replaceChild(nc, canvas);
994
- }
995
-
996
- // For example :
997
- //
998
- // Fluo.resize('fluo', 0.5)
999
- //
1000
- function resize (canvas, factor) {
1001
-
1002
- canvas = resolveCanvas(canvas);
1003
- var w = canvas.width;
1004
- var h = canvas.height;
1005
- canvas.style.width = '' + (w * factor) + 'px';
1006
- canvas.style.height = '' + (h * factor) + 'px';
1007
- }
1008
-
1009
- // For example :
1010
- //
1011
- // Fluo.resizeForMaxWidth('fluo', 200)
1012
- //
1013
- function resizeForMaxWidth (canvas, maxWidth) {
1014
-
1015
- canvas = resolveCanvas(canvas);
1016
- var w = canvas.width;
1017
-
1018
- if (w < maxWidth) return;
1019
-
1020
- resize(canvas, maxWidth / w);
1021
- }
1022
-
1023
- function neutralizeContext (c) {
1024
- if (window.navigator.userAgent.match(/Firefox/)) {
1025
- c.write = function (t) {
1026
- this.mozDrawText(t);
1027
- }
1028
- c.measure = function (t) {
1029
- return this.mozMeasureText(t);
1030
- }
1031
- }
1032
- else { // Safari 4
1033
- c.write = function (t) {
1034
- this.fillText(t, 0, 0);
1035
- }
1036
- c.measure = function (t) {
1037
- return this.measureText(t).width;
1038
- return t.length * 5;
1039
- }
1040
- }
1041
- }
1042
-
1043
- function isSubprocessName (exp, name) {
1044
- if ((typeof exp) == 'string') return false;
1045
- if (DEFINERS.indexOf(exp[0]) > -1 && exp[1]['name'] == name) return true;
1046
- for (var i = 0; i < exp[2].length; i++) {
1047
- if (isSubprocessName(exp[2][i], name)) return true;
1048
- }
1049
- return false;
1050
- }
1051
-
1052
- // returns the raw height of an expression (caches it too)
1053
- //
1054
- function getHeight (c, exp) {
1055
- if ((typeof exp) == 'string') return getHandler(c, exp).getHeight(c, exp);
1056
- if (exp.height) return exp.height;
1057
- var h = getHandler(c, exp);
1058
- if (h.adjust && ! exp.adjusted) { h.adjust(exp); exp.adjusted = true; }
1059
- exp.height = h.getHeight(c, exp);
1060
- return exp.height;
1061
- }
1062
-
1063
- // return the raw width of an expression
1064
- //
1065
- function getWidth (c, exp) {
1066
- if ((typeof exp) == 'string') return getHandler(c, exp).getWidth(c, exp);
1067
- if (exp.width) return exp.width;
1068
- var h = getHandler(c, exp);
1069
- if (h.adjust && ! exp.adjusted) { h.adjust(exp); exp.adjusted = true; }
1070
- exp.width = h.getWidth(c, exp);
1071
- return exp.width;
1072
- }
1073
-
1074
- function getHandler (c, exp) {
1075
- if ((typeof exp) == 'string') return StringHandler;
1076
- var h = HANDLERS[exp[0]];
1077
- if (h) return h;
1078
- //if (childText(exp)) return GenericHandler;
1079
- if (exp[2].length > 0) return GenericWithChildrenHandler;
1080
- if (isSubprocessName(c.canvas.flow, exp[0])) return SubprocessHandler;
1081
- return GenericHandler;
1082
- }
1083
-
1084
- function clearDimCache (exp) {
1085
- if ((typeof exp) == 'string') return;
1086
- exp.width = null;
1087
- exp.height = null;
1088
- for (var i = 0; i < exp[2].length; i++) clearDimCache(exp[2][i]);
1089
- }
1090
-
1091
- function toggleMinor (canvas) {
1092
- canvas = resolveCanvas(canvas);
1093
- canvas.hideMinor = ! canvas.hideMinor;
1094
- clearDimCache(canvas.flow);
1095
- renderFlow(canvas, canvas.flow);
1096
- }
1097
-
1098
- function toggleVertical (canvas) {
1099
- canvas = resolveCanvas(canvas);
1100
- canvas.horizontal = ! canvas.horizontal;
1101
- clearDimCache(canvas.flow);
1102
- renderFlow(canvas, canvas.flow);
1103
- }
1104
-
1105
- return {
1106
- HANDLERS: HANDLERS,
1107
- MINORS: MINORS,
1108
- renderFlow: renderFlow,
1109
- highlight: highlight,
1110
- getHeight: getHeight,
1111
- getWidth: getWidth,
1112
- crop: crop,
1113
- resize: resize,
1114
- resizeForMaxWidth: resizeForMaxWidth,
1115
- toggleMinor: toggleMinor,
1116
- toggleVertical: toggleVertical
1117
- };
1118
- }();