Start process of better client-side file locations.
[openemr.git] / public / assets / literallycanvas-0-4-13 / js / tools / Text.js
blob5178cd6c40c18e64ffa7af855fe1662354ce8b05
1 var Text, Tool, createShape, getIsPointInBox,
2   extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
3   hasProp = {}.hasOwnProperty;
5 Tool = require('./base').Tool;
7 createShape = require('../core/shapes').createShape;
9 getIsPointInBox = function(point, box) {
10   if (point.x < box.x) {
11     return false;
12   }
13   if (point.y < box.y) {
14     return false;
15   }
16   if (point.x > box.x + box.width) {
17     return false;
18   }
19   if (point.y > box.y + box.height) {
20     return false;
21   }
22   return true;
25 module.exports = Text = (function(superClass) {
26   extend(Text, superClass);
28   Text.prototype.name = 'Text';
30   Text.prototype.iconName = 'text';
32   function Text() {
33     this.text = '';
34     this.font = 'bold 18px sans-serif';
35     this.currentShape = null;
36     this.currentShapeState = null;
37     this.initialShapeBoundingRect = null;
38     this.dragAction = null;
39     this.didDrag = false;
40   }
42   Text.prototype.didBecomeActive = function(lc) {
43     var switchAway, unsubscribeFuncs, updateInputEl;
44     unsubscribeFuncs = [];
45     this.unsubscribe = (function(_this) {
46       return function() {
47         var func, i, len, results;
48         results = [];
49         for (i = 0, len = unsubscribeFuncs.length; i < len; i++) {
50           func = unsubscribeFuncs[i];
51           results.push(func());
52         }
53         return results;
54       };
55     })(this);
56     switchAway = (function(_this) {
57       return function() {
58         _this._ensureNotEditing(lc);
59         _this._clearCurrentShape(lc);
60         return lc.repaintLayer('main');
61       };
62     })(this);
63     updateInputEl = (function(_this) {
64       return function() {
65         return _this._updateInputEl(lc);
66       };
67     })(this);
68     unsubscribeFuncs.push(lc.on('drawingChange', switchAway));
69     unsubscribeFuncs.push(lc.on('zoom', updateInputEl));
70     unsubscribeFuncs.push(lc.on('imageSizeChange', updateInputEl));
71     unsubscribeFuncs.push(lc.on('snapshotLoad', (function(_this) {
72       return function() {
73         _this._clearCurrentShape(lc);
74         return lc.repaintLayer('main');
75       };
76     })(this)));
77     unsubscribeFuncs.push(lc.on('primaryColorChange', (function(_this) {
78       return function(newColor) {
79         if (!_this.currentShape) {
80           return;
81         }
82         _this.currentShape.color = newColor;
83         _this._updateInputEl(lc);
84         return lc.repaintLayer('main');
85       };
86     })(this)));
87     return unsubscribeFuncs.push(lc.on('setFont', (function(_this) {
88       return function(font) {
89         if (!_this.currentShape) {
90           return;
91         }
92         _this.font = font;
93         _this.currentShape.setFont(font);
94         _this._setShapesInProgress(lc);
95         _this._updateInputEl(lc);
96         return lc.repaintLayer('main');
97       };
98     })(this)));
99   };
101   Text.prototype.willBecomeInactive = function(lc) {
102     if (this.currentShape) {
103       this._ensureNotEditing(lc);
104       this.commit(lc);
105     }
106     return this.unsubscribe();
107   };
109   Text.prototype.setText = function(text) {
110     return this.text = text;
111   };
113   Text.prototype._ensureNotEditing = function(lc) {
114     if (this.currentShapeState === 'editing') {
115       return this._exitEditingState(lc);
116     }
117   };
119   Text.prototype._clearCurrentShape = function(lc) {
120     this.currentShape = null;
121     this.initialShapeBoundingRect = null;
122     this.currentShapeState = null;
123     return lc.setShapesInProgress([]);
124   };
126   Text.prototype.commit = function(lc) {
127     if (this.currentShape.text) {
128       lc.saveShape(this.currentShape);
129     }
130     this._clearCurrentShape(lc);
131     return lc.repaintLayer('main');
132   };
134   Text.prototype._getSelectionShape = function(ctx, backgroundColor) {
135     if (backgroundColor == null) {
136       backgroundColor = null;
137     }
138     return createShape('SelectionBox', {
139       shape: this.currentShape,
140       ctx: ctx,
141       backgroundColor: backgroundColor
142     });
143   };
145   Text.prototype._setShapesInProgress = function(lc) {
146     switch (this.currentShapeState) {
147       case 'selected':
148         return lc.setShapesInProgress([this._getSelectionShape(lc.ctx), this.currentShape]);
149       case 'editing':
150         return lc.setShapesInProgress([this._getSelectionShape(lc.ctx, '#fff')]);
151       default:
152         return lc.setShapesInProgress([this.currentShape]);
153     }
154   };
156   Text.prototype.begin = function(x, y, lc) {
157     var br, point, selectionBox, selectionShape;
158     this.dragAction = 'none';
159     this.didDrag = false;
160     if (this.currentShapeState === 'selected' || this.currentShapeState === 'editing') {
161       br = this.currentShape.getBoundingRect(lc.ctx);
162       selectionShape = this._getSelectionShape(lc.ctx);
163       selectionBox = selectionShape.getBoundingRect();
164       point = {
165         x: x,
166         y: y
167       };
168       if (getIsPointInBox(point, br)) {
169         this.dragAction = 'move';
170       }
171       if (getIsPointInBox(point, selectionShape.getBottomRightHandleRect())) {
172         this.dragAction = 'resizeBottomRight';
173       }
174       if (getIsPointInBox(point, selectionShape.getTopLeftHandleRect())) {
175         this.dragAction = 'resizeTopLeft';
176       }
177       if (getIsPointInBox(point, selectionShape.getBottomLeftHandleRect())) {
178         this.dragAction = 'resizeBottomLeft';
179       }
180       if (getIsPointInBox(point, selectionShape.getTopRightHandleRect())) {
181         this.dragAction = 'resizeTopRight';
182       }
183       if (this.dragAction === 'none' && this.currentShapeState === 'editing') {
184         this.dragAction = 'stop-editing';
185         this._exitEditingState(lc);
186       }
187     } else {
188       this.color = lc.getColor('primary');
189       this.currentShape = createShape('Text', {
190         x: x,
191         y: y,
192         text: this.text,
193         color: this.color,
194         font: this.font,
195         v: 1
196       });
197       this.dragAction = 'place';
198       this.currentShapeState = 'selected';
199     }
200     if (this.dragAction === 'none') {
201       this.commit(lc);
202       return;
203     }
204     this.initialShapeBoundingRect = this.currentShape.getBoundingRect(lc.ctx);
205     this.dragOffset = {
206       x: x - this.initialShapeBoundingRect.x,
207       y: y - this.initialShapeBoundingRect.y
208     };
209     this._setShapesInProgress(lc);
210     return lc.repaintLayer('main');
211   };
213   Text.prototype["continue"] = function(x, y, lc) {
214     var br, brBottom, brRight;
215     if (this.dragAction === 'none') {
216       return;
217     }
218     br = this.initialShapeBoundingRect;
219     brRight = br.x + br.width;
220     brBottom = br.y + br.height;
221     switch (this.dragAction) {
222       case 'place':
223         this.currentShape.x = x;
224         this.currentShape.y = y;
225         this.didDrag = true;
226         break;
227       case 'move':
228         this.currentShape.x = x - this.dragOffset.x;
229         this.currentShape.y = y - this.dragOffset.y;
230         this.didDrag = true;
231         break;
232       case 'resizeBottomRight':
233         this.currentShape.setSize(x - (this.dragOffset.x - this.initialShapeBoundingRect.width) - br.x, y - (this.dragOffset.y - this.initialShapeBoundingRect.height) - br.y);
234         break;
235       case 'resizeTopLeft':
236         this.currentShape.setSize(brRight - x + this.dragOffset.x, brBottom - y + this.dragOffset.y);
237         this.currentShape.setPosition(x - this.dragOffset.x, y - this.dragOffset.y);
238         break;
239       case 'resizeBottomLeft':
240         this.currentShape.setSize(brRight - x + this.dragOffset.x, y - (this.dragOffset.y - this.initialShapeBoundingRect.height) - br.y);
241         this.currentShape.setPosition(x - this.dragOffset.x, this.currentShape.y);
242         break;
243       case 'resizeTopRight':
244         this.currentShape.setSize(x - (this.dragOffset.x - this.initialShapeBoundingRect.width) - br.x, brBottom - y + this.dragOffset.y);
245         this.currentShape.setPosition(this.currentShape.x, y - this.dragOffset.y);
246     }
247     this._setShapesInProgress(lc);
248     lc.repaintLayer('main');
249     return this._updateInputEl(lc);
250   };
252   Text.prototype.end = function(x, y, lc) {
253     if (!this.currentShape) {
254       return;
255     }
256     this.currentShape.setSize(this.currentShape.forcedWidth, 0);
257     if (this.currentShapeState === 'selected') {
258       if (this.dragAction === 'place' || (this.dragAction === 'move' && !this.didDrag)) {
259         this._enterEditingState(lc);
260       }
261     }
262     this._setShapesInProgress(lc);
263     lc.repaintLayer('main');
264     return this._updateInputEl(lc);
265   };
267   Text.prototype._enterEditingState = function(lc) {
268     var onChange;
269     this.currentShapeState = 'editing';
270     if (this.inputEl) {
271       throw "State error";
272     }
273     this.inputEl = document.createElement('textarea');
274     this.inputEl.className = 'text-tool-input';
275     this.inputEl.style.position = 'absolute';
276     this.inputEl.style.transformOrigin = '0px 0px';
277     this.inputEl.style.backgroundColor = 'transparent';
278     this.inputEl.style.border = 'none';
279     this.inputEl.style.outline = 'none';
280     this.inputEl.style.margin = '0';
281     this.inputEl.style.padding = '4px';
282     this.inputEl.style.zIndex = '1000';
283     this.inputEl.style.overflow = 'hidden';
284     this.inputEl.style.resize = 'none';
285     this.inputEl.value = this.currentShape.text;
286     this.inputEl.addEventListener('mousedown', function(e) {
287       return e.stopPropagation();
288     });
289     this.inputEl.addEventListener('touchstart', function(e) {
290       return e.stopPropagation();
291     });
292     onChange = (function(_this) {
293       return function(e) {
294         _this.currentShape.setText(e.target.value);
295         _this.currentShape.enforceMaxBoundingRect(lc);
296         _this._setShapesInProgress(lc);
297         lc.repaintLayer('main');
298         _this._updateInputEl(lc);
299         return e.stopPropagation();
300       };
301     })(this);
302     this.inputEl.addEventListener('keydown', (function(_this) {
303       return function() {
304         return _this._updateInputEl(lc, true);
305       };
306     })(this));
307     this.inputEl.addEventListener('keyup', onChange);
308     this.inputEl.addEventListener('change', onChange);
309     this._updateInputEl(lc);
310     lc.containerEl.appendChild(this.inputEl);
311     this.inputEl.focus();
312     return this._setShapesInProgress(lc);
313   };
315   Text.prototype._exitEditingState = function(lc) {
316     this.currentShapeState = 'selected';
317     lc.containerEl.removeChild(this.inputEl);
318     this.inputEl = null;
319     this._setShapesInProgress(lc);
320     return lc.repaintLayer('main');
321   };
323   Text.prototype._updateInputEl = function(lc, withMargin) {
324     var br, transformString;
325     if (withMargin == null) {
326       withMargin = false;
327     }
328     if (!this.inputEl) {
329       return;
330     }
331     br = this.currentShape.getBoundingRect(lc.ctx, true);
332     this.inputEl.style.font = this.currentShape.font;
333     this.inputEl.style.color = this.currentShape.color;
334     this.inputEl.style.left = (lc.position.x / lc.backingScale + br.x * lc.scale - 4) + "px";
335     this.inputEl.style.top = (lc.position.y / lc.backingScale + br.y * lc.scale - 4) + "px";
336     if (withMargin && !this.currentShape.forcedWidth) {
337       this.inputEl.style.width = (br.width + 10 + this.currentShape.renderer.emDashWidth) + "px";
338     } else {
339       this.inputEl.style.width = (br.width + 12) + "px";
340     }
341     if (withMargin) {
342       this.inputEl.style.height = (br.height + 10 + this.currentShape.renderer.metrics.leading) + "px";
343     } else {
344       this.inputEl.style.height = (br.height + 10) + "px";
345     }
346     transformString = "scale(" + lc.scale + ")";
347     this.inputEl.style.transform = transformString;
348     this.inputEl.style.webkitTransform = transformString;
349     this.inputEl.style.MozTransform = transformString;
350     this.inputEl.style.msTransform = transformString;
351     return this.inputEl.style.OTransform = transformString;
352   };
354   Text.prototype.optionsStyle = 'font';
356   return Text;
358 })(Tool);