devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
130 lines (129 loc) • 6.77 kB
JavaScript
import { RichEditUnit } from '../../utils/unit-converter';
import { PaperKind, PaperSizeConverter } from '../../model/section/paper-kind';
import { UnitConverter } from '@devexpress/utils/lib/class/unit-converter';
import { BoundaryInterval } from '@devexpress/utils/lib/intervals/boundary';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { RulerColumnsControl } from './controls/column';
import { DivisionInfo, RulerDivisionsControl } from './controls/divisions';
import { RulerFirstLineIndentDragHandle } from './controls/indent/first-line';
import { RulerLeftIndentDragHandle } from './controls/indent/left';
import { RulerRightIndentDragHandle } from './controls/indent/right';
import { RulerLeftMarginDragHandle } from './controls/margin/left';
import { RulerRightMarginDragHandle } from './controls/margin/right';
import { RulerControl } from './controls/ruler';
import { RulerTabsControl } from './controls/tab/tab';
import { RulerTabTypeControl } from './controls/tab/tab-type';
import { RulerTablesControl } from './controls/table';
import { RulerVerticalLineControl } from './controls/vertical-line';
import { RulerWrapper } from './controls/wrapper';
import { RulerMouseEventsManager } from './events/mouse';
import { RulerViewElementScrollManager } from './events/scroll';
import { RulerMouseHandler } from './mouse-handler';
export class RulerControls {
get paragraphLeftPosition() {
let pos = this.leftMargin.currModelState.modelValue + this.columns.currModelState.activeColumn.leftPos;
if (this.tables.currModelState.columnSeparators.hasItems) {
const item = this.tables.currModelState.columnSeparators.currItem;
pos += this.tables.currModelState.columnSeparators.cellSpacing + item.leftMargin + item.position;
}
return pos;
}
get paragraphRightPosition() {
const colSeps = this.tables.currModelState.columnSeparators;
if (colSeps.hasItems) {
const nextSeparatorItem = colSeps.items[colSeps.index + 1];
return this.leftMargin.currModelState.modelValue + this.columns.currModelState.activeColumn.leftPos +
(nextSeparatorItem.position - colSeps.cellSpacing - colSeps.currItem.rightMargin);
}
else
return this.leftMargin.currModelState.modelValue + this.columns.currModelState.activeColumn.rightPos;
}
constructor(canvas, modelData) {
this.mouseEventsManager = new RulerMouseEventsManager();
this.viewElementScrollManager = new RulerViewElementScrollManager();
this.canvas = canvas;
const divisionInfo = DivisionInfo.create(modelData.unitType);
const maxPageWidth = UnitConverter.twipsToPixelsF(PaperSizeConverter.calculatePaperSize(PaperKind.PrcEnvelopeNumber10Rotated).width);
this.moveStepSize = modelData.unitType == RichEditUnit.Inch ? divisionInfo.stepSize / 2 : divisionInfo.stepSize;
this.wrapper = new RulerWrapper(modelData, this);
this.ruler = new RulerControl(modelData, this);
this.tabTypeBox = new RulerTabTypeControl(modelData, this);
this.divisions = new RulerDivisionsControl(modelData, this, divisionInfo, maxPageWidth);
this.leftMargin = new RulerLeftMarginDragHandle(modelData, this, maxPageWidth);
this.rightMargin = new RulerRightMarginDragHandle(modelData, this, maxPageWidth);
this.leftIndent = new RulerLeftIndentDragHandle(modelData, this);
this.firstLineIndent = new RulerFirstLineIndentDragHandle(modelData, this);
this.rightIndent = new RulerRightIndentDragHandle(modelData, this);
this.columns = new RulerColumnsControl(modelData, this);
this.tables = new RulerTablesControl(modelData, this);
this.tabs = new RulerTabsControl(modelData, this);
this.ruler.init();
this.tabTypeBox.init();
this.lineControl = new RulerVerticalLineControl(this.canvas, modelData.styles.line.className, this.ruler.rootElement);
this.mouseHandler = new RulerMouseHandler(modelData, this);
this.mouseEventsManager.addListener(this.mouseHandler);
this.viewElementScrollManager.addListener(this.ruler, this.canvas);
}
dispose() {
this.lineControl.dispose();
this.wrapper.dispose();
this.ruler.dispose();
this.tabTypeBox.dispose();
this.divisions.dispose();
this.leftMargin.dispose();
this.rightMargin.dispose();
this.leftIndent.dispose();
this.firstLineIndent.dispose();
this.rightIndent.dispose();
this.columns.dispose();
this.tables.dispose();
this.tabs.dispose();
this.mouseEventsManager.dispose();
this.viewElementScrollManager.dispose();
}
update() {
this.updateModelState();
this.updateView();
}
updateModelState() {
this.ruler.updateModelState();
this.leftMargin.updateModelState();
this.rightMargin.updateModelState();
this.divisions.updateModelState();
this.columns.updateModelState();
this.tables.updateModelState();
this.rightIndent.updateModelState();
this.leftIndent.updateModelState();
this.firstLineIndent.updateModelState();
this.tabs.updateModelState();
}
updateView() {
this.ruler.updateView();
this.leftMargin.updateView();
this.rightMargin.updateView();
this.divisions.updateView();
this.columns.updateView();
this.tables.updateView();
this.rightIndent.updateView();
this.leftIndent.updateView();
this.firstLineIndent.updateView();
this.tabs.updateView();
}
adjust() {
this.ruler.adjust();
}
chooseClosestAnchorPosition(leftPos, additionalPositions, minMax) {
const boundInterval = new BoundaryInterval(minMax.minElement, minMax.maxElement);
let poss = ListUtils.addListOnTail(this.getClosestAnchorPositions(leftPos, 0), additionalPositions);
poss.push(minMax.minElement);
poss.push(minMax.maxElement);
poss = ListUtils.reducedMap(poss, p => boundInterval.containsWithIntervalEnd(p) ? p : null).sort((a, b) => a - b);
return poss.length ?
ListUtils.min(poss, p => Math.abs(p - leftPos)) :
ListUtils.min([minMax.minElement, minMax.maxElement], p => Math.abs(p - leftPos));
}
getClosestAnchorPositions(leftPos, relative) {
const stepIndex = (leftPos - relative) / this.moveStepSize;
return [this.moveStepSize * Math.floor(stepIndex), this.moveStepSize * Math.ceil(stepIndex)];
}
}