selector.ts 19 KB

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