UNPKG

devexpress-richedit

Version:

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

138 lines (137 loc) 7.34 kB
import { EvtUtils } from '@devexpress/utils/lib/utils/evt'; import { LayoutAnchorObjectFinder } from '../layout-anchor-object-finder'; import { LayoutPositionCreatorConflictFlags, LayoutPositionMainSubDocumentCreator, LayoutPositionOtherSubDocumentCreator } from '../layout-position-creator'; import { LayoutChangeType } from '../../layout-formatter/changes/changes/layout-change-base'; import { DocumentLayoutDetailsLevel } from '../../layout/document-layout-details-level'; import { LayoutBoxType } from '../../layout/main-structures/layout-boxes/layout-box'; import { Point } from '@devexpress/utils/lib/geometry/point'; import { Rectangle } from '@devexpress/utils/lib/geometry/rectangle'; import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed'; import { ListUtils } from '@devexpress/utils/lib/utils/list'; import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number'; import { FrameBaseListener } from '../../canvas/listeners/frame-base-listener'; import { ReadOnlyMode } from '../../interfaces/i-rich-edit-core'; import { MouseEventSource } from '../../mouse-handler/mouse-event-source'; import { BaseVisualizer } from './base-visualizer'; import { RendererClassNames } from '../../canvas/renderer-class-names'; export class ResizeBoxVisualizer extends BaseVisualizer { NotifySelectionChanged(selection) { if (selection.specialRunInfo.isSelected()) this.setBox(); else if (this.initBounds) this.hide(); } NotifyScrollPositionChanged() { } NotifyFullyFormatted(_pageCount) { } ; NotifyPagesReady(pageChanges) { const specRunInfo = this.control.selection.specialRunInfo; if (!specRunInfo.isSelected()) return; const subDoc = specRunInfo.getParentSubDocument(); const pos = specRunInfo.getPosition(); if (subDoc.isMain()) { if (ListUtils.unsafeAnyOf(pageChanges, (pageChange) => pageChange.changeType == LayoutChangeType.Deleted ? null : new LayoutAnchorObjectFinder(this.control.layout, pos, subDoc.id, pageChange.index).obj || ListUtils.unsafeAnyOf(this.control.layout.pages[pageChange.index].getContentIntervals(), (interval) => interval.contains(pos) ? pageChange : null))) this.setBox(); } else { if (ListUtils.unsafeAnyOf(pageChanges, (pageChange) => pageChange.changeType == LayoutChangeType.Deleted ? null : NumberMapUtils.containsBy(this.control.layout.pages[pageChange.index].otherPageAreas, (pageArea) => pageArea.subDocument.id == subDoc.id))) this.setBox(); } } setBox() { const specRunInfo = this.control.selection.specialRunInfo; const pos = specRunInfo.getPosition(); if (specRunInfo.isSelectedAnchorObject) { const parentSubDoc = specRunInfo.getParentSubDocument(); const finder = new LayoutAnchorObjectFinder(this.control.layout, pos, parentSubDoc.id, parentSubDoc.isHeaderFooter() ? this.control.selection.pageIndex : undefined); if (finder.obj) this.show(finder.page.index, null, null, null, finder.obj); return; } const subDocument = this.control.selection.activeSubDocument; const layoutPosition = (subDocument.isMain() ? new LayoutPositionMainSubDocumentCreator(this.control.layout, subDocument, pos, DocumentLayoutDetailsLevel.Box) : new LayoutPositionOtherSubDocumentCreator(this.control.layout, subDocument, pos, this.control.selection.pageIndex, DocumentLayoutDetailsLevel.Box)) .create(new LayoutPositionCreatorConflictFlags().setDefault(false), new LayoutPositionCreatorConflictFlags().setDefault(false)); if (layoutPosition) this.show(layoutPosition.pageIndex, layoutPosition.pageArea, layoutPosition.column, layoutPosition.row, layoutPosition.box); } reset() { this.initBounds = null; super.reset(); } show(pageIndex, pageArea, column, row, box) { this.pageIndex = pageIndex; this.tip = box.hyperlinkTip; const boxType = box.getType(); this.isTextBox = boxType == LayoutBoxType.AnchorTextBox; this.isAnchoredObject = boxType == LayoutBoxType.AnchorPicture || boxType == LayoutBoxType.AnchorTextBox; this.initBounds = new Rectangle(0, 0, 0, 0); if (this.isAnchoredObject) { this.initBounds.copyFrom(box); this.rotation = boxType == LayoutBoxType.AnchorTextBox && this.control.selection.activeSubDocument.isTextBox() ? 0 : box.rotationInRadians; } else { const boxY = Math.max(0, row.baseLine - box.getAscent()); this.initBounds .setPosition(new Point(pageArea.x + column.x + row.x + box.x, pageArea.y + column.y + row.y + boxY)) .setSize(box); this.rotation = 0; } this.recalculate(null, null, null); } showAtPos(pageIndex, position) { this.pageIndex = pageIndex; this.initBounds.x = position.x; this.initBounds.y = position.y; this.recalculate(null, null, null); } recalculate(size, positionDelta, newRotation) { this.bounds = size != null ? new Rectangle(this.initBounds.x + positionDelta.width, this.initBounds.y + positionDelta.height, size.width, size.height) : this.initBounds.createRectangle(); if (newRotation != null) this.rotation = newRotation; this.raiseShow(); } isResizeBoxVisible() { return !!this.bounds; } shouldCapture(evt) { return !this.control.isReadOnlyPersistent && !!ResizeBoxVisualizer.shouldCaptureEvents[evt.source]; } static shouldRotate(evt, control) { return control.readOnly != ReadOnlyMode.Persistent && ResizeBoxVisualizer.isEventSourceHasClassName(evt, FrameBaseListener.CLASSNAMES.ROTATION_BOX) && control.selection.activeSubDocument.isEditable([new FixedInterval(control.selection.specialRunInfo.getPosition(), 1)]); } static shouldHandleTextBoxAreaClick(evt) { return ResizeBoxVisualizer.isEventSourceHasClassName(evt, FrameBaseListener.CLASSNAMES.TEXTBOX_AREA) || ResizeBoxVisualizer.isEventSourceHasClassName(evt, RendererClassNames.SELECTED_TEXTBOX); } static isEventSourceHasClassName(evt, className) { let element = EvtUtils.getEventSource(evt.mouseEvent); while (element) { if (element.className.indexOf(className) > -1) return true; if (element.className.indexOf(RendererClassNames.PAGES) > -1) return false; element = element.parentElement; } return false; } } ResizeBoxVisualizer.shouldCaptureEvents = { [MouseEventSource.ResizeBox_E]: true, [MouseEventSource.ResizeBox_N]: true, [MouseEventSource.ResizeBox_NE]: true, [MouseEventSource.ResizeBox_NW]: true, [MouseEventSource.ResizeBox_S]: true, [MouseEventSource.ResizeBox_SE]: true, [MouseEventSource.ResizeBox_SW]: true, [MouseEventSource.ResizeBox_W]: true, };