ruote-kit 2.1.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }();