@itwin/core-frontend 5.15.0-dev.2 → 5.15.0-dev.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/lib/cjs/GeoServices.d.ts +13 -3
- package/lib/cjs/GeoServices.d.ts.map +1 -1
- package/lib/cjs/GeoServices.js +51 -18
- package/lib/cjs/GeoServices.js.map +1 -1
- package/lib/cjs/IModelApp.d.ts +19 -1
- package/lib/cjs/IModelApp.d.ts.map +1 -1
- package/lib/cjs/IModelApp.js +15 -0
- package/lib/cjs/IModelApp.js.map +1 -1
- package/lib/cjs/IModelConnection.d.ts +14 -8
- package/lib/cjs/IModelConnection.d.ts.map +1 -1
- package/lib/cjs/IModelConnection.js +24 -5
- package/lib/cjs/IModelConnection.js.map +1 -1
- package/lib/cjs/RealityDataSourceCesiumIonAssetImpl.d.ts.map +1 -1
- package/lib/cjs/RealityDataSourceCesiumIonAssetImpl.js +7 -14
- package/lib/cjs/RealityDataSourceCesiumIonAssetImpl.js.map +1 -1
- package/lib/cjs/extension/ExtensionRuntime.js +1 -0
- package/lib/cjs/extension/ExtensionRuntime.js.map +1 -1
- package/lib/cjs/internal/tile/OrbitGtTileTree.d.ts.map +1 -1
- package/lib/cjs/internal/tile/OrbitGtTileTree.js +16 -5
- package/lib/cjs/internal/tile/OrbitGtTileTree.js.map +1 -1
- package/lib/cjs/quantity-formatting/FormatsProviderReloadCoordinator.d.ts +53 -0
- package/lib/cjs/quantity-formatting/FormatsProviderReloadCoordinator.d.ts.map +1 -0
- package/lib/cjs/quantity-formatting/FormatsProviderReloadCoordinator.js +145 -0
- package/lib/cjs/quantity-formatting/FormatsProviderReloadCoordinator.js.map +1 -0
- package/lib/cjs/quantity-formatting/QuantityFormatter.d.ts +23 -34
- package/lib/cjs/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
- package/lib/cjs/quantity-formatting/QuantityFormatter.js +107 -93
- package/lib/cjs/quantity-formatting/QuantityFormatter.js.map +1 -1
- package/lib/cjs/quantity-formatting/UnitsData.d.ts.map +1 -1
- package/lib/cjs/quantity-formatting/UnitsData.js +3 -0
- package/lib/cjs/quantity-formatting/UnitsData.js.map +1 -1
- package/lib/cjs/tile/map/CesiumTerrainProvider.d.ts +27 -6
- package/lib/cjs/tile/map/CesiumTerrainProvider.d.ts.map +1 -1
- package/lib/cjs/tile/map/CesiumTerrainProvider.js +51 -21
- package/lib/cjs/tile/map/CesiumTerrainProvider.js.map +1 -1
- package/lib/cjs/tile/map/MapLayerAuthentication.js.map +1 -1
- package/lib/cjs/tools/ToolAdmin.d.ts +7 -0
- package/lib/cjs/tools/ToolAdmin.d.ts.map +1 -1
- package/lib/cjs/tools/ToolAdmin.js +23 -2
- package/lib/cjs/tools/ToolAdmin.js.map +1 -1
- package/lib/esm/GeoServices.d.ts +13 -3
- package/lib/esm/GeoServices.d.ts.map +1 -1
- package/lib/esm/GeoServices.js +51 -18
- package/lib/esm/GeoServices.js.map +1 -1
- package/lib/esm/IModelApp.d.ts +19 -1
- package/lib/esm/IModelApp.d.ts.map +1 -1
- package/lib/esm/IModelApp.js +15 -0
- package/lib/esm/IModelApp.js.map +1 -1
- package/lib/esm/IModelConnection.d.ts +14 -8
- package/lib/esm/IModelConnection.d.ts.map +1 -1
- package/lib/esm/IModelConnection.js +24 -5
- package/lib/esm/IModelConnection.js.map +1 -1
- package/lib/esm/RealityDataSourceCesiumIonAssetImpl.d.ts.map +1 -1
- package/lib/esm/RealityDataSourceCesiumIonAssetImpl.js +7 -14
- package/lib/esm/RealityDataSourceCesiumIonAssetImpl.js.map +1 -1
- package/lib/esm/extension/ExtensionRuntime.js +2 -1
- package/lib/esm/extension/ExtensionRuntime.js.map +1 -1
- package/lib/esm/internal/tile/OrbitGtTileTree.d.ts.map +1 -1
- package/lib/esm/internal/tile/OrbitGtTileTree.js +16 -5
- package/lib/esm/internal/tile/OrbitGtTileTree.js.map +1 -1
- package/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.d.ts +53 -0
- package/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.d.ts.map +1 -0
- package/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.js +140 -0
- package/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.js.map +1 -0
- package/lib/esm/quantity-formatting/QuantityFormatter.d.ts +23 -34
- package/lib/esm/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
- package/lib/esm/quantity-formatting/QuantityFormatter.js +107 -93
- package/lib/esm/quantity-formatting/QuantityFormatter.js.map +1 -1
- package/lib/esm/quantity-formatting/UnitsData.d.ts.map +1 -1
- package/lib/esm/quantity-formatting/UnitsData.js +3 -0
- package/lib/esm/quantity-formatting/UnitsData.js.map +1 -1
- package/lib/esm/tile/map/CesiumTerrainProvider.d.ts +27 -6
- package/lib/esm/tile/map/CesiumTerrainProvider.d.ts.map +1 -1
- package/lib/esm/tile/map/CesiumTerrainProvider.js +50 -22
- package/lib/esm/tile/map/CesiumTerrainProvider.js.map +1 -1
- package/lib/esm/tile/map/MapLayerAuthentication.js.map +1 -1
- package/lib/esm/tools/ToolAdmin.d.ts +7 -0
- package/lib/esm/tools/ToolAdmin.d.ts.map +1 -1
- package/lib/esm/tools/ToolAdmin.js +23 -2
- package/lib/esm/tools/ToolAdmin.js.map +1 -1
- package/lib/public/locales/en/iModelJs.json +3 -1
- package/lib/public/scripts/parse-imdl-worker.js +2 -2
- package/lib/test-public/scripts/checkbrowser.js +24 -0
- package/lib/test-public/scripts/draco_encoder.js +52 -0
- package/lib/test-public/scripts/draco_wasm_wrapper.js +117 -0
- package/lib/test-public/scripts/parse-imdl-worker.js +2 -0
- package/lib/test-public/test-worker.js +1 -0
- package/package.json +22 -23
|
@@ -10,6 +10,7 @@ import { BasicUnitsProvider, Format, FormatSpecHandle, FormatterSpec, Formatting
|
|
|
10
10
|
import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory";
|
|
11
11
|
import { IModelApp } from "../IModelApp";
|
|
12
12
|
import { getDefaultAlternateUnitLabels } from "./AlternateUnitLabels";
|
|
13
|
+
import { FormatsProviderReloadCoordinator } from "./FormatsProviderReloadCoordinator";
|
|
13
14
|
// cSpell:ignore FORMATPROPS FORMATKEY ussurvey uscustomary USCUSTOM
|
|
14
15
|
/**
|
|
15
16
|
* Defines standard format types for tools that need to display measurements to user.
|
|
@@ -44,7 +45,12 @@ export var QuantityType;
|
|
|
44
45
|
export class AlternateUnitLabelsRegistry {
|
|
45
46
|
_alternateLabelRegistry = new Map();
|
|
46
47
|
addAlternateLabels(key, ...labels) {
|
|
47
|
-
|
|
48
|
+
let entry = this._alternateLabelRegistry.get(key);
|
|
49
|
+
if (!entry) {
|
|
50
|
+
entry = new Set();
|
|
51
|
+
this._alternateLabelRegistry.set(key, entry);
|
|
52
|
+
}
|
|
53
|
+
labels.forEach((value) => entry.add(value));
|
|
48
54
|
}
|
|
49
55
|
constructor(defaultAlternates) {
|
|
50
56
|
if (defaultAlternates) {
|
|
@@ -194,12 +200,24 @@ export class FormatsProviderManager {
|
|
|
194
200
|
}
|
|
195
201
|
get formatsProvider() { return this; }
|
|
196
202
|
set formatsProvider(formatsProvider) {
|
|
203
|
+
this.setFormatsProvider(formatsProvider);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Replaces the underlying formats provider and raises an event indicating that all formats changed.
|
|
207
|
+
* @param formatsProvider The formats provider to use for subsequent format lookups.
|
|
208
|
+
* @param impliedUnitSystem The unit system implied by the replacement provider, if any. Not stored here; [[QuantityFormatter]] applies it as the active unit system when handling `onFormatsChanged`.
|
|
209
|
+
* @internal
|
|
210
|
+
*/
|
|
211
|
+
setFormatsProvider(formatsProvider, impliedUnitSystem) {
|
|
197
212
|
this._removeProviderListener?.();
|
|
198
213
|
this._formatsProvider = formatsProvider;
|
|
199
214
|
this._removeProviderListener = this._formatsProvider.onFormatsChanged.addListener((args) => {
|
|
200
215
|
this.onFormatsChanged.raiseEvent(args);
|
|
201
216
|
});
|
|
202
|
-
|
|
217
|
+
const args = { formatsChanged: "all" };
|
|
218
|
+
if (impliedUnitSystem !== undefined)
|
|
219
|
+
args.impliedUnitSystem = impliedUnitSystem;
|
|
220
|
+
this.onFormatsChanged.raiseEvent(args);
|
|
203
221
|
}
|
|
204
222
|
}
|
|
205
223
|
/** The QuantityFormatter class provides methods for formatting and parsing quantities. There are a set of standard quantity types
|
|
@@ -280,10 +298,13 @@ export class QuantityFormatter {
|
|
|
280
298
|
_hasEverBeenReady = false;
|
|
281
299
|
_initializedPromise;
|
|
282
300
|
_resolveInitialized;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
301
|
+
_emitSystemChangedOnReady = false;
|
|
302
|
+
_isDisposed = false;
|
|
303
|
+
_disposedError = new Error("QuantityFormatter was disposed before the reload completed.");
|
|
304
|
+
_reloadCoordinator;
|
|
286
305
|
_removeFormatsProviderListener;
|
|
306
|
+
_activeFormatSpecsTarget;
|
|
307
|
+
_activeParserSpecsTarget;
|
|
287
308
|
/**
|
|
288
309
|
* constructor
|
|
289
310
|
* @param showMetricOrUnitSystem - Pass in `true` to show Metric formatted quantity values. Defaults to Imperial. To explicitly
|
|
@@ -293,6 +314,12 @@ export class QuantityFormatter {
|
|
|
293
314
|
this._initializedPromise = new Promise((resolve) => {
|
|
294
315
|
this._resolveInitialized = resolve;
|
|
295
316
|
});
|
|
317
|
+
this._reloadCoordinator = new FormatsProviderReloadCoordinator({
|
|
318
|
+
startReload: () => { this._isReady = false; },
|
|
319
|
+
executeReload: async (intent) => this._executeReload(intent),
|
|
320
|
+
finalizeReload: async () => this.finalizeReload(),
|
|
321
|
+
handleReloadFailure: (error) => this._handleReloadFailure(error),
|
|
322
|
+
}, this._disposedError);
|
|
296
323
|
if (undefined !== showMetricOrUnitSystem) {
|
|
297
324
|
if (typeof showMetricOrUnitSystem === "boolean")
|
|
298
325
|
this._activeUnitSystem = showMetricOrUnitSystem ? "metric" : "imperial";
|
|
@@ -301,70 +328,44 @@ export class QuantityFormatter {
|
|
|
301
328
|
}
|
|
302
329
|
}
|
|
303
330
|
[Symbol.dispose]() {
|
|
331
|
+
if (this._isDisposed)
|
|
332
|
+
return;
|
|
333
|
+
this._isDisposed = true;
|
|
334
|
+
this._isReady = false;
|
|
335
|
+
this._emitSystemChangedOnReady = false;
|
|
336
|
+
this._reloadCoordinator.dispose();
|
|
304
337
|
if (this._removeFormatsProviderListener) {
|
|
305
338
|
this._removeFormatsProviderListener();
|
|
306
339
|
this._removeFormatsProviderListener = undefined;
|
|
307
340
|
}
|
|
308
341
|
}
|
|
342
|
+
/** Runs an action that schedules a reload and waits for the reload queue to drain.
|
|
343
|
+
* The most recent call wins. If another call is made before this reload queue drains, this call is rejected.
|
|
344
|
+
* @internal
|
|
345
|
+
*/
|
|
346
|
+
async runAndWaitForReload(action) {
|
|
347
|
+
return this._reloadCoordinator.runAndWaitForReload(action);
|
|
348
|
+
}
|
|
309
349
|
/** Schedule an async reload. If no reload is in flight, runs immediately. If a reload is
|
|
310
|
-
* already in flight, stores the intent as pending
|
|
311
|
-
*
|
|
350
|
+
* already in flight, stores the intent as pending. Pending format changes are merged and run before
|
|
351
|
+
* the latest other pending intent. `finalizeReload()` fires only when the queue is fully drained.
|
|
312
352
|
*
|
|
313
353
|
* **Await semantics:** When a reload is already in flight, the returned promise resolves
|
|
314
354
|
* immediately *without* the requested reload having run. Callers that need to know when
|
|
315
|
-
*
|
|
355
|
+
* an explicitly triggered reload has actually completed should use [[runAndWaitForReload]].
|
|
316
356
|
*
|
|
317
|
-
* Reload intents:
|
|
318
|
-
* - `"full"` — rebuild entire registry + re-register provider listener (onInitialized, setUnitsProvider)
|
|
319
|
-
* - `"formatsChanged"` — patch registry from provider + load maps (formatsChanged listener)
|
|
320
|
-
* - `"activeSystem"` — reload format/parsing maps for current unit system (setActiveUnitSystem, reinitializeFormatAndParsingsMaps)
|
|
321
357
|
* @internal
|
|
322
358
|
*/
|
|
323
359
|
async scheduleReload(intent) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
360
|
+
return this._reloadCoordinator.scheduleReload(intent);
|
|
361
|
+
}
|
|
362
|
+
_handleReloadFailure(error) {
|
|
363
|
+
if (!this._isDisposed)
|
|
364
|
+
Logger.logError(`${FrontendLoggerCategory.Package}.QuantityFormatter`, BentleyError.getErrorMessage(error));
|
|
365
|
+
if (this._hasEverBeenReady && !this._isDisposed) {
|
|
366
|
+
Logger.logWarning(`${FrontendLoggerCategory.Package}.QuantityFormatter`, "Reload failed — restoring previous ready state. Cached specs may be stale.");
|
|
367
|
+
this._isReady = true;
|
|
328
368
|
}
|
|
329
|
-
this._reloadInFlight = true;
|
|
330
|
-
this._isReady = false;
|
|
331
|
-
this._deferredSystemChangedEmit = undefined; // Clear stale deferred from prior cycle
|
|
332
|
-
try {
|
|
333
|
-
await this._executeReload(intent);
|
|
334
|
-
}
|
|
335
|
-
catch (err) {
|
|
336
|
-
Logger.logError(`${FrontendLoggerCategory.Package}.QuantityFormatter`, BentleyError.getErrorMessage(err));
|
|
337
|
-
this._reloadInFlight = false;
|
|
338
|
-
// If there's a pending reload, still try to run it
|
|
339
|
-
if (this._pendingReload) {
|
|
340
|
-
const next = this._pendingReload;
|
|
341
|
-
this._pendingReload = undefined;
|
|
342
|
-
return this.scheduleReload(next);
|
|
343
|
-
}
|
|
344
|
-
// Restore prior ready state so stale-but-usable specs remain accessible
|
|
345
|
-
if (this._hasEverBeenReady) {
|
|
346
|
-
Logger.logWarning(`${FrontendLoggerCategory.Package}.QuantityFormatter`, "Reload failed — restoring previous ready state. Cached specs may be stale.");
|
|
347
|
-
this._isReady = true;
|
|
348
|
-
}
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
// Current reload succeeded — check if another was queued
|
|
352
|
-
if (this._pendingReload) {
|
|
353
|
-
const next = this._pendingReload;
|
|
354
|
-
this._pendingReload = undefined;
|
|
355
|
-
this._reloadInFlight = false;
|
|
356
|
-
return this.scheduleReload(next);
|
|
357
|
-
}
|
|
358
|
-
// Queue is drained — finalize
|
|
359
|
-
await this.finalizeReload();
|
|
360
|
-
// A new reload may have been queued during the async finalizeReload window
|
|
361
|
-
if (this._pendingReload) {
|
|
362
|
-
const next = this._pendingReload;
|
|
363
|
-
this._pendingReload = undefined;
|
|
364
|
-
this._reloadInFlight = false;
|
|
365
|
-
return this.scheduleReload(next);
|
|
366
|
-
}
|
|
367
|
-
this._reloadInFlight = false;
|
|
368
369
|
}
|
|
369
370
|
/** Execute the reload work for a given intent. All reload logic is centralized here.
|
|
370
371
|
* @internal
|
|
@@ -373,47 +374,51 @@ export class QuantityFormatter {
|
|
|
373
374
|
switch (intent.scope) {
|
|
374
375
|
case "full":
|
|
375
376
|
await this._reloadCore();
|
|
377
|
+
return;
|
|
378
|
+
case "formatsChanged":
|
|
379
|
+
await this._rebuildRegistryFromProvider(intent.args);
|
|
376
380
|
break;
|
|
377
|
-
case "formatsChanged": {
|
|
378
|
-
const { args } = intent;
|
|
379
|
-
await this._rebuildRegistryFromProvider(args);
|
|
380
|
-
if (args.impliedUnitSystem && args.impliedUnitSystem !== this._activeUnitSystem) {
|
|
381
|
-
this._activeUnitSystem = args.impliedUnitSystem;
|
|
382
|
-
}
|
|
383
|
-
await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
|
|
384
|
-
if (args.impliedUnitSystem) {
|
|
385
|
-
this._deferredSystemChangedEmit = { system: this._activeUnitSystem };
|
|
386
|
-
}
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
389
|
-
case "activeSystem":
|
|
390
|
-
await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
|
|
391
|
-
if (intent.emitSystemChanged) {
|
|
392
|
-
this._deferredSystemChangedEmit = { system: this._activeUnitSystem };
|
|
393
|
-
}
|
|
394
|
-
break;
|
|
395
381
|
}
|
|
382
|
+
// Build the active specs in temporary maps so readers keep using complete specs until the new ones are ready.
|
|
383
|
+
const nextFormatSpecs = new Map();
|
|
384
|
+
const nextParserSpecs = new Map();
|
|
385
|
+
this._activeFormatSpecsTarget = nextFormatSpecs;
|
|
386
|
+
this._activeParserSpecsTarget = nextParserSpecs;
|
|
387
|
+
try {
|
|
388
|
+
await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
|
|
389
|
+
}
|
|
390
|
+
finally {
|
|
391
|
+
this._activeFormatSpecsTarget = undefined;
|
|
392
|
+
this._activeParserSpecsTarget = undefined;
|
|
393
|
+
}
|
|
394
|
+
this._activeFormatSpecsByType = nextFormatSpecs;
|
|
395
|
+
this._activeParserSpecsByType = nextParserSpecs;
|
|
396
396
|
}
|
|
397
397
|
/** Called when the reload queue is fully drained after a successful reload.
|
|
398
398
|
* Sets `isReady` to true, resolves `whenInitialized` (one-shot), and emits ready events.
|
|
399
399
|
* @internal
|
|
400
400
|
*/
|
|
401
401
|
async finalizeReload() {
|
|
402
|
+
if (this._isDisposed)
|
|
403
|
+
return;
|
|
402
404
|
// Phase 1: Let providers register async work
|
|
403
405
|
const collector = new FormattingReadyCollector();
|
|
404
406
|
this.onBeforeFormattingReady.raiseEvent(collector);
|
|
405
407
|
await collector.awaitAll();
|
|
408
|
+
if (this._isDisposed)
|
|
409
|
+
return;
|
|
406
410
|
// Phase 2: Signal ready to consumers
|
|
407
411
|
this._isReady = true;
|
|
408
412
|
this._hasEverBeenReady = true;
|
|
409
413
|
this._resolveInitialized();
|
|
410
414
|
this.onFormattingReady.emit();
|
|
411
|
-
|
|
415
|
+
if (this._isDisposed)
|
|
416
|
+
return;
|
|
417
|
+
// Phase 3: Emit unit-system-changed if the unit system was changed since the last ready state, reporting the system that is now active.
|
|
412
418
|
// This fires after isReady === true so listeners can safely use the formatter.
|
|
413
|
-
if (this.
|
|
414
|
-
|
|
415
|
-
this.
|
|
416
|
-
this.onActiveFormattingUnitSystemChanged.emit(args);
|
|
419
|
+
if (this._emitSystemChangedOnReady) {
|
|
420
|
+
this._emitSystemChangedOnReady = false;
|
|
421
|
+
this.onActiveFormattingUnitSystemChanged.emit({ system: this._activeUnitSystem });
|
|
417
422
|
}
|
|
418
423
|
}
|
|
419
424
|
getOverrideFormatPropsByQuantityType(quantityTypeKey, unitSystem) {
|
|
@@ -484,8 +489,8 @@ export class QuantityFormatter {
|
|
|
484
489
|
async loadFormatAndParserSpec(quantityTypeDefinition, formatProps) {
|
|
485
490
|
const formatterSpec = await quantityTypeDefinition.generateFormatterSpec(formatProps, this.unitsProvider);
|
|
486
491
|
const parserSpec = await quantityTypeDefinition.generateParserSpec(formatProps, this.unitsProvider, this.alternateUnitLabelsProvider);
|
|
487
|
-
this._activeFormatSpecsByType.set(quantityTypeDefinition.key, formatterSpec);
|
|
488
|
-
this._activeParserSpecsByType.set(quantityTypeDefinition.key, parserSpec);
|
|
492
|
+
(this._activeFormatSpecsTarget ?? this._activeFormatSpecsByType).set(quantityTypeDefinition.key, formatterSpec);
|
|
493
|
+
(this._activeParserSpecsTarget ?? this._activeParserSpecsByType).set(quantityTypeDefinition.key, parserSpec);
|
|
489
494
|
}
|
|
490
495
|
// repopulate formatSpec and parserSpec entries using only default format
|
|
491
496
|
async loadDefaultFormatAndParserSpecForQuantity(typeKey) {
|
|
@@ -542,17 +547,20 @@ export class QuantityFormatter {
|
|
|
542
547
|
* @internal
|
|
543
548
|
*/
|
|
544
549
|
async onInitialized() {
|
|
550
|
+
// Register once, before the first reload, so provider changes made while a units-provider reload is running are not missed.
|
|
551
|
+
this._removeFormatsProviderListener ??= IModelApp.formatsProvider.onFormatsChanged.addListener((args) => {
|
|
552
|
+
if (args.impliedUnitSystem && args.impliedUnitSystem !== this._activeUnitSystem) {
|
|
553
|
+
this._activeUnitSystem = args.impliedUnitSystem;
|
|
554
|
+
this._emitSystemChangedOnReady = true;
|
|
555
|
+
}
|
|
556
|
+
void this.scheduleReload({ scope: "formatsChanged", args });
|
|
557
|
+
});
|
|
545
558
|
await this.scheduleReload({ scope: "full" });
|
|
546
559
|
}
|
|
547
560
|
/** Core reload logic — does all async I/O and cache rebuilding without events or state management.
|
|
548
561
|
* @internal
|
|
549
562
|
*/
|
|
550
563
|
async _reloadCore() {
|
|
551
|
-
// Remove any existing listener before re-registering to avoid duplicates when called via setUnitsProvider.
|
|
552
|
-
if (this._removeFormatsProviderListener) {
|
|
553
|
-
this._removeFormatsProviderListener();
|
|
554
|
-
this._removeFormatsProviderListener = undefined;
|
|
555
|
-
}
|
|
556
564
|
await this.initializeQuantityTypesRegistry();
|
|
557
565
|
const initialKoQs = [["DefaultToolsUnits.LENGTH", "Units.M"], ["DefaultToolsUnits.ANGLE", "Units.RAD"], ["DefaultToolsUnits.AREA", "Units.SQ_M"], ["DefaultToolsUnits.VOLUME", "Units.CUB_M"], ["DefaultToolsUnits.LENGTH_COORDINATE", "Units.M"], ["CivilUnits.STATION", "Units.M"], ["CivilUnits.LENGTH", "Units.M"], ["AecUnits.LENGTH", "Units.M"]];
|
|
558
566
|
for (const entry of initialKoQs) {
|
|
@@ -565,10 +573,6 @@ export class QuantityFormatter {
|
|
|
565
573
|
}
|
|
566
574
|
}
|
|
567
575
|
}
|
|
568
|
-
// Register formatsProvider listener that triggers a queued reload when formats change
|
|
569
|
-
this._removeFormatsProviderListener = IModelApp.formatsProvider.onFormatsChanged.addListener((args) => {
|
|
570
|
-
void this.scheduleReload({ scope: "formatsChanged", args });
|
|
571
|
-
});
|
|
572
576
|
// initialize default format and parsing specs
|
|
573
577
|
await this.loadFormatAndParsingMapsForSystem();
|
|
574
578
|
}
|
|
@@ -662,6 +666,9 @@ export class QuantityFormatter {
|
|
|
662
666
|
await IModelApp.quantityFormatter.resetToUseInternalUnitsProvider();
|
|
663
667
|
return;
|
|
664
668
|
}
|
|
669
|
+
// Disposal can occur while the reload is awaited, so do not notify afterward.
|
|
670
|
+
if (this._isDisposed)
|
|
671
|
+
return;
|
|
665
672
|
this.onUnitsProviderChanged.emit();
|
|
666
673
|
}
|
|
667
674
|
/**
|
|
@@ -701,7 +708,11 @@ export class QuantityFormatter {
|
|
|
701
708
|
this._overrideFormatPropsByUnitSystem = overrideFormatPropsByUnitSystem;
|
|
702
709
|
}
|
|
703
710
|
unitSystemKey && (this._activeUnitSystem = unitSystemKey);
|
|
704
|
-
|
|
711
|
+
if (fireUnitSystemChanged)
|
|
712
|
+
this._emitSystemChangedOnReady = true;
|
|
713
|
+
await this.scheduleReload({ scope: "activeSystem" });
|
|
714
|
+
if (this._isDisposed)
|
|
715
|
+
return;
|
|
705
716
|
IModelApp.toolAdmin && startDefaultTool && await IModelApp.toolAdmin.startDefaultTool();
|
|
706
717
|
}
|
|
707
718
|
/** Set the Active unit system to one of the supported types. This will asynchronously load the formatter and parser specs for the activated system. */
|
|
@@ -714,7 +725,10 @@ export class QuantityFormatter {
|
|
|
714
725
|
if (this._activeUnitSystem === systemType)
|
|
715
726
|
return;
|
|
716
727
|
this._activeUnitSystem = systemType;
|
|
717
|
-
|
|
728
|
+
this._emitSystemChangedOnReady = true;
|
|
729
|
+
await this.scheduleReload({ scope: "activeSystem" });
|
|
730
|
+
if (this._isDisposed)
|
|
731
|
+
return;
|
|
718
732
|
// allow settings provider to store the change
|
|
719
733
|
await this._unitFormattingSettingsProvider?.storeUnitSystemSetting({ system: systemType });
|
|
720
734
|
if (IModelApp.toolAdmin && restartActiveTool)
|
|
@@ -839,7 +853,7 @@ export class QuantityFormatter {
|
|
|
839
853
|
const entry = this.quantityTypesRegistry.get(quantityKey);
|
|
840
854
|
if (!entry)
|
|
841
855
|
throw new Error(`Unable to find registered quantity type with key ${quantityKey}`);
|
|
842
|
-
return entry.generateParserSpec(this.getFormatPropsByQuantityTypeEntryAndSystem(entry, requestedSystem), this.unitsProvider);
|
|
856
|
+
return entry.generateParserSpec(this.getFormatPropsByQuantityTypeEntryAndSystem(entry, requestedSystem), this.unitsProvider, this.alternateUnitLabelsProvider);
|
|
843
857
|
}
|
|
844
858
|
/** Asynchronous Call to get a ParserSpec for a QuantityType.
|
|
845
859
|
* @param type One of the built-in quantity types supported.
|
|
@@ -987,7 +1001,7 @@ export class QuantityFormatter {
|
|
|
987
1001
|
const { persistenceUnitName, formatProps, formatName } = props;
|
|
988
1002
|
const persistenceUnitProps = await this._unitsProvider.findUnitByName(persistenceUnitName);
|
|
989
1003
|
const format = await Format.createFromJSON(formatName ?? "temp", this._unitsProvider, formatProps);
|
|
990
|
-
return ParserSpec.create(format, this._unitsProvider, persistenceUnitProps);
|
|
1004
|
+
return ParserSpec.create(format, this._unitsProvider, persistenceUnitProps, this.alternateUnitLabelsProvider);
|
|
991
1005
|
}
|
|
992
1006
|
/**
|
|
993
1007
|
* @beta
|