selector.ts 19 KB

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