treeItemSelectableComponent.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { TreeItemSpecializedComponent } from "./treeItemSpecializedComponent";
  2. import { Observable, Nullable, IExplorerExtensibilityGroup } from "babylonjs";
  3. import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
  4. import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
  5. import { Tools } from "../../tools";
  6. import * as ReactDOM from "react-dom";
  7. import * as React from "react";
  8. export interface ITreeItemSelectableComponentProps {
  9. entity: any,
  10. selectedEntity?: any,
  11. mustExpand?: boolean,
  12. offset: number,
  13. extensibilityGroups?: IExplorerExtensibilityGroup[],
  14. onSelectionChangedObservable?: Observable<any>,
  15. filter: Nullable<string>
  16. }
  17. export class TreeItemSelectableComponent extends React.Component<ITreeItemSelectableComponentProps, { isExpanded: boolean, isSelected: boolean }> {
  18. private _wasSelected = false;
  19. constructor(props: ITreeItemSelectableComponentProps) {
  20. super(props);
  21. this.state = { isSelected: this.props.entity === this.props.selectedEntity, isExpanded: this.props.mustExpand || Tools.LookForItem(this.props.entity, this.props.selectedEntity) };
  22. }
  23. switchExpandedState(): void {
  24. this.setState({ isExpanded: !this.state.isExpanded });
  25. }
  26. shouldComponentUpdate(nextProps: ITreeItemSelectableComponentProps, nextState: { isExpanded: boolean, isSelected: boolean }) {
  27. if (!nextState.isExpanded && this.state.isExpanded) {
  28. return true;
  29. }
  30. if (nextProps.selectedEntity) {
  31. if (nextProps.entity === nextProps.selectedEntity) {
  32. nextState.isSelected = true;
  33. return true;
  34. } else {
  35. nextState.isSelected = false;
  36. }
  37. if (Tools.LookForItem(nextProps.entity, nextProps.selectedEntity)) {
  38. nextState.isExpanded = true;
  39. return true;
  40. }
  41. }
  42. return true;
  43. }
  44. scrollIntoView() {
  45. const element = ReactDOM.findDOMNode(this) as Element;
  46. if (element) {
  47. element.scrollIntoView();
  48. }
  49. }
  50. componentDidMount() {
  51. if (this.state.isSelected) {
  52. this.scrollIntoView();
  53. }
  54. }
  55. componentDidUpdate() {
  56. if (this.state.isSelected && !this._wasSelected) {
  57. this.scrollIntoView();
  58. }
  59. this._wasSelected = false;
  60. }
  61. onSelect() {
  62. if (!this.props.onSelectionChangedObservable) {
  63. return;
  64. }
  65. this._wasSelected = true;
  66. const entity = this.props.entity;
  67. this.props.onSelectionChangedObservable.notifyObservers(entity);
  68. }
  69. renderChildren() {
  70. const entity = this.props.entity;
  71. if (!entity.getChildren && !entity.children || !this.state.isExpanded) {
  72. return null;
  73. }
  74. const children = Tools.SortAndFilter(entity, entity.getChildren ? entity.getChildren() : entity.children);
  75. return (
  76. children.map(item => {
  77. return (
  78. <TreeItemSelectableComponent mustExpand={this.props.mustExpand} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.props.selectedEntity} key={item.uniqueId} offset={this.props.offset + 2} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
  79. );
  80. })
  81. )
  82. }
  83. render() {
  84. const marginStyle = {
  85. paddingLeft: (10 * (this.props.offset + 0.5)) + "px"
  86. };
  87. const entity = this.props.entity;
  88. const chevron = this.state.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
  89. const children = Tools.SortAndFilter(entity, entity.getChildren ? entity.getChildren() : entity.children);
  90. const hasChildren = children.length > 0;
  91. if (!entity.reservedDataStore) {
  92. entity.reservedDataStore = {};
  93. }
  94. entity.reservedDataStore.setExpandedState = (value: boolean) => {
  95. this.setState({ isExpanded: value });
  96. }
  97. entity.reservedDataStore.isExpanded = this.state.isExpanded;
  98. if (this.props.filter) {
  99. const lowerCaseFilter = this.props.filter.toLowerCase();
  100. if (!entity.name || entity.name.toLowerCase().indexOf(lowerCaseFilter) === -1) {
  101. if (!hasChildren) {
  102. return null;
  103. }
  104. if (entity.getDescendants) {
  105. if (entity.getDescendants(false, (n: any) => {
  106. console.log(n.name);
  107. return n.name && n.name.toLowerCase().indexOf(lowerCaseFilter) !== -1
  108. }).length === 0) {
  109. return null;
  110. }
  111. }
  112. }
  113. }
  114. return (
  115. <div>
  116. <div className={this.state.isSelected ? "itemContainer selected" : "itemContainer"} style={marginStyle} >
  117. {
  118. hasChildren &&
  119. <div className="arrow icon" onClick={() => this.switchExpandedState()}>
  120. {chevron}
  121. </div>
  122. }
  123. <TreeItemSpecializedComponent extensibilityGroups={this.props.extensibilityGroups} label={entity.name} entity={entity} onClick={() => this.onSelect()} onSelectionChangedObservable={this.props.onSelectionChangedObservable} />
  124. </div>
  125. {
  126. this.renderChildren()
  127. }
  128. </div >
  129. );
  130. }
  131. }