coordinates.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Graphics utility functions for advanced coordinates.
  16. *
  17. * This file assists the use of advanced coordinates in goog.graphics. Coords
  18. * can be specified as simple numbers which will correspond to units in the
  19. * graphics element's coordinate space. Alternately, coords can be expressed
  20. * in pixels, meaning no matter what tranformations or coordinate system changes
  21. * are present, the number of pixel changes will remain constant. Coords can
  22. * also be expressed as percentages of their parent's size.
  23. *
  24. * This file also allows for elements to have margins, expressable in any of
  25. * the ways described above.
  26. *
  27. * Additional pieces of advanced coordinate functionality can (soon) be found in
  28. * element.js and groupelement.js.
  29. *
  30. * @author robbyw@google.com (Robby Walker)
  31. */
  32. goog.provide('goog.graphics.ext.coordinates');
  33. goog.require('goog.string');
  34. /**
  35. * Cache of boolean values. For a given string (key), is it special? (value)
  36. * @type {Object}
  37. * @private
  38. */
  39. goog.graphics.ext.coordinates.specialCoordinateCache_ = {};
  40. /**
  41. * Determines if the given coordinate is a percent based coordinate or an
  42. * expression with a percent based component.
  43. * @param {string} coord The coordinate to test.
  44. * @return {boolean} Whether the coordinate contains the string '%'.
  45. * @private
  46. */
  47. goog.graphics.ext.coordinates.isPercent_ = function(coord) {
  48. return goog.string.contains(coord, '%');
  49. };
  50. /**
  51. * Determines if the given coordinate is a pixel based coordinate or an
  52. * expression with a pixel based component.
  53. * @param {string} coord The coordinate to test.
  54. * @return {boolean} Whether the coordinate contains the string 'px'.
  55. * @private
  56. */
  57. goog.graphics.ext.coordinates.isPixels_ = function(coord) {
  58. return goog.string.contains(coord, 'px');
  59. };
  60. /**
  61. * Determines if the given coordinate is special - i.e. not just a number.
  62. * @param {string|number|null} coord The coordinate to test.
  63. * @return {boolean} Whether the coordinate is special.
  64. */
  65. goog.graphics.ext.coordinates.isSpecial = function(coord) {
  66. var cache = goog.graphics.ext.coordinates.specialCoordinateCache_;
  67. if (!(coord in cache)) {
  68. cache[coord] = goog.isString(coord) &&
  69. (goog.graphics.ext.coordinates.isPercent_(coord) ||
  70. goog.graphics.ext.coordinates.isPixels_(coord));
  71. }
  72. return cache[coord];
  73. };
  74. /**
  75. * Returns the value of the given expression in the given context.
  76. *
  77. * Should be treated as package scope.
  78. *
  79. * @param {string|number} coord The coordinate to convert.
  80. * @param {number} size The size of the parent element.
  81. * @param {number} scale The ratio of pixels to units.
  82. * @return {number} The number of coordinate space units that corresponds to
  83. * this coordinate.
  84. */
  85. goog.graphics.ext.coordinates.computeValue = function(coord, size, scale) {
  86. var number = parseFloat(String(coord));
  87. if (goog.isString(coord)) {
  88. if (goog.graphics.ext.coordinates.isPercent_(coord)) {
  89. return number * size / 100;
  90. } else if (goog.graphics.ext.coordinates.isPixels_(coord)) {
  91. return number / scale;
  92. }
  93. }
  94. return number;
  95. };
  96. /**
  97. * Converts the given coordinate to a number value in units.
  98. *
  99. * Should be treated as package scope.
  100. *
  101. * @param {string|number} coord The coordinate to retrieve the value for.
  102. * @param {boolean|undefined} forMaximum Whether we are computing the largest
  103. * value this coordinate would be in a parent of no size. The container
  104. * size in this case should be set to the size of the current element.
  105. * @param {number} containerSize The unit value of the size of the container of
  106. * this element. Should be set to the minimum width of this element if
  107. * forMaximum is true.
  108. * @param {number} scale The ratio of pixels to units.
  109. * @param {Object=} opt_cache Optional (but highly recommend) object to store
  110. * cached computations in. The calling class should manage clearing out
  111. * the cache when the scale or containerSize changes.
  112. * @return {number} The correct number of coordinate space units.
  113. */
  114. goog.graphics.ext.coordinates.getValue = function(
  115. coord, forMaximum, containerSize, scale, opt_cache) {
  116. if (!goog.isNumber(coord)) {
  117. var cacheString = opt_cache && ((forMaximum ? 'X' : '') + coord);
  118. if (opt_cache && cacheString in opt_cache) {
  119. coord = opt_cache[cacheString];
  120. } else {
  121. if (goog.graphics.ext.coordinates.isSpecial(
  122. /** @type {string} */ (coord))) {
  123. coord = goog.graphics.ext.coordinates.computeValue(
  124. coord, containerSize, scale);
  125. } else {
  126. // Simple coordinates just need to be converted from a string to a
  127. // number.
  128. coord = parseFloat(/** @type {string} */ (coord));
  129. }
  130. // Cache the result.
  131. if (opt_cache) {
  132. opt_cache[cacheString] = coord;
  133. }
  134. }
  135. }
  136. return coord;
  137. };