| 967 | |
| 968 | // TODO Maybe split this into two methods: expand() and collapse() |
| 969 | toggleIsCollapsed(id: number, isCollapsed: boolean): void { |
| 970 | let didMutate = false; |
| 971 | |
| 972 | const element = this.getElementByID(id); |
| 973 | if (element !== null) { |
| 974 | if (isCollapsed) { |
| 975 | if (element.type === ElementTypeRoot) { |
| 976 | this._throwAndEmitError(Error('Root nodes cannot be collapsed')); |
| 977 | } |
| 978 | |
| 979 | if (!element.isCollapsed) { |
| 980 | didMutate = true; |
| 981 | element.isCollapsed = true; |
| 982 | |
| 983 | const weightDelta = 1 - element.weight; |
| 984 | |
| 985 | let parentElement = this._idToElement.get(element.parentID); |
| 986 | while (parentElement !== undefined) { |
| 987 | // We don't need to break on a collapsed parent in the same way as the expand case below. |
| 988 | // That's because collapsing a node doesn't "bubble" and affect its parents. |
| 989 | parentElement.weight += weightDelta; |
| 990 | parentElement = this._idToElement.get(parentElement.parentID); |
| 991 | } |
| 992 | } |
| 993 | } else { |
| 994 | let currentElement: ?Element = element; |
| 995 | while (currentElement != null) { |
| 996 | const oldWeight = currentElement.isCollapsed |
| 997 | ? 1 |
| 998 | : currentElement.weight; |
| 999 | |
| 1000 | if (currentElement.isCollapsed) { |
| 1001 | didMutate = true; |
| 1002 | currentElement.isCollapsed = false; |
| 1003 | |
| 1004 | const newWeight = currentElement.isCollapsed |
| 1005 | ? 1 |
| 1006 | : currentElement.weight; |
| 1007 | const weightDelta = newWeight - oldWeight; |
| 1008 | |
| 1009 | let parentElement = this._idToElement.get(currentElement.parentID); |
| 1010 | while (parentElement !== undefined) { |
| 1011 | parentElement.weight += weightDelta; |
| 1012 | if (parentElement.isCollapsed) { |
| 1013 | // It's important to break on a collapsed parent when expanding nodes. |
| 1014 | // That's because expanding a node "bubbles" up and expands all parents as well. |
| 1015 | // Breaking in this case prevents us from over-incrementing the expanded weights. |
| 1016 | break; |
| 1017 | } |
| 1018 | parentElement = this._idToElement.get(parentElement.parentID); |
| 1019 | } |
| 1020 | } |
| 1021 | |
| 1022 | currentElement = |
| 1023 | currentElement.parentID !== 0 |
| 1024 | ? this.getElementByID(currentElement.parentID) |
| 1025 | : null; |
| 1026 | } |