treeItemComponent.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. <span className="arrow icon" onClick={() => this.props.onClick()}>
  27. {chevron}
  28. </span> {this.props.label}
  29. </div>
  30. <div className="expandAll icon" onClick={() => this.expandAll()} title={this.props.isExpanded ? "Collapse all" : "Expand all"}>
  31. {expandAll}
  32. </div>
  33. </div>
  34. )
  35. }
  36. }
  37. interface ITreeItemRootHeaderComponentProps {
  38. label: string
  39. }
  40. class TreeItemRootHeaderComponent extends React.Component<ITreeItemRootHeaderComponentProps> {
  41. constructor(props: ITreeItemRootHeaderComponentProps) {
  42. super(props);
  43. }
  44. render() {
  45. return (
  46. <div>
  47. <span className="arrow icon">
  48. <FontAwesomeIcon icon={faBan} />
  49. </span> {this.props.label}
  50. </div>
  51. )
  52. }
  53. }
  54. export interface ITreeItemComponentProps {
  55. items?: Nullable<any[]>,
  56. label: string,
  57. offset: number,
  58. filter: Nullable<string>,
  59. onSelectionChangedObservable?: Observable<any>,
  60. entity?: any,
  61. selectedEntity: any,
  62. extensibilityGroups?: IExplorerExtensibilityGroup[]
  63. }
  64. export class TreeItemComponent extends React.Component<ITreeItemComponentProps, { isExpanded: boolean, mustExpand: boolean }> {
  65. constructor(props: ITreeItemComponentProps) {
  66. super(props);
  67. this.state = { isExpanded: false, mustExpand: false };
  68. }
  69. switchExpandedState(): void {
  70. this.setState({ isExpanded: !this.state.isExpanded, mustExpand: false });
  71. }
  72. shouldComponentUpdate(nextProps: ITreeItemComponentProps, nextState: { isExpanded: boolean }) {
  73. if (!nextState.isExpanded && this.state.isExpanded) {
  74. return true;
  75. }
  76. const items = nextProps.items;
  77. if (items && items.length) {
  78. if (nextProps.selectedEntity) {
  79. for (var item of items) {
  80. if (Tools.LookForItem(item, nextProps.selectedEntity)) {
  81. nextState.isExpanded = true;
  82. return true;
  83. }
  84. }
  85. }
  86. }
  87. return true;
  88. }
  89. expandAll(expand: boolean) {
  90. this.setState({isExpanded: expand, mustExpand: expand});
  91. }
  92. render() {
  93. const items = this.props.items;
  94. const marginStyle = {
  95. paddingLeft: (10 * (this.props.offset + 0.5)) + "px"
  96. }
  97. if (!items) {
  98. return (
  99. <div className="groupContainer" style={marginStyle}>
  100. <div>
  101. {this.props.label}
  102. </div>
  103. </div>
  104. )
  105. }
  106. if (!items.length) {
  107. return (
  108. <div className="groupContainer" style={marginStyle}>
  109. <TreeItemRootHeaderComponent label={this.props.label} />
  110. </div>
  111. )
  112. }
  113. if (!this.state.isExpanded) {
  114. return (
  115. <div className="groupContainer" style={marginStyle}>
  116. <TreeItemExpandableHeaderComponent isExpanded={false} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
  117. </div >
  118. )
  119. }
  120. const sortedItems = Tools.SortAndFilter(null, items);
  121. return (
  122. <div>
  123. <div className="groupContainer" style={marginStyle}>
  124. <TreeItemExpandableHeaderComponent isExpanded={this.state.isExpanded} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
  125. </div>
  126. {
  127. sortedItems.map(item => {
  128. return (
  129. <TreeItemSelectableComponent mustExpand={this.state.mustExpand} extensibilityGroups={this.props.extensibilityGroups} key={item.uniqueId} offset={this.props.offset + 2} selectedEntity={this.props.selectedEntity} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
  130. );
  131. })
  132. }
  133. </div>
  134. );
  135. }
  136. }