feat: add event bus
This commit is contained in:
@@ -79,6 +79,8 @@ import { INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
||||
import { ListParticle } from './particle/ListParticle'
|
||||
import { Placeholder } from './frame/Placeholder'
|
||||
import { WORD_LIKE_REG } from '../../dataset/constant/Regular'
|
||||
import { EventBus } from '../event/eventbus/EventBus'
|
||||
import { EventBusMap } from '../../interface/EventBus'
|
||||
|
||||
export class Draw {
|
||||
private container: HTMLDivElement
|
||||
@@ -95,6 +97,7 @@ export class Draw {
|
||||
private elementList: IElement[]
|
||||
private footerElementList: IElement[]
|
||||
private listener: Listener
|
||||
private eventBus: EventBus<EventBusMap>
|
||||
|
||||
private i18n: I18n
|
||||
private canvasEvent: CanvasEvent
|
||||
@@ -146,7 +149,8 @@ export class Draw {
|
||||
rootContainer: HTMLElement,
|
||||
options: DeepRequired<IEditorOption>,
|
||||
data: IEditorData,
|
||||
listener: Listener
|
||||
listener: Listener,
|
||||
eventBus: EventBus<EventBusMap>
|
||||
) {
|
||||
this.container = this._wrapContainer(rootContainer)
|
||||
this.pageList = []
|
||||
@@ -159,6 +163,7 @@ export class Draw {
|
||||
this.elementList = data.main
|
||||
this.footerElementList = data.footer || []
|
||||
this.listener = listener
|
||||
this.eventBus = eventBus
|
||||
|
||||
this._formatContainer()
|
||||
this.pageContainer = this._createPageContainer()
|
||||
@@ -336,6 +341,9 @@ export class Draw {
|
||||
if (this.listener.visiblePageNoListChange) {
|
||||
this.listener.visiblePageNoListChange(this.visiblePageNoList)
|
||||
}
|
||||
if (this.eventBus.isSubscribe('visiblePageNoListChange')) {
|
||||
this.eventBus.emit('visiblePageNoListChange', this.visiblePageNoList)
|
||||
}
|
||||
}
|
||||
|
||||
public getIntersectionPageNo(): number {
|
||||
@@ -347,6 +355,9 @@ export class Draw {
|
||||
if (this.listener.intersectionPageNoChange) {
|
||||
this.listener.intersectionPageNoChange(this.intersectionPageNo)
|
||||
}
|
||||
if (this.eventBus.isSubscribe('intersectionPageNoChange')) {
|
||||
this.eventBus.emit('intersectionPageNoChange', this.intersectionPageNo)
|
||||
}
|
||||
}
|
||||
|
||||
public getPageNo(): number {
|
||||
@@ -569,6 +580,10 @@ export class Draw {
|
||||
return this.listener
|
||||
}
|
||||
|
||||
public getEventBus(): EventBus<EventBusMap> {
|
||||
return this.eventBus
|
||||
}
|
||||
|
||||
public getCursor(): Cursor {
|
||||
return this.cursor
|
||||
}
|
||||
@@ -709,6 +724,9 @@ export class Draw {
|
||||
if (this.listener.pageModeChange) {
|
||||
this.listener.pageModeChange(payload)
|
||||
}
|
||||
if (this.eventBus.isSubscribe('pageModeChange')) {
|
||||
this.eventBus.emit('pageModeChange', payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1801,9 +1819,17 @@ export class Draw {
|
||||
if (this.listener.pageSizeChange) {
|
||||
this.listener.pageSizeChange(this.pageRowList.length)
|
||||
}
|
||||
if (this.eventBus.isSubscribe('pageSizeChange')) {
|
||||
this.eventBus.emit('pageSizeChange', this.pageRowList.length)
|
||||
}
|
||||
// 文档内容改变
|
||||
if (this.listener.contentChange && isSubmitHistory) {
|
||||
this.listener.contentChange()
|
||||
if (isSubmitHistory) {
|
||||
if (this.listener.contentChange) {
|
||||
this.listener.contentChange()
|
||||
}
|
||||
if (this.eventBus.isSubscribe('contentChange')) {
|
||||
this.eventBus.emit('contentChange')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,13 +7,15 @@ import {
|
||||
IControlOption
|
||||
} from '../../../interface/Control'
|
||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||
import { EventBusMap } from '../../../interface/EventBus'
|
||||
import { IRange } from '../../../interface/Range'
|
||||
import { deepClone, splitText } from '../../../utils'
|
||||
import { deepClone, nextTick, splitText } from '../../../utils'
|
||||
import {
|
||||
formatElementContext,
|
||||
pickElementAttr,
|
||||
zipElementList
|
||||
} from '../../../utils/element'
|
||||
import { EventBus } from '../../event/eventbus/EventBus'
|
||||
import { Listener } from '../../listener/Listener'
|
||||
import { RangeManager } from '../../range/RangeManager'
|
||||
import { Draw } from '../Draw'
|
||||
@@ -29,6 +31,7 @@ export class Control {
|
||||
private draw: Draw
|
||||
private range: RangeManager
|
||||
private listener: Listener
|
||||
private eventBus: EventBus<EventBusMap>
|
||||
private options: IControlOption
|
||||
private activeControl: IControlInstance | null
|
||||
|
||||
@@ -36,6 +39,8 @@ export class Control {
|
||||
this.draw = draw
|
||||
this.range = draw.getRange()
|
||||
this.listener = draw.getListener()
|
||||
this.eventBus = draw.getEventBus()
|
||||
|
||||
this.options = draw.getOptions().control
|
||||
this.activeControl = null
|
||||
}
|
||||
@@ -132,16 +137,23 @@ export class Control {
|
||||
this.activeControl = new CheckboxControl(element, this)
|
||||
}
|
||||
// 激活控件回调
|
||||
setTimeout(() => {
|
||||
if (this.listener.controlChange) {
|
||||
let payload: IControl
|
||||
const value = this.activeControl?.getValue()
|
||||
if (value && value.length) {
|
||||
payload = zipElementList(value)[0].control!
|
||||
} else {
|
||||
payload = pickElementAttr(deepClone(element)).control!
|
||||
}
|
||||
this.listener.controlChange(payload)
|
||||
nextTick(() => {
|
||||
const controlChangeListener = this.listener.controlChange
|
||||
const isSubscribeControlChange =
|
||||
this.eventBus.isSubscribe('controlChange')
|
||||
if (!controlChangeListener && !isSubscribeControlChange) return
|
||||
let payload: IControl
|
||||
const value = this.activeControl?.getValue()
|
||||
if (value && value.length) {
|
||||
payload = zipElementList(value)[0].control!
|
||||
} else {
|
||||
payload = pickElementAttr(deepClone(element)).control!
|
||||
}
|
||||
if (controlChangeListener) {
|
||||
controlChangeListener(payload)
|
||||
}
|
||||
if (isSubscribeControlChange) {
|
||||
this.eventBus.emit('controlChange', payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -153,9 +165,16 @@ export class Control {
|
||||
}
|
||||
this.activeControl = null
|
||||
// 销毁控件回调
|
||||
setTimeout(() => {
|
||||
if (this.listener.controlChange) {
|
||||
this.listener.controlChange(null)
|
||||
nextTick(() => {
|
||||
const controlChangeListener = this.listener.controlChange
|
||||
const isSubscribeControlChange =
|
||||
this.eventBus.isSubscribe('controlChange')
|
||||
if (!controlChangeListener && !isSubscribeControlChange) return
|
||||
if (controlChangeListener) {
|
||||
controlChangeListener(null)
|
||||
}
|
||||
if (isSubscribeControlChange) {
|
||||
this.eventBus.emit('controlChange', null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
export class EventBus<EventMap> {
|
||||
private eventHub: Map<string, Set<Function>>
|
||||
|
||||
constructor() {
|
||||
this.eventHub = new Map()
|
||||
}
|
||||
|
||||
public on<K extends string & keyof EventMap>(
|
||||
eventName: K,
|
||||
callback: EventMap[K]
|
||||
) {
|
||||
if (!eventName || typeof callback !== 'function') return
|
||||
const eventSet = this.eventHub.get(eventName) || new Set()
|
||||
eventSet.add(callback)
|
||||
this.eventHub.set(eventName, eventSet)
|
||||
}
|
||||
|
||||
public emit<K extends string & keyof EventMap>(
|
||||
eventName: K,
|
||||
payload?: EventMap[K] extends (payload: infer P) => void ? P : never
|
||||
) {
|
||||
if (!eventName) return
|
||||
const callBackSet = this.eventHub.get(eventName)
|
||||
if (!callBackSet) return
|
||||
if (callBackSet.size === 1) {
|
||||
const callBack = [...callBackSet]
|
||||
return callBack[0](payload)
|
||||
}
|
||||
callBackSet.forEach(callBack => callBack(payload))
|
||||
}
|
||||
|
||||
public off<K extends string & keyof EventMap>(
|
||||
eventName: K,
|
||||
callback: EventMap[K]
|
||||
) {
|
||||
if (!eventName || typeof callback !== 'function') return
|
||||
const callBackSet = this.eventHub.get(eventName)
|
||||
if (!callBackSet) return
|
||||
callBackSet.delete(callback)
|
||||
}
|
||||
|
||||
public isSubscribe<K extends string & keyof EventMap>(eventName: K): boolean {
|
||||
const eventSet = this.eventHub.get(eventName)
|
||||
return !!eventSet && eventSet.size > 0
|
||||
}
|
||||
}
|
||||
@@ -308,6 +308,10 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
||||
if (listener.saved) {
|
||||
listener.saved(draw.getValue())
|
||||
}
|
||||
const eventBus = draw.getEventBus()
|
||||
if (eventBus.isSubscribe('saved')) {
|
||||
eventBus.emit('saved', draw.getValue())
|
||||
}
|
||||
evt.preventDefault()
|
||||
} else if (evt.key === KeyMap.ESC) {
|
||||
// 退出格式刷
|
||||
|
||||
@@ -4,9 +4,12 @@ import { TEXTLIKE_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
||||
import { ControlComponent } from '../../dataset/enum/Control'
|
||||
import { IEditorOption } from '../../interface/Editor'
|
||||
import { IElement } from '../../interface/Element'
|
||||
import { EventBusMap } from '../../interface/EventBus'
|
||||
import { IRangeStyle } from '../../interface/Listener'
|
||||
import { IRange, RangeRowArray, RangeRowMap } from '../../interface/Range'
|
||||
import { getAnchorElement } from '../../utils/element'
|
||||
import { Draw } from '../draw/Draw'
|
||||
import { EventBus } from '../event/eventbus/EventBus'
|
||||
import { HistoryManager } from '../history/HistoryManager'
|
||||
import { Listener } from '../listener/Listener'
|
||||
import { Position } from '../position/Position'
|
||||
@@ -16,6 +19,7 @@ export class RangeManager {
|
||||
private options: Required<IEditorOption>
|
||||
private range: IRange
|
||||
private listener: Listener
|
||||
private eventBus: EventBus<EventBusMap>
|
||||
private position: Position
|
||||
private historyManager: HistoryManager
|
||||
|
||||
@@ -23,6 +27,7 @@ export class RangeManager {
|
||||
this.draw = draw
|
||||
this.options = draw.getOptions()
|
||||
this.listener = draw.getListener()
|
||||
this.eventBus = draw.getEventBus()
|
||||
this.position = draw.getPosition()
|
||||
this.historyManager = draw.getHistoryManager()
|
||||
this.range = {
|
||||
@@ -241,7 +246,10 @@ export class RangeManager {
|
||||
}
|
||||
|
||||
public setRangeStyle() {
|
||||
if (!this.listener.rangeStyleChange) return
|
||||
const rangeStyleChangeListener = this.listener.rangeStyleChange
|
||||
const isSubscribeRangeStyleChange =
|
||||
this.eventBus.isSubscribe('rangeStyleChange')
|
||||
if (!rangeStyleChangeListener && !isSubscribeRangeStyleChange) return
|
||||
// 结束光标位置
|
||||
const { startIndex, endIndex, isCrossRowCol } = this.range
|
||||
if (!~startIndex && !~endIndex) return
|
||||
@@ -281,7 +289,7 @@ export class RangeManager {
|
||||
const painter = !!this.draw.getPainterStyle()
|
||||
const undo = this.historyManager.isCanUndo()
|
||||
const redo = this.historyManager.isCanRedo()
|
||||
this.listener.rangeStyleChange({
|
||||
const rangeStyle: IRangeStyle = {
|
||||
type,
|
||||
undo,
|
||||
redo,
|
||||
@@ -300,18 +308,27 @@ export class RangeManager {
|
||||
level,
|
||||
listType,
|
||||
listStyle
|
||||
})
|
||||
}
|
||||
if (rangeStyleChangeListener) {
|
||||
rangeStyleChangeListener(rangeStyle)
|
||||
}
|
||||
if (isSubscribeRangeStyleChange) {
|
||||
this.eventBus.emit('rangeStyleChange', rangeStyle)
|
||||
}
|
||||
}
|
||||
|
||||
public recoveryRangeStyle() {
|
||||
if (!this.listener.rangeStyleChange) return
|
||||
const rangeStyleChangeListener = this.listener.rangeStyleChange
|
||||
const isSubscribeRangeStyleChange =
|
||||
this.eventBus.isSubscribe('rangeStyleChange')
|
||||
if (!rangeStyleChangeListener && !isSubscribeRangeStyleChange) return
|
||||
const font = this.options.defaultFont
|
||||
const size = this.options.defaultSize
|
||||
const rowMargin = this.options.defaultRowMargin
|
||||
const painter = !!this.draw.getPainterStyle()
|
||||
const undo = this.historyManager.isCanUndo()
|
||||
const redo = this.historyManager.isCanRedo()
|
||||
this.listener.rangeStyleChange({
|
||||
const rangeStyle: IRangeStyle = {
|
||||
type: null,
|
||||
undo,
|
||||
redo,
|
||||
@@ -330,7 +347,13 @@ export class RangeManager {
|
||||
level: null,
|
||||
listType: null,
|
||||
listStyle: null
|
||||
})
|
||||
}
|
||||
if (rangeStyleChangeListener) {
|
||||
rangeStyleChangeListener(rangeStyle)
|
||||
}
|
||||
if (isSubscribeRangeStyleChange) {
|
||||
this.eventBus.emit('rangeStyleChange', rangeStyle)
|
||||
}
|
||||
}
|
||||
|
||||
public shrinkBoundary() {
|
||||
|
||||
@@ -59,6 +59,10 @@ export class Zone {
|
||||
if (listener.zoneChange) {
|
||||
listener.zoneChange(payload)
|
||||
}
|
||||
const eventBus = this.draw.getEventBus()
|
||||
if (eventBus.isSubscribe('zoneChange')) {
|
||||
eventBus.emit('zoneChange', payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -57,10 +57,13 @@ import { IPlaceholder } from './interface/Placeholder'
|
||||
import { defaultPlaceholderOption } from './dataset/constant/Placeholder'
|
||||
import { Plugin } from './core/plugin/Plugin'
|
||||
import { UsePlugin } from './interface/Plugin'
|
||||
import { EventBus } from './core/event/eventbus/EventBus'
|
||||
import { EventBusMap } from './interface/EventBus'
|
||||
|
||||
export default class Editor {
|
||||
public command: Command
|
||||
public listener: Listener
|
||||
public eventBus: EventBus<EventBusMap>
|
||||
public register: Register
|
||||
public destroy: () => void
|
||||
public use: UsePlugin
|
||||
@@ -179,6 +182,8 @@ export default class Editor {
|
||||
})
|
||||
// 监听
|
||||
this.listener = new Listener()
|
||||
// 事件
|
||||
this.eventBus = new EventBus<EventBusMap>()
|
||||
// 启动
|
||||
const draw = new Draw(
|
||||
container,
|
||||
@@ -188,7 +193,8 @@ export default class Editor {
|
||||
main: mainElementList,
|
||||
footer: footerElementList
|
||||
},
|
||||
this.listener
|
||||
this.listener,
|
||||
this.eventBus
|
||||
)
|
||||
// 命令
|
||||
this.command = new Command(new CommandAdapt(draw))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
IContentChange,
|
||||
IControlChange,
|
||||
IIntersectionPageNoChange,
|
||||
IPageModeChange,
|
||||
IPageScaleChange,
|
||||
IPageSizeChange,
|
||||
IRangeStyleChange,
|
||||
ISaved,
|
||||
IVisiblePageNoListChange,
|
||||
IZoneChange
|
||||
} from './Listener'
|
||||
|
||||
export interface EventBusMap {
|
||||
rangeStyleChange: IRangeStyleChange
|
||||
visiblePageNoListChange: IVisiblePageNoListChange
|
||||
intersectionPageNoChange: IIntersectionPageNoChange
|
||||
pageSizeChange: IPageSizeChange
|
||||
pageScaleChange: IPageScaleChange
|
||||
saved: ISaved
|
||||
contentChange: IContentChange
|
||||
controlChange: IControlChange
|
||||
pageModeChange: IPageModeChange
|
||||
zoneChange: IZoneChange
|
||||
}
|
||||
Reference in New Issue
Block a user