@itwin/presentation-frontend
Version:
Frontend of iModel.js Presentation library
157 lines • 6.27 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/* eslint-disable @typescript-eslint/no-deprecated */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/** @packageDocumentation
* @module UnifiedSelection
*/
import { from, shareReplay } from "rxjs";
import { eachValueFrom } from "rxjs-for-await";
import { ContentFlags, DEFAULT_KEYS_BATCH_SIZE, DefaultContentDisplayTypes, Key, KeySet } from "@itwin/presentation-common";
import { Presentation } from "../Presentation.js";
// @ts-ignore TS complains about `with` in CJS builds, but not ESM
import hiliteRuleset from "./HiliteRules.json" with { type: "json" };
import { TRANSIENT_ELEMENT_CLASSNAME } from "@itwin/unified-selection";
const HILITE_RULESET = hiliteRuleset;
/**
* Presentation-based provider which uses presentation ruleset to determine
* what `HiliteSet` should be hilited in the graphics viewport based on the
* supplied `KeySet`.
*
* @public
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `HiliteSetProvider` from [@itwin/unified-selection](https://github.com/iTwin/presentation/blob/master/packages/unified-selection/README.md#hilite-sets) package instead.
*/
export class HiliteSetProvider {
_imodel;
_cache;
constructor(props) {
this._imodel = props.imodel;
}
/**
* Create a hilite set provider for the specified iModel.
*/
static create(props) {
return new HiliteSetProvider(props);
}
/**
* Get hilite set for instances and/or nodes whose keys are specified in the
* given KeySet.
*
* Note: The provider caches result of the last request, so subsequent requests
* for the same input doesn't cost.
*/
async getHiliteSet(selection) {
const modelIds = new Array();
const subCategoryIds = new Array();
const elementIds = new Array();
const iterator = this.getHiliteSetIterator(selection);
for await (const set of iterator) {
modelIds.push(...(set.models ?? []));
subCategoryIds.push(...(set.subCategories ?? []));
elementIds.push(...(set.elements ?? []));
}
return {
models: modelIds.length ? modelIds : undefined,
subCategories: subCategoryIds.length ? subCategoryIds : undefined,
elements: elementIds.length ? elementIds : undefined,
};
}
/**
* Get hilite set iterator for provided keys. It loads content in batches and
* yields hilite set created from each batch after it is loaded.
*/
getHiliteSetIterator(selection) {
if (!this._cache || this._cache.keysGuid !== selection.guid) {
this._cache = {
keysGuid: selection.guid,
observable: from(this.createHiliteSetIterator(selection)).pipe(shareReplay({ refCount: true })),
};
}
return eachValueFrom(this._cache.observable);
}
async *createHiliteSetIterator(selection) {
const { keys, transientIds } = this.handleTransientKeys(selection);
const { options, keyBatches } = this.getContentOptions(keys);
if (transientIds.length !== 0) {
yield { elements: transientIds };
}
for (const batch of keyBatches) {
let loadedItems = 0;
while (true) {
const content = await Presentation.presentation.getContentIterator({
...options,
paging: { start: loadedItems, size: CONTENT_SET_PAGE_SIZE },
keys: batch,
});
if (!content) {
break;
}
const items = new Array();
for await (const item of content.items) {
items.push(item);
}
const result = this.createHiliteSet(items);
yield result;
loadedItems += items.length;
if (loadedItems >= content.total) {
break;
}
}
}
}
createHiliteSet(records) {
const modelIds = new Array();
const subCategoryIds = new Array();
const elementIds = new Array();
records.forEach((rec) => {
const ids = isModelRecord(rec) ? modelIds : isSubCategoryRecord(rec) ? subCategoryIds : elementIds;
rec.primaryKeys.forEach((pk) => ids.push(pk.id));
});
return {
models: modelIds.length ? modelIds : undefined,
subCategories: subCategoryIds.length ? subCategoryIds : undefined,
elements: elementIds.length ? elementIds : undefined,
};
}
getContentOptions(keys) {
const descriptor = {
displayType: DefaultContentDisplayTypes.Viewport,
contentFlags: ContentFlags.KeysOnly,
};
const options = {
imodel: this._imodel,
rulesetOrId: HILITE_RULESET,
descriptor,
};
const keyBatches = new Array();
keys.forEachBatch(DEFAULT_KEYS_BATCH_SIZE, (batch) => {
keyBatches.push(batch);
});
return {
options,
keyBatches,
};
}
handleTransientKeys(selection) {
// need to create a new set without transients
const transientIds = new Array();
const keys = new KeySet();
keys.add(selection, (key) => {
if (Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME) {
transientIds.push(key.id);
return false;
}
return true;
});
return {
transientIds,
keys,
};
}
}
const CONTENT_SET_PAGE_SIZE = 1000;
const isModelRecord = (rec) => rec.extendedData && rec.extendedData.isModel;
const isSubCategoryRecord = (rec) => rec.extendedData && rec.extendedData.isSubCategory;
//# sourceMappingURL=HiliteSetProvider.js.map