ruote-kit 2.1.4

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 (73) hide show
  1. data/.document +0 -0
  2. data/.gitignore +8 -0
  3. data/Gemfile +10 -0
  4. data/README.rdoc +132 -0
  5. data/Rakefile +57 -0
  6. data/config.ru +21 -0
  7. data/lib/ruote-kit/application.rb +50 -0
  8. data/lib/ruote-kit/configuration.rb +52 -0
  9. data/lib/ruote-kit/helpers/engine_helpers.rb +24 -0
  10. data/lib/ruote-kit/helpers/form_helpers.rb +11 -0
  11. data/lib/ruote-kit/helpers/launch_item_parser.rb +59 -0
  12. data/lib/ruote-kit/helpers/navigation_helpers.rb +54 -0
  13. data/lib/ruote-kit/helpers/render_helpers.rb +103 -0
  14. data/lib/ruote-kit/helpers.rb +9 -0
  15. data/lib/ruote-kit/public/_ruote/images/bg.gif +0 -0
  16. data/lib/ruote-kit/public/_ruote/images/bg_button_left.gif +0 -0
  17. data/lib/ruote-kit/public/_ruote/images/bg_button_left_cancel.gif +0 -0
  18. data/lib/ruote-kit/public/_ruote/images/bg_button_left_submit.gif +0 -0
  19. data/lib/ruote-kit/public/_ruote/images/bg_button_right.gif +0 -0
  20. data/lib/ruote-kit/public/_ruote/javascripts/SimplyButtons.js +191 -0
  21. data/lib/ruote-kit/public/_ruote/javascripts/fluo-can.js +1111 -0
  22. data/lib/ruote-kit/public/_ruote/javascripts/fluo-dial.js +149 -0
  23. data/lib/ruote-kit/public/_ruote/javascripts/fluo-json.js +183 -0
  24. data/lib/ruote-kit/public/_ruote/javascripts/fluo-tred.js +515 -0
  25. data/lib/ruote-kit/public/_ruote/stylesheets/SimplyButtons.css +226 -0
  26. data/lib/ruote-kit/public/_ruote/stylesheets/base.css +336 -0
  27. data/lib/ruote-kit/public/_ruote/stylesheets/rk.css +30 -0
  28. data/lib/ruote-kit/public/_ruote/stylesheets/style.css +393 -0
  29. data/lib/ruote-kit/resources/expressions.rb +55 -0
  30. data/lib/ruote-kit/resources/processes.rb +52 -0
  31. data/lib/ruote-kit/resources/workitems.rb +64 -0
  32. data/lib/ruote-kit/spec/ruote_helpers.rb +47 -0
  33. data/lib/ruote-kit/vendor/sinatra-respond_to/LICENSE +21 -0
  34. data/lib/ruote-kit/vendor/sinatra-respond_to/README.markdown +102 -0
  35. data/lib/ruote-kit/vendor/sinatra-respond_to/Rakefile +30 -0
  36. data/lib/ruote-kit/vendor/sinatra-respond_to/VERSION.yml +4 -0
  37. data/lib/ruote-kit/vendor/sinatra-respond_to/lib/sinatra/respond_to.rb +206 -0
  38. data/lib/ruote-kit/vendor/sinatra-respond_to/sinatra-respond_to.gemspec +56 -0
  39. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/public/static folder/.keep +0 -0
  40. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/public/static.txt +1 -0
  41. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/test_app.rb +53 -0
  42. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/unreachable_static.txt +1 -0
  43. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/views/layout.html.haml +2 -0
  44. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/views/resource.html.haml +1 -0
  45. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/views/resource.js.erb +3 -0
  46. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/app/views/resource.xml.builder +3 -0
  47. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/extension_spec.rb +403 -0
  48. data/lib/ruote-kit/vendor/sinatra-respond_to/spec/spec_helper.rb +18 -0
  49. data/lib/ruote-kit/views/expression.html.haml +38 -0
  50. data/lib/ruote-kit/views/expressions.html.haml +30 -0
  51. data/lib/ruote-kit/views/index.html.haml +1 -0
  52. data/lib/ruote-kit/views/launch_process.html.haml +19 -0
  53. data/lib/ruote-kit/views/layout.html.haml +46 -0
  54. data/lib/ruote-kit/views/process.html.haml +55 -0
  55. data/lib/ruote-kit/views/processes.html.haml +27 -0
  56. data/lib/ruote-kit/views/resource_not_found.html.haml +7 -0
  57. data/lib/ruote-kit/views/workitem.html.haml +39 -0
  58. data/lib/ruote-kit/views/workitems.html.haml +23 -0
  59. data/lib/ruote-kit.rb +105 -0
  60. data/ruote-kit.gemspec +136 -0
  61. data/spec/helpers/render_helpers_spec.rb +211 -0
  62. data/spec/resources/expressions_spec.rb +179 -0
  63. data/spec/resources/index_spec.rb +46 -0
  64. data/spec/resources/processes_spec.rb +259 -0
  65. data/spec/resources/workitems_spec.rb +308 -0
  66. data/spec/ruote-kit_spec.rb +4 -0
  67. data/spec/spec.opts +2 -0
  68. data/spec/spec_helper.rb +152 -0
  69. data/spec/views/launch_process.html.haml_spec.rb +21 -0
  70. data/spec/views/process.html.haml_spec.rb +16 -0
  71. data/spec/views/processes.html.haml_spec.rb +30 -0
  72. data/spec/views/workitems.html.haml_spec.rb +68 -0
  73. metadata +185 -0
@@ -0,0 +1,1111 @@
1
+
2
+ /*
3
+ * Ruote - open source ruby workflow engine
4
+ * (c) 2005-2009 jmettraux@gmail.com
5
+ *
6
+ * OpenWFEru is freely distributable under the terms
7
+ * of a BSD-style license.
8
+ * For details, see the OpenWFEru web site: http://openwferu.rubyforge.org
9
+ *
10
+ * Made in Japan
11
+ *
12
+ * John Mettraux
13
+ * Juan-Pedro Paredes
14
+ */
15
+
16
+ //function dinspect (o) {
17
+ // var s = "[\n";
18
+ // for (var k in o) {
19
+ // s += ("" + k + ": " + o[k]);
20
+ // s += ",\n";
21
+ // }
22
+ // s += "]";
23
+ // return s;
24
+ //}
25
+
26
+ var FluoCon = {
27
+
28
+ RGB_WHITE: 'rgb(255, 255, 255)',
29
+ RGB_HIGHLIGHT: 'rgb(220, 220, 220)',
30
+ LINE_HEIGHT: 20,
31
+ MIN_ACTIVITY_WIDTH: 110
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 = FluoCon.RGB_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 = FluoCon.RGB_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 = FluoCon.RGB_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 FluoCan = 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 = FluoCan[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 += FluoCan[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 + ': ' + fluoToJson(exp[1][attname], false);
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
+ function childText (exp) {
335
+ //var exp2 = exp[2];
336
+ //if (exp2.length == 1 && ((typeof exp2[0]) == 'string')) return exp2[0];
337
+ //return null;
338
+ for (var k in exp[1]) {
339
+ var v = exp[1][k];
340
+ if (v == null) return k;
341
+ }
342
+ return null;
343
+ }
344
+
345
+ // returns the list of attribute names (sorted)
346
+ //
347
+ function attributeNames (exp) {
348
+ var an = [];
349
+ for (var k in exp[1]) { an.push(k); }
350
+ return an.sort();
351
+ }
352
+
353
+ function attributeCount (exp) {
354
+ //var l = attributeNames(exp).length;
355
+ //var ct = strchild && childText(exp);
356
+ //return l + (ct ? 1 : 0);
357
+ return attributeNames(exp).length;
358
+ }
359
+
360
+ function carriageReturn (c) {
361
+ if (c.canvas.horizontal == true) c.translate(-FluoCon.LINE_HEIGHT, 0);
362
+ else c.translate(0, FluoCon.LINE_HEIGHT);
363
+ }
364
+
365
+ function drawAttributes (c, exp, expname, namePlus, width, height) {
366
+
367
+ if (expname) {
368
+ FluoCanvas.drawText(c, exp[0], width, height);
369
+ carriageReturn(c);
370
+ }
371
+
372
+ //var ct = strchild && childText(exp);
373
+ var ct = childText(exp);
374
+ if (namePlus && ct) {
375
+ FluoCanvas.drawText(c, ct, width, height);
376
+ carriageReturn(c);
377
+ }
378
+
379
+ var attname;
380
+ var attnames = attributeNames(exp, expname);
381
+
382
+ while (attname = attnames.shift()) {
383
+
384
+ var v = exp[1][attname];
385
+ if (v != null) v = fluoToJson(v, false);
386
+
387
+ if (attname.match(/^on[-\_]error$/)) {
388
+ FluoCanvas.drawText(c, v, width, height, 'drawError');
389
+ carriageReturn(c);
390
+ }
391
+ else if (attname.match(/^on[-\_]cancel$/)) {
392
+ FluoCanvas.drawText(c, v, width, height, 'drawCancel');
393
+ carriageReturn(c);
394
+ }
395
+ else {
396
+ var t = attname;
397
+ //alert(fluoToJson([ t, ct, namePlus ]));
398
+ if (t != ct) {
399
+ if (v != null) t = t + ': ' + v;
400
+ FluoCanvas.drawText(c, t, width, height);
401
+ carriageReturn(c);
402
+ }
403
+ }
404
+ }
405
+ }
406
+
407
+ //
408
+ // the methods (and fields) shared by all handler are here
409
+ //
410
+ var Handler = {};
411
+ Handler.getHeight = function (c, exp) {
412
+ if (c.canvas.horizontal == true) return this.getRealWidth(c, exp);
413
+ return this.getRealHeight(c, exp);
414
+ };
415
+ Handler.getWidth = function (c, exp) {
416
+ if (c.canvas.horizontal == true) return this.getRealHeight(c, exp);
417
+ return this.getRealWidth(c, exp);
418
+ };
419
+
420
+ //
421
+ // creates a new Handler (a copy of Handler), if the parentHandler is
422
+ // given, will spawn a copy of it instead of a copy of Handler.
423
+ // (dead simple inheritance).
424
+ //
425
+ function newHandler (parentHandler) {
426
+ if ( ! parentHandler) parentHandler = Handler;
427
+ var result = {};
428
+ for (var k in parentHandler) result[k] = parentHandler[k];
429
+ for (var k in parentHandler) result['super_'+k] = parentHandler[k];
430
+ return result;
431
+ }
432
+
433
+ function getChildren (c, exp) {
434
+ var cs = exp[2];
435
+ if ( ! c.canvas.hideMinor) return cs;
436
+ if (exp.majorChildren) return exp.majorChildren;
437
+ var r = [];
438
+ for (var i = 0; i < cs.length; i++) {
439
+ var c = cs[i];
440
+ if (MINORS.indexOf(c[0]) < 0) r.push(c);
441
+ }
442
+ exp.majorChildren = r; // caching the result
443
+ return r;
444
+ }
445
+
446
+ //
447
+ // EXPRESSION HANDLERS
448
+
449
+ var GenericHandler = newHandler();
450
+ GenericHandler.adjust = function (exp) {
451
+ var ct = childText(exp);
452
+ if (ct) exp[0] = exp[0] + ' ' + ct;
453
+ }
454
+ GenericHandler.render = function (c, exp) {
455
+ var width = this.getWidth(c, exp);
456
+ var height = this.getHeight(c, exp);
457
+ FluoCanvas.drawRoundedRect(c, width, height, 8);
458
+ c.save();
459
+ drawAttributes(c, exp, true, false, width, height);
460
+ c.restore();
461
+ };
462
+ GenericHandler.getRealHeight = function (c, exp) {
463
+ return 7 + (1 + attributeCount(exp)) * FluoCon.LINE_HEIGHT;
464
+ };
465
+ GenericHandler.getRealWidth = function (c, exp) {
466
+ //return 10 + attributeMaxWidth(c, exp, exp[0]);
467
+ return Math.max(10 + attributeMaxWidth(c, exp, exp[0]), FluoCon.MIN_ACTIVITY_WIDTH);
468
+ };
469
+
470
+ var AttributeOnlyHandler = newHandler();
471
+ AttributeOnlyHandler.adjust = function (exp) {
472
+ var ct = childText(exp);
473
+ if (ct) exp[0] = exp[0] + ' ' + ct;
474
+ }
475
+ AttributeOnlyHandler.render = function (c, exp) {
476
+ var width = this.getWidth(c, exp);
477
+ var height = this.getHeight(c, exp);
478
+ c.save();
479
+ drawAttributes(c, exp, false, false, width, height);
480
+ c.restore();
481
+ };
482
+ AttributeOnlyHandler.getRealHeight = function (c, exp) {
483
+ return 7 + attributeCount(exp) * FluoCon.LINE_HEIGHT;
484
+ };
485
+ AttributeOnlyHandler.getRealWidth = function (c, exp) {
486
+ return attributeMaxWidth(c, exp, exp[0]);
487
+ };
488
+
489
+ var SubprocessHandler = newHandler(GenericHandler);
490
+ SubprocessHandler.adjust = function (exp) {
491
+ if (exp[2].length == 1) exp[1]['ref'] = exp[2][0];
492
+ }
493
+ SubprocessHandler.render = function (c, exp) {
494
+ var width = this.getWidth(c, exp);
495
+ var height = this.getHeight(c, exp);
496
+ FluoCanvas.drawRoundedRect(c, width, height, 8);
497
+ c.save();
498
+ drawAttributes(c, exp, true, false, width, height);
499
+ c.restore();
500
+ FluoCanvas.drawCrossInABox(c, height);
501
+ };
502
+ SubprocessHandler.getRealHeight = function (c, exp) {
503
+ return 12 + 7 + (1 + attributeCount(exp)) * FluoCon.LINE_HEIGHT;
504
+ };
505
+
506
+
507
+ // TODO : fix rotated mode
508
+ //
509
+ var GenericWithChildrenHandler = newHandler();
510
+ GenericWithChildrenHandler.render = function (c, exp) {
511
+ var width = this.getWidth(c, exp);
512
+ var height = this.getHeight(c, exp);
513
+ var attWidth = attributeMaxWidth(c, exp, exp[0]) + 7;
514
+ var attHeight = attributeCount(exp) * FluoCon.LINE_HEIGHT;
515
+ var children = getChildren(c, exp);
516
+ if (c.canvas.horizontal == true) {
517
+ var w = attWidth;
518
+ attWidth = attHeight;
519
+ attHeight = w;
520
+ }
521
+ FluoCanvas.drawRoundedRect(c, width, height, 8);
522
+ c.save();
523
+ c.translate(-width/2 + attWidth/2 + 5 , 7);
524
+ if (c.canvas.horizontal == true) c.translate(attHeight/2, 0);
525
+ drawAttributes(c, exp, true, false, attWidth, attHeight);
526
+ c.restore();
527
+ c.save();
528
+ c.translate(width/2 - childrenMax(c, exp, 'getWidth')/2 - 7, 8);
529
+ for (var i = 0; i < children.length; i++) {
530
+ var child = children[i];
531
+ renderExp(c, child);
532
+ //c.translate(0, 7 + FluoCan.getHeight(c, child));
533
+ c.translate(0, FluoCan.getHeight(c, child));
534
+ if (this.drawArrow && i < children.length -1) FluoCanvas.drawArrow(c, 10);
535
+ c.translate(0, 10);
536
+ }
537
+ c.restore();
538
+ };
539
+ GenericWithChildrenHandler.drawArrow = false;
540
+ GenericWithChildrenHandler.getHeight = function (c, exp) {
541
+ var rightHeight =
542
+ (getChildren(c, exp).length + 1) * 9 + childrenSum(c, exp, 'getHeight');
543
+ var leftHeight =
544
+ GenericHandler.getHeight(c, exp);
545
+ return (rightHeight > leftHeight) ? rightHeight : leftHeight;
546
+ };
547
+ GenericWithChildrenHandler.getWidth = function (c, exp) {
548
+ return(
549
+ attributeMaxWidth(c, exp, exp[0]) +
550
+ 28 +
551
+ childrenMax(c, exp, 'getWidth'));
552
+ };
553
+
554
+ var LoopHandler = newHandler(GenericWithChildrenHandler);
555
+ LoopHandler.drawArrow = true;
556
+ LoopHandler.render = function (c, exp) {
557
+ this.super_render(c, exp);
558
+ FluoCanvas.drawLoopSymbol(c, this.getHeight(c, exp));
559
+ }
560
+ LoopHandler.getHeight = function (c, exp) {
561
+ return 12 + this.super_getHeight(c, exp);
562
+ }
563
+
564
+ var ConcurrentIteratorHandler = newHandler(GenericWithChildrenHandler);
565
+ ConcurrentIteratorHandler.render = function (c, exp) {
566
+ this.super_render(c, exp);
567
+ FluoCanvas.drawParaSymbol(c, this.getHeight(c, exp));
568
+ }
569
+ ConcurrentIteratorHandler.getHeight = function (c, exp) {
570
+ return 12 + this.super_getHeight(c, exp);
571
+ }
572
+
573
+
574
+ // TODO : fix in rotated mode
575
+ //
576
+ var TextHandler = newHandler();
577
+ TextHandler.render = function (c, exp) {
578
+ var h = getHeight(c, exp);
579
+ var w = getWidth(c, exp);
580
+ FluoCanvas.drawText(c, this.getText(exp), h, w);
581
+ };
582
+ TextHandler.getText = function (exp) {
583
+ var t = exp[0];
584
+ var ct = childText(exp); if (ct) t += (' ' + ct);
585
+ for (var attname in exp[1]) {
586
+ var v = exp[1][attname];
587
+ t += (' ' + attname + ': "' + v + '"');
588
+ }
589
+ return t;
590
+ };
591
+ TextHandler.getRealHeight = function (c, exp) {
592
+ return FluoCon.LINE_HEIGHT;
593
+ };
594
+ TextHandler.getRealWidth = function (c, exp) {
595
+ return c.measure(this.getText(exp));
596
+ };
597
+
598
+ // TODO : fix rotated mode
599
+ //
600
+ var SymbolHandler = newHandler();
601
+ SymbolHandler.SYMBOL_HEIGHT = 22;
602
+ SymbolHandler.render = function (c, exp) {
603
+ var w = this.getWidth(c, exp);
604
+ var h = this.getHeight(c, exp);
605
+ c.save();
606
+ if (c.canvas.horizontal == true) {
607
+ c.translate(w/2, h/2);
608
+ c.rotate(-Math.PI/2);
609
+ }
610
+ c.translate(0, 12);
611
+ FluoCanvas['draw_'+exp[0]+'_symbol'](c, SymbolHandler.SYMBOL_HEIGHT);
612
+ c.translate(0, 12);
613
+ drawAttributes(c, exp, false, true, this.getWidth(c, exp), this.getHeight(c, exp));
614
+ c.restore();
615
+ };
616
+ SymbolHandler.getRealHeight = function (c, exp) {
617
+ return attributeCount(exp) * FluoCon.LINE_HEIGHT + SymbolHandler.SYMBOL_HEIGHT;
618
+ };
619
+ SymbolHandler.getRealWidth = function (c, exp) {
620
+ return attributeMaxWidth(c, exp, exp[0]);
621
+ };
622
+
623
+ var StringHandler = newHandler(TextHandler);
624
+ StringHandler.getText = function (exp) {
625
+ return exp;
626
+ };
627
+
628
+ var VerticalHandler = newHandler();
629
+ VerticalHandler.adjust = function (exp) {
630
+ if (attributeCount(exp) > 0) exp[2].unshift([ '_atts_', exp[1], [] ]);
631
+ }
632
+ VerticalHandler.render = function (c, exp) {
633
+ c.save();
634
+ var children = getChildren(c, exp);
635
+ for (var i = 0; i < children.length; i++) {
636
+ var child = children[i];
637
+ renderExp(c, child);
638
+ c.translate(0, FluoCan.getHeight(c, child));
639
+ if (i < children.length - 1) {
640
+ FluoCanvas.drawArrow(c, 14);
641
+ c.translate(0, 14);
642
+ }
643
+ }
644
+ c.restore();
645
+ };
646
+ VerticalHandler.getHeight = function (c, exp) {
647
+ return (getChildren(c, exp).length - 1) * 14 + childrenSum(c, exp, 'getHeight');
648
+ };
649
+ VerticalHandler.getWidth = function (c, exp) {
650
+ return childrenMax(c, exp, 'getWidth');
651
+ };
652
+
653
+ var HorizontalHandler = newHandler();
654
+ HorizontalHandler.render = function (c, exp) {
655
+ var children = getChildren(c, exp);
656
+ var dist = this.computeDistribution(c, exp);
657
+ var childrenHeight = this.getChildrenHeight(c, exp);
658
+ this.renderHeader(c, exp, dist);
659
+ c.save();
660
+ c.translate(0, this.getHeaderHeight(c, exp));
661
+ for (var i=0; i < children.length; i++) {
662
+ var child = children[i];
663
+ c.save();
664
+ c.translate(dist[i], 0);
665
+ this.renderChild(c, child, childrenHeight);
666
+ c.restore();
667
+ }
668
+ c.restore();
669
+ this.renderFooter(c, exp, dist, childrenHeight);
670
+ };
671
+ HorizontalHandler.getHeaderHeight = function (c, exp) {
672
+ if (c.canvas.horizontal == true) return 23 + attributeMaxWidth(c, exp);
673
+ return 23 + attributeCount(exp) * FluoCon.LINE_HEIGHT;
674
+ };
675
+ HorizontalHandler.getChildrenHeight = function (c, exp) {
676
+ return childrenMax(c, exp, 'getHeight');
677
+ };
678
+ HorizontalHandler.getHeight = function (c, exp) {
679
+ return this.getHeaderHeight(c, exp) + this.getChildrenHeight(c, exp) + 10;
680
+ };
681
+ HorizontalHandler.getWidth = function (c, exp) {
682
+ return (getChildren(c, exp).length - 1) * 3 + childrenSum(c, exp, 'getWidth');
683
+ //return Math.max(
684
+ // attributeMaxWidth(c, exp),
685
+ // (getChildren(c, exp).length - 1) * 3 + childrenSum(c, exp, 'getWidth'));
686
+ };
687
+ HorizontalHandler.computeDistribution = function (c, exp) {
688
+ var children = getChildren(c, exp);
689
+ var totalWidth = this.getWidth(c, exp);
690
+ var offset = -totalWidth/2;
691
+ var dist = new Array(children.length);
692
+ for (var i = 0; i < children.length; i++) {
693
+ var cWidth = FluoCan.getWidth(c, children[i]);
694
+ dist[i] = offset + cWidth / 2;
695
+ offset += (cWidth + 3);
696
+ }
697
+ return dist;
698
+ };
699
+ HorizontalHandler.renderHeader = function (c, exp, distribution) {
700
+ var hheight = this.getHeaderHeight(c, exp) - 10;
701
+ c.save();
702
+ c.translate(0, 10);
703
+ FluoCanvas.drawQuadraticPath(
704
+ c, distribution[0], hheight, 8);
705
+ FluoCanvas.drawQuadraticPath(
706
+ c, distribution[distribution.length-1], hheight, 8);
707
+ for (var i = 1; i < distribution.length - 1; i++) {
708
+ FluoCanvas.drawVerticalLine(c, distribution[i], hheight);
709
+ }
710
+ c.restore();
711
+ this.renderHeaderSymbol(c);
712
+ this.renderHeaderLabel(c, exp);
713
+ };
714
+ HorizontalHandler.renderHeaderSymbol = function (c) {
715
+ FluoCanvas.drawDiamond(c, FluoCon.LINE_HEIGHT);
716
+ };
717
+ HorizontalHandler.renderHeaderLabel = function (c, exp) {
718
+ var width = attributeMaxWidth(c, exp);
719
+ var height = attributeCount(exp) * FluoCon.LINE_HEIGHT;
720
+ if (c.canvas.horizontal == true) {
721
+ var w = width;
722
+ width = height;
723
+ height = w;
724
+ }
725
+ c.save();
726
+ c.translate(0, FluoCon.LINE_HEIGHT);
727
+ c.save();
728
+ c.fillStyle = FluoCon.RGB_WHITE;
729
+ c.fillRect(-width/2, 0, width, height);
730
+ c.restore();
731
+ drawAttributes(c, exp, false, false, width, height);
732
+ c.restore();
733
+ };
734
+ HorizontalHandler.renderChild = function (c, exp, childrenHeight) {
735
+ var cheight = FluoCan.getHeight(c, exp);
736
+ renderExp(c, exp);
737
+ c.beginPath();
738
+ c.moveTo(0, cheight); c.lineTo(0, childrenHeight);
739
+ c.stroke();
740
+ };
741
+ HorizontalHandler.renderFooter = function (c, exp, distribution) {
742
+ var childrenHeight = this.getChildrenHeight(c, exp);
743
+ c.save();
744
+ c.translate(
745
+ 0, this.getHeaderHeight(c, exp) + this.getChildrenHeight(c, exp) + 10);
746
+ if (distribution.length == 1) {
747
+ FluoCanvas.drawVerticalLine(c, distribution[0], -10);
748
+ }
749
+ else {
750
+ FluoCanvas.drawQuadraticPath(
751
+ c, distribution[0], -10, 8);
752
+ FluoCanvas.drawQuadraticPath(
753
+ c, distribution[distribution.length-1], -10, 8);
754
+ for (var i = 1; i < distribution.length - 1; i++) {
755
+ FluoCanvas.drawVerticalLine(c, distribution[i], -10);
756
+ }
757
+ }
758
+ c.restore();
759
+ };
760
+ HorizontalHandler.renderFooterDiamond = function (c) {
761
+ };
762
+
763
+ var ConcurrenceHandler = newHandler(HorizontalHandler);
764
+ ConcurrenceHandler.renderHeaderSymbol = function (c) {
765
+ FluoCanvas.drawParaDiamond(c, 20);
766
+ };
767
+
768
+ var IfHandler = newHandler(HorizontalHandler);
769
+ IfHandler.adjust = function (exp) {
770
+ //
771
+ // all the crazy legwork to adapt to the 'if' expression
772
+ //
773
+ if ( ! (exp[1]['test'] || exp[1]['not'])) {
774
+ // ok, steal first exp
775
+ var cond = exp[2].shift();
776
+ if (cond) {
777
+ exp[1] = cond[1];
778
+ exp[1]['condition'] = cond[0];
779
+ }
780
+ }
781
+ for (var i = 0; i < 2 - exp[2].length; i++) exp[2].push([ '_', {}, [] ]);
782
+ // adding ghost expressions
783
+ };
784
+
785
+ //
786
+ // used for empty else clause
787
+ //
788
+ var GhostHandler = newHandler();
789
+ GhostHandler.render = function (c, exp) {
790
+ };
791
+ GhostHandler.getHeight = function (c, exp) {
792
+ return 0;
793
+ };
794
+ GhostHandler.getWidth = function (c, exp) {
795
+ return 35;
796
+ };
797
+
798
+ var HANDLERS = {
799
+
800
+ //'participant': ParticipantHandler
801
+
802
+ 'sequence': VerticalHandler,
803
+ 'concurrence': ConcurrenceHandler,
804
+ 'if': IfHandler,
805
+ 'set': TextHandler,
806
+ 'unset': TextHandler,
807
+ 'sleep': SymbolHandler,
808
+ 'wait': SymbolHandler,
809
+ 'error': SymbolHandler,
810
+ 'subprocess': SubprocessHandler,
811
+ 'loop': LoopHandler,
812
+ 'repeat': LoopHandler,
813
+ 'cursor': LoopHandler,
814
+ 'concurrent-iterator': ConcurrentIteratorHandler,
815
+
816
+ 'rewind': TextHandler,
817
+ 'continue': TextHandler,
818
+ 'back': TextHandler,
819
+ 'break': TextHandler,
820
+ 'cancel': TextHandler,
821
+ 'skip': TextHandler,
822
+ 'jump': TextHandler,
823
+ // 'commands'
824
+
825
+ '_atts_': AttributeOnlyHandler,
826
+ '_': GhostHandler
827
+ };
828
+
829
+ var MINORS = [ 'set', 'set-fields', 'unset', 'description' ];
830
+
831
+ var DEFINERS = [ 'process-definition', 'workflow-definition', 'define' ];
832
+
833
+ function identifyExpressions (exp, expid) {
834
+ if (exp.expid) return; // identify only once
835
+ if ( ! expid) expid = '0';
836
+ exp.expid = expid;
837
+ if ((typeof exp) == 'string') return;
838
+ for (var i = 0; i < exp[2].length; i++) {
839
+ identifyExpressions(exp[2][i], expid + '_' + i);
840
+ }
841
+ }
842
+
843
+ function setOption (context, options, optname, defval) {
844
+ var v = options[optname];
845
+ if (v) {
846
+ context.canvas[optname] = v;
847
+ }
848
+ else if (optname in options) { // v is null
849
+ context.canvas[optname] = null;
850
+ }
851
+ else if (defval && ! (context.canvas[optname])) {
852
+ context.canvas[optname] = defval;
853
+ }
854
+ }
855
+
856
+ function renderFlow (context, flow, options) {
857
+
858
+ if ( ! options) options = {};
859
+
860
+ identifyExpressions(flow);
861
+
862
+ context = resolveContext(context);
863
+ neutralizeContext(context);
864
+
865
+ context.canvas.flow = flow;
866
+
867
+ setOption(context, options, 'workitems', []);
868
+ setOption(context, options, 'highlight');
869
+ setOption(context, options, 'hideMinor');
870
+ setOption(context, options, 'horizontal');
871
+
872
+ context.save();
873
+
874
+ if (context.canvas.horizontal == true) {
875
+ context.translate(0, flow.width + 2);
876
+ context.rotate(-Math.PI/2);
877
+ }
878
+
879
+ context.mozTextStyle = "12px Helvetica Neue";
880
+ context.font = "12px Helvetica Neue";
881
+
882
+ var fs = context.fillStyle;
883
+ context.fillStyle = FluoCon.RGB_WHITE;
884
+ context.fillRect(0, 0, context.canvas.width, context.canvas.height);
885
+ context.fillStyle = fs;
886
+
887
+ //context.translate(context.canvas.width/2, 0);
888
+ var w = getWidth(context, flow);
889
+ context.translate(w/2 + 1, 1); // aligning left
890
+
891
+ renderExp(context, flow);
892
+
893
+ context.restore();
894
+
895
+ //flow.width = getWidth(context, flow);
896
+ //flow.height = getHeight(context, flow);
897
+ getWidth(context, flow);
898
+ getHeight(context, flow);
899
+ }
900
+
901
+ function highlight (c, highlight) {
902
+ canvas = resolveCanvas(c);
903
+ //clear(canvas);
904
+ //renderFlow(canvas, canvas.flow, canvas.workitems, highlight);
905
+ renderFlow(canvas, canvas.flow, {'highlight': highlight});
906
+ }
907
+
908
+ function drawWorkitem (c, exp) {
909
+ var ww = c.measure('wi');
910
+ c.save();
911
+ if (c.canvas.horizontal == true) {
912
+ c.rotate(Math.PI/2);
913
+ c.translate(5, -14);
914
+ }
915
+ else {
916
+ c.translate(20, -7);
917
+ }
918
+ c.fillStyle = '#F4D850';
919
+ c.moveTo(0, 0);
920
+ c.beginPath();
921
+ c.arc(0, 0, 10, Math.PI, 0, false);
922
+ c.lineTo(0, 20);
923
+ c.lineTo(-10, 0);
924
+ c.fill();
925
+ c.fillStyle = 'black';
926
+ c.moveTo(0, 0);
927
+ c.beginPath();
928
+ c.arc(0, 0, 10, Math.PI, 0, false);
929
+ c.lineTo(0, 20);
930
+ c.lineTo(-10, 0);
931
+ c.stroke();
932
+ c.translate(-ww/2, 3);
933
+ c.write('wi');
934
+ c.restore();
935
+ }
936
+
937
+ function renderExp (c, exp) {
938
+
939
+ var handler = getHandler(c, exp);
940
+
941
+ if (handler.adjust && ! exp.adjusted) {
942
+ handler.adjust(exp);
943
+ exp.adjusted = true;
944
+ }
945
+
946
+ if (c.canvas.highlight && exp.expid == c.canvas.highlight) { // highlight
947
+ var w = getWidth(c, exp);
948
+ var h = getHeight(c, exp);
949
+ var t = 7;
950
+ c.save();
951
+ c.fillStyle = FluoCon.RGB_HIGHLIGHT;
952
+ c.fillRect(-w/2, 0, w, h);
953
+ c.fillStyle = FluoCon.RGB_WHITE;
954
+ c.fillRect(-w/2 + t, 0 + t , w - 2 * t, h - 2 * t);
955
+ c.restore();
956
+ }
957
+
958
+ handler.render(c, exp);
959
+
960
+ if (c.canvas.workitems.indexOf(exp.expid) > -1) { // workitem
961
+ drawWorkitem(c, exp);
962
+ }
963
+ }
964
+
965
+ /*
966
+ function clear (c) {
967
+ c = resolveContext(c);
968
+ c.clearRect(0, 0, c.canvas.width, c.canvas.height);
969
+ }
970
+ */
971
+
972
+ function resolveCanvas (c) {
973
+ if (c.getContext != null) return c;
974
+ if (c.canvas != null) return c.canvas;
975
+ return document.getElementById(c);
976
+ }
977
+
978
+ function resolveContext (c) {
979
+ if (c.translate != null) return c;
980
+ return resolveCanvas(c).getContext('2d');
981
+ }
982
+
983
+ // replaces the canvas element with a new, cropped, one
984
+ //
985
+ function crop (canvas) {
986
+
987
+ canvas = resolveCanvas(canvas);
988
+ var nc = document.createElement("canvas");
989
+
990
+ nc.id = canvas.id;
991
+
992
+ var w = canvas.flow.width + 2;
993
+ var h = canvas.flow.height + 2;
994
+
995
+ if (canvas.horizontal == true) {
996
+ var x = w; w = h; h = x;
997
+ }
998
+
999
+ nc.setAttribute('width', w);
1000
+ nc.setAttribute('height', h);
1001
+
1002
+ nc.hideMinor = canvas.hideMinor;
1003
+ nc.horizontal = canvas.horizontal;
1004
+ nc.workitems = canvas.workitems;
1005
+
1006
+ //renderFlow(nc, canvas.flow, canvas.workitems, canvas.highlight);
1007
+ renderFlow(nc, canvas.flow);
1008
+ canvas.parentNode.replaceChild(nc, canvas);
1009
+ }
1010
+
1011
+ function neutralizeContext (c) {
1012
+ //if (window.navigator.userAgent.match(/Firefox/)) return;
1013
+ //c.mozDrawText = function (t) {
1014
+ // // do nothing
1015
+ //};
1016
+ //c.mozMeasureText = function (t) {
1017
+ // return t.length * 5;
1018
+ //};
1019
+ if (window.navigator.userAgent.match(/Firefox/)) {
1020
+ c.write = function (t) {
1021
+ this.mozDrawText(t);
1022
+ }
1023
+ c.measure = function (t) {
1024
+ return this.mozMeasureText(t);
1025
+ }
1026
+ }
1027
+ else { // Safari 4
1028
+ c.write = function (t) {
1029
+ this.fillText(t, 0, 0);
1030
+ }
1031
+ c.measure = function (t) {
1032
+ return this.measureText(t).width;
1033
+ return t.length * 5;
1034
+ }
1035
+ }
1036
+ }
1037
+
1038
+ function isSubprocessName (exp, name) {
1039
+ if ((typeof exp) == 'string') return false;
1040
+ if (DEFINERS.indexOf(exp[0]) > -1 && exp[1]['name'] == name) return true;
1041
+ for (var i = 0; i < exp[2].length; i++) {
1042
+ if (isSubprocessName(exp[2][i], name)) return true;
1043
+ }
1044
+ return false;
1045
+ }
1046
+
1047
+ // returns the raw height of an expression (caches it too)
1048
+ //
1049
+ function getHeight (c, exp) {
1050
+ if ((typeof exp) == 'string') return getHandler(c, exp).getHeight(c, exp);
1051
+ if (exp.height) return exp.height;
1052
+ var h = getHandler(c, exp);
1053
+ if (h.adjust && ! exp.adjusted) { h.adjust(exp); exp.adjusted = true; }
1054
+ exp.height = h.getHeight(c, exp);
1055
+ return exp.height;
1056
+ }
1057
+
1058
+ // return the raw width of an expression
1059
+ //
1060
+ function getWidth (c, exp) {
1061
+ if ((typeof exp) == 'string') return getHandler(c, exp).getWidth(c, exp);
1062
+ if (exp.width) return exp.width;
1063
+ var h = getHandler(c, exp);
1064
+ if (h.adjust && ! exp.adjusted) { h.adjust(exp); exp.adjusted = true; }
1065
+ exp.width = h.getWidth(c, exp);
1066
+ return exp.width;
1067
+ }
1068
+
1069
+ function getHandler (c, exp) {
1070
+ if ((typeof exp) == 'string') return StringHandler;
1071
+ var h = HANDLERS[exp[0]];
1072
+ if (h) return h;
1073
+ //if (childText(exp)) return GenericHandler;
1074
+ if (exp[2].length > 0) return GenericWithChildrenHandler;
1075
+ if (isSubprocessName(c.canvas.flow, exp[0])) return SubprocessHandler;
1076
+ return GenericHandler;
1077
+ }
1078
+
1079
+ function clearDimCache (exp) {
1080
+ if ((typeof exp) == 'string') return;
1081
+ exp.width = null;
1082
+ exp.height = null;
1083
+ for (var i = 0; i < exp[2].length; i++) clearDimCache(exp[2][i]);
1084
+ }
1085
+
1086
+ function toggleMinor (canvas) {
1087
+ canvas = resolveCanvas(canvas);
1088
+ canvas.hideMinor = ! canvas.hideMinor;
1089
+ clearDimCache(canvas.flow);
1090
+ renderFlow(canvas, canvas.flow);
1091
+ }
1092
+
1093
+ function toggleVertical (canvas) {
1094
+ canvas = resolveCanvas(canvas);
1095
+ canvas.horizontal = ! canvas.horizontal;
1096
+ clearDimCache(canvas.flow);
1097
+ renderFlow(canvas, canvas.flow);
1098
+ }
1099
+
1100
+ return {
1101
+ HANDLERS: HANDLERS,
1102
+ MINORS: MINORS,
1103
+ renderFlow: renderFlow,
1104
+ highlight: highlight,
1105
+ getHeight: getHeight,
1106
+ getWidth: getWidth,
1107
+ crop: crop,
1108
+ toggleMinor: toggleMinor,
1109
+ toggleVertical: toggleVertical
1110
+ };
1111
+ }();