TimelineGrid.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
  3. * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
  4. * Copyright (C) 2009 Google Inc. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  16. * its contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /**
  31. * @constructor
  32. */
  33. WebInspector.TimelineGrid = function()
  34. {
  35. this.element = document.createElement("div");
  36. this._itemsGraphsElement = document.createElement("div");
  37. this._itemsGraphsElement.id = "resources-graphs";
  38. this.element.appendChild(this._itemsGraphsElement);
  39. this._dividersElement = this.element.createChild("div", "resources-dividers");
  40. this._gridHeaderElement = document.createElement("div");
  41. this._eventDividersElement = this._gridHeaderElement.createChild("div", "resources-event-dividers");
  42. this._dividersLabelBarElement = this._gridHeaderElement.createChild("div", "resources-dividers-label-bar");
  43. this.element.appendChild(this._gridHeaderElement);
  44. this._leftCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-left");
  45. this._rightCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-right");
  46. }
  47. WebInspector.TimelineGrid.prototype = {
  48. get itemsGraphsElement()
  49. {
  50. return this._itemsGraphsElement;
  51. },
  52. get dividersElement()
  53. {
  54. return this._dividersElement;
  55. },
  56. get dividersLabelBarElement()
  57. {
  58. return this._dividersLabelBarElement;
  59. },
  60. get gridHeaderElement()
  61. {
  62. return this._gridHeaderElement;
  63. },
  64. removeDividers: function()
  65. {
  66. this._dividersElement.removeChildren();
  67. this._dividersLabelBarElement.removeChildren();
  68. },
  69. updateDividers: function(calculator)
  70. {
  71. var dividersElementClientWidth = this._dividersElement.clientWidth;
  72. var dividerCount = Math.round(dividersElementClientWidth / 64);
  73. var slice = calculator.boundarySpan() / dividerCount;
  74. this._currentDividerSlice = slice;
  75. // Reuse divider elements and labels.
  76. var divider = this._dividersElement.firstChild;
  77. var dividerLabelBar = this._dividersLabelBarElement.firstChild;
  78. var sliceRemainder = (calculator.minimumBoundary() - calculator.zeroTime()) % slice;
  79. for (var i = 0; i <= dividerCount; ++i) {
  80. if (!divider) {
  81. divider = document.createElement("div");
  82. divider.className = "resources-divider";
  83. this._dividersElement.appendChild(divider);
  84. dividerLabelBar = document.createElement("div");
  85. dividerLabelBar.className = "resources-divider";
  86. var label = document.createElement("div");
  87. label.className = "resources-divider-label";
  88. dividerLabelBar._labelElement = label;
  89. dividerLabelBar.appendChild(label);
  90. this._dividersLabelBarElement.appendChild(dividerLabelBar);
  91. }
  92. if (!i) {
  93. divider.addStyleClass("first");
  94. dividerLabelBar.addStyleClass("first");
  95. } else {
  96. divider.removeStyleClass("first");
  97. dividerLabelBar.removeStyleClass("first");
  98. }
  99. if (i === dividerCount) {
  100. divider.addStyleClass("last");
  101. dividerLabelBar.addStyleClass("last");
  102. } else {
  103. divider.removeStyleClass("last");
  104. dividerLabelBar.removeStyleClass("last");
  105. }
  106. var left;
  107. if (!slice) {
  108. left = dividersElementClientWidth / dividerCount * i;
  109. dividerLabelBar._labelElement.textContent = "";
  110. } else {
  111. left = calculator.computePosition(calculator.minimumBoundary() + slice * i - sliceRemainder);
  112. dividerLabelBar._labelElement.textContent = calculator.formatTime(slice * i - sliceRemainder);
  113. }
  114. var percentLeft = 100 * left / dividersElementClientWidth;
  115. this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft);
  116. divider = divider.nextSibling;
  117. dividerLabelBar = dividerLabelBar.nextSibling;
  118. }
  119. // Remove extras.
  120. while (divider) {
  121. var nextDivider = divider.nextSibling;
  122. this._dividersElement.removeChild(divider);
  123. divider = nextDivider;
  124. }
  125. while (dividerLabelBar) {
  126. var nextDivider = dividerLabelBar.nextSibling;
  127. this._dividersLabelBarElement.removeChild(dividerLabelBar);
  128. dividerLabelBar = nextDivider;
  129. }
  130. return true;
  131. },
  132. _setDividerAndBarLeft: function(divider, dividerLabelBar, percentLeft)
  133. {
  134. var percentStyleLeft = parseFloat(divider.style.left);
  135. if (!isNaN(percentStyleLeft) && Math.abs(percentStyleLeft - percentLeft) < 0.1)
  136. return;
  137. divider.style.left = percentLeft + "%";
  138. dividerLabelBar.style.left = percentLeft + "%";
  139. },
  140. addEventDivider: function(divider)
  141. {
  142. this._eventDividersElement.appendChild(divider);
  143. },
  144. addEventDividers: function(dividers)
  145. {
  146. this._gridHeaderElement.removeChild(this._eventDividersElement);
  147. for (var i = 0; i < dividers.length; ++i) {
  148. if (dividers[i])
  149. this._eventDividersElement.appendChild(dividers[i]);
  150. }
  151. this._gridHeaderElement.appendChild(this._eventDividersElement);
  152. },
  153. removeEventDividers: function()
  154. {
  155. this._eventDividersElement.removeChildren();
  156. },
  157. hideEventDividers: function()
  158. {
  159. this._eventDividersElement.addStyleClass("hidden");
  160. },
  161. showEventDividers: function()
  162. {
  163. this._eventDividersElement.removeStyleClass("hidden");
  164. },
  165. hideCurtains: function()
  166. {
  167. this._leftCurtainElement.addStyleClass("hidden");
  168. this._rightCurtainElement.addStyleClass("hidden");
  169. },
  170. /**
  171. * @param {number} gapOffset
  172. * @param {number} gapWidth
  173. */
  174. showCurtains: function(gapOffset, gapWidth)
  175. {
  176. this._leftCurtainElement.style.width = gapOffset + "px";
  177. this._leftCurtainElement.removeStyleClass("hidden");
  178. this._rightCurtainElement.style.left = (gapOffset + gapWidth) + "px";
  179. this._rightCurtainElement.removeStyleClass("hidden");
  180. },
  181. setScrollAndDividerTop: function(scrollTop, dividersTop)
  182. {
  183. this._dividersElement.style.top = scrollTop + "px";
  184. this._leftCurtainElement.style.top = scrollTop + "px";
  185. this._rightCurtainElement.style.top = scrollTop + "px";
  186. }
  187. }
  188. /**
  189. * @interface
  190. */
  191. WebInspector.TimelineGrid.Calculator = function() { }
  192. WebInspector.TimelineGrid.Calculator.prototype = {
  193. /** @param {number} time */
  194. computePosition: function(time) { },
  195. /** @param {number} time */
  196. formatTime: function(time) { },
  197. /** @return {number} */
  198. minimumBoundary: function() { },
  199. /** @return {number} */
  200. zeroTime: function() { },
  201. /** @return {number} */
  202. maximumBoundary: function() { },
  203. /** @return {number} */
  204. boundarySpan: function() { }
  205. }