Merge pull request #22 from Hufe921/feature/mode

Feature/mode
pr675
Hufe 4 years ago committed by GitHub
commit 6f7b079af2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -163,16 +163,16 @@
</div> </div>
<div class="menu-divider"></div> <div class="menu-divider"></div>
<div class="menu-item"> <div class="menu-item">
<div class="menu-item__search"> <div class="menu-item__search" data-menu="search">
<i></i> <i></i>
</div> </div>
<div class="menu-item__search__collapse"> <div class="menu-item__search__collapse" data-menu="search">
<div class="menu-item__search__collapse__search"> <div class="menu-item__search__collapse__search">
<input type="text" /> <input type="text" />
<span>×</span> <span>×</span>
</div> </div>
</div> </div>
<div class="menu-item__print"> <div class="menu-item__print" data-menu="print">
<i></i> <i></i>
</div> </div>
</div> </div>
@ -183,6 +183,7 @@
<span>可见页码:<span class="page-no-list">1</span></span> <span>可见页码:<span class="page-no-list">1</span></span>
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span> <span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
</div> </div>
<div class="editor-mode">编辑模式</div>
<div> <div>
<div class="page-scale-minus"> <div class="page-scale-minus">
<i></i> <i></i>

@ -1,4 +1,5 @@
import { IElement } from "../.." import { IElement } from "../.."
import { EditorMode } from "../../dataset/enum/Editor"
import { RowFlex } from "../../dataset/enum/Row" import { RowFlex } from "../../dataset/enum/Row"
import { IDrawImagePayload } from "../../interface/Draw" import { IDrawImagePayload } from "../../interface/Draw"
import { IWatermark } from "../../interface/Watermark" import { IWatermark } from "../../interface/Watermark"
@ -6,6 +7,7 @@ import { CommandAdapt } from "./CommandAdapt"
export class Command { export class Command {
private static mode: Function
private static cut: Function private static cut: Function
private static copy: Function private static copy: Function
private static paste: Function private static paste: Function
@ -53,6 +55,7 @@ export class Command {
private static insertElementList: Function private static insertElementList: Function
constructor(adapt: CommandAdapt) { constructor(adapt: CommandAdapt) {
Command.mode = adapt.mode.bind(adapt)
Command.cut = adapt.cut.bind(adapt) Command.cut = adapt.cut.bind(adapt)
Command.copy = adapt.copy.bind(adapt) Command.copy = adapt.copy.bind(adapt)
Command.paste = adapt.paste.bind(adapt) Command.paste = adapt.paste.bind(adapt)
@ -101,6 +104,10 @@ export class Command {
} }
// 全局命令 // 全局命令
public executeMode(payload: EditorMode) {
return Command.mode(payload)
}
public executeCut() { public executeCut() {
return Command.cut() return Command.cut()
} }

@ -1,7 +1,7 @@
import { WRAP, ZERO } from "../../dataset/constant/Common" import { WRAP, ZERO } from "../../dataset/constant/Common"
import { EDITOR_ELEMENT_STYLE_ATTR, TEXTLIKE_ELEMENT_TYPE } from "../../dataset/constant/Element" import { EDITOR_ELEMENT_STYLE_ATTR, TEXTLIKE_ELEMENT_TYPE } from "../../dataset/constant/Element"
import { defaultWatermarkOption } from "../../dataset/constant/Watermark" import { defaultWatermarkOption } from "../../dataset/constant/Watermark"
import { EditorContext } from "../../dataset/enum/Editor" import { EditorContext, EditorMode } from "../../dataset/enum/Editor"
import { ElementType } from "../../dataset/enum/Element" import { ElementType } from "../../dataset/enum/Element"
import { ElementStyleKey } from "../../dataset/enum/ElementStyle" import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
import { RowFlex } from "../../dataset/enum/Row" import { RowFlex } from "../../dataset/enum/Row"
@ -45,7 +45,19 @@ export class CommandAdapt {
this.options = draw.getOptions() this.options = draw.getOptions()
} }
public mode(payload: EditorMode) {
const mode = this.draw.getMode()
if (mode === payload) return
this.draw.setMode(payload)
this.draw.render({
isSetCursor: false,
isSubmitHistory: false
})
}
public cut() { public cut() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
this.canvasEvent.cut() this.canvasEvent.cut()
} }
@ -54,6 +66,8 @@ export class CommandAdapt {
} }
public async paste() { public async paste() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const text = await navigator.clipboard.readText() const text = await navigator.clipboard.readText()
if (text) { if (text) {
this.canvasEvent.input(text) this.canvasEvent.input(text)
@ -65,14 +79,20 @@ export class CommandAdapt {
} }
public undo() { public undo() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
this.historyManager.undo() this.historyManager.undo()
} }
public redo() { public redo() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
this.historyManager.redo() this.historyManager.redo()
} }
public painter() { public painter() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const painterStyle: IElementStyle = {} const painterStyle: IElementStyle = {}
@ -89,6 +109,8 @@ export class CommandAdapt {
} }
public format() { public format() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
selection.forEach(el => { selection.forEach(el => {
@ -103,6 +125,8 @@ export class CommandAdapt {
} }
public font(payload: string) { public font(payload: string) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
selection.forEach(el => { selection.forEach(el => {
@ -112,6 +136,8 @@ export class CommandAdapt {
} }
public sizeAdd() { public sizeAdd() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const lessThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size + 2 <= 72) const lessThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size + 2 <= 72)
@ -128,6 +154,8 @@ export class CommandAdapt {
} }
public sizeMinus() { public sizeMinus() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const greaterThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size - 2 >= 8) const greaterThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size - 2 >= 8)
@ -144,6 +172,8 @@ export class CommandAdapt {
} }
public bold() { public bold() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const noBoldIndex = selection.findIndex(s => !s.bold) const noBoldIndex = selection.findIndex(s => !s.bold)
@ -154,6 +184,8 @@ export class CommandAdapt {
} }
public italic() { public italic() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const noItalicIndex = selection.findIndex(s => !s.italic) const noItalicIndex = selection.findIndex(s => !s.italic)
@ -164,6 +196,8 @@ export class CommandAdapt {
} }
public underline() { public underline() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const noUnderlineIndex = selection.findIndex(s => !s.underline) const noUnderlineIndex = selection.findIndex(s => !s.underline)
@ -174,6 +208,8 @@ export class CommandAdapt {
} }
public strikeout() { public strikeout() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const noStrikeoutIndex = selection.findIndex(s => !s.strikeout) const noStrikeoutIndex = selection.findIndex(s => !s.strikeout)
@ -184,6 +220,8 @@ export class CommandAdapt {
} }
public superscript() { public superscript() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const superscriptIndex = selection.findIndex(s => s.type === ElementType.SUPERSCRIPT) const superscriptIndex = selection.findIndex(s => s.type === ElementType.SUPERSCRIPT)
@ -205,6 +243,8 @@ export class CommandAdapt {
} }
public subscript() { public subscript() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
const subscriptIndex = selection.findIndex(s => s.type === ElementType.SUBSCRIPT) const subscriptIndex = selection.findIndex(s => s.type === ElementType.SUBSCRIPT)
@ -226,6 +266,8 @@ export class CommandAdapt {
} }
public color(payload: string) { public color(payload: string) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
selection.forEach(el => { selection.forEach(el => {
@ -235,6 +277,8 @@ export class CommandAdapt {
} }
public highlight(payload: string) { public highlight(payload: string) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const selection = this.range.getSelection() const selection = this.range.getSelection()
if (!selection) return if (!selection) return
selection.forEach(el => { selection.forEach(el => {
@ -244,6 +288,8 @@ export class CommandAdapt {
} }
public rowFlex(payload: RowFlex) { public rowFlex(payload: RowFlex) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const pageNo = this.draw.getPageNo() const pageNo = this.draw.getPageNo()
@ -268,6 +314,8 @@ export class CommandAdapt {
} }
public rowMargin(payload: number) { public rowMargin(payload: number) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const pageNo = this.draw.getPageNo() const pageNo = this.draw.getPageNo()
@ -292,6 +340,8 @@ export class CommandAdapt {
} }
public insertTable(row: number, col: number) { public insertTable(row: number, col: number) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -341,6 +391,8 @@ export class CommandAdapt {
} }
public insertTableTopRow() { public insertTableTopRow() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, trIndex, tableId } = positionContext const { index, trIndex, tableId } = positionContext
@ -403,6 +455,8 @@ export class CommandAdapt {
} }
public insertTableBottomRow() { public insertTableBottomRow() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, trIndex, tableId } = positionContext const { index, trIndex, tableId } = positionContext
@ -468,6 +522,8 @@ export class CommandAdapt {
} }
public insertTableLeftCol() { public insertTableLeftCol() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, tdIndex, tableId } = positionContext const { index, tdIndex, tableId } = positionContext
@ -524,6 +580,8 @@ export class CommandAdapt {
} }
public insertTableRightCol() { public insertTableRightCol() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, tdIndex, tableId } = positionContext const { index, tdIndex, tableId } = positionContext
@ -580,6 +638,8 @@ export class CommandAdapt {
} }
public deleteTableRow() { public deleteTableRow() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, trIndex } = positionContext const { index, trIndex } = positionContext
@ -631,6 +691,8 @@ export class CommandAdapt {
} }
public deleteTableCol() { public deleteTableCol() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, tdIndex, trIndex } = positionContext const { index, tdIndex, trIndex } = positionContext
@ -687,6 +749,8 @@ export class CommandAdapt {
} }
public deleteTable() { public deleteTable() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const originalElementList = this.draw.getOriginalElementList() const originalElementList = this.draw.getOriginalElementList()
@ -702,6 +766,8 @@ export class CommandAdapt {
} }
public mergeTableCell() { public mergeTableCell() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange() const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
@ -809,6 +875,8 @@ export class CommandAdapt {
} }
public cancelMergeTableCell() { public cancelMergeTableCell() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return if (!positionContext.isTable) return
const { index, tdIndex, trIndex } = positionContext const { index, tdIndex, trIndex } = positionContext
@ -869,6 +937,8 @@ export class CommandAdapt {
} }
public hyperlink(payload: IElement) { public hyperlink(payload: IElement) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -893,6 +963,8 @@ export class CommandAdapt {
} }
public separator(payload: number[]) { public separator(payload: number[]) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -930,6 +1002,8 @@ export class CommandAdapt {
} }
public addWatermark(payload: IWatermark) { public addWatermark(payload: IWatermark) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const options = this.draw.getOptions() const options = this.draw.getOptions()
const { color, size, opacity, font } = defaultWatermarkOption const { color, size, opacity, font } = defaultWatermarkOption
options.watermark.data = payload.data options.watermark.data = payload.data
@ -944,6 +1018,8 @@ export class CommandAdapt {
} }
public deleteWatermark() { public deleteWatermark() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const options = this.draw.getOptions() const options = this.draw.getOptions()
if (options.watermark && options.watermark.data) { if (options.watermark && options.watermark.data) {
options.watermark = { ...defaultWatermarkOption } options.watermark = { ...defaultWatermarkOption }
@ -955,6 +1031,8 @@ export class CommandAdapt {
} }
public image(payload: IDrawImagePayload) { public image(payload: IDrawImagePayload) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -1102,6 +1180,8 @@ export class CommandAdapt {
} }
public insertElementList(payload: IElement[]) { public insertElementList(payload: IElement[]) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
if (!payload.length) return if (!payload.length) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return if (!~startIndex && !~endIndex) return

@ -16,6 +16,7 @@ interface IRenderPayload {
export class ContextMenu { export class ContextMenu {
private draw: Draw
private command: Command private command: Command
private range: RangeManager private range: RangeManager
private position: Position private position: Position
@ -25,6 +26,7 @@ export class ContextMenu {
private contextMenuRelationShip: Map<HTMLDivElement, HTMLDivElement> private contextMenuRelationShip: Map<HTMLDivElement, HTMLDivElement>
constructor(draw: Draw, command: Command) { constructor(draw: Draw, command: Command) {
this.draw = draw
this.command = command this.command = command
this.range = draw.getRange() this.range = draw.getRange()
this.position = draw.getPosition() this.position = draw.getPosition()
@ -81,6 +83,8 @@ export class ContextMenu {
} }
private _getContext(): IContextMenuContext { private _getContext(): IContextMenuContext {
// 是否是只读模式
const isReadonly = this.draw.isReadonly()
const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange() const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange()
// 是否存在焦点 // 是否存在焦点
const editorTextFocus = !!(~startIndex || ~endIndex) const editorTextFocus = !!(~startIndex || ~endIndex)
@ -92,6 +96,7 @@ export class ContextMenu {
// 是否存在跨行/列 // 是否存在跨行/列
const isCrossRowCol = isInTable && !!crossRowCol const isCrossRowCol = isInTable && !!crossRowCol
return { return {
isReadonly,
editorHasSelection, editorHasSelection,
editorTextFocus, editorTextFocus,
isInTable, isInTable,

@ -6,7 +6,7 @@ export const globalMenus: IRegisterContextMenu[] = [
name: '剪切', name: '剪切',
shortCut: 'Ctrl + X', shortCut: 'Ctrl + X',
when: (payload) => { when: (payload) => {
return payload.editorHasSelection return !payload.isReadonly && payload.editorHasSelection
}, },
callback: (command: Command) => { callback: (command: Command) => {
command.executeCut() command.executeCut()
@ -26,7 +26,7 @@ export const globalMenus: IRegisterContextMenu[] = [
name: '粘贴', name: '粘贴',
shortCut: 'Ctrl + V', shortCut: 'Ctrl + V',
when: (payload) => { when: (payload) => {
return payload.editorTextFocus return !payload.isReadonly && payload.editorTextFocus
}, },
callback: (command: Command) => { callback: (command: Command) => {
command.executePaste() command.executePaste()

@ -9,7 +9,7 @@ export const tableMenus: IRegisterContextMenu[] = [
name: '插入行列', name: '插入行列',
icon: 'insert-row-col', icon: 'insert-row-col',
when: (payload) => { when: (payload) => {
return payload.isInTable return !payload.isReadonly && payload.isInTable
}, },
childMenus: [ childMenus: [
{ {
@ -50,7 +50,7 @@ export const tableMenus: IRegisterContextMenu[] = [
name: '删除行列', name: '删除行列',
icon: 'delete-row-col', icon: 'delete-row-col',
when: (payload) => { when: (payload) => {
return payload.isInTable return !payload.isReadonly && payload.isInTable
}, },
childMenus: [ childMenus: [
{ {
@ -83,7 +83,7 @@ export const tableMenus: IRegisterContextMenu[] = [
name: '合并单元格', name: '合并单元格',
icon: 'merge-cell', icon: 'merge-cell',
when: (payload) => { when: (payload) => {
return payload.isCrossRowCol return !payload.isReadonly && payload.isCrossRowCol
}, },
callback: (command: Command) => { callback: (command: Command) => {
command.executeMergeTableCell() command.executeMergeTableCell()
@ -93,7 +93,7 @@ export const tableMenus: IRegisterContextMenu[] = [
name: '取消合并', name: '取消合并',
icon: 'merge-cancel-cell', icon: 'merge-cancel-cell',
when: (payload) => { when: (payload) => {
return payload.isInTable return !payload.isReadonly && payload.isInTable
}, },
callback: (command: Command) => { callback: (command: Command) => {
command.executeCancelMergeTableCell() command.executeCancelMergeTableCell()

@ -35,6 +35,7 @@ export class Cursor {
} }
public drawCursor() { public drawCursor() {
const isReadonly = this.draw.isReadonly()
const cursorPosition = this.position.getCursorPosition() const cursorPosition = this.position.getCursorPosition()
if (!cursorPosition) return if (!cursorPosition) return
// 设置光标代理 // 设置光标代理
@ -60,7 +61,7 @@ export class Cursor {
// 模拟光标显示 // 模拟光标显示
this.cursorDom.style.left = `${cursorLeft}px` this.cursorDom.style.left = `${cursorLeft}px`
this.cursorDom.style.top = `${cursorTop}px` this.cursorDom.style.top = `${cursorTop}px`
this.cursorDom.style.display = 'block' this.cursorDom.style.display = isReadonly ? 'none' : 'block'
this.cursorDom.style.height = `${cursorHeight}px` this.cursorDom.style.height = `${cursorHeight}px`
setTimeout(() => { setTimeout(() => {
this.cursorDom.classList.add('cursor--animation') this.cursorDom.classList.add('cursor--animation')

@ -33,6 +33,7 @@ import { SubscriptParticle } from "./particle/Subscript"
import { SeparatorParticle } from "./particle/Separator" import { SeparatorParticle } from "./particle/Separator"
import { PageBreakParticle } from "./particle/PageBreak" import { PageBreakParticle } from "./particle/PageBreak"
import { Watermark } from "./frame/Watermark" import { Watermark } from "./frame/Watermark"
import { EditorMode } from "../../dataset/enum/Editor"
export class Draw { export class Draw {
@ -41,6 +42,7 @@ export class Draw {
private pageList: HTMLCanvasElement[] private pageList: HTMLCanvasElement[]
private ctxList: CanvasRenderingContext2D[] private ctxList: CanvasRenderingContext2D[]
private pageNo: number private pageNo: number
private mode: EditorMode
private options: Required<IEditorOption> private options: Required<IEditorOption>
private position: Position private position: Position
private elementList: IElement[] private elementList: IElement[]
@ -85,6 +87,7 @@ export class Draw {
this.pageList = [] this.pageList = []
this.ctxList = [] this.ctxList = []
this.pageNo = 0 this.pageNo = 0
this.mode = options.defaultMode
this.options = options this.options = options
this.elementList = elementList this.elementList = elementList
this.listener = listener this.listener = listener
@ -131,6 +134,18 @@ export class Draw {
this.render({ isSetCursor: false }) this.render({ isSetCursor: false })
} }
public getMode(): EditorMode {
return this.mode
}
public setMode(payload: EditorMode) {
this.mode = payload
}
public isReadonly() {
return this.mode === EditorMode.READONLY
}
public getWidth(): number { public getWidth(): number {
return Math.floor(this.options.width * this.options.scale) return Math.floor(this.options.width * this.options.scale)
} }
@ -650,7 +665,9 @@ export class Draw {
} else if (element.type === ElementType.SEPARATOR) { } else if (element.type === ElementType.SEPARATOR) {
this.separatorParticle.render(ctx, element, x, y) this.separatorParticle.render(ctx, element, x, y)
} else if (element.type === ElementType.PAGE_BREAK) { } else if (element.type === ElementType.PAGE_BREAK) {
if (this.mode !== EditorMode.CLEAN) {
this.pageBreakParticle.render(ctx, element, x, y) this.pageBreakParticle.render(ctx, element, x, y)
}
} else { } else {
this.textParticle.record(ctx, element, x, y + offsetY) this.textParticle.record(ctx, element, x, y + offsetY)
} }

@ -146,6 +146,7 @@ export class CanvasEvent {
public mousedown(evt: MouseEvent) { public mousedown(evt: MouseEvent) {
if (evt.button === MouseEventButton.RIGHT) return if (evt.button === MouseEventButton.RIGHT) return
const isReadonly = this.draw.isReadonly()
const target = evt.target as HTMLDivElement const target = evt.target as HTMLDivElement
const pageIndex = target.dataset.index const pageIndex = target.dataset.index
// 设置pageNo // 设置pageNo
@ -207,12 +208,12 @@ export class CanvasEvent {
const curElement = elementList[curIndex] const curElement = elementList[curIndex]
// 图片尺寸拖拽组件 // 图片尺寸拖拽组件
this.imageParticle.clearResizer() this.imageParticle.clearResizer()
if (isDirectHitImage) { if (isDirectHitImage && !isReadonly) {
this.imageParticle.drawResizer(curElement, positionList[curIndex]) this.imageParticle.drawResizer(curElement, positionList[curIndex])
} }
// 表格工具组件 // 表格工具组件
this.tableTool.dispose() this.tableTool.dispose()
if (isTable) { if (isTable && !isReadonly) {
const originalElementList = this.draw.getOriginalElementList() const originalElementList = this.draw.getOriginalElementList()
const originalPositionList = this.position.getOriginalPositionList() const originalPositionList = this.position.getOriginalPositionList()
this.tableTool.render(originalElementList[index], originalPositionList[index]) this.tableTool.render(originalElementList[index], originalPositionList[index])
@ -232,6 +233,7 @@ export class CanvasEvent {
} }
public keydown(evt: KeyboardEvent) { public keydown(evt: KeyboardEvent) {
const isReadonly = this.draw.isReadonly()
const cursorPosition = this.position.getCursorPosition() const cursorPosition = this.position.getCursorPosition()
if (!cursorPosition) return if (!cursorPosition) return
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -240,6 +242,7 @@ export class CanvasEvent {
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
const isCollapsed = startIndex === endIndex const isCollapsed = startIndex === endIndex
if (evt.key === KeyMap.Backspace) { if (evt.key === KeyMap.Backspace) {
if (isReadonly) return
// 判断是否允许删除 // 判断是否允许删除
if (elementList[index].value === ZERO && index === 0) { if (elementList[index].value === ZERO && index === 0) {
evt.preventDefault() evt.preventDefault()
@ -254,6 +257,7 @@ export class CanvasEvent {
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
this.draw.render({ curIndex }) this.draw.render({ curIndex })
} else if (evt.key === KeyMap.Delete) { } else if (evt.key === KeyMap.Delete) {
if (isReadonly) return
if (!isCollapsed) { if (!isCollapsed) {
elementList.splice(startIndex + 1, endIndex - startIndex) elementList.splice(startIndex + 1, endIndex - startIndex)
} else { } else {
@ -263,6 +267,7 @@ export class CanvasEvent {
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
this.draw.render({ curIndex }) this.draw.render({ curIndex })
} else if (evt.key === KeyMap.Enter) { } else if (evt.key === KeyMap.Enter) {
if (isReadonly) return
// 表格需要上下文信息 // 表格需要上下文信息
const positionContext = this.position.getPositionContext() const positionContext = this.position.getPositionContext()
let restArg = {} let restArg = {}
@ -283,6 +288,7 @@ export class CanvasEvent {
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
this.draw.render({ curIndex }) this.draw.render({ curIndex })
} else if (evt.key === KeyMap.Left) { } else if (evt.key === KeyMap.Left) {
if (isReadonly) return
if (index > 0) { if (index > 0) {
const curIndex = index - 1 const curIndex = index - 1
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
@ -293,6 +299,7 @@ export class CanvasEvent {
}) })
} }
} else if (evt.key === KeyMap.Right) { } else if (evt.key === KeyMap.Right) {
if (isReadonly) return
if (index < position.length - 1) { if (index < position.length - 1) {
const curIndex = index + 1 const curIndex = index + 1
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
@ -303,6 +310,7 @@ export class CanvasEvent {
}) })
} }
} else if (evt.key === KeyMap.Up || evt.key === KeyMap.Down) { } else if (evt.key === KeyMap.Up || evt.key === KeyMap.Down) {
if (isReadonly) return
const { rowNo, index, coordinate: { leftTop, rightTop } } = cursorPosition const { rowNo, index, coordinate: { leftTop, rightTop } } = cursorPosition
if ((evt.key === KeyMap.Up && rowNo !== 0) || (evt.key === KeyMap.Down && rowNo !== this.draw.getRowCount())) { if ((evt.key === KeyMap.Up && rowNo !== 0) || (evt.key === KeyMap.Down && rowNo !== this.draw.getRowCount())) {
// 下一个光标点所在行位置集合 // 下一个光标点所在行位置集合
@ -344,18 +352,22 @@ export class CanvasEvent {
}) })
} }
} else if (evt.ctrlKey && evt.key === KeyMap.Z) { } else if (evt.ctrlKey && evt.key === KeyMap.Z) {
if (isReadonly) return
this.historyManager.undo() this.historyManager.undo()
evt.preventDefault() evt.preventDefault()
} else if (evt.ctrlKey && evt.key === KeyMap.Y) { } else if (evt.ctrlKey && evt.key === KeyMap.Y) {
if (isReadonly) return
this.historyManager.redo() this.historyManager.redo()
evt.preventDefault() evt.preventDefault()
} else if (evt.ctrlKey && evt.key === KeyMap.C) { } else if (evt.ctrlKey && evt.key === KeyMap.C) {
this.copy() this.copy()
} else if (evt.ctrlKey && evt.key === KeyMap.X) { } else if (evt.ctrlKey && evt.key === KeyMap.X) {
if (isReadonly) return
this.cut() this.cut()
} else if (evt.ctrlKey && evt.key === KeyMap.A) { } else if (evt.ctrlKey && evt.key === KeyMap.A) {
this.selectAll() this.selectAll()
} else if (evt.ctrlKey && evt.key === KeyMap.S) { } else if (evt.ctrlKey && evt.key === KeyMap.S) {
if (isReadonly) return
const saved = this.listener.saved const saved = this.listener.saved
if (saved) { if (saved) {
saved(this.save()) saved(this.save())
@ -365,6 +377,8 @@ export class CanvasEvent {
} }
public input(data: string) { public input(data: string) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
if (!this.cursor) return if (!this.cursor) return
const cursorPosition = this.position.getCursorPosition() const cursorPosition = this.position.getCursorPosition()
if (!data || !cursorPosition || this.isCompositing) return if (!data || !cursorPosition || this.isCompositing) return
@ -423,6 +437,8 @@ export class CanvasEvent {
} }
public cut() { public cut() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
if (startIndex !== endIndex) { if (startIndex !== endIndex) {

@ -10,3 +10,9 @@ export enum EditorContext {
PAGE = 'page', PAGE = 'page',
TABLE = 'table' TABLE = 'table'
} }
export enum EditorMode {
EDIT = 'edit',
CLEAN = 'clean',
READONLY = 'readonly'
}

@ -13,7 +13,7 @@ import { globalMenus } from './core/contextmenu/menus/GlobalMenus'
import { ContextMenu } from './core/contextmenu/ContextMenu' import { ContextMenu } from './core/contextmenu/ContextMenu'
import { tableMenus } from './core/contextmenu/menus/tableMenus' import { tableMenus } from './core/contextmenu/menus/tableMenus'
import { IContextMenuContext, IRegisterContextMenu } from './interface/contextmenu/ContextMenu' import { IContextMenuContext, IRegisterContextMenu } from './interface/contextmenu/ContextMenu'
import { EditorComponent } from './dataset/enum/Editor' import { EditorComponent, EditorMode } from './dataset/enum/Editor'
import { EDITOR_COMPONENT } from './dataset/constant/Editor' import { EDITOR_COMPONENT } from './dataset/constant/Editor'
import { IHeader } from './interface/Header' import { IHeader } from './interface/Header'
import { IWatermark } from './interface/Watermark' import { IWatermark } from './interface/Watermark'
@ -36,6 +36,7 @@ export default class Editor {
...options.watermark ...options.watermark
} }
const editorOptions: Required<IEditorOption> = { const editorOptions: Required<IEditorOption> = {
defaultMode: EditorMode.EDIT,
defaultType: 'TEXT', defaultType: 'TEXT',
defaultFont: 'Yahei', defaultFont: 'Yahei',
defaultSize: 16, defaultSize: 16,
@ -92,6 +93,7 @@ export default class Editor {
export { export {
Editor, Editor,
RowFlex, RowFlex,
EditorMode,
ElementType, ElementType,
EditorComponent, EditorComponent,
EDITOR_COMPONENT EDITOR_COMPONENT

@ -1,8 +1,10 @@
import { IElement } from ".." import { IElement } from ".."
import { EditorMode } from "../dataset/enum/Editor"
import { IHeader } from "./Header" import { IHeader } from "./Header"
import { IWatermark } from "./Watermark" import { IWatermark } from "./Watermark"
export interface IEditorOption { export interface IEditorOption {
defaultMode?: EditorMode;
defaultType?: string; defaultType?: string;
defaultFont?: string; defaultFont?: string;
defaultSize?: number; defaultSize?: number;

@ -1,4 +1,5 @@
export interface IContextMenuContext { export interface IContextMenuContext {
isReadonly: boolean;
editorHasSelection: boolean; editorHasSelection: boolean;
editorTextFocus: boolean; editorTextFocus: boolean;
isInTable: boolean; isInTable: boolean;

@ -1,6 +1,6 @@
import './style.css' import './style.css'
import prism from "prismjs" import prism from "prismjs"
import Editor, { ElementType, IElement, RowFlex } from './editor' import Editor, { EditorMode, ElementType, IElement, RowFlex } from './editor'
import { Dialog } from './components/dialog/Dialog' import { Dialog } from './components/dialog/Dialog'
import { formatPrismToken } from './utils/prism' import { formatPrismToken } from './utils/prism'
@ -623,6 +623,36 @@ window.onload = function () {
instance.command.executePageScaleAdd() instance.command.executePageScaleAdd()
} }
let modeIndex = 0
const modeList = [{
mode: EditorMode.EDIT,
name: '编辑模式'
}, {
mode: EditorMode.CLEAN,
name: '清洁模式'
}, {
mode: EditorMode.READONLY,
name: '只读模式'
}]
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
modeElement.onclick = function () {
// 模式选择循环
modeIndex === 2 ? modeIndex = 0 : modeIndex++
// 设置模式
const { name, mode } = modeList[modeIndex]
modeElement.innerText = name
instance.command.executeMode(mode)
// 设置菜单栏权限视觉反馈
const isReadonly = mode === EditorMode.READONLY
const enableMenuList = ['search', 'print']
document.querySelectorAll<HTMLDivElement>('.menu-item>div').forEach(dom => {
const menu = dom.dataset.menu
isReadonly && (!menu || !enableMenuList.includes(menu))
? dom.classList.add('disable')
: dom.classList.remove('disable')
})
}
// 内部事件监听 // 内部事件监听
instance.listener.rangeStyleChange = function (payload) { instance.listener.rangeStyleChange = function (payload) {
// 控件类型 // 控件类型

@ -167,7 +167,8 @@ ul {
} }
.menu-item__undo.no-allow, .menu-item__undo.no-allow,
.menu-item__redo.no-allow { .menu-item__redo.no-allow,
.menu-item>div.disable {
color: #c0c4cc; color: #c0c4cc;
cursor: not-allowed; cursor: not-allowed;
opacity: 0.4; opacity: 0.4;
@ -564,3 +565,8 @@ ul {
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
.footer .editor-mode {
cursor: pointer;
user-select: none;
}
Loading…
Cancel
Save