UNPKG

devexpress-richedit

Version:

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

92 lines (91 loc) 4.88 kB
import { DocumentLayoutDetailsLevel } from "../../../common/layout/document-layout-details-level"; import { LayoutPoint } from "../../../common/layout/layout-point"; import { SetSelectionStateOptions } from "../../../common/selection/selection"; import { SelectionCommandBase } from "./selection-command-base"; import { ScrollTopInfo } from "../../../common/canvas/canvas-manager"; import { ScrollState } from "../../../common/scroll/model-states"; import { LayoutPositionMainSubDocumentCreator, LayoutPositionCreatorConflictFlags } from "../../../common/layout-engine/layout-position-creator"; import { FixedInterval } from "@devexpress/utils/lib/intervals/fixed"; export class GoToPageCommandBase extends SelectionCommandBase { get scale() { return this.control.viewManager.zoomLevel; } executeCore(_state, _options) { const selection = this.selection; const initPosition = selection.forwardDirection ? selection.lastSelectedInterval.end : selection.lastSelectedInterval.start; const layoutPosition = new LayoutPositionMainSubDocumentCreator(this.control.layout, this.selection.activeSubDocument, initPosition, DocumentLayoutDetailsLevel.Box) .create(new LayoutPositionCreatorConflictFlags().setDefault(false), new LayoutPositionCreatorConflictFlags().setDefault(true)); if (!layoutPosition) return false; const charOffset = initPosition - layoutPosition.getLogPosition(DocumentLayoutDetailsLevel.Box); const x = layoutPosition.pageArea.x + layoutPosition.column.x + layoutPosition.row.x + layoutPosition.box.x + layoutPosition.box.getCharOffsetXInPixels(this.control.measurer, charOffset); const y = layoutPosition.pageArea.y + layoutPosition.column.y + layoutPosition.row.y + layoutPosition.box.y; this.goToPage(layoutPosition, x, y); return true; } getPageOffsetY(pageIndex) { const page = this.control.layout.pages[pageIndex]; return this.control.viewManager.sizes.getPageOffsetY(page); } findPageIndexByOffsetY(offsetY) { return this.control.layout.findPageIndexByOffsetY(offsetY, this.control.viewManager.sizes); } tryFindVisiblePosition(x, top, bottom) { let prevResult; while (true) { const mid = (top + bottom) / 2; const pageIndex = this.findPageIndexByOffsetY(mid); const pageY = this.getPageOffsetY(pageIndex); const htr = this.calculateHitTestResult(pageIndex, x, mid - pageY); const rowHeight = htr.row.height; if (bottom - top < rowHeight) break; const halfOfRowHeight = rowHeight / 2; const y = htr.getLayoutY() + this.getPageOffsetY(htr.page.index) + halfOfRowHeight; if (htr.detailsLevel >= DocumentLayoutDetailsLevel.Row && y > top && y < bottom) { if (prevResult?.getPosition() === htr.getPosition()) return htr.getPosition(); prevResult = htr; } if (y < mid) top = mid; else bottom = mid; } return prevResult ? prevResult.getPosition() : null; } calculateHitTestResult(pageIndex, x, y) { const point = new LayoutPoint(pageIndex, x, y); const htr = this.control.hitTestManager.calculate(point, DocumentLayoutDetailsLevel.Character, this.selection.activeSubDocument); if (!this.extendSelection()) htr.correctAsVisibleBox(); return htr; } changeSelection(position) { const selection = this.selection; if (this.extendSelection()) selection.changeState((newState) => newState.extendLastInterval(position)); else { const options = new SetSelectionStateOptions(); options.useFieldUiChecks = true; options.correctIntervalDueToTables = true; options.correctIntervalDueToFields = true; selection.changeState((newState) => { newState.setInterval(new FixedInterval(position, 0)) .setKeepX(selection.keepX) .setEndOfLine(selection.endOfLine) .setForwardDirection(true); }, options); } } scrollToPosition(pageIndex, offsetY) { const page = this.control.layout.pages[pageIndex]; const pageY = this.control.viewManager.sizes.getPageOffsetY(page); const scrollInfo = new ScrollTopInfo(pageIndex, offsetY - pageY); const state = new ScrollState().byScrollInfo.setPageInfo(scrollInfo); this.control.scrollManager.setScroll(state); } isEnabled() { return super.isEnabled() && this.selection.activeSubDocument.isMain(); } }