terriajs
Version:
Geospatial data visualization platform.
156 lines (139 loc) • 4.85 kB
text/typescript
import { action, computed, makeObservable } from "mobx";
import DeveloperError from "terriajs-cesium/Source/Core/DeveloperError";
import { JsonObject, isJsonObject } from "../../Core/Json";
import Result from "../../Core/Result";
import TerriaError from "../../Core/TerriaError";
import isDefined from "../../Core/isDefined";
import MappableMixin from "../../ModelMixins/MappableMixin";
import ModelReference from "../../Traits/ModelReference";
import {
BaseMapTraits,
BaseMapsTraits
} from "../../Traits/TraitsClasses/BaseMapTraits";
import BingMapsCatalogItem from "../Catalog/CatalogItems/BingMapsCatalogItem";
import CommonStrata from "../Definition/CommonStrata";
import CreateModel from "../Definition/CreateModel";
import { BaseModel, ModelConstructorParameters } from "../Definition/Model";
import ModelPropertiesFromTraits from "../Definition/ModelPropertiesFromTraits";
import updateModelFromJson from "../Definition/updateModelFromJson";
import Terria from "../Terria";
import { defaultBaseMaps } from "./defaultBaseMaps";
export class BaseMapModel extends CreateModel(BaseMapTraits) {}
export type BaseMapJson = Partial<
Omit<ModelPropertiesFromTraits<BaseMapTraits>, "item"> & {
item: JsonObject | string;
}
>;
export type BaseMapsJson = Partial<
Omit<ModelPropertiesFromTraits<BaseMapsTraits>, "items"> & {
items: BaseMapJson[];
}
>;
export interface BaseMapItem {
image?: string;
contrastColor?: string;
backgroundColor?: string;
item: MappableMixin.Instance;
}
export class BaseMapsModel extends CreateModel(BaseMapsTraits) {
constructor(...args: ModelConstructorParameters) {
super(...args);
makeObservable(this);
}
/**
* List of the basemaps to show in setting panel
*/
get baseMapItems(): BaseMapItem[] {
const enabledBaseMaps: BaseMapItem[] = [];
const baseMapItems =
this.enabledBaseMaps
?.map((enabledBaseMapId) => {
return this.items.find((item) => item.item === enabledBaseMapId);
})
.filter(isDefined) ?? this.items;
baseMapItems.forEach((baseMapItem) => {
if (baseMapItem.item && !ModelReference.isRemoved(baseMapItem.item)) {
const itemModel = this.terria.getModelById(BaseModel, baseMapItem.item);
if (MappableMixin.isMixedInto(itemModel)) {
enabledBaseMaps.push({
image: baseMapItem.image,
contrastColor: baseMapItem.contrastColor,
backgroundColor: baseMapItem.backgroundColor,
item: itemModel
});
}
}
});
return enabledBaseMaps;
}
// Can't do this in constructor since {@link CatalogMemberFactory} doesn't
// have any values at the moment of initializing Terria class.
initializeDefaultBaseMaps(): Result {
return this.loadFromJson(CommonStrata.definition, {
items: defaultBaseMaps(this.terria)
});
}
private add(stratumId: string, baseMap: BaseMapModel) {
if (baseMap.item === undefined) {
throw new DeveloperError(
"A model without a `uniqueId` cannot be added to a group."
);
}
const resolvedItem = this.terria.getModelById(
BaseModel,
baseMap.item as any
);
if (resolvedItem instanceof BingMapsCatalogItem) {
addBingMapsKey(resolvedItem, this.terria);
}
const items = this.getTrait(stratumId, "items");
if (isDefined(items)) {
items.push(baseMap);
} else {
this.setTrait(stratumId, "items", [baseMap]);
}
}
loadFromJson(stratumId: CommonStrata, newBaseMaps: BaseMapsJson): Result {
const errors: TerriaError[] = [];
const { items, ...rest } = newBaseMaps;
if (items !== undefined) {
const { items: itemsTrait } = this.traits;
const newItemsIds = itemsTrait.fromJson(this, stratumId, items);
newItemsIds
.pushErrorTo(errors)
?.forEach((member: BaseMapModel, i: number) => {
const existingItem = this.items.find(
(baseMap) => baseMap.item === member.item
);
if (existingItem) {
// object array trait doesn't automatically update model item
updateModelFromJson(existingItem, stratumId, items[i]);
} else {
this.add(stratumId, member);
}
});
}
if (isJsonObject(rest))
updateModelFromJson(this, stratumId, rest).pushErrorTo(errors);
else errors.push(TerriaError.from("Invalid JSON object"));
return new Result(
undefined,
TerriaError.combine(
errors,
`Failed to add members from JSON for model \`${this.uniqueId}\``
)
);
}
}
function addBingMapsKey(item: BingMapsCatalogItem, terria: Terria) {
if (!item.key) {
item.setTrait(
CommonStrata.defaults,
"key",
terria.configParameters.bingMapsKey
);
}
}