selector.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. import {Rectangle} from "./rectangle";
  2. import {StackPanel} from "./stackPanel";
  3. import {Control} from "./control";
  4. import {TextBlock} from "./textBlock";
  5. import {Checkbox} from "./checkbox";
  6. import {RadioButton} from "./radioButton";
  7. import {Slider} from "./slider";
  8. /** Class used to create a RadioGroup
  9. * which contains groups of radio buttons
  10. */
  11. export class SelectorGroup {
  12. private _groupPanel = new StackPanel();
  13. private _selectors: StackPanel[] = new Array();
  14. private _groupHeader: TextBlock;
  15. /**
  16. * Creates a new SelectorGroup
  17. * @param name of group, used as a group heading
  18. */
  19. constructor(
  20. /** name of SelectorGroup */
  21. public name: string, ) {
  22. this._groupPanel.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  23. this._groupPanel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  24. this._groupHeader = this._addGroupHeader(name);
  25. }
  26. /** Gets the groupPanel of the SelectorGroup */
  27. public get groupPanel(): StackPanel {
  28. return this._groupPanel;
  29. }
  30. /** Gets the selectors array */
  31. public get selectors(): StackPanel[] {
  32. return this._selectors;
  33. }
  34. /** Gets and sets the group header */
  35. public get header() {
  36. return this._groupHeader.text;
  37. }
  38. public set header(label: string) {
  39. if(this._groupHeader.text === "label") {
  40. return
  41. }
  42. this._groupHeader.text = label
  43. }
  44. /** @hidden */
  45. private _addGroupHeader(text: string): TextBlock {
  46. var groupHeading = new TextBlock("groupHead", text);
  47. groupHeading.width = 0.9;
  48. groupHeading.height = "30px";
  49. groupHeading.textWrapping = true;
  50. groupHeading.color = "black";
  51. groupHeading.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  52. groupHeading.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  53. groupHeading.left = "2px";
  54. this._groupPanel.addControl(groupHeading);
  55. return groupHeading;
  56. }
  57. /** @hidden*/
  58. public _getSelector(selectorNb: number) {
  59. if(selectorNb < 0 || selectorNb >= this._selectors.length) {
  60. return;
  61. }
  62. return this._selectors[selectorNb];
  63. }
  64. /** Removes the selector at the given position
  65. * @param selectorNb the position of the selector within the group
  66. */
  67. public removeSelector(selectorNb: number) {
  68. if(selectorNb < 0 || selectorNb >= this._selectors.length) {
  69. return;
  70. }
  71. this._groupPanel.removeControl(this._selectors[selectorNb]);
  72. this._selectors.splice(selectorNb, 1);
  73. }
  74. }
  75. /** Class used to create a CheckboxGroup
  76. * which contains groups of checkbox buttons
  77. */
  78. export class CheckboxGroup extends SelectorGroup{
  79. /** Adds a checkbox as a control
  80. * @param text is the label for the selector
  81. * @param func is the function called when the Selector is checked
  82. * @param checked is true when Selector is checked
  83. */
  84. public addCheckbox(text: string, func = (s: boolean)=>{}, checked: boolean = false): void {
  85. var checked = checked || false;
  86. var button = new Checkbox();
  87. button.width = "20px";
  88. button.height = "20px";
  89. button.color = "#364249";
  90. button.background = "#CCCCCC";
  91. button.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  92. button.onIsCheckedChangedObservable.add(function(state) {
  93. func(state);
  94. });
  95. var _selector = Control.AddHeader(button, text, "200px", { isHorizontal: true, controlFirst: true });
  96. _selector.height = "30px";
  97. _selector.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  98. _selector.left = "4px";
  99. this.groupPanel.addControl(_selector);
  100. this.selectors.push(_selector);
  101. button.isChecked = checked;
  102. if(this.groupPanel.parent && this.groupPanel.parent.parent) {
  103. button.color = (<SelectionPanel>this.groupPanel.parent.parent).buttonColor;
  104. button.background = (<SelectionPanel>this.groupPanel.parent.parent).buttonBackground;
  105. }
  106. }
  107. /** @hidden */
  108. public _setSelectorLabel(selectorNb: number, label: string) {
  109. (<TextBlock>this.selectors[selectorNb].children[1]).text = label;
  110. }
  111. /** @hidden */
  112. public _setSelectorLabelColor(selectorNb: number, color: string) {
  113. (<TextBlock>this.selectors[selectorNb].children[1]).color = color;
  114. }
  115. /** @hidden */
  116. public _setSelectorButtonColor(selectorNb: number, color: string) {
  117. this.selectors[selectorNb].children[0].color = color;
  118. }
  119. /** @hidden */
  120. public _setSelectorButtonBackground(selectorNb: number, color: string) {
  121. (<Checkbox>this.selectors[selectorNb].children[0]).background = color;
  122. }
  123. }
  124. /** Class used to create a RadioGroup
  125. * which contains groups of radio buttons
  126. */
  127. export class RadioGroup extends SelectorGroup{
  128. private _selectNb = 0;
  129. /** Adds a radio button as a control
  130. * @param label is the label for the selector
  131. * @param func is the function called when the Selector is checked
  132. * @param checked is true when Selector is checked
  133. */
  134. public addRadio(label: string, func = (n:number) => {} , checked = false): void {
  135. var nb = this._selectNb++;
  136. var button = new RadioButton();
  137. button.name = label;
  138. button.width = "20px";
  139. button.height = "20px";
  140. button.color = "#364249";
  141. button.background = "#CCCCCC";
  142. button.group = this.name;
  143. button.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  144. button.onIsCheckedChangedObservable.add(function(state) {
  145. if(state) {
  146. func(nb);
  147. }
  148. });
  149. var _selector = Control.AddHeader(button, label, "200px", { isHorizontal: true, controlFirst: true });
  150. _selector.height = "30px";
  151. _selector.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  152. _selector.left = "4px";
  153. this.groupPanel.addControl(_selector);
  154. this.selectors.push(_selector);
  155. button.isChecked = checked;
  156. if(this.groupPanel.parent && this.groupPanel.parent.parent) {
  157. button.color = (<SelectionPanel>this.groupPanel.parent.parent).buttonColor;
  158. button.background = (<SelectionPanel>this.groupPanel.parent.parent).buttonBackground;
  159. }
  160. }
  161. /** @hidden */
  162. public _setSelectorLabel(selectorNb: number, label: string) {
  163. (<TextBlock>this.selectors[selectorNb].children[1]).text = label;
  164. }
  165. /** @hidden */
  166. public _setSelectorLabelColor(selectorNb: number, color: string) {
  167. (<TextBlock>this.selectors[selectorNb].children[1]).color = color;
  168. }
  169. /** @hidden */
  170. public _setSelectorButtonColor(selectorNb: number, color: string) {
  171. this.selectors[selectorNb].children[0].color = color;
  172. }
  173. /** @hidden */
  174. public _setSelectorButtonBackground(selectorNb: number, color: string) {
  175. (<RadioButton>this.selectors[selectorNb].children[0]).background = color;
  176. }
  177. }
  178. /** Class used to create a SliderGroup
  179. * which contains groups of slider buttons
  180. */
  181. export class SliderGroup extends SelectorGroup{
  182. /**
  183. * Adds a slider to the SelectorGroup
  184. * @param label is the label for the SliderBar
  185. * @param func is the function called when the Slider moves
  186. * @param unit is a string describing the units used, eg degrees or metres
  187. * @param min is the minimum value for the Slider
  188. * @param max is the maximum value for the Slider
  189. * @param value is the start value for the Slider between min and max
  190. * @param onValueChange is the function used to format the value displayed, eg radians to degrees
  191. */
  192. public addSlider(label: string, func = (v:number) => {}, unit: string = "Units", min: number = 0, max: number = 0, value: number = 0, onValueChange = (v:number)=>{return v | 0}): void {
  193. var button = new Slider();
  194. button.name = unit;
  195. button.value = value;
  196. button.minimum = min;
  197. button.maximum = max;
  198. button.width = 0.9;
  199. button.height = "20px";
  200. button.color = "#364249";
  201. button.background = "#CCCCCC";
  202. button.borderColor = "black";
  203. button.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  204. button.left = "4px";
  205. button.paddingBottom = "4px";
  206. button.onValueChangedObservable.add(function(value) {
  207. (<TextBlock>button.parent!.children[0]).text = button.parent!.children[0].name + ": " + onValueChange(value) + " " + button.name;
  208. func(value);
  209. });
  210. var _selector = Control.AddHeader(button, label + ": " + onValueChange(value) + " " + unit, "30px", { isHorizontal: false, controlFirst: false });
  211. _selector.height = "60px";
  212. _selector.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  213. _selector.left = "4px";
  214. _selector.children[0].name = label;
  215. this.groupPanel.addControl(_selector);
  216. this.selectors.push(_selector);
  217. if(this.groupPanel.parent && this.groupPanel.parent.parent) {
  218. button.color = (<SelectionPanel>this.groupPanel.parent.parent).buttonColor;
  219. button.background = (<SelectionPanel>this.groupPanel.parent.parent).buttonBackground;
  220. }
  221. }
  222. /** @hidden */
  223. public _setSelectorLabel(selectorNb: number, label: string) {
  224. this.selectors[selectorNb].children[0].name = label;
  225. (<TextBlock>this.selectors[selectorNb].children[0]).text = label + ": " + (<Slider>this.selectors[selectorNb].children[1]).value + " " + this.selectors[selectorNb].children[1].name;
  226. }
  227. /** @hidden */
  228. public _setSelectorLabelColor(selectorNb: number, color: string) {
  229. (<TextBlock>this.selectors[selectorNb].children[0]).color = color;
  230. }
  231. /** @hidden */
  232. public _setSelectorButtonColor(selectorNb: number, color: string) {
  233. this.selectors[selectorNb].children[1].color = color;
  234. }
  235. /** @hidden */
  236. public _setSelectorButtonBackground(selectorNb: number, color: string) {
  237. (<Slider>this.selectors[selectorNb].children[1]).background = color;
  238. }
  239. }
  240. /** Class used to hold the controls for the checkboxes, radio buttons and sliders
  241. * @see http://doc.babylonjs.com/how_to/selector
  242. */
  243. export class SelectionPanel extends Rectangle {
  244. private _panel: StackPanel;
  245. private _buttonColor: string = "#364249";
  246. private _buttonBackground: string = "#CCCCCC";
  247. private _headerColor: string = "black";
  248. private _barColor: string = "white";
  249. private _labelColor: string;
  250. private _groups: SelectorGroup[];
  251. private _bars: any[] = new Array();
  252. /**
  253. * Creates a new SelectionPanel
  254. * @param name of SelectionPanel
  255. * @param groups is an array of SelectionGroups
  256. */
  257. constructor(
  258. /** name of SelectionPanel */
  259. public name: string,
  260. /** an array of SelectionGroups */
  261. public groups: SelectorGroup[] = []) {
  262. super(name);
  263. this._groups = groups;
  264. this.thickness = 4;
  265. this._panel = new StackPanel();
  266. this._panel.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  267. this._panel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  268. this._panel.top = 5;
  269. this._panel.left = 5;
  270. this._panel.width = 0.95;
  271. if(groups.length > 0) {
  272. for(var i = 0; i < groups.length - 1; i++) {
  273. this._panel.addControl(groups[i].groupPanel);
  274. this._addSpacer();
  275. }
  276. this._panel.addControl(groups[groups.length - 1].groupPanel);
  277. }
  278. this.addControl(this._panel);
  279. }
  280. protected _getTypeName(): string {
  281. return "SelectionPanel";
  282. }
  283. /** Gets or sets the headerColor */
  284. public get headerColor(): string {
  285. return this._headerColor;
  286. }
  287. public set headerColor(color: string) {
  288. if(this._headerColor === color) {
  289. return;
  290. }
  291. this._headerColor = color;
  292. this._setHeaderColor();
  293. }
  294. private _setHeaderColor() {
  295. for(var i = 0; i < this._groups.length; i++) {
  296. this._groups[i].groupPanel.children[0].color = this._headerColor;
  297. }
  298. }
  299. /** Gets or sets the button color */
  300. public get buttonColor(): string {
  301. return this._buttonColor;
  302. }
  303. public set buttonColor(color: string) {
  304. if(this._buttonColor === color) {
  305. return;
  306. }
  307. this._buttonColor = color;
  308. this._setbuttonColor();
  309. }
  310. private _setbuttonColor() {
  311. for(var i = 0; i < this._groups.length; i++) {
  312. for(var j = 0; j < this._groups[i].selectors.length; j++) {
  313. (<CheckboxGroup|RadioGroup|SliderGroup>this._groups[i])._setSelectorButtonColor(j, this._buttonColor);
  314. }
  315. }
  316. }
  317. /** Gets or sets the label color */
  318. public get labelColor(): string {
  319. return this._labelColor;
  320. }
  321. public set labelColor(color: string) {
  322. if(this._labelColor === color) {
  323. return;
  324. }
  325. this._labelColor = color;
  326. this._setLabelColor();
  327. }
  328. private _setLabelColor() {
  329. for(var i = 0; i < this._groups.length; i++) {
  330. for(var j = 0; j < this._groups[i].selectors.length; j++) {
  331. (<CheckboxGroup|RadioGroup|SliderGroup>this._groups[i])._setSelectorLabelColor(j, this._labelColor);
  332. }
  333. }
  334. }
  335. /** Gets or sets the button background */
  336. public get buttonBackground(): string {
  337. return this._buttonBackground;
  338. }
  339. public set buttonBackground(color: string) {
  340. if(this._buttonBackground === color) {
  341. return;
  342. }
  343. this._buttonBackground = color;
  344. this._setButtonBackground();
  345. }
  346. private _setButtonBackground() {
  347. for(var i = 0; i < this._groups.length; i++) {
  348. for(var j = 0; j < this._groups[i].selectors.length; j++) {
  349. (<CheckboxGroup|RadioGroup|SliderGroup>this._groups[i])._setSelectorButtonBackground(j, this._buttonBackground);
  350. }
  351. }
  352. }
  353. /** Gets or sets the color of separator bar */
  354. public get barColor(): string {
  355. return this._barColor;
  356. }
  357. public set barColor(color: string) {
  358. if(this._barColor === color) {
  359. return;
  360. }
  361. this._barColor = color;
  362. this._setBarColor();
  363. }
  364. private _setBarColor() {
  365. for(var i = 0; i < this._bars.length; i++) {
  366. this._bars[i].background = this._barColor;
  367. }
  368. }
  369. /** Adds a bar between groups */
  370. private _addSpacer(): void {
  371. var separator = new Rectangle();
  372. separator.width = 1;
  373. separator.height = "5px";
  374. separator.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  375. separator.background = this._barColor;
  376. separator.color = "transparent";
  377. this._panel.addControl(separator);
  378. this._bars.push(separator);
  379. }
  380. /** Add a group to the selection panel
  381. * @param group is the selector group to add
  382. */
  383. public addGroup(group: SelectorGroup): void {
  384. if(this._groups.length > 0) {
  385. this._addSpacer();
  386. }
  387. this._panel.addControl(group.groupPanel);
  388. this._groups.push(group);
  389. group.groupPanel.children[0].color = this._headerColor;
  390. for(var j = 0; j < group.selectors.length; j++) {
  391. (<CheckboxGroup|RadioGroup|SliderGroup>group)._setSelectorButtonColor(j, this._buttonColor);
  392. (<CheckboxGroup|RadioGroup|SliderGroup>group)._setSelectorButtonBackground(j, this._buttonBackground);
  393. }
  394. }
  395. /** Remove the group from the given position
  396. * @param groupNb is the position of the group in the list
  397. */
  398. public removeGroup(groupNb: number): void {
  399. if(groupNb < 0 || groupNb >= this._groups.length) {
  400. return;
  401. }
  402. var group = this._groups[groupNb];
  403. this._panel.removeControl(group.groupPanel);
  404. this._groups.splice(groupNb, 1);
  405. if(groupNb < this._bars.length) {
  406. this._panel.removeControl(this._bars[groupNb]);
  407. this._bars.splice(groupNb, 1);
  408. }
  409. }
  410. /** Change a group header label
  411. * @param label is the new group header label
  412. * @param groupNb is the number of the group to relabel
  413. * */
  414. public setHeaderName(label: string, groupNb: number) {
  415. if(groupNb < 0 || groupNb >= this._groups.length) {
  416. return;
  417. }
  418. var group = this._groups[groupNb];
  419. (<TextBlock>group.groupPanel.children[0]).text = label;
  420. }
  421. /** Change selector label to the one given
  422. * @param label is the new selector label
  423. * @param groupNb is the number of the groupcontaining the selector
  424. * @param selectorNb is the number of the selector within a group to relabel
  425. * */
  426. public relabel(label: string, groupNb: number, selectorNb: number): void {
  427. if(groupNb < 0 || groupNb >= this._groups.length) {
  428. return;
  429. }
  430. var group = this._groups[groupNb];
  431. if(selectorNb < 0 || selectorNb >= group.selectors.length) {
  432. return;
  433. }
  434. (<CheckboxGroup|RadioGroup|SliderGroup>group)._setSelectorLabel(selectorNb, label);
  435. }
  436. /** For a given group position remove the selector at the given position
  437. * @param groupNb is the number of the group to remove the selector from
  438. * @param selectorNb is the number of the selector within the group
  439. */
  440. public removeFromGroupSelector(groupNb: number, selectorNb: number): void {
  441. if(groupNb < 0 || groupNb >= this._groups.length) {
  442. return;
  443. }
  444. var group = this._groups[groupNb];
  445. if(selectorNb < 0 || selectorNb >= group.selectors.length) {
  446. return;
  447. }
  448. group.removeSelector(selectorNb);
  449. }
  450. /** For a given group position of correct type add a checkbox button
  451. * @param groupNb is the number of the group to remove the selector from
  452. * @param label is the label for the selector
  453. * @param func is the function called when the Selector is checked
  454. * @param checked is true when Selector is checked
  455. */
  456. public addToGroupCheckbox(groupNb: number, label: string, func = () => {} , checked: boolean = false): void {
  457. if(groupNb < 0 || groupNb >= this._groups.length) {
  458. return;
  459. }
  460. var group = this._groups[groupNb];
  461. (<CheckboxGroup>group).addCheckbox(label, func, checked);
  462. }
  463. /** For a given group position of correct type add a radio button
  464. * @param groupNb is the number of the group to remove the selector from
  465. * @param label is the label for the selector
  466. * @param func is the function called when the Selector is checked
  467. * @param checked is true when Selector is checked
  468. */
  469. public addToGroupRadio(groupNb: number, label: string, func = () => {} , checked: boolean = false): void {
  470. if(groupNb < 0 || groupNb >= this._groups.length) {
  471. return;
  472. }
  473. var group = this._groups[groupNb];
  474. (<RadioGroup>group).addRadio(label, func, checked);
  475. }
  476. /**
  477. * For a given slider group add a slider
  478. * @param groupNb is the number of the group to add the slider to
  479. * @param label is the label for the Slider
  480. * @param func is the function called when the Slider moves
  481. * @param unit is a string describing the units used, eg degrees or metres
  482. * @param min is the minimum value for the Slider
  483. * @param max is the maximum value for the Slider
  484. * @param value is the start value for the Slider between min and max
  485. * @param onVal is the function used to format the value displayed, eg radians to degrees
  486. */
  487. public addToGroupSlider(groupNb: number, label: string, func = () => {}, unit: string = "Units", min: number = 0, max: number = 0, value: number = 0, onVal = (v:number)=>{return v | 0}): void {
  488. if(groupNb < 0 || groupNb >= this._groups.length) {
  489. return;
  490. }
  491. var group = this._groups[groupNb];
  492. (<SliderGroup>group).addSlider(label, func, unit, min, max, value, onVal);
  493. }
  494. }