UNPKG

@itwin/core-backend

Version:
411 lines (410 loc) • 17.1 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Elements */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AnnotationTextStyle = exports.TextAnnotation3d = exports.TextAnnotation2d = void 0; const core_common_1 = require("@itwin/core-common"); const Element_1 = require("../Element"); const core_bentley_1 = require("@itwin/core-bentley"); const TextBlockLayout_1 = require("./TextBlockLayout"); const TextAnnotationGeometry_1 = require("./TextAnnotationGeometry"); const ElementDrivesTextAnnotation_1 = require("./ElementDrivesTextAnnotation"); function parseTextAnnotationData(json) { if (!json) return undefined; try { return JSON.parse(json); } catch { return undefined; } } function getElementGeometryBuilderParams(iModel, modelId, _placementProps, stringifiedAnnotationProps, categoryId, _subCategory) { const annotationProps = parseTextAnnotationData(stringifiedAnnotationProps); const textBlock = core_common_1.TextAnnotation.fromJSON(annotationProps).textBlock; const textStyleResolver = new TextBlockLayout_1.TextStyleResolver({ textBlock, iModel, modelId }); const layout = (0, TextBlockLayout_1.layoutTextBlock)({ iModel, textBlock, textStyleResolver }); const builder = new core_common_1.ElementGeometry.Builder(); (0, TextAnnotationGeometry_1.appendTextAnnotationGeometry)({ layout, textStyleResolver, annotationProps: annotationProps ?? {}, builder, categoryId }); return { entryArray: builder.entries }; } /** An element that displays textual content within a 2d model. * The text is stored as a [TextAnnotation]($common) from which the element's [geometry]($docs/learning/common/GeometryStream.md) and [Placement]($common) are computed. * @see [[setAnnotation]] to change the textual content. * @public @preview */ class TextAnnotation2d extends Element_1.AnnotationElement2d /* implements ITextAnnotation */ { /** @internal */ static get className() { return "TextAnnotation2d"; } /** Optional string containing the data associated with the text annotation. */ _textAnnotationData; /** Extract the textual content, if present. * @see [[setAnnotation]] to change it. */ getAnnotation() { const textAnnotationProps = parseTextAnnotationData(this._textAnnotationData); return textAnnotationProps ? core_common_1.TextAnnotation.fromJSON(textAnnotationProps) : undefined; } /** Change the textual content of the `TextAnnotation2d`. * @see [[getAnnotation]] to extract the current annotation. * @param annotation The new annotation */ setAnnotation(annotation) { this._textAnnotationData = annotation ? JSON.stringify(annotation.toJSON()) : undefined; } constructor(props, iModel) { super(props, iModel); this._textAnnotationData = props.textAnnotationData; } /** Creates a new instance of `TextAnnotation2d` from its JSON representation. */ static fromJSON(props, iModel) { return new TextAnnotation2d(props, iModel); } /** * Converts the current `TextAnnotation2d` instance to its JSON representation. * It also computes the `elementGeometryBuilderParams` property used to create the GeometryStream. * @inheritdoc */ toJSON() { const props = super.toJSON(); props.textAnnotationData = this._textAnnotationData; if (this._textAnnotationData) { props.elementGeometryBuilderParams = getElementGeometryBuilderParams(this.iModel, this.model, this.placement, this._textAnnotationData, this.category); } return props; } /** Creates a new `TextAnnotation2d` instance with the specified properties. * @param iModelDb The iModel. * @param category The category ID for the annotation. * @param model The model ID where the annotation will be placed. * @param placement The placement properties for the annotation. * @param textAnnotationData Optional [[TextAnnotation]] JSON representation used to create the `TextAnnotation2d`. Essentially an empty element if not provided. * @param code Optional code for the element. */ static create(iModelDb, category, model, placement, textAnnotationData, code) { const props = { classFullName: this.classFullName, textAnnotationData: JSON.stringify(textAnnotationData), placement, model, category, code: code ?? core_common_1.Code.createEmpty(), }; return new this(props, iModelDb); } /** * Updates the geometry of the TextAnnotation2d on insert. * @inheritdoc * @beta */ static onInsert(arg) { super.onInsert(arg); this.updateGeometry(arg.iModel, arg.props); } /** * Updates the geometry of the TextAnnotation2d on update. * @inheritdoc * @beta */ static onUpdate(arg) { super.onUpdate(arg); this.updateGeometry(arg.iModel, arg.props); } /** * Populates the `elementGeometryBuilderParams` property in the [TextAnnotation2dProps]($common). * It only does this if the `elementGeometryBuilderParams` is not already set and if there is actually a text annotation to produce geometry for. */ static updateGeometry(iModelDb, props) { if (props.elementGeometryBuilderParams || !props.textAnnotationData) { return; } props.elementGeometryBuilderParams = getElementGeometryBuilderParams(iModelDb, props.model, props.placement ?? core_common_1.Placement2d.fromJSON(), props.textAnnotationData, props.category); } /** * Collects reference IDs used by this `TextAnnotation2d`. * @inheritdoc */ collectReferenceIds(ids) { super.collectReferenceIds(ids); const annotation = this.getAnnotation(); if (!annotation) { return; } if (annotation.textBlock.styleId) ids.addElement(annotation.textBlock.styleId); } /** @internal */ getTextBlocks() { return getTextBlocks(this); } /** @internal */ updateTextBlocks(textBlocks) { return updateTextBlocks(this, textBlocks); } /** @internal */ static onInserted(arg) { super.onInserted(arg); ElementDrivesTextAnnotation_1.ElementDrivesTextAnnotation.updateFieldDependencies(arg.id, arg.iModel); } /** @internal */ static onUpdated(arg) { super.onUpdated(arg); ElementDrivesTextAnnotation_1.ElementDrivesTextAnnotation.updateFieldDependencies(arg.id, arg.iModel); } } exports.TextAnnotation2d = TextAnnotation2d; /** An element that displays textual content within a 3d model. * The text is stored as a [TextAnnotation]($common) from which the element's [geometry]($docs/learning/common/GeometryStream.md) and [Placement]($common) are computed. * @see [[setAnnotation]] to change the textual content. * @public @preview */ class TextAnnotation3d extends Element_1.GraphicalElement3d /* implements ITextAnnotation */ { /** @internal */ static get className() { return "TextAnnotation3d"; } /** Optional string containing the data associated with the text annotation. */ _textAnnotationData; /** Extract the textual content, if present. * @see [[setAnnotation]] to change it. */ getAnnotation() { const textAnnotationProps = parseTextAnnotationData(this._textAnnotationData); return textAnnotationProps ? core_common_1.TextAnnotation.fromJSON(textAnnotationProps) : undefined; } /** Change the textual content of the `TextAnnotation3d`. * @see [[getAnnotation]] to extract the current annotation. * @param annotation The new annotation */ setAnnotation(annotation) { this._textAnnotationData = annotation ? JSON.stringify(annotation.toJSON()) : undefined; } constructor(props, iModel) { super(props, iModel); this._textAnnotationData = props.textAnnotationData; } /** Creates a new instance of `TextAnnotation3d` from its JSON representation. */ static fromJSON(props, iModel) { return new TextAnnotation3d(props, iModel); } /** * Converts the current `TextAnnotation3d` instance to its JSON representation. * It also computes the `elementGeometryBuilderParams` property used to create the GeometryStream. * @inheritdoc */ toJSON() { const props = super.toJSON(); props.textAnnotationData = this._textAnnotationData; if (this._textAnnotationData) { props.elementGeometryBuilderParams = getElementGeometryBuilderParams(this.iModel, this.model, this.placement, this._textAnnotationData, this.category); } return props; } /** Creates a new `TextAnnotation3d` instance with the specified properties. * @param iModelDb The iModel. * @param category The category ID for the annotation. * @param model The model ID where the annotation will be placed. * @param placement The placement properties for the annotation. * @param textAnnotationData Optional [[TextAnnotation]] JSON representation used to create the `TextAnnotation3d`. Essentially an empty element if not provided. * @param code Optional code for the element. */ static create(iModelDb, category, model, placement, textAnnotationData, code) { const props = { classFullName: this.classFullName, textAnnotationData: JSON.stringify(textAnnotationData), placement, model, category, code: code ?? core_common_1.Code.createEmpty(), }; return new this(props, iModelDb); } /** * Updates the geometry of the TextAnnotation3d on insert. * @inheritdoc * @beta */ static onInsert(arg) { super.onInsert(arg); this.updateGeometry(arg.iModel, arg.props); } /** * Updates the geometry of the TextAnnotation3d on update. * @inheritdoc * @beta */ static onUpdate(arg) { super.onUpdate(arg); this.updateGeometry(arg.iModel, arg.props); } /** * Populates the `elementGeometryBuilderParams` property in the [TextAnnotation3dProps]($common). * It only does this if the `elementGeometryBuilderParams` is not already set and if there is actually a text annotation to produce geometry for. */ static updateGeometry(iModelDb, props) { if (props.elementGeometryBuilderParams || !props.textAnnotationData) { return; } props.elementGeometryBuilderParams = getElementGeometryBuilderParams(iModelDb, props.model, props.placement ?? core_common_1.Placement3d.fromJSON(), props.textAnnotationData, props.category); } /** * Collects reference IDs used by this `TextAnnotation3d`. * @inheritdoc */ collectReferenceIds(ids) { super.collectReferenceIds(ids); const annotation = this.getAnnotation(); if (!annotation) { return; } if (annotation.textBlock.styleId) ids.addElement(annotation.textBlock.styleId); } /** @internal */ getTextBlocks() { return getTextBlocks(this); } /** @internal */ updateTextBlocks(textBlocks) { return updateTextBlocks(this, textBlocks); } /** @internal */ static onInserted(arg) { super.onInserted(arg); ElementDrivesTextAnnotation_1.ElementDrivesTextAnnotation.updateFieldDependencies(arg.id, arg.iModel); } /** @internal */ static onUpdated(arg) { super.onUpdated(arg); ElementDrivesTextAnnotation_1.ElementDrivesTextAnnotation.updateFieldDependencies(arg.id, arg.iModel); } } exports.TextAnnotation3d = TextAnnotation3d; function getTextBlocks(elem) { const annotation = elem.getAnnotation(); return annotation ? [{ textBlock: annotation.textBlock, id: undefined }] : []; } function updateTextBlocks(elem, textBlocks) { (0, core_bentley_1.assert)(textBlocks.length === 1); (0, core_bentley_1.assert)(textBlocks[0].id === undefined); const annotation = elem.getAnnotation(); if (!annotation) { // We must obtain the TextBlockAndId from the element in the first place, so the only way we could end up here is if // somebody removed the text annotation after we called getTextBlocks. That's gotta be a mistake. throw new Error("Text annotation element has no text"); } annotation.textBlock = textBlocks[0].textBlock; elem.setAnnotation(annotation); elem.update(); } /** * The definition element that holds text style information. * The style is stored as a [TextStyleSettings]($common). * @beta */ class AnnotationTextStyle extends Element_1.DefinitionElement { /** @internal */ static get className() { return "AnnotationTextStyle"; } /** * Optional text describing the `AnnotationTextStyle`. */ description; /** * The text style settings for the `AnnotationTextStyle`. * @see [[TextStyleSettings]] for more information. */ settings; constructor(props, iModel) { super(props, iModel); this.description = props.description; const settingsProps = AnnotationTextStyle.parseTextStyleSettings(props.settings); this.settings = core_common_1.TextStyleSettings.fromJSON(settingsProps); } /** * Creates a Code for an `AnnotationTextStyle` given a name that is meant to be unique within the scope of the specified DefinitionModel. * * @param iModel - The IModelDb. * @param definitionModelId - The ID of the DefinitionModel that contains the AnnotationTextStyle and provides the scope for its name. * @param name - The AnnotationTextStyle name. */ static createCode(iModel, definitionModelId, name) { const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.annotationTextStyle); return new core_common_1.Code({ spec: codeSpec.id, scope: definitionModelId, value: name }); } /** * Creates a new instance of `AnnotationTextStyle` with the specified properties. * * @param iModelDb - The iModelDb. * @param definitionModelId - The ID of the [[DefinitionModel]]. * @param name - The name to assign to the `AnnotationTextStyle`. * @param settings - Optional text style settings used to create the `AnnotationTextStyle`. Default settings will be used if not provided. * @param description - Optional description for the `AnnotationTextStyle`. */ static create(iModelDb, definitionModelId, name, settings, description) { const props = { classFullName: this.classFullName, model: definitionModelId, code: this.createCode(iModelDb, definitionModelId, name).toJSON(), description, settings: JSON.stringify(settings), }; return new this(props, iModelDb); } /** * Converts the current `AnnotationTextStyle` instance to its JSON representation. * @inheritdoc */ toJSON() { const props = super.toJSON(); props.description = this.description; props.settings = JSON.stringify(this.settings.toJSON()); return props; } /** Creates a new instance of `AnnotationTextStyle` from its JSON representation. */ static fromJSON(props, iModel) { return new AnnotationTextStyle(props, iModel); } /** * Validates that the AnnotationTextStyle's settings are valid before insert. * @inheritdoc * @beta */ static onInsert(arg) { super.onInsert(arg); this.validateSettings(arg.props); } /** * Validates that the AnnotationTextStyle's settings are valid before update. * @inheritdoc * @beta */ static onUpdate(arg) { super.onUpdate(arg); this.validateSettings(arg.props); } static validateSettings(props) { const settingProps = AnnotationTextStyle.parseTextStyleSettings(props.settings); if (!settingProps) return; const settings = core_common_1.TextStyleSettings.fromJSON(settingProps); const errors = settings.getValidationErrors(); if (errors.length > 0) { throw new Error(`Invalid AnnotationTextStyle settings: ${errors.join(", ")}`); } } static parseTextStyleSettings(json) { if (!json) return undefined; try { return JSON.parse(json); } catch { return undefined; } } } exports.AnnotationTextStyle = AnnotationTextStyle; //# sourceMappingURL=TextAnnotationElement.js.map