scrollViewer.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import { Measure } from "../measure";
  2. import { Rectangle } from "./rectangle";
  3. import { Grid } from "./grid";
  4. import { Control } from "./control";
  5. import { Slider } from "./slider";
  6. import { ValueAndUnit } from "../valueAndUnit";
  7. import { Container } from "./container";
  8. import { TextBlock } from "./textBlock";
  9. /**
  10. * Class used to hold a viewer window and sliders in a grid
  11. */
  12. export class ScrollViewer extends Rectangle {
  13. private _grid: Grid;
  14. private _horizontalBarSpace: Rectangle;
  15. private _verticalBarSpace: Rectangle;
  16. private _dragSpace: Rectangle;
  17. private _horizontalBar: Slider;
  18. private _verticalBar: Slider;
  19. private _barColor: string = "grey";
  20. private _barBorderColor: string = "#444444";
  21. private _barBackground: string = "white";
  22. private _scrollGridWidth: number = 30;
  23. private _scrollGridHeight: number = 30;
  24. private _widthScale: number;
  25. private _heightScale: number;
  26. private _endLeft: number;
  27. private _endTop: number;
  28. private _window: Container;
  29. private _windowContents: Control;
  30. /**
  31. * Adds windowContents to the grid view window
  32. * @param windowContents the contents to add the grid view window
  33. */
  34. public addToWindow(windowContents: Control): void {
  35. this._window.removeControl(this._windowContents);
  36. this._windowContents.dispose();
  37. this._windowContents = windowContents;
  38. if (windowContents.typeName === "TextBlock") {
  39. this._updateTextBlock(windowContents);
  40. }
  41. else {
  42. this._updateScroller(windowContents);
  43. }
  44. this._window.addControl(windowContents);
  45. }
  46. /**
  47. * Gets or sets a value indicating the padding to use on the left of the viewer window
  48. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  49. */
  50. public get paddingLeft(): string | number {
  51. return this._windowContents.paddingLeft;
  52. }
  53. /**
  54. * Gets a value indicating the padding in pixels to use on the left of the viewer window
  55. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  56. */
  57. public get paddingLeftInPixels(): number {
  58. return this._windowContents.paddingLeftInPixels;
  59. }
  60. public set paddingLeft(value: string | number) {
  61. this._windowContents.paddingLeft = value;
  62. }
  63. /**
  64. * Gets or sets a value indicating the padding to use on the right of the viewer window
  65. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  66. */
  67. public get paddingRight(): string | number {
  68. return this._windowContents.paddingRight;
  69. }
  70. /**
  71. * Gets a value indicating the padding in pixels to use on the right of the viewer window
  72. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  73. */
  74. public get paddingRightInPixels(): number {
  75. return this._windowContents.paddingRightInPixels;
  76. }
  77. public set paddingRight(value: string | number) {
  78. this._windowContents.paddingRight = value;
  79. }
  80. /**
  81. * Gets or sets a value indicating the padding to use on the top of the viewer window
  82. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  83. */
  84. public get paddingTop(): string | number {
  85. return this._windowContents.paddingTop;
  86. }
  87. /**
  88. * Gets a value indicating the padding in pixels to use on the top of the viewer window
  89. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  90. */
  91. public get paddingTopInPixels(): number {
  92. return this._windowContents.paddingTopInPixels;
  93. }
  94. public set paddingTop(value: string | number) {
  95. this._windowContents.paddingTop = value;
  96. }
  97. /**
  98. * Gets or sets a value indicating the padding to use on the bottom of the viewer window
  99. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  100. */
  101. public get paddingBottom(): string | number {
  102. return this._windowContents.paddingBottom;
  103. }
  104. /**
  105. * Gets a value indicating the padding in pixels to use on the bottom of the viewer window
  106. * @see http://doc.babylonjs.com/how_to/gui#position-and-size
  107. */
  108. public get paddingBottomInPixels(): number {
  109. return this._windowContents.paddingBottomInPixels;
  110. }
  111. public set paddingBottom(value: string | number) {
  112. this._windowContents.paddingBottom = value;
  113. }
  114. /**
  115. * Creates a new ScrollViewer
  116. * @param name of ScrollViewer
  117. */
  118. constructor(
  119. /** name of ScrollViewer */
  120. public name?: string) {
  121. super(name);
  122. this.onDirtyObservable.add(() => {
  123. this._horizontalBarSpace.color = this.color;
  124. this._verticalBarSpace.color = this.color;
  125. this._dragSpace.color = this.color;
  126. this._updateScroller(this._windowContents);
  127. if (this._windowContents.typeName === "TextBlock") {
  128. this._updateTextBlock(this._windowContents);
  129. }
  130. });
  131. this._grid = new Grid();
  132. this._horizontalBar = new Slider();
  133. this._verticalBar = new Slider();
  134. this._window = new Container();
  135. this._window.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  136. this._window.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  137. this._windowContents = new Control();
  138. this._window.addControl(this._windowContents);
  139. this._width = new ValueAndUnit(0.25, ValueAndUnit.UNITMODE_PERCENTAGE, false);
  140. this._height = new ValueAndUnit(0.25, ValueAndUnit.UNITMODE_PERCENTAGE, false);
  141. this._background = "black";
  142. this.fontSize = "16px";
  143. this._grid.addColumnDefinition(1, true);
  144. this._grid.addColumnDefinition(this._scrollGridWidth, true);
  145. this._grid.addRowDefinition(1, true);
  146. this._grid.addRowDefinition(this._scrollGridHeight, true);
  147. this.addControl(this._grid);
  148. this._grid.addControl(this._window, 0, 0);
  149. this._verticalBar.paddingLeft = 0;
  150. this._verticalBar.width = "25px";
  151. this._verticalBar.value = 0;
  152. this._verticalBar.maximum = 100;
  153. this._verticalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
  154. this._verticalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
  155. this._verticalBar.left = 0.05;
  156. this._verticalBar.isThumbClamped = true;
  157. this._verticalBar.color = "grey";
  158. this._verticalBar.borderColor = "#444444";
  159. this._verticalBar.background = "white";
  160. this._verticalBar.isVertical = true;
  161. this._verticalBar.rotation = Math.PI;
  162. this._verticalBarSpace = new Rectangle();
  163. this._verticalBarSpace.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  164. this._verticalBarSpace.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  165. this._verticalBarSpace.color = this.color;
  166. this._verticalBarSpace.thickness = 1;
  167. this._grid.addControl(this._verticalBarSpace, 0, 1);
  168. this._verticalBarSpace.addControl(this._verticalBar);
  169. this._verticalBar.onValueChangedObservable.add((value) => {
  170. this._window.top = value * this._endTop / 100 + "px";
  171. });
  172. this._horizontalBar.paddingLeft = 0;
  173. this._horizontalBar.height = "25px";
  174. this._horizontalBar.value = 0;
  175. this._horizontalBar.maximum = 100;
  176. this._horizontalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
  177. this._horizontalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
  178. this._horizontalBar.left = 0.05;
  179. this._horizontalBar.isThumbClamped = true;
  180. this._horizontalBar.color = "grey";
  181. this._horizontalBar.borderColor = "#444444";
  182. this._horizontalBar.background = "white";
  183. this._horizontalBarSpace = new Rectangle();
  184. this._horizontalBarSpace.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  185. this._horizontalBarSpace.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  186. this._horizontalBarSpace.color = this.color;
  187. this._horizontalBarSpace.thickness = 1;
  188. this._grid.addControl(this._horizontalBarSpace, 1, 0);
  189. this._horizontalBarSpace.addControl(this._horizontalBar);
  190. this._horizontalBar.onValueChangedObservable.add((value) => {
  191. this._window.left = value * this._endLeft / 100 + "px";
  192. });
  193. this._dragSpace = new Rectangle();
  194. this._dragSpace.color = this.color;
  195. this._dragSpace.thickness = 2;
  196. this._dragSpace.background = this._barColor;
  197. this._grid.addControl(this._dragSpace, 1, 1);
  198. }
  199. /** Gets or sets the bar color */
  200. public get barColor(): string {
  201. return this._barColor;
  202. }
  203. public set barColor(color: string) {
  204. if (this._barColor === color) {
  205. return;
  206. }
  207. this._barColor = color;
  208. this._horizontalBar.color = color;
  209. this._verticalBar.color = color;
  210. this._dragSpace.background = color;
  211. }
  212. /** Gets or sets the bar color */
  213. public get barBorderColor(): string {
  214. return this._barBorderColor;
  215. }
  216. public set barBorderColor(color: string) {
  217. if (this._barBorderColor === color) {
  218. return;
  219. }
  220. this._barBorderColor = color;
  221. this._horizontalBar.borderColor = color;
  222. this._verticalBar.borderColor = color;
  223. }
  224. /** Gets or sets the bar background */
  225. public get barBackground(): string {
  226. return this._barBackground;
  227. }
  228. public set barBackground(color: string) {
  229. if (this._barBackground === color) {
  230. return;
  231. }
  232. this._barBackground = color;
  233. this._horizontalBar.background = color;
  234. this._verticalBar.background = color;
  235. }
  236. /** @hidden */
  237. protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  238. super._additionalProcessing(parentMeasure, context);
  239. let viewerWidth = this._width.getValueInPixel(this._host, parentMeasure.width);
  240. let viewerHeight = this._height.getValueInPixel(this._host, parentMeasure.height);
  241. let innerWidth = viewerWidth - this._scrollGridWidth - 2 * this.thickness;
  242. let innerHeight = viewerHeight - this._scrollGridHeight - 2 * this.thickness;
  243. this._horizontalBar.width = (innerWidth * 0.8) + "px";
  244. this._verticalBar.height = (innerHeight * 0.8) + "px";
  245. this._grid.setColumnDefinition(0, innerWidth, true);
  246. this._grid.setRowDefinition(0, innerHeight, true);
  247. }
  248. /** @hidden */
  249. private _updateScroller(windowContents: Control): void {
  250. let windowContentsWidth: number = parseFloat(windowContents.width.toString());
  251. if (windowContents._width.unit === 0) {
  252. this._widthScale = windowContentsWidth / 100;
  253. windowContentsWidth = this._host.getSize().width * this._widthScale;
  254. windowContents.width = windowContentsWidth + "px";
  255. }
  256. let windowContentsHeight: number = parseFloat(windowContents.height.toString());
  257. if (windowContents._height.unit === 0) {
  258. this._heightScale = windowContentsHeight / 100;
  259. windowContentsHeight = this._host.getSize().height * this._heightScale;
  260. windowContents.height = this._host.getSize().height * this._heightScale + "px";
  261. }
  262. this._window.width = windowContents.width;
  263. this._window.height = windowContents.height;
  264. this._windowContents.width = windowContents.width;
  265. this._windowContents.height = windowContents.height;
  266. let viewerWidth = this._width.getValueInPixel(this._host, this._host.getSize().width);
  267. let viewerHeight = this._height.getValueInPixel(this._host, this._host.getSize().height);
  268. let innerWidth = viewerWidth - this._scrollGridWidth - 2 * this.thickness;
  269. let innerHeight = viewerHeight - this._scrollGridHeight - 2 * this.thickness;
  270. if (windowContentsWidth <= innerWidth) {
  271. this._grid.setRowDefinition(0, viewerHeight - 2 * this.thickness , true);
  272. this._grid.setRowDefinition(1, 0, true);
  273. this._horizontalBar.isVisible = false;
  274. }
  275. else {
  276. this._grid.setRowDefinition(0, innerHeight, true);
  277. this._grid.setRowDefinition(1, this._scrollGridHeight, true);
  278. this._horizontalBar.isVisible = true;
  279. }
  280. if (windowContentsHeight < innerHeight) {
  281. this._grid.setColumnDefinition(0, viewerWidth - 2 * this.thickness, true);
  282. this._grid.setColumnDefinition(1, 0, true);
  283. this._verticalBar.isVisible = false;
  284. }
  285. else {
  286. this._grid.setColumnDefinition(0, innerWidth, true);
  287. this._grid.setColumnDefinition(1, this._scrollGridWidth, true);
  288. this._verticalBar.isVisible = true;
  289. }
  290. this._endLeft = innerWidth - windowContentsWidth;
  291. this._endTop = innerHeight - windowContentsHeight;
  292. }
  293. /** @hidden */
  294. private _updateTextBlock(windowContents: Control): void {
  295. let viewerWidth = this._width.getValueInPixel(this._host, this._host.getSize().width);
  296. let innerWidth = viewerWidth - this._scrollGridWidth - 2 * this.thickness;
  297. windowContents.width = innerWidth + "px";
  298. this._window.width = windowContents.width;
  299. this._windowContents.width = windowContents.width;
  300. (<TextBlock>windowContents).onLinesReadyObservable.add(() => {
  301. let windowContentsHeight = (this.fontOffset.height) * (<TextBlock>windowContents).lines.length + windowContents.paddingTopInPixels + windowContents.paddingBottomInPixels;
  302. windowContents.height = windowContentsHeight + "px";
  303. this._window.height = windowContents.height;
  304. this._windowContents.height = windowContents.height;
  305. this._updateScroller(windowContents);
  306. });
  307. }
  308. }