treeItemSelectableComponent.tsx 5.1 KB

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