UNPKG

devexpress-richedit

Version:

DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.

126 lines (125 loc) 7.44 kB
import { ApiParametersChecker } from '../api-utils/parameter-checker'; import { Field } from '../../../common/model/fields/field'; import { UpdateFieldsOptions } from '../../../common/model/fields/tree-creator'; import { FieldInsertHistoryItem } from '../../../common/model/history/items/field-insert-history-item'; import { InsertTextHistoryItem } from '../../../common/model/history/items/insert-text-history-item'; import { UpdateFieldsManipulatorParams } from '../../../common/model/manipulators/fields-manipulator'; import { InsertTextManipulatorParams } from '../../../common/model/manipulators/text-manipulator/insert-text-manipulator-params'; import { RunType } from '../../../common/model/runs/run-type'; import { SubDocumentIntervals, SubDocumentPosition } from '../../../common/model/sub-document'; import { InputPositionBase } from '../../../common/selection/input-position-base'; import { SelectionIntervalsInfo } from '../../../common/selection/selection-intervals-info'; import { IntervalAlgorithms } from '@devexpress/utils/lib/intervals/algorithms'; import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed'; import { isNumber } from '@devexpress/utils/lib/utils/common'; import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number'; import { MathUtils } from '@devexpress/utils/lib/utils/math'; import { getRestrictedInterval } from '../api-utils/api-utils'; import { ModelParametersChecker } from '../api-utils/model-parameter-checker'; import { FieldApi } from '../field'; import { Collection } from './collection'; export class FieldCollection extends Collection { constructor(processor, subDocument) { super(processor); this._subDocument = subDocument; } create(position, code) { const codeInterval = ApiParametersChecker.check(position, 1, false, [ ModelParametersChecker.intervalDescriptor("codeInterval", interval => getRestrictedInterval(interval, 0, this._subDocument.getDocumentEndPosition())), ApiParametersChecker.numberDescriptor("position", (n) => new FixedInterval(MathUtils.restrictValue(n, 0, this._subDocument.getDocumentEndPosition() - 1), 0)), ]); if (isNumber(position)) code = ApiParametersChecker.check(code, 2, true, [ ApiParametersChecker.stringDescriptor("code", (s) => s, true) ]); else code = undefined; const inputPos = new InputPositionBase().setIntervals(new SelectionIntervalsInfo(this._subDocument, [new FixedInterval(codeInterval.start, 0)])); this._processor.beginUpdate(); this._processor.modelManager.history.beginTransaction(); this._processor.modelManager.history.addAndRedo(new FieldInsertHistoryItem(this._processor.modelManager.modelManipulator, this._subDocument, codeInterval.start, codeInterval.length, 0, true, inputPos.charPropsBundle)); if (code) { this._processor.modelManager.history.addAndRedo(new InsertTextHistoryItem(this._processor.modelManager.modelManipulator, new InsertTextManipulatorParams(new SubDocumentPosition(this._subDocument, codeInterval.start + 1), inputPos.charPropsBundle, RunType.TextRun, code))); } this._processor.modelManager.history.endTransaction(); this._processor.endUpdate(); return this._getItem(this._subDocument.fields[Field.binaryIndexOf(this._subDocument.fields, codeInterval.start + 1)]); } createMergeField(position, name) { return this.create(position, `MERGEFIELD "${name}"`); } find(position) { const interval = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor("position", (n) => new FixedInterval(n, 0)), ModelParametersChecker.intervalDescriptor("interval", (interval) => new FixedInterval(interval.start, interval.length)) ]); return findFields(this._subDocument.fields, interval).map(f => this._getItem(f)); } showAllFieldResults(doInAllSubDocuments) { this._showAllFieldCodesCore(doInAllSubDocuments, false); } showAllFieldCodes(doInAllSubDocuments) { this._showAllFieldCodesCore(doInAllSubDocuments, true); } updateAllFields(callback, options) { if (callback) callback = ApiParametersChecker.check(callback, 1, true, [ ApiParametersChecker.functionDescriptor('callback', (val) => val) ]); if (options) options = ApiParametersChecker.check(options, 2, false, [ ApiParametersChecker.objectDescriptor('options', 'UpdateFieldsOptions', (val) => val) ]); else options = new UpdateFieldsOptionsApi(true, true); const sdInfo = options.doInAllSubDocuments ? NumberMapUtils.toListBy(this._processor.modelManager.model.subDocuments, (sd) => new SubDocumentIntervals(sd, [sd.interval])) : [new SubDocumentIntervals(this._subDocument, [this._subDocument.interval])]; this._processor.beginUpdate(); this._processor.modelManager.history.beginTransaction(); return this._processor.modelManager.modelManipulator.field.updateFields(this._processor.layoutFormatterManager, this._processor.createFieldRequestManager(), new UpdateFieldsManipulatorParams(sdInfo, () => { this._processor.modelManager.history.endTransaction(); this._processor.endUpdate(); if (callback) callback(); }, new UpdateFieldsOptions(options.updateTocFields))); } _showAllFieldCodesCore(doInAllSubDocuments = true, showCode) { doInAllSubDocuments = ApiParametersChecker.check(doInAllSubDocuments, 1, true, [ ApiParametersChecker.booleanDescriptor('doInAllSubDocuments', (val) => val) ]); const subDocumentsList = doInAllSubDocuments ? NumberMapUtils.toList(this._processor.modelManager.model.subDocuments) : [this._subDocument]; this._processor.beginUpdate(); this._processor.modelManager.modelManipulator.field.setAllFieldsShowCode(showCode, subDocumentsList); this._processor.endUpdate(); } _getItem(coreItem) { return new FieldApi(this._processor, this._subDocument, coreItem); } _getCoreItems() { return this._subDocument.fields; } } export class UpdateFieldsOptionsApi { constructor(doInAllSubDocuments = true, updateTocFields = true) { this.doInAllSubDocuments = doInAllSubDocuments; this.updateTocFields = updateTocFields; } } export function findFields(fields, interval) { if (fields.length == 0) return []; let fieldIndex = fields[Math.max(0, Field.normedBinaryIndexOf(fields, interval.start))].getAbsolutelyTopLevelField().index; const resultFields = []; for (let field; field = fields[fieldIndex]; fieldIndex++) { const fieldInterval = field.getAllFieldInterval(); const intersection = IntervalAlgorithms.getIntersection(fieldInterval, interval); if (intersection && (!!intersection.length || fieldInterval.contains(intersection.start))) resultFields.push(field); else if (!field.parent && field.getFieldStartPosition() >= interval.end) break; } return resultFields; }