treeItemComponent.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import * as React from "react";
  2. import { Nullable, Observable, IExplorerExtensibilityGroup } from "babylonjs";
  3. import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
  4. import { faPlus, faMinus, faBan, faExpandArrowsAlt, faCompress } from '@fortawesome/free-solid-svg-icons';
  5. import { TreeItemSelectableComponent } from "./treeItemSelectableComponent";
  6. import { Tools } from "../../tools";
  7. interface ITreeItemExpandableHeaderComponentProps {
  8. isExpanded: boolean,
  9. label: string,
  10. onClick: () => void,
  11. onExpandAll: (expand: boolean) => void
  12. }
  13. class TreeItemExpandableHeaderComponent extends React.Component<ITreeItemExpandableHeaderComponentProps> {
  14. constructor(props: ITreeItemExpandableHeaderComponentProps) {
  15. super(props);
  16. }
  17. expandAll() {
  18. this.props.onExpandAll(!this.props.isExpanded);
  19. }
  20. render() {
  21. const chevron = this.props.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
  22. const expandAll = this.props.isExpanded ? <FontAwesomeIcon icon={faCompress} /> : <FontAwesomeIcon icon={faExpandArrowsAlt} />
  23. return (
  24. <div className="expandableHeader">
  25. <div className="text">
  26. <div className="arrow icon" onClick={() => this.props.onClick()}>
  27. {chevron}
  28. </div>
  29. <div className="text-value">
  30. {this.props.label}
  31. </div>
  32. </div>
  33. <div className="expandAll icon" onClick={() => this.expandAll()} title={this.props.isExpanded ? "Collapse all" : "Expand all"}>
  34. {expandAll}
  35. </div>
  36. </div>
  37. )
  38. }
  39. }
  40. interface ITreeItemRootHeaderComponentProps {
  41. label: string
  42. }
  43. class TreeItemRootHeaderComponent extends React.Component<ITreeItemRootHeaderComponentProps> {
  44. constructor(props: ITreeItemRootHeaderComponentProps) {
  45. super(props);
  46. }
  47. render() {
  48. return (
  49. <div className="expandableHeader">
  50. <div className="text">
  51. <div className="arrow icon">
  52. <FontAwesomeIcon icon={faBan} />
  53. </div>
  54. <div className="text-value">
  55. {this.props.label}
  56. </div>
  57. </div>
  58. </div>
  59. )
  60. }
  61. }
  62. export interface ITreeItemComponentProps {
  63. items?: Nullable<any[]>,
  64. label: string,
  65. offset: number,
  66. filter: Nullable<string>,
  67. onSelectionChangedObservable?: Observable<any>,
  68. entity?: any,
  69. selectedEntity: any,
  70. extensibilityGroups?: IExplorerExtensibilityGroup[]
  71. }
  72. export class TreeItemComponent extends React.Component<ITreeItemComponentProps, { isExpanded: boolean, mustExpand: boolean }> {
  73. constructor(props: ITreeItemComponentProps) {
  74. super(props);
  75. this.state = { isExpanded: false, mustExpand: false };
  76. }
  77. switchExpandedState(): void {
  78. this.setState({ isExpanded: !this.state.isExpanded, mustExpand: false });
  79. }
  80. shouldComponentUpdate(nextProps: ITreeItemComponentProps, nextState: { isExpanded: boolean }) {
  81. if (!nextState.isExpanded && this.state.isExpanded) {
  82. return true;
  83. }
  84. const items = nextProps.items;
  85. if (items && items.length) {
  86. if (nextProps.selectedEntity) {
  87. for (var item of items) {
  88. if (Tools.LookForItem(item, nextProps.selectedEntity)) {
  89. nextState.isExpanded = true;
  90. return true;
  91. }
  92. }
  93. }
  94. }
  95. return true;
  96. }
  97. expandAll(expand: boolean) {
  98. this.setState({isExpanded: expand, mustExpand: expand});
  99. }
  100. render() {
  101. const items = this.props.items;
  102. const marginStyle = {
  103. paddingLeft: (10 * (this.props.offset + 0.5)) + "px"
  104. }
  105. if (!items) {
  106. return (
  107. <div className="groupContainer" style={marginStyle}>
  108. <div>
  109. {this.props.label}
  110. </div>
  111. </div>
  112. )
  113. }
  114. if (!items.length) {
  115. return (
  116. <div className="groupContainer" style={marginStyle}>
  117. <TreeItemRootHeaderComponent label={this.props.label} />
  118. </div>
  119. )
  120. }
  121. if (!this.state.isExpanded) {
  122. return (
  123. <div className="groupContainer" style={marginStyle}>
  124. <TreeItemExpandableHeaderComponent isExpanded={false} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
  125. </div >
  126. )
  127. }
  128. const sortedItems = Tools.SortAndFilter(null, items);
  129. return (
  130. <div>
  131. <div className="groupContainer" style={marginStyle}>
  132. <TreeItemExpandableHeaderComponent isExpanded={this.state.isExpanded} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
  133. </div>
  134. {
  135. sortedItems.map(item => {
  136. return (
  137. <TreeItemSelectableComponent mustExpand={this.state.mustExpand} extensibilityGroups={this.props.extensibilityGroups} key={item.uniqueId} offset={this.props.offset + 1} selectedEntity={this.props.selectedEntity} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
  138. );
  139. })
  140. }
  141. </div>
  142. );
  143. }
  144. }