Skip to content

[Tree widget]: parent elements correct visibility on next#1686

Merged
JonasDov merged 28 commits into
tree-widget/nextfrom
JonasD/phase-3
May 22, 2026
Merged

[Tree widget]: parent elements correct visibility on next#1686
JonasDov merged 28 commits into
tree-widget/nextfrom
JonasD/phase-3

Conversation

@JonasDov
Copy link
Copy Markdown
Contributor

@JonasDov JonasDov commented May 19, 2026

Phase 3a. of #1678.

Skipping phase 2 for now, since it would add child categories (and visibilities would become confusing). Will do it after phase 3 is done. Changes:

BaseVisibilityHelper.ts:

  • Rewrote getElementsVisibilityStatus to compute descendant visibility per-category using DescendantsCountCache
  • Added getElementsOwnVisibilityStatus - computes element's own visibility without descendants
  • Added getDescendantsVisibilityStatus - groups descendant categories by default visibility (visible/hidden), queries always/neverDrawn sets filtered by category, and merges statuses
  • Replaced childrenCount parameter with computeOnlyOwnStatus flag
  • Simplified getVisibilityFromAlwaysAndNeverDrawnElements now it accepts only category path (previously element and category)

AlwaysAndNeverDrawnElementInfoCache.ts:

  • Added optional childCategoryIds?: Id64Set filter to getAlwaysOrNeverDrawnElements - returns only elements whose actual category matches the filter

Tree handlers (models, categories, classifications):

  • Removed childrenCount from all getElementsVisibilityStatus calls
  • Search results: non-search-target elements now use computeOnlyOwnStatus: true instead of childrenCount: undefined
  • Removed childrenCount/searchTargets from grouping node extended data and tree definitions
  • Cleaned up groupingNodeDataFromChildren utility

Copilot AI review requested due to automatic review settings May 19, 2026 13:57
@JonasDov JonasDov requested review from a team as code owners May 19, 2026 13:57
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tree-Widget Next benchmark

Benchmark suite Current: 778a56b Previous: 514cc88 Deviation Status
models tree 50k 3D elements search > get search paths 946 ms 1236 ms -23.46%
models tree 50k 3D elements search > get search paths (P95 of main thread blocks) 55 ms 60 ms -8.33% 〰️
models tree 50k 3D elements search > load hierarchy from search paths 94539 ms 110512 ms -14.45%
models tree 50k 3D elements search > load hierarchy from search paths (P95 of main thread blocks) 26 ms 37 ms -29.73% 〰️
models tree 50k categories > collect nodes 2486 ms 2893 ms -14.07%
models tree 50k categories > collect nodes (P95 of main thread blocks) 73 ms 131 ms -44.27%
models tree 50k categories > validate initial visibility 1838 ms 2078 ms -11.55%
models tree 50k categories > validate initial visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k categories > change visibility 67 ms 71 ms -5.63% 〰️
models tree 50k categories > change visibility (P95 of main thread blocks) 57 ms 60 ms -5% 〰️
models tree 50k categories > validate changed visibility 3273 ms 3685 ms -11.18%
models tree 50k categories > validate changed visibility (P95 of main thread blocks) 23 ms 22 ms 4.55% 〰️
models tree 50k 3D elements > collect nodes 36931 ms 43988 ms -16.04%
models tree 50k 3D elements > collect nodes (P95 of main thread blocks) 56 ms 69 ms -18.84% 〰️
models tree 50k 3D elements > validate initial visibility 1512 ms 2096 ms -27.86%
models tree 50k 3D elements > validate initial visibility (P95 of main thread blocks) 0 ms 26 ms -100% 〰️
models tree 50k 3D elements > change model visibility 15 ms 20 ms -25% 〰️
models tree 50k 3D elements > change model visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > validate changed model visibility 3122 ms 2050 ms 52.29% 🚨
models tree 50k 3D elements > validate changed model visibility (P95 of main thread blocks) 25 ms 0 ms 2500% 〰️
models tree 50k 3D elements > change category node visibility 411 ms 517 ms -20.50%
models tree 50k 3D elements > change category node visibility (P95 of main thread blocks) 43 ms 57 ms -24.56% 〰️
models tree 50k 3D elements > validate changed category visibility 1982 ms 2053 ms -3.46% 〰️
models tree 50k 3D elements > validate changed category visibility (P95 of main thread blocks) 33 ms 0 ms 3300% 〰️
models tree 50k 3D elements > validate per-model category override 1808 ms 2019 ms -10.45%
models tree 50k 3D elements > validate per-model category override (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > change element visibility 33 ms 56 ms -41.07% 〰️
models tree 50k 3D elements > change element visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D elements > validate changed element visibility 2244 ms 2779 ms -19.25%
models tree 50k 3D elements > validate changed element visibility (P95 of main thread blocks) 58 ms 86 ms -32.56% 〰️
models tree 50k 3D child elements with different categories > collect nodes 37849 ms 44118 ms -14.21%
models tree 50k 3D child elements with different categories > collect nodes (P95 of main thread blocks) 49 ms 62 ms -20.97% 〰️
models tree 50k 3D child elements with different categories > validate initial visibility 1544 ms 1992 ms -22.49%
models tree 50k 3D child elements with different categories > validate initial visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D child elements with different categories > change visibility 50 ms 52 ms -3.85% 〰️
models tree 50k 3D child elements with different categories > change visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
models tree 50k 3D child elements with different categories > validate changed visibility 3821 ms 2793 ms 36.81% 🚨
models tree 50k 3D child elements with different categories > validate changed visibility (P95 of main thread blocks) 146 ms 68 ms 114.71% 🚨
categories tree 50k subCategories search > get search paths 1476 ms 1824 ms -19.08%
categories tree 50k subCategories search > get search paths (P95 of main thread blocks) 31 ms 42 ms -26.19% 〰️
categories tree 50k subCategories search > load hierarchy from search paths 4303 ms 5443 ms -20.94%
categories tree 50k subCategories search > load hierarchy from search paths (P95 of main thread blocks) 36 ms 48 ms -25% 〰️
categories tree 50k subCategories > collect nodes 4699 ms 5948 ms -21.00%
categories tree 50k subCategories > collect nodes (P95 of main thread blocks) 34 ms 45 ms -24.44% 〰️
categories tree 50k subCategories > validate initial visibility 1083 ms 1219 ms -11.16%
categories tree 50k subCategories > validate initial visibility (P95 of main thread blocks) 22 ms 25 ms -12% 〰️
categories tree 50k subCategories > change visibility 339 ms 348 ms -2.59% 〰️
categories tree 50k subCategories > change visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
categories tree 50k subCategories > validate changed visibility 1080 ms 1142 ms -5.43% 〰️
categories tree 50k subCategories > validate changed visibility (P95 of main thread blocks) 28 ms 25 ms 12% 〰️
categories tree 50k categories > collect nodes 2070 ms 2481 ms -16.57%
categories tree 50k categories > collect nodes (P95 of main thread blocks) 118 ms 131 ms -9.92% 〰️
categories tree 50k categories > validate initial visibility 5576 ms 6393 ms -12.78%
categories tree 50k categories > validate initial visibility (P95 of main thread blocks) 109 ms 130 ms -16.15% 〰️
categories tree 50k categories > change visibility 662 ms 673 ms -1.63% 〰️
categories tree 50k categories > change visibility (P95 of main thread blocks) 50 ms 49 ms 2.04% 〰️
categories tree 50k categories > validate changed visibility 5197 ms 6092 ms -14.69%
categories tree 50k categories > validate changed visibility (P95 of main thread blocks) 40 ms 34 ms 17.65% 〰️
classifications tree 50k classifications search > get search paths 1722 ms 2177 ms -20.90%
classifications tree 50k classifications search > get search paths (P95 of main thread blocks) 119 ms 126 ms -5.56% 〰️
classifications tree 50k classifications search > load hierarchy from search paths 58202 ms 67599 ms -13.90%
classifications tree 50k classifications search > load hierarchy from search paths (P95 of main thread blocks) 0 ms 31 ms -100% 〰️
classifications tree 50k classifications > collect nodes 27878 ms 36671 ms -23.98%
classifications tree 50k classifications > collect nodes (P95 of main thread blocks) 72 ms 88 ms -18.18% 〰️
classifications tree 50k classifications > validate initial visibility 3590 ms 4143 ms -13.35%
classifications tree 50k classifications > validate initial visibility (P95 of main thread blocks) 55 ms 72 ms -23.61% 〰️
classifications tree 50k classifications > change visibility 26 ms 30 ms -13.33% 〰️
classifications tree 50k classifications > change visibility (P95 of main thread blocks) 0 ms 0 ms 0% 🟰
classifications tree 50k classifications > validate changed visibility 3915 ms 4484 ms -12.69%
classifications tree 50k classifications > validate changed visibility (P95 of main thread blocks) 74 ms 83 ms -10.84% 〰️

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Tree Widget element visibility computation to correctly reflect parent-element visibility when navigating “next”, by separating an element’s own visibility from its descendants’ visibility and computing descendant visibility per actual descendant category (via DescendantsCountCache). It also removes the prior childrenCount-based approach and simplifies search-results handling by using an ignoreDescendants flag.

Changes:

  • Reworked BaseVisibilityHelper.getElementsVisibilityStatus into “own visibility” + “descendants visibility (grouped by actual category)” + “sub-models”, and added ignoreDescendants.
  • Extended AlwaysAndNeverDrawnElementInfoCache.getAlwaysOrNeverDrawnElements with an optional childCategoryIds filter to support descendant-category-specific queries.
  • Removed childrenCount and searchTargets extended data (and related ECSQL selectors) across tree definitions/handlers; updated tests to match new visibility semantics.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.ts Removes childrenCount extended data and its recursive ECSQL selector from models tree nodes.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.ts Updates helper calls to new getElementsVisibilityStatus signature (no childrenCount).
packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.ts Updates search-target visibility logic to split search targets vs non-targets using ignoreDescendants.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.ts Removes childrenCount/searchTargets from internal node typing.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.ts Core refactor: compute own visibility separately; compute descendants visibility per descendant category; introduces ignoreDescendants.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/Utils.ts Simplifies groupingNodeDataFromChildren to only derive search-related flags.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.ts Adjusts getSearchTargetsVisibilityStatus signature usage (no node parameter).
packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/AlwaysAndNeverDrawnElementInfoCache.ts Adds childCategoryIds filtering when collecting always/never-drawn element IDs.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.ts Updates element/search-target visibility logic to use ignoreDescendants instead of childrenCount.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.ts Removes childrenCount from internal node typing.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.ts Removes recursive ECSQL childrenCount selector from classification element nodes.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.ts Updates helper calls to new getElementsVisibilityStatus signature (no childrenCount).
packages/itwin/tree-widget/src/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.ts Updates search-target visibility logic to split search targets vs non-targets using ignoreDescendants.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.ts Removes childrenCount/searchTargets from internal node typing.
packages/itwin/tree-widget/src/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.ts Removes childrenCount extended data and its recursive ECSQL selector from categories tree nodes.
packages/itwin/tree-widget/src/test/trees/models-tree/Utils.ts Updates test node factories to remove childrenCount.
packages/itwin/tree-widget/src/test/trees/models-tree/internal/ModelsTreeVisibilityHandler.test.ts Updates expectations and adds coverage for parent partial visibility when descendant category differs.
packages/itwin/tree-widget/src/test/trees/categories-tree/internal/Utils.ts Updates test node factories to remove childrenCount.
Comments suppressed due to low confidence (1)

packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.ts:399

  • getDescendantsVisibilityStatus iterates elementIds using from(Id64.iterable(...)), which emits synchronously and can enqueue a large number of descendant-count queries without yielding. To avoid UI jank for large grouped-element sets, consider using fromWithRelease({ source: elementIds, releaseOnCount: ... }) (consistent with other loops in this file) and, if needed, a mergeMap concurrency limit.
    return from(Id64.iterable(elementIds)).pipe(
      mergeMap((elementId) => this.#props.baseIdsCache.getDescendantsCounts({ parentElementId: elementId, modelId })),
      reduce(

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JonasDov JonasDov merged commit 2d9a816 into tree-widget/next May 22, 2026
11 checks passed
@JonasDov JonasDov deleted the JonasD/phase-3 branch May 22, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants