devexpress-reporting
Version:
DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.
277 lines (276 loc) • 11.9 kB
JavaScript
/**
* DevExpress HTML/JS Reporting (rich-edit\utils\_model.js)
* Version: 25.1.3
* Build date: Jun 26, 2025
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* License: https://www.devexpress.com/Support/EULAs/universal.xml
*/
import { PaddingModel } from '@devexpress/analytics-core/analytics-elements';
import { guid, NotifyAboutWarning } from '@devexpress/analytics-core/analytics-internal';
import { Disposable } from '@devexpress/analytics-core/analytics-utils';
import { availableFonts, FontModel } from '@devexpress/analytics-core/analytics-widgets-internal';
import * as ko from 'knockout';
import { XRRichTextStreamType } from '../../designer/controls/xrRichText';
import { recalculateUnit } from '../../designer/internal/_utils';
import { createRichEdit, createRichEditOptions, getRichEditInstance } from '../instance';
import { RichEditLoadDispatcher } from './_loaddispatcher';
import { ToolbarSurface } from './_toolbar';
import { RichAction } from './_utils';
export class XRRichEditControlModel extends Disposable {
setRichHeight(value) {
this._richHeight = value;
}
_elementExists() {
return !!document.getElementById(this._element.id);
}
getToolbar() { return this._toolbar; }
getRealControl() {
return this._richEdit;
}
getRealControlNative() {
return this._richEdit['_native'];
}
updateCanvasScroll() {
this.getRealControlNative().core.viewManager.canvasListener.onCanvasScroll();
}
dispose() {
super.dispose();
this._toolbar.dispose();
this._dispatcher.dispose();
this._richEdit.dispose();
}
constructor(element, inlineControl, selected) {
super();
this.disableCommands = [
getRichEditInstance().HomeTabCommandId.Find,
getRichEditInstance().HomeTabCommandId.Replace,
];
this._verticalScrollOffset = 0;
this._richHeight = null;
this._disposables.push(this.visible = ko.pureComputed({
read: () => { return inlineControl.visible() && selected(); },
write: (value) => { inlineControl.visible(value); }
}));
this._disposables.push(this.className = ko.computed(() => {
return ['dxrd-rich-surface', this.visible() ? '' : 'dxrd-richedit-readonly'].join(' ');
}));
this._element = element;
this._element.id = 'rich' + guid().replace(/-/g, '');
this._richEdit = createRichEdit()(element, this.createOptions());
for (const commandId of this.disableCommands)
this._richEdit.setCommandEnabled(commandId, false);
this._dispatcher = new RichEditLoadDispatcher(this);
this.createToolbar();
}
executeCommand(commandId, parameter, setFocus = false) {
if (!this._richEdit.isDisposed) {
this._richEdit.executeCommand(commandId, parameter);
if (setFocus)
this._richEdit.focus();
}
}
insertHtml(html) {
if (!this._richEdit.isDisposed)
this.getRealControlNative().core.commandManager.getCommand(376).execute(false, html);
}
createOptions() {
const options = createRichEditOptions()();
options.ribbon.visible = false;
options.view.viewType = getRichEditInstance().ViewType.Simple;
options.autoCorrect.correctTwoInitialCapitals = true;
options.confirmOnLosingChanges.enabled = false;
options.width = '100%';
options.height = '100%';
options.contextMenu.enabled = false;
options.view.simpleViewSettings.paddings = { left: 1.92, right: 1.92, top: 0.01, bottom: 0.01 };
options.events.commandStateChanged = (s, e) => this._toolbar && this._toolbar.onCommandStateChanged(s, e);
options.fonts = this.getRichEditFonts();
const _self = this;
options['internalApi'] = {
getVerticalScrollOffset: () => {
return this._verticalScrollOffset;
},
get getVisibleAreaHeight() {
return _self._richHeight === null ? 0 : () => _self._richHeight;
}
};
return options;
}
getFonts() {
return Object.keys(ko.unwrap(availableFonts)).sort((a, b) => a < b ? -1 : 1);
}
getRichEditFonts() {
const rdFonts = this.getFonts();
const resultFonts = [];
for (const fontName of rdFonts)
resultFonts.push({ name: fontName, fontFamily: fontName });
return {
fonts: resultFonts,
mappings: {
defaultFontName: rdFonts[0],
},
};
}
createToolbar() {
this._toolbar = new ToolbarSurface({
executeCommand: this.executeCommand.bind(this),
commandManager: this.getRealControlNative().core.commandManager,
richEditPublic: this._richEdit,
visible: this.visible,
fonts: this.getFonts(),
});
}
saveDocumentNative(documentFormat, onResultReady) {
if (this._richEdit.hasUnsavedChanges) {
if (onResultReady) {
const handler = function (sender, arg2) {
onResultReady(arg2.base64);
sender.events.saving.removeHandler(handler, sender);
};
this._richEdit.events.saving.addHandler(handler, this._richEdit);
}
this._richEdit.saveDocument(documentFormat);
}
else {
this._richEdit.exportToBase64((base64) => {
if (onResultReady) {
onResultReady(base64);
}
}, documentFormat);
}
}
newDocumentNative(onResultReady) {
if (onResultReady) {
const handler = function (sender, arg2) {
onResultReady();
sender.events.documentLoaded.removeHandler(handler, sender);
};
this._richEdit.events.documentLoaded.addHandler(handler, this._richEdit);
}
this.executeCommand(getRichEditInstance().FileTabCommandId.CreateDocument);
}
openDocumentNative(base64, documentFormat, onResultReady, onError) {
const handler = function (sender, arg2) {
onResultReady();
sender.events.documentLoaded.removeHandler(handler, sender);
};
if (onResultReady) {
this._richEdit.events.documentLoaded.addHandler(handler, this._richEdit);
}
this._richEdit.openDocument(base64, '', documentFormat, (result) => {
if (!result && onError) {
this._richEdit.events.documentLoaded.removeHandler(handler, this._richEdit);
onError();
}
});
}
saveDocument(documentFormat, onResultReady) {
this._dispatcher.process({ documentConverted: onResultReady, queueAction: RichAction.SaveDocument, documentFormat: documentFormat, base64: undefined, ready: undefined, errorCallBack: undefined });
}
newDocument(onResultReady) {
this._dispatcher.process({ documentConverted: undefined, queueAction: RichAction.NewDocument, documentFormat: undefined, base64: undefined, ready: onResultReady, errorCallBack: undefined });
}
openDocument(base64, documentFormat, onResultReady, onError) {
this._dispatcher.process({ documentConverted: undefined, queueAction: RichAction.OpenDocument, documentFormat: documentFormat, base64: base64, ready: onResultReady, errorCallBack: onError });
}
changeSize() {
this._richEdit.adjust();
}
focusChanged(inFocus) {
if (!inFocus) {
this._richEdit.selection.setSelection(0);
}
this.changeSize();
}
getText(interval) {
return this._richEdit.document.getText(interval);
}
documentIsEmpty() {
return this._richEdit.document.length == 1;
}
}
export class RichLoader extends Disposable {
set textConverted(textConverted) {
this._textConverted = textConverted;
}
constructor(richEdit) {
super();
this.richEdit = richEdit;
}
load(loadData) {
if (!loadData.data) {
this.richEdit.newDocument(() => {
this.richEdit.insertHtml('');
this.richEdit.saveDocument(2, (result) => {
this._textConverted(result);
});
});
return;
}
let formatKey;
if (loadData.dataFormat === XRRichTextStreamType.HtmlText) {
formatKey = getRichEditInstance().DocumentFormat.Html;
}
else if (loadData.dataFormat === XRRichTextStreamType.PlainText) {
formatKey = getRichEditInstance().DocumentFormat.PlainText;
}
else if (loadData.dataFormat === XRRichTextStreamType.RtfText) {
formatKey = 2;
}
else if (loadData.dataFormat === XRRichTextStreamType.XmlText) {
formatKey = getRichEditInstance().DocumentFormat.OpenXml;
}
this.richEdit.openDocument(loadData.data, formatKey, () => {
this.richEdit.saveDocument(2, (result) => {
this._textConverted(result);
});
}, () => {
this.richEdit.openDocument(loadData.oldText, 2, () => {
this.richEdit.saveDocument(2, (result) => {
this._textConverted(result);
NotifyAboutWarning('The document is corrupted and cannot be opened', true);
});
});
});
}
}
export class RichEditPaddingModelWrapper extends Disposable {
_setPaddings() {
const rich = this._richEdit.getRealControl();
const paddings = rich.simpleViewSettings.paddings;
['left', 'right', 'top', 'bottom'].forEach(side => paddings[side] = recalculateUnit(this._paddingModel[side]() || 0.01, this._paddingModel._get('dpi')));
rich.simpleViewSettings.paddings = paddings;
}
constructor(padding, _richEdit) {
super();
this._richEdit = _richEdit;
this._paddingModel = new PaddingModel();
this._disposables.push(padding.subscribe((newVal) => {
this._paddingModel.applyFromString(newVal);
this._setPaddings();
}));
this._disposables.push(this._paddingModel);
}
}
export class RichEditFontModel extends FontModel {
constructor(value, richEdit, foreColor, controller) {
super(value);
this.richEdit = richEdit;
this.controller = controller;
for (const data of [
[this.family, fontName => this.applyCommand(getRichEditInstance().HomeTabCommandId.ChangeFontName, fontName)],
[this.size, size => this.applyCommand(getRichEditInstance().HomeTabCommandId.ChangeFontSize, size)],
[foreColor, foreColor => this.applyCommand(getRichEditInstance().HomeTabCommandId.ChangeFontForeColor, foreColor)],
[this.modificators.bold, bold => this.applyCommand(getRichEditInstance().HomeTabCommandId.ToggleFontBold, bold)],
[this.modificators.italic, italic => this.applyCommand(getRichEditInstance().HomeTabCommandId.ToggleFontItalic, italic)],
[this.modificators.strikeout, strikeout => this.applyCommand(getRichEditInstance().HomeTabCommandId.ToggleFontStrikeout, strikeout)],
[this.modificators.underline, underline => this.applyCommand(getRichEditInstance().HomeTabCommandId.ToggleFontUnderline, underline)],
])
this._disposables.push(data[0].subscribe(data[1]));
}
applyCommand(commandId, parameter) {
this.richEdit.getRealControl().executeCommand(commandId, parameter);
if (!this.richEdit.visible())
this.richEdit.saveDocument(2, newRtf => this.controller.setRtfString(newRtf));
}
}