1 | define(["dojo/_base/lang", "dojo/_base/declare", "dojo/dom-geometry", "dijit/registry", "dijit/_WidgetBase", "dojo/_base/html", |
---|
2 | "dojo/_base/event", "dojox/gfx", "dojox/widget/_Invalidating","./ScaleBase", "dojox/gfx/matrix"], |
---|
3 | function(lang, // lang.extend |
---|
4 | declare, domGeom, WidgetRegistry, _WidgetBase, html, event, gfx, _Invalidating, ScaleBase, matrix){ |
---|
5 | return declare("dojox.dgauges.GaugeBase", [_WidgetBase, _Invalidating], { |
---|
6 | // summary: |
---|
7 | // This class is the base class for the circular and |
---|
8 | // rectangular (horizontal and vertical) gauge components. |
---|
9 | // A gauge is a composition of elements added to the gauge using the addElement method. |
---|
10 | // Elements are drawn from back to front in the same order they are added (using addElement). |
---|
11 | // An elements can be: |
---|
12 | // |
---|
13 | // - A GFX drawing functions typically used for defining the style of the gauge. |
---|
14 | // - A scale: CircularScale or RectangularScale depending on the type of gauge. |
---|
15 | // - A text, using the TextIndicator |
---|
16 | // Note: Indicator classes (value indicators, range indicators) are sub-elements of scales |
---|
17 | // To create a custom gauge, subclass CircularGauge or RectangularGauge and |
---|
18 | // configure its elements in the constructor. |
---|
19 | // Ready to use, predefined gauges are available in dojox/dgauges/components/ |
---|
20 | // They are good examples of gauges built on top of the framework. |
---|
21 | |
---|
22 | _elements: null, |
---|
23 | _scales: null, |
---|
24 | _elementsIndex: null, |
---|
25 | _elementsRenderers: null, |
---|
26 | _gfxGroup: null, |
---|
27 | _mouseShield: null, |
---|
28 | _widgetBox: null, |
---|
29 | _node: null, |
---|
30 | |
---|
31 | // value: Number |
---|
32 | // This property acts as a top-level wrapper for the value of the first indicator added to |
---|
33 | // its scale with the name "indicator", i.e. myScale.addIndicator("indicator", myIndicator). |
---|
34 | // This property must be manipulated with get("value") and set("value", xxx). |
---|
35 | value: 0, |
---|
36 | _mainIndicator: null, |
---|
37 | |
---|
38 | _getValueAttr: function(){ |
---|
39 | // summary: |
---|
40 | // Internal method. |
---|
41 | // tags: |
---|
42 | // private |
---|
43 | if(this._mainIndicator){ |
---|
44 | return this._mainIndicator.get("value"); |
---|
45 | }else{ |
---|
46 | this._setMainIndicator(); |
---|
47 | if(this._mainIndicator){ |
---|
48 | return this._mainIndicator.get("value"); |
---|
49 | } |
---|
50 | } |
---|
51 | return this.value; |
---|
52 | }, |
---|
53 | |
---|
54 | _setValueAttr: function(value){ |
---|
55 | // summary: |
---|
56 | // Internal method. |
---|
57 | // tags: |
---|
58 | // private |
---|
59 | this._set("value", value); |
---|
60 | if(this._mainIndicator){ |
---|
61 | this._mainIndicator.set("value", value); |
---|
62 | }else{ |
---|
63 | this._setMainIndicator(); |
---|
64 | if(this._mainIndicator){ |
---|
65 | this._mainIndicator.set("value", value); |
---|
66 | } |
---|
67 | } |
---|
68 | }, |
---|
69 | |
---|
70 | _setMainIndicator: function(){ |
---|
71 | // summary: |
---|
72 | // Internal method. |
---|
73 | // tags: |
---|
74 | // private |
---|
75 | var indicator; |
---|
76 | for(var i=0; i<this._scales.length; i++){ |
---|
77 | indicator = this._scales[i].getIndicator("indicator"); |
---|
78 | if(indicator){ |
---|
79 | this._mainIndicator = indicator; |
---|
80 | } |
---|
81 | } |
---|
82 | }, |
---|
83 | |
---|
84 | _resetMainIndicator: function(){ |
---|
85 | // summary: |
---|
86 | // Internal method. |
---|
87 | // tags: |
---|
88 | // private |
---|
89 | this._mainIndicator = null; |
---|
90 | }, |
---|
91 | |
---|
92 | // font: Object |
---|
93 | // The font of the gauge used by elements if not overridden. |
---|
94 | font: null, |
---|
95 | |
---|
96 | constructor: function(/* Object */args, /* DOMNode */ node){ |
---|
97 | this.font = { |
---|
98 | family: "Helvetica", |
---|
99 | style: "normal", |
---|
100 | variant: "small-caps", |
---|
101 | weight: "bold", |
---|
102 | size: "10pt", |
---|
103 | color: "black" |
---|
104 | }; |
---|
105 | this._elements = []; |
---|
106 | this._scales = []; |
---|
107 | this._elementsIndex = {}; |
---|
108 | this._elementsRenderers = {}; |
---|
109 | this._node = WidgetRegistry.byId(node); |
---|
110 | var box = html.getMarginBox(node); |
---|
111 | |
---|
112 | this.surface = gfx.createSurface(this._node, box.w || 1, box.h || 1); |
---|
113 | this._widgetBox = box; |
---|
114 | // _baseGroup is a workaround for http://bugs.dojotoolkit.org/ticket/14471 |
---|
115 | this._baseGroup = this.surface.createGroup(); |
---|
116 | this._mouseShield = this._baseGroup.createGroup(); |
---|
117 | this._gfxGroup = this._baseGroup.createGroup(); |
---|
118 | }, |
---|
119 | |
---|
120 | _setCursor: function(type){ |
---|
121 | // summary: |
---|
122 | // Internal method. |
---|
123 | // tags: |
---|
124 | // private |
---|
125 | if(this._node) |
---|
126 | this._node.style.cursor = type; |
---|
127 | }, |
---|
128 | |
---|
129 | _computeBoundingBox: function(/* Object */element){ |
---|
130 | // summary: |
---|
131 | // Internal method. |
---|
132 | // tags: |
---|
133 | // private |
---|
134 | return element ? element.getBoundingBox() : {x:0, y:0, width:0, height:0}; |
---|
135 | }, |
---|
136 | |
---|
137 | destroy: function(){ |
---|
138 | // summary: |
---|
139 | // Cleanup when a gauge is to be destroyed. |
---|
140 | this.surface.destroy(); |
---|
141 | this.inherited(arguments); |
---|
142 | }, |
---|
143 | |
---|
144 | resize: function(width, height){ |
---|
145 | // summary: |
---|
146 | // Resize the gauge to the dimensions of width and height. |
---|
147 | // description: |
---|
148 | // Resize the gauge and its surface to the width and height dimensions. |
---|
149 | // If a single argument of the form {w: value1, h: value2} is provided take that argument as the dimensions to use. |
---|
150 | // Finally if no argument is provided, resize the surface to the marginBox of the gauge. |
---|
151 | // width: Number|Object? |
---|
152 | // The new width of the gauge or the box definition. |
---|
153 | // height: Number? |
---|
154 | // The new height of the gauge. |
---|
155 | // returns: dojox/dgauges/GaugeBase |
---|
156 | // A reference to the current gauge for functional chaining. |
---|
157 | switch(arguments.length){ |
---|
158 | // case 0, do not resize the div, just the surface |
---|
159 | case 1: |
---|
160 | // argument, override node box |
---|
161 | domGeom.setMarginBox(this._node, width); |
---|
162 | break; |
---|
163 | case 2: |
---|
164 | |
---|
165 | // argument, override node box |
---|
166 | domGeom.setMarginBox(this._node, {w: width, h: height}); |
---|
167 | break; |
---|
168 | } |
---|
169 | // in all cases take back the computed box |
---|
170 | var box = domGeom.getMarginBox(this._node); |
---|
171 | this._widgetBox = box; |
---|
172 | var d = this.surface.getDimensions(); |
---|
173 | if(d.width != box.w || d.height != box.h){ |
---|
174 | // and set it on the surface |
---|
175 | this.surface.setDimensions(box.w, box.h); |
---|
176 | this._mouseShield.clear(); |
---|
177 | this._mouseShield.createRect({x:0,y:0,width:box.w,height:box.h}).setFill([0, 0, 0, 0]); |
---|
178 | return this.invalidateRendering(); |
---|
179 | }else{ |
---|
180 | return this; |
---|
181 | } |
---|
182 | }, |
---|
183 | |
---|
184 | addElement: function(/* String */name, /* Object */ element){ |
---|
185 | // summary: |
---|
186 | // Adds a element to the gauge. |
---|
187 | // name: String |
---|
188 | // The name of the element to be added. |
---|
189 | // element: Object |
---|
190 | // This parameter can be: |
---|
191 | // |
---|
192 | // - A function which takes on argument of type GFX Group and return null or a |
---|
193 | // GFX element retrievable using the getElementRenderer() method. |
---|
194 | // - A Scale instance, i.e. CircularScale or RectangularScale. |
---|
195 | // - A TextIndicator instance. |
---|
196 | if(this._elementsIndex[name] && this._elementsIndex[name] != element){ |
---|
197 | this.removeElement(name); |
---|
198 | } |
---|
199 | |
---|
200 | if(lang.isFunction(element)){ |
---|
201 | var gfxHolder = {}; |
---|
202 | lang.mixin(gfxHolder, new _Invalidating()); |
---|
203 | gfxHolder._name = name; |
---|
204 | gfxHolder._gfxGroup = this._gfxGroup.createGroup(); |
---|
205 | gfxHolder.width = 0; |
---|
206 | gfxHolder.height = 0; |
---|
207 | gfxHolder._isGFX = true; |
---|
208 | gfxHolder.refreshRendering = function(){ |
---|
209 | gfxHolder._gfxGroup.clear(); |
---|
210 | return element(gfxHolder._gfxGroup, gfxHolder.width, gfxHolder.height); |
---|
211 | }; |
---|
212 | this._elements.push(gfxHolder); |
---|
213 | this._elementsIndex[name] = gfxHolder; |
---|
214 | }else{ |
---|
215 | element._name = name; |
---|
216 | element._gfxGroup = this._gfxGroup.createGroup(); |
---|
217 | element._gauge = this; |
---|
218 | this._elements.push(element); |
---|
219 | this._elementsIndex[name] = element; |
---|
220 | |
---|
221 | if(element instanceof ScaleBase){ |
---|
222 | this._scales.push(element); |
---|
223 | } |
---|
224 | } |
---|
225 | return this.invalidateRendering(); |
---|
226 | }, |
---|
227 | |
---|
228 | removeElement: function(/* String */name){ |
---|
229 | // summary: |
---|
230 | // Remove the element defined by name from the gauge. |
---|
231 | // name: String |
---|
232 | // The name of the element as defined using addElement. |
---|
233 | // returns: Object |
---|
234 | // A reference to the removed element. |
---|
235 | |
---|
236 | var element = this._elementsIndex[name]; |
---|
237 | |
---|
238 | if(element){ |
---|
239 | element._gfxGroup.removeShape(); |
---|
240 | var idx = this._elements.indexOf(element); |
---|
241 | this._elements.splice(idx, 1); |
---|
242 | |
---|
243 | if(element instanceof ScaleBase){ |
---|
244 | var idxs = this._scales.indexOf(element); |
---|
245 | this._scales.splice(idxs, 1); |
---|
246 | this._resetMainIndicator(); |
---|
247 | } |
---|
248 | delete this._elementsIndex[name]; |
---|
249 | delete this._elementsRenderers[name]; |
---|
250 | } |
---|
251 | this.invalidateRendering(); |
---|
252 | return element; |
---|
253 | }, |
---|
254 | |
---|
255 | getElement: function(/* String */name){ |
---|
256 | // summary: |
---|
257 | // Get the given element, by name. |
---|
258 | // name: String |
---|
259 | // The name of the element as defined using addElement. |
---|
260 | // returns: Object |
---|
261 | // The element. |
---|
262 | return this._elementsIndex[name]; |
---|
263 | }, |
---|
264 | |
---|
265 | getElementRenderer: function(/* String */name){ |
---|
266 | // summary: |
---|
267 | // Get the given element renderer, by name. |
---|
268 | // name: String |
---|
269 | // The name of the element as defined using addElement. |
---|
270 | // returns: Object |
---|
271 | // The element renderer returned by the |
---|
272 | // drawing function or by the refreshRendering() method |
---|
273 | // in the case of framework classes. |
---|
274 | return this._elementsRenderers[name]; |
---|
275 | }, |
---|
276 | |
---|
277 | onStartEditing: function(event){ |
---|
278 | // summary: |
---|
279 | // Called when an interaction begins (keyboard, mouse or gesture). |
---|
280 | // event: |
---|
281 | // On object with a unique member "indicator". This member is a reference to the modified indicator. |
---|
282 | // tags: |
---|
283 | // callback |
---|
284 | }, |
---|
285 | |
---|
286 | onEndEditing: function(event){ |
---|
287 | // summary: |
---|
288 | // Called when an interaction ends (keyboard, mouse or gesture). |
---|
289 | // event: |
---|
290 | // On object with a unique member "indicator". This member is a reference to the modified indicator. |
---|
291 | // tags: |
---|
292 | // callback |
---|
293 | } |
---|
294 | }) |
---|
295 | }); |
---|