GlossyHorizontalGauge.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. define("dojox/gauges/GlossyHorizontalGauge", ["dojo/_base/declare","dojo/_base/connect","dojo/_base/lang","dojo/_base/Color","dojox/gfx","./BarGauge","./BarCircleIndicator","./GlossyHorizontalGaugeMarker"],
  2. function(declare, connect, lang, Color, gfx, BarGauge, BarCircleIndicator, GlossyHorizontalGaugeMarker) {
  3. var NumberUtils
  4. /*=====
  5. BarGauge = dojox.gauges.BarGauge;
  6. =====*/
  7. return declare("dojox.gauges.GlossyHorizontalGauge", [BarGauge], {
  8. // summary:
  9. // Represents an horizontal bar gauge with a glossy appearance.
  10. //
  11. // example:
  12. // | <div dojoType="dojox.gauges.GlossyHorizontalGauge"
  13. // | id="testGauge"
  14. // | width="500"
  15. // | height="100"
  16. // | min="0"
  17. // | max="100"
  18. // | value="0"
  19. // | majorTicksInterval="10"
  20. // | majorTicksColor="#c4c4c4"
  21. // | minorTicksInterval="5"
  22. // | minorTicksColor="#c4c4c4"
  23. // | color="black"
  24. // | markerColor="#c4c4c4"
  25. // | font="normal normal normal 10pt sans-serif"
  26. // | noChange="true"
  27. // | title="title"
  28. // | scalePrecision="0"
  29. // | >
  30. // | </div>
  31. // the type of default indicator to create
  32. _defaultIndicator: BarCircleIndicator,
  33. // color: String
  34. // The main color of the gauge.
  35. color: 'black',
  36. // needleColor: Color
  37. // The main color of the needle.
  38. markerColor: 'black',
  39. // majorTicksInterval: Number
  40. // Interval between major ticks
  41. majorTicksInterval: 10,
  42. // _majorTicksLength: Number
  43. // Major tick size, at design
  44. _majorTicksLength: 10,
  45. // majorTicksColor: Color
  46. // Color of major tick marks
  47. majorTicksColor: '#c4c4c4',
  48. // minorTicksInterval: Number
  49. // Interval between minor ticks
  50. minorTicksInterval: 5,
  51. // _minorTicksLength: Number
  52. // Minor tick size, at design
  53. _minorTicksLength: 6,
  54. // minorTicksColor: Color
  55. // Color of minor tick marks
  56. minorTicksColor: '#c4c4c4',
  57. // value: Number
  58. // The value of the gauge.
  59. value: 0,
  60. // noChange: Boolean
  61. // Indicates if the gauge reacts to touch events
  62. noChange: false,
  63. // title: String
  64. // The title displayed in the needle's tooltip
  65. title: "",
  66. // font: Object
  67. // The font of the gauge
  68. font: "normal normal normal 10pt serif",
  69. // scalePrecision: Number
  70. // The precision for the formatting of numbers in the scale (default is 0)
  71. scalePrecision: 0,
  72. _font: null,
  73. _margin: 2,
  74. _minBorderWidth: 2,
  75. _maxBorderWidth: 6,
  76. _tickLabelOffset: 5,
  77. _designHeight: 100,
  78. constructor: function(){
  79. this.min = 0;
  80. this.max = 100;
  81. },
  82. startup: function(){
  83. this.inherited(arguments);
  84. if (this._gaugeStarted) return;
  85. this._gaugeStarted = true;
  86. var scale = this.height / this._designHeight;
  87. this._minorTicksLength = this._minorTicksLength * scale;
  88. this._majorTicksLength = this._majorTicksLength * scale;
  89. var font = this._font;
  90. this._computeDataRectangle();
  91. // computing scale height
  92. var th = gfx.normalizedLength(font.size);
  93. var scaleHeight = th + this._tickLabelOffset + Math.max(this._majorTicksLength, this._minorTicksLength);
  94. // indicator in the middle of the gauge
  95. var yOffset = Math.max(0, (this.height - scaleHeight) / 2);
  96. this.addRange({
  97. low: this.min ? this.min : 0,
  98. high: this.max ? this.max : 100,
  99. color: [0, 0, 0, 0]
  100. });
  101. this.setMajorTicks({
  102. fixedPrecision: true,
  103. precision: this.scalePrecision,
  104. font: font,
  105. labelPlacement: 'inside',
  106. offset: yOffset - this._majorTicksLength / 2,
  107. interval: this.majorTicksInterval,
  108. length: this._majorTicksLength,
  109. color: this.majorTicksColor
  110. });
  111. this.setMinorTicks({
  112. labelPlacement: 'inside',
  113. offset: yOffset - this._minorTicksLength / 2,
  114. interval: this.minorTicksInterval,
  115. length: this._minorTicksLength,
  116. color: this.minorTicksColor
  117. });
  118. this._needle = new GlossyHorizontalGaugeMarker({
  119. hideValue: true,
  120. title: this.title,
  121. noChange: this.noChange,
  122. offset: yOffset,
  123. color: this.markerColor,
  124. value: this.value
  125. });
  126. this.addIndicator(this._needle);
  127. connect.connect(this._needle, "valueChanged", lang.hitch(this, function(){
  128. this.value = this._needle.value;
  129. this.onValueChanged();
  130. }));
  131. },
  132. _layoutGauge: function(){
  133. // summary:
  134. // Layout the gauge elements depending on the various parameters (size, font, tick length..)
  135. if (!this._gaugeStarted)
  136. return;
  137. var font = this._font;
  138. this._computeDataRectangle();
  139. var th = gfx.normalizedLength(font.size);
  140. var scaleHeight = th + this._tickLabelOffset + Math.max(this._majorTicksLength, this._minorTicksLength);
  141. // indicator in the middle of the gauge
  142. var yOffset = Math.max(0, (this.height - scaleHeight) / 2);
  143. this._setMajorTicksProperty({
  144. fixedPrecision: true,
  145. precision: this.scalePrecision,
  146. font: font,
  147. offset: yOffset - this._majorTicksLength / 2,
  148. interval: this.majorTicksInterval,
  149. length: this._majorTicksLength
  150. });
  151. this._setMinorTicksProperty({
  152. offset: yOffset - this._minorTicksLength / 2,
  153. interval: this.minorTicksInterval,
  154. length: this._minorTicksLength
  155. });
  156. this.removeIndicator(this._needle);
  157. this._needle.offset = yOffset;
  158. this.addIndicator(this._needle);
  159. },
  160. _formatNumber: function(val){
  161. var NumberUtils = this._getNumberModule();
  162. if(NumberUtils){ // use internationalization if loaded
  163. return NumberUtils.format(val, {
  164. places: this.scalePrecision
  165. });
  166. }else{
  167. return val.toFixed(this.scalePrecision);
  168. }
  169. },
  170. _computeDataRectangle: function(){
  171. // summary:
  172. // Computes the rectangle that defines the data area of the gauge.
  173. if (!this._gaugeStarted)
  174. return;
  175. var font = this._font;
  176. var leftTextMargin = this._getTextWidth(this._formatNumber(this.min), font) / 2;
  177. var rightTextMargin = this._getTextWidth(this._formatNumber(this.max), font) / 2;
  178. var textMargin = Math.max(leftTextMargin, rightTextMargin);
  179. var margin = this._getBorderWidth() + Math.max(this._majorTicksLength, this._majorTicksLength) / 2 + textMargin;
  180. this.dataHeight = this.height;
  181. this.dataY = 0;
  182. this.dataX = margin + this._margin;
  183. this.dataWidth = Math.max(0, this.width - 2 * this.dataX);
  184. },
  185. _getTextWidth: function(s, font){
  186. return gfx._base._getTextBox(s, {
  187. font: gfx.makeFontString(gfx.makeParameters(gfx.defaultFont, font))
  188. }).w ||
  189. 0;
  190. },
  191. _getBorderWidth: function(){
  192. // summary:
  193. // Computes the width of the border surrounding the gauge
  194. return Math.max(this._minBorderWidth, Math.min(this._maxBorderWidth, this._maxBorderWidth * this.height / this._designHeight));
  195. },
  196. drawBackground: function(group){
  197. // summary:
  198. // Draws the background of the gauge
  199. // group: dojox.gfx.Group
  200. // The GFX group where the background must be drawn
  201. if (this._gaugeBackground){
  202. return;
  203. }
  204. var lighterColor = Color.blendColors(new Color(this.color), new Color('white'), 0.4);
  205. this._gaugeBackground = group.createGroup();
  206. var borderWidth = this._getBorderWidth();
  207. var margin = this._margin;
  208. var w = this.width;
  209. var h = this.height;
  210. var radius = Math.min(h / 4, 23);
  211. this._gaugeBackground.createRect({
  212. x: margin,
  213. y: margin,
  214. width: Math.max(0, w - 2 * margin),
  215. height: Math.max(0, h - 2 * margin),
  216. r: radius
  217. }).setFill(this.color);
  218. var left = margin + borderWidth;
  219. var right = w - borderWidth - margin;
  220. var top = margin + borderWidth;
  221. var w2 = w - 2 * borderWidth - 2 * margin;
  222. var h2 = h - 2 * borderWidth - 2 * margin;
  223. if (w2 <= 0 || h2 <= 0)
  224. return;
  225. radius = Math.min(radius, w2 / 2);
  226. radius = Math.min(radius, h2 / 2);
  227. this._gaugeBackground.createRect({
  228. x: left,
  229. y: top,
  230. width: w2,
  231. height: h2,
  232. r: radius
  233. }).setFill({
  234. type: "linear",
  235. x1: left,
  236. y1: 0,
  237. x2: left,
  238. y2: h - borderWidth - margin,
  239. colors: [{
  240. offset: 0,
  241. color: lighterColor
  242. }, {
  243. offset: .2,
  244. color: this.color
  245. }, {
  246. offset: .8,
  247. color: this.color
  248. }, {
  249. offset: 1,
  250. color: lighterColor
  251. }]
  252. });
  253. var f = 4 * (Math.sqrt(2) - 1) / 3 * radius;
  254. this._gaugeBackground.createPath({
  255. path: 'M' + left + ' ' + (top + radius) +
  256. 'C' +
  257. left +
  258. ' ' +
  259. (top + radius - f) +
  260. ' ' +
  261. (left + radius - f) +
  262. ' ' +
  263. top +
  264. ' ' +
  265. (left + radius) +
  266. ' ' +
  267. top +
  268. 'L' +
  269. (right - radius) +
  270. ' ' +
  271. top +
  272. 'C' +
  273. (right - radius + f) +
  274. ' ' +
  275. top +
  276. ' ' +
  277. right +
  278. ' ' +
  279. (top + radius - f) +
  280. ' ' +
  281. right +
  282. ' ' +
  283. (top + radius) +
  284. 'L' +
  285. right +
  286. ' ' +
  287. (top + h / 2) +
  288. 'L' +
  289. left +
  290. ' ' +
  291. (top + h / 3) +
  292. 'Z'
  293. }).setFill({
  294. type: "linear",
  295. x1: left,
  296. y1: top,
  297. x2: left,
  298. y2: top + this.height / 2,
  299. colors: [{
  300. offset: 0,
  301. color: lighterColor
  302. }, {
  303. offset: 1,
  304. color: Color.blendColors(new Color(this.color), new Color('white'), 0.2)
  305. }]
  306. });
  307. },
  308. onValueChanged: function(){
  309. // summary:
  310. // Callback when the value of the gauge has changed.
  311. },
  312. //*******************************************************************************************
  313. //* Property getters and setters
  314. //*******************************************************************************************
  315. _setColorAttr: function(color){
  316. // summary:
  317. // Sets the main color of the gauge
  318. // color: String
  319. // The color
  320. this.color = color ? color : 'black';
  321. if (this._gaugeBackground && this._gaugeBackground.parent)
  322. this._gaugeBackground.parent.remove(this._gaugeBackground);
  323. this._gaugeBackground = null;
  324. this.draw();
  325. },
  326. _setMarkerColorAttr: function(color){
  327. // summary:
  328. // Sets the main color of the marker
  329. // color: String
  330. // The color
  331. this.markerColor = color;
  332. if (this._needle){
  333. this.removeIndicator(this._needle);
  334. this._needle.color = color;
  335. this._needle.shape = null;
  336. this.addIndicator(this._needle);
  337. }
  338. },
  339. _setMajorTicksIntervalAttr: function(interval){
  340. // summary:
  341. // Sets the interval between major ticks
  342. this.majorTicksInterval = interval;
  343. this._setMajorTicksProperty({
  344. 'interval': this.majorTicksInterval
  345. });
  346. },
  347. setMajorTicksLength: function(length){
  348. // summary:
  349. // Sets the size of the major ticks.
  350. this._majorTicksLength = length;
  351. this._layoutGauge();
  352. return this;
  353. },
  354. getMajorTicksLength: function(){
  355. // summary:
  356. // Returns the size of the major ticks.
  357. return this._majorTicksLength;
  358. },
  359. _setMajorTicksColorAttr: function(color){
  360. // summary:
  361. // Sets the color of the major ticks.
  362. this.majorTicksColor = color;
  363. this._setMajorTicksProperty({
  364. 'color': this.majorTicksColor
  365. });
  366. },
  367. _setMajorTicksProperty: function(prop){
  368. if (this.majorTicks == null){
  369. return;
  370. }
  371. lang.mixin(this.majorTicks, prop);
  372. this.setMajorTicks(this.majorTicks);
  373. },
  374. _setMinorTicksIntervalAttr: function(interval){
  375. // summary:
  376. // Sets the interval between minor ticks
  377. this.minorTicksInterval = interval;
  378. this._setMinorTicksProperty({
  379. 'interval': this.minorTicksInterval
  380. });
  381. },
  382. setMinorTicksLength: function(length){
  383. // summary:
  384. // Sets the size of the minor ticks.
  385. this._minorTicksLength = length;
  386. this._layoutGauge();
  387. return this;
  388. },
  389. getMinorTicksLength: function(){
  390. // summary:
  391. // Gets the size of the minor ticks.
  392. return this._minorTicksLength;
  393. },
  394. _setMinorTicksColorAttr: function(color){
  395. // summary:
  396. // Sets the color of the minor ticks.
  397. this.minorTicksColor = color;
  398. this._setMinorTicksProperty({
  399. 'color': this.minorTicksColor
  400. });
  401. },
  402. _setMinorTicksProperty: function(prop){
  403. if (this.minorTicks == null){
  404. return;
  405. }
  406. lang.mixin(this.minorTicks, prop);
  407. this.setMinorTicks(this.minorTicks);
  408. },
  409. _setMinAttr: function(min){
  410. this.min = min;
  411. this._computeDataRectangle();
  412. if (this.majorTicks != null)
  413. this.setMajorTicks(this.majorTicks);
  414. if (this.minorTicks != null)
  415. this.setMinorTicks(this.minorTicks);
  416. this.draw();
  417. },
  418. _setMaxAttr: function(max){
  419. this.max = max;
  420. this._computeDataRectangle();
  421. if (this.majorTicks != null)
  422. this.setMajorTicks(this.majorTicks);
  423. if (this.minorTicks != null)
  424. this.setMinorTicks(this.minorTicks);
  425. this.draw();
  426. },
  427. _setValueAttr: function(value){
  428. // summary:
  429. // Changes the value of the gauge
  430. // value: Number
  431. // The new value for the gauge.
  432. value = Math.min(this.max, value);
  433. value = Math.max(this.min, value);
  434. this.value = value;
  435. if (this._needle){
  436. // update will not work if noChange is true.
  437. var noChange = this._needle.noChange;
  438. this._needle.noChange = false;
  439. this._needle.update(value);
  440. this._needle.noChange = noChange;
  441. }
  442. },
  443. _setScalePrecisionAttr: function(value){
  444. // summary:
  445. // Changes precision of the numbers in the scale of the gauge
  446. // value: Number
  447. // The new value
  448. this.scalePrecision = value;
  449. this._layoutGauge();
  450. },
  451. _setNoChangeAttr: function(value){
  452. // summary:
  453. // Indicates if the value of the gauge can be changed or not
  454. // value: boolean
  455. // true indicates that the gauge's value cannot be changed
  456. this.noChange = value;
  457. if (this._needle)
  458. this._needle.noChange = this.noChange;
  459. },
  460. _setTitleAttr: function(value){
  461. // summary:
  462. // Sets the title displayed by the needle's tooltip .
  463. // value: String
  464. // the title
  465. this.title = value;
  466. if (this._needle){
  467. this._needle.title = this.title;
  468. }
  469. },
  470. _setFontAttr: function(font){
  471. // summary:
  472. // Sets the font of the gauge
  473. // summary:
  474. // Sets the font of the gauge
  475. // font: String
  476. // An string representing the font such as 'normal normal normal 10pt Helvetica,Arial,sans-serif'
  477. //
  478. this.font = font;
  479. this._font = gfx.splitFontString(font);
  480. this._layoutGauge();
  481. }
  482. });
  483. });