devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
217 lines (216 loc) • 12.7 kB
JavaScript
import { MapCreator } from '../../utils/map-creator';
import { RendererClassNames } from '../renderer-class-names';
import { LayoutPageFlags } from '../../layout/main-structures/layout-page';
import { ColorHelper } from '../../model/color/color';
import { Log } from '../../rich-utils/debug/logger/base-logger/log';
import { LogListHelper } from '../../rich-utils/debug/logger/base-logger/log-list-helper';
import { LogSource } from '../../rich-utils/debug/logger/base-logger/log-source';
import { LogObjToStrLayout } from '../../rich-utils/debug/logger/layout-logger/log-obj-to-str-layout';
import { ViewType } from '../../view-settings/views-settings';
import { DomUtils } from '@devexpress/utils/lib/utils/dom';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number';
import { CanvasManager } from '../canvas-manager';
import { CanvasScrollInfo } from '../canvas-scroll-info';
import { CanvasScrollManager } from '../canvas-scroll-manager';
import { CanvasSizeInfo } from '../canvas-size-info';
import { PrintLayoutViewCanvasListener } from './canvas-listener/print-layout-view-canvas-listener';
import { SimpleViewCanvasListener } from './canvas-listener/simple-view-canvas-listener';
import { RendererManager } from './change-active-sub-document/renderer';
import { DocumentRenderer } from './common/document-renderer';
import { PrintLayoutRenderer } from './common/print-layout-renderer';
import { SimpleViewRenderer } from './common/simple-view-renderer';
import { MisspelledSelectionRenderer } from './selection-renderers/misspelled-selection-renderer';
import { RangePermissionRenderer } from './selection-renderers/range-permission-renderer';
import { SearchSelectionRenderer } from './selection-renderers/search-selection-renderer';
import { SelectionRenderer } from './selection-renderers/selection-renderer';
import { ControlOptions, DocumentCapability } from '../../model/options/control';
import { RichEditClientCommand } from '../../commands/client-command';
import { ZoomLevelChange } from '../../model/changes/model/zoom-level';
import { ModelChangeType } from '../../model/changes/enums';
import { MixedSize } from '../../../common/utils/mixed-size';
export class ViewManager {
renderers;
get renderer() { return this.renderers[this.innerClientProperties.viewsSettings.viewType]; }
get printLayoutRenderer() { return this.renderers[ViewType.PrintLayout]; }
lastUsedRendererType;
canvasListeners;
get canvasListener() { return this.canvasListeners[this.innerClientProperties.viewsSettings.viewType]; }
canvasManager;
innerClientProperties;
canvas;
cache = [];
selection;
searchSelection;
misspelledSelection;
rangePermission;
imageCache;
pagesContainer;
serviceContainer;
inputController;
changeActiveSubDocumentRenderer;
layout;
sizes = new CanvasSizeInfo(this);
canvasScrollManager;
scroll;
stringResources;
readOnlyPropertyHolder;
layoutFormatterManagerHolder;
internalApi;
fieldOptions;
control;
constructor(control, canvas, eventManager, stringResources, horizontalRuler, inputController, innerClientProperties, readOnlyPropertyHolder, layoutFormatterManagerHolder, internalApi, fieldOptions) {
this.control = control;
this.readOnlyPropertyHolder = readOnlyPropertyHolder;
this.layoutFormatterManagerHolder = layoutFormatterManagerHolder;
this.internalApi = internalApi;
this.fieldOptions = fieldOptions;
this.canvas = canvas;
this.stringResources = stringResources;
this.inputController = inputController;
this.innerClientProperties = innerClientProperties;
this.addTopLevelContainers();
this.canvasManager = new CanvasManager(this, eventManager);
this.scroll = new CanvasScrollInfo(canvas, this.sizes, this.internalApi);
this.canvasScrollManager = new CanvasScrollManager(this, horizontalRuler);
this.renderers = new MapCreator()
.add(ViewType.PrintLayout, new PrintLayoutRenderer(this))
.add(ViewType.Simple, new SimpleViewRenderer(this))
.get();
this.canvasListeners = new MapCreator()
.add(ViewType.PrintLayout, new PrintLayoutViewCanvasListener(this, this.renderers[ViewType.PrintLayout]))
.add(ViewType.Simple, new SimpleViewCanvasListener(this, this.renderers[ViewType.Simple]))
.get();
const layoutSelection = null;
this.selection = new SelectionRenderer(this.cache, layoutSelection);
this.searchSelection = new SearchSelectionRenderer(this.cache, layoutSelection);
this.misspelledSelection = new MisspelledSelectionRenderer(this.cache, layoutSelection);
this.rangePermission = new RangePermissionRenderer(this.cache, layoutSelection);
this.changeActiveSubDocumentRenderer = new RendererManager(this, stringResources);
}
dispose() {
this.canvasManager.dispose();
this.canvasScrollManager.dispose();
this.selection.dispose();
this.pagesContainer = null;
}
modelChanged(change) {
if (change.type == ModelChangeType.ZoomLevelChanged) {
this.canvas.scrollTop = this.canvas.scrollTop / change.prevZoomLevel * change.zoomLevel;
this.pagesContainer.style.zoom = change.zoomLevel.toString();
this.sizes.updateSize(this.canvas);
}
}
adjust(force) {
if ((force || !this.sizes.isInitialized()) && this.cache.length > 0) {
const firstRenderedPageIndex = Math.min(this.cache.length, Math.max(0, ListUtils.indexBy(this.layout.pages, (page) => page.flags.get(LayoutPageFlags.ContentRendered))));
this.sizes.initialize(this.cache[firstRenderedPageIndex].page, this.canvas);
const oldPageIndo = this.innerClientProperties.viewsSettings.pageVerticalInfo.clone();
this.innerClientProperties.viewsSettings.pageVerticalInfo.copyFrom(this.sizes.pageVerticalInfo);
if (this.innerClientProperties.viewsSettings.isSimpleView && !this.innerClientProperties.viewsSettings.pageVerticalInfo.equals(oldPageIndo)) {
const page = this.layout.pages[firstRenderedPageIndex];
if (this.layoutFormatterManagerHolder.layoutFormatterManager && page)
this.layoutFormatterManagerHolder.layoutFormatterManager.invalidator.onChangedAllLayout();
}
if (force) {
this.canvasScrollManager.updateScrollVisibility();
this.canvasListener.onCanvasScroll();
}
}
else if (this.sizes.updateSize(this.canvas))
this.scroll.onCanvasSizeChanged();
}
NotifyPagesReady(pageChanges) {
this.canvasListener.onPagesReady(pageChanges);
}
NotifyFullyFormatted(_pageCount) { }
;
NotifySelectionLayoutChanged() {
const layoutSelection = this.selection.layoutSelection;
this.changeActiveSubDocumentRenderer.update(layoutSelection);
Log.print(LogSource.CanvasManager, "onSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.selectionInfo.changes, "", "\n"));
if (this.innerClientProperties.viewsSettings.isSimpleView)
this.selection.renderAllPageSelection(this.layout, 0, true);
else
this.selection.applySelectionChanges(this.layout);
const pageIndex = ListUtils.reverseIndexBy(layoutSelection.selectionInfo.pageInfos, pageInfo => pageInfo.oldItems.length > 0);
if (pageIndex > -1) {
const pageInfo = layoutSelection.selectionInfo.pageInfos[pageIndex];
const item = pageInfo.oldItems[0];
const layoutPage = this.layout.pages[pageIndex];
const x = MixedSize.fromLayout(layoutPage.x + this.cache[pageIndex].page.offsetLeft + item.x).useScale(this.zoomLevel);
const y = MixedSize.fromLayout(this.sizes.getPageOffsetY(layoutPage) + item.y).useScale(this.zoomLevel);
this.inputController.setPosition(x.UISize, y.UISize);
}
}
NotifySearchSelectionLayoutChanged() {
Log.print(LogSource.CanvasManager, "onSearchSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.searchInfo.changes, "", "\n"));
if (this.innerClientProperties.viewsSettings.isSimpleView)
this.searchSelection.renderAllPageSelection(this.layout, 0, true);
else
this.searchSelection.applySelectionChanges(this.layout);
}
NotifyMisspelledSelectionLayoutChanged() {
Log.print(LogSource.CanvasManager, "onMisspelledSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.misspelledInfo.changes, "", "\n"));
if (this.innerClientProperties.viewsSettings.isSimpleView)
this.misspelledSelection.renderAllPageSelection(this.layout, 0, true);
else
this.misspelledSelection.applySelectionChanges(this.layout);
}
NotifyRangePermissionLayoutChanged() {
Log.print(LogSource.CanvasManager, "onRangePermissionsLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.rangePermissionInfo.changes, "", "\n"));
if (this.innerClientProperties.viewsSettings.isSimpleView)
this.rangePermission.renderAllPageSelection(this.layout, 0, true);
else
this.rangePermission.applySelectionChanges(this.layout);
}
addTopLevelContainers() {
this.pagesContainer = DocumentRenderer.renderContainer(RendererClassNames.PAGES);
this.pagesContainer.style.zoom = this.zoomLevel.toString();
this.serviceContainer = DocumentRenderer.renderContainer(RendererClassNames.TOP_LEVEL_SERVICE_CONTAINER);
DocumentRenderer.insertInContainer(this.canvas, 0, this.pagesContainer, (node) => node);
this.canvas.appendChild(this.serviceContainer);
}
setWorkSession(layout, layoutSelection, imageCache) {
this.layout = layout;
this.imageCache = imageCache;
this.changeActiveSubDocumentRenderer.init();
this.selection.layoutSelection = layoutSelection;
this.searchSelection.layoutSelection = layoutSelection;
this.misspelledSelection.layoutSelection = layoutSelection;
this.rangePermission.layoutSelection = layoutSelection;
this.selection.touchSelectionCircleElementsManager.layoutSelection = layoutSelection;
}
closeDocument() {
DomUtils.clearInnerHtml(this.pagesContainer);
this.cache.splice(0);
this.canvasManager.closeDocument();
this.selection.closeDocument();
this.searchSelection.closeDocument();
this.misspelledSelection.closeDocument();
this.rangePermission.closeDocument();
NumberMapUtils.forEach(this.canvasListeners, (r) => r.closeDocument());
this.layout.setEmptyLayout(ColorHelper.NO_COLOR);
}
ensureFirstPageIsRendered() {
const firstPage = this.layout?.pages?.[0];
if (!firstPage)
return;
if (this.lastUsedRendererType === ViewType.PrintLayout && !firstPage.flags.get(LayoutPageFlags.ContentRendered)) {
this.printLayoutRenderer.renderPage(firstPage, firstPage.index, true);
this.changeActiveSubDocumentRenderer.updatePage(this.searchSelection.layoutSelection, firstPage.index);
firstPage.flags.set(LayoutPageFlags.ContentRendered, true);
}
}
get zoomLevel() { return this.innerClientProperties.viewsSettings.zoomLevel; }
set zoomLevel(value) {
const prevZoomLevel = this.zoomLevel;
this.innerClientProperties.viewsSettings.zoomLevel = value;
this.control.modelManager.modelManipulator.notifyModelChanged(new ZoomLevelChange(this.zoomLevel, prevZoomLevel));
}
get allowZoom() { return ControlOptions.isEnabled(this.control.modelManager.richOptions.control.allowZoom); }
set allowZoom(value) {
this.control.modelManager.richOptions.control.allowZoom = value ? DocumentCapability.Enabled : DocumentCapability.Hidden;
this.control.barHolder.forceUpdate({ [RichEditClientCommand.ChangeZoomLevel]: true });
}
}