Skip to content

Commit

Permalink
refactor: use an enum for the event names
Browse files Browse the repository at this point in the history
this just will make it a bit easier to track down which things are bound to/call different events
  • Loading branch information
hiddenist committed Dec 23, 2023
1 parent 702032b commit 29172b1
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 77 deletions.
18 changes: 9 additions & 9 deletions apps/web/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "./style.css"

import { WebDrawingEngine, ToolNames } from "@libs/drawing-engine"
import { WebDrawingEngine, EventType, ToolNames } from "@libs/drawing-engine"
import { ColorPicker } from "@libs/color-picker"
import { Color } from "@libs/shared"

Expand Down Expand Up @@ -140,13 +140,13 @@ function makeToolbar<T extends string>(
},
})

options.addListener("draw", () => {
options.addListener(EventType.draw, () => {
recentColors.setSelectedColor(picker.getColor())
})
options.addListener("pickColor", ({ color }) => {
options.addListener(EventType.pickColor, ({ color }) => {
picker.setColor(color)
})
options.addListener("previewColor", ({ color }) => {
options.addListener(EventType.previewColor, ({ color }) => {
picker.setColorPreview(color)
})

Expand All @@ -158,7 +158,7 @@ function makeToolbar<T extends string>(

const toolSelect = document.createElement("select")

options.addListener("changeTool", ({ tool }) => {
options.addListener(EventType.changeTool, ({ tool }) => {
toolSelect.value = tool
})
toolSelect.classList.add("tool-select")
Expand Down Expand Up @@ -252,15 +252,15 @@ function makeToolbar<T extends string>(
e.preventDefault()
options.onRedo()
})
options.addListener("draw", () => {
options.addListener(EventType.draw, () => {
undoButton.disabled = false
redoButton.disabled = true
})
options.addListener("undo", ({ canUndo }) => {
options.addListener(EventType.undo, ({ canUndo }) => {
undoButton.disabled = !canUndo
redoButton.disabled = false
})
options.addListener("redo", ({ canRedo }) => {
options.addListener(EventType.redo, ({ canRedo }) => {
undoButton.disabled = false
redoButton.disabled = !canRedo
})
Expand All @@ -277,7 +277,7 @@ function makeToolbar<T extends string>(
setHasDrawn(false)
})
inputTray.append(clearButton)
options.addListener("draw", () => {
options.addListener(EventType.draw, () => {
setHasDrawn(true)
})

Expand Down
10 changes: 5 additions & 5 deletions libs/drawing-engine/src/engine/CanvasHistory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LineDrawInfo } from "../tools/LineTool"
import { DrawingEngine } from "./DrawingEngine"
import { DrawingEngine, EventType } from "./DrawingEngine"

type ToolInfo = LineDrawInfo

Expand Down Expand Up @@ -65,7 +65,7 @@ export class CanvasHistory {
}
public async undo() {
if (!this.canUndo()) {
this.engine.callListeners("undo", { toolInfo: null, canUndo: false })
this.engine.callListeners(EventType.undo, { toolInfo: null, canUndo: false })
return
}
const undoneState = this.history.pop()
Expand All @@ -77,12 +77,12 @@ export class CanvasHistory {
this.redoHistory.push(undoneState)

const toolInfo = await this.drawState(currentState)
this.engine.callListeners("undo", { toolInfo, canUndo: this.canUndo() })
this.engine.callListeners(EventType.undo, { toolInfo, canUndo: this.canUndo() })
}

public async redo() {
if (!this.canRedo()) {
this.engine.callListeners("redo", { toolInfo: null, canRedo: false })
this.engine.callListeners(EventType.redo, { toolInfo: null, canRedo: false })
return
}
const state = this.redoHistory.pop()
Expand All @@ -93,7 +93,7 @@ export class CanvasHistory {
this.engine.setTool(state.toolInfo.tool)

const toolInfo = await this.drawState(state)
this.engine.callListeners("redo", { toolInfo, canRedo: this.canRedo() })
this.engine.callListeners(EventType.redo, { toolInfo, canRedo: this.canRedo() })
}

protected addHistory(state: HistoryState) {
Expand Down
67 changes: 39 additions & 28 deletions libs/drawing-engine/src/engine/DrawingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,40 @@ export interface DrawingEngineOptions {

type ToolInfo = LineDrawInfo

export interface DrawingEngineEventMap {
draw: ToolInfo
undo: { toolInfo: HistoryState["toolInfo"] | null; canUndo: boolean }
redo: { toolInfo: HistoryState["toolInfo"] | null; canRedo: boolean }
pickColor: { color: Color }
previewColor: { color: Color | null }
clear: undefined
changeTool: { tool: ToolName }

press: { position: Readonly<InputPoint> }
move: { positions: ReadonlyArray<InputPoint>; isPressed: boolean }
release: { position: Readonly<InputPoint> }
cancel: undefined
export enum EventType {
draw = "draw",
undo = "undo",
redo = "redo",
pickColor = "pickColor",
previewColor = "previewColor",
clear = "clear",
changeTool = "changeTool",
press = "press",
move = "move",
release = "release",
cancel = "cancel",
}

export type DrawingEngineEvent<T extends DrawingEngineEventName> = {
export interface DrawingEngineEventMap {
[EventType.draw]: ToolInfo
[EventType.undo]: { toolInfo: HistoryState["toolInfo"] | null; canUndo: boolean }
[EventType.redo]: { toolInfo: HistoryState["toolInfo"] | null; canRedo: boolean }
[EventType.pickColor]: { color: Color }
[EventType.previewColor]: { color: Color | null }
[EventType.clear]: undefined
[EventType.changeTool]: { tool: ToolName }
[EventType.press]: { position: Readonly<InputPoint> }
[EventType.move]: { positions: ReadonlyArray<InputPoint>; isPressed: boolean }
[EventType.release]: { position: Readonly<InputPoint> }
[EventType.cancel]: undefined
}
export type DrawingEngineEvent<T extends EventType> = {
eventName: T
} & (DrawingEngineEventMap[T] extends undefined ? {} : DrawingEngineEventMap[T])
export type DrawingEngineEventName = keyof DrawingEngineEventMap
export type DrawingEventHandler<T extends DrawingEngineEventName> = (event: DrawingEngineEvent<T>) => void
export type DrawingEventHandler<T extends EventType> = (event: DrawingEngineEvent<T>) => void

type DrawingEventListeners = {
[Key in DrawingEngineEventName]: Array<DrawingEventHandler<Key>>
[Key in EventType]: Array<DrawingEventHandler<Key>>
}

const defaultTool = ToolNames.brush
Expand Down Expand Up @@ -110,7 +121,7 @@ export class DrawingEngine {
[ToolNames.eyedropper]: new EyeDropperTool(this),
}

this.callListeners("changeTool", { tool: this.state.tool })
this.callListeners(EventType.changeTool, { tool: this.state.tool })
}

private makeLayer(options?: Partial<LayerSettings>) {
Expand Down Expand Up @@ -153,7 +164,7 @@ export class DrawingEngine {
this.commitToSavedLayer()
this.state.prevTool = this.state.tool
this.state.tool = tool
this.callListeners("changeTool", { tool })
this.callListeners(EventType.changeTool, { tool })
}

public usePrevTool() {
Expand Down Expand Up @@ -183,7 +194,7 @@ export class DrawingEngine {
this._clear()
this.program.draw(this.activeDrawingLayer, this.savedDrawingLayer)

this.callListeners("clear", undefined)
this.callListeners(EventType.clear, undefined)
}

protected clearCurrent() {
Expand All @@ -193,20 +204,20 @@ export class DrawingEngine {

protected handlePointerDown(position: Readonly<InputPoint>) {
this.state.isPressed = true
this.callListeners("press", { position })
this.callListeners(EventType.press, { position })
}

protected handlePointerUp(position: Readonly<InputPoint>) {
this.state.isPressed = false
this.callListeners("release", { position })
this.callListeners(EventType.release, { position })
}

protected handlePointerMove(positions: ReadonlyArray<InputPoint>) {
this.callListeners("move", { positions, isPressed: this.state.isPressed })
this.callListeners(EventType.move, { positions, isPressed: this.state.isPressed })
}

protected handleCancel() {
this.callListeners("cancel", undefined)
this.callListeners(EventType.cancel, undefined)
}

public isPositionInCanvas(position: Readonly<Vec2>) {
Expand All @@ -218,7 +229,7 @@ export class DrawingEngine {
this.program.createTextureImage(layer, () => {
const drawData = drawCallback()
if (drawData) {
this.callListeners("draw", drawData)
this.callListeners(EventType.draw, drawData)
}
})
this.render()
Expand Down Expand Up @@ -247,7 +258,7 @@ export class DrawingEngine {
this.program[mode](this.activeDrawingLayer, this.savedDrawingLayer)
}

public addListener<E extends DrawingEngineEventName>(eventName: E, cb: DrawingEventHandler<E>) {
public addListener<E extends EventType>(eventName: E, cb: DrawingEventHandler<E>) {
let listeners = this.listeners[eventName]
if (!listeners) {
listeners = []
Expand All @@ -257,7 +268,7 @@ export class DrawingEngine {
return this
}

public removeListener<E extends DrawingEngineEventName>(eventName: E, cb: DrawingEventHandler<E>) {
public removeListener<E extends EventType>(eventName: E, cb: DrawingEventHandler<E>) {
const index = this.listeners[eventName]?.indexOf(cb) ?? -1
if (index === -1) {
return this
Expand All @@ -266,7 +277,7 @@ export class DrawingEngine {
return this
}

public callListeners<E extends DrawingEngineEventName>(eventName: E, data: DrawingEngineEventMap[E]) {
public callListeners<E extends EventType>(eventName: E, data: DrawingEngineEventMap[E]) {
this.listeners[eventName]?.forEach((listener) => listener({ eventName, ...data }))
}

Expand Down
8 changes: 4 additions & 4 deletions libs/drawing-engine/src/engine/WebDrawingEngine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Color, getEventPosition } from "@libs/shared"
import { DrawingEngine, DrawingEngineOptions } from "./DrawingEngine"
import { DrawingEngine, DrawingEngineOptions, EventType } from "./DrawingEngine"
import { ToolNames } from "../tools/Tools"
import { Vec2 } from "@libs/shared"
import { SourceImage } from "../utils/image/SourceImage"
Expand Down Expand Up @@ -42,7 +42,7 @@ export class WebDrawingEngine extends DrawingEngine implements IWebDrawingEngine

this.bindBrowserEvents()

this.addListener("changeTool", ({ tool }) => {
this.addListener(EventType.changeTool, ({ tool }) => {
this.root.dataset.tool = tool
})
}
Expand Down Expand Up @@ -161,13 +161,13 @@ export class WebDrawingEngine extends DrawingEngine implements IWebDrawingEngine
/**
* Add multiple events to one listener.
*/
// private addListeners<K extends keyof HTMLElementEventMap>(
// private addListenersEventType.Kextends keyof HTMLElementEventMap>(
// eventNames: Array<K>,
// handler?: (event: DrawingEvent<HTMLElementEventMap[K]>) => void,
// element: HTMLElement = this.root,
// ) {
// for (const eventName of eventNames) {
// this.addListener(eventName, handler, element)
// this.addListener(EventType.ventName handler, element)
// }
// }

Expand Down
1 change: 1 addition & 0 deletions libs/drawing-engine/src/exports.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./engine/WebDrawingEngine"
export { EventType } from "./engine/DrawingEngine"
export type { ToolName } from "./tools/Tools"
export { ToolNames } from "./tools/Tools"
32 changes: 16 additions & 16 deletions libs/drawing-engine/src/tools/EyeDropperTool.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BaseProgram, Color } from "@libs/shared"
import { DrawingEngine, DrawingEngineEvent } from "../engine/DrawingEngine"
import { DrawingEngine, DrawingEngineEvent, EventType } from "../engine/DrawingEngine"
import { InputPoint } from "./InputPoint"
import { ToolNames } from "./Tools"

Expand All @@ -23,40 +23,40 @@ export class EyeDropperTool {
cancel: this.onCancel.bind(this),
}

this.engine.addListener("changeTool", ({ tool }) => {
this.engine.addListener(EventType.changeTool, ({ tool }) => {
if (tool === this.toolName) {
this.engine.addListener("press", listeners.press)
this.engine.addListener("move", listeners.move)
this.engine.addListener("release", listeners.release)
this.engine.addListener("cancel", listeners.cancel)
this.engine.addListener(EventType.press, listeners.press)
this.engine.addListener(EventType.move, listeners.move)
this.engine.addListener(EventType.release, listeners.release)
this.engine.addListener(EventType.cancel, listeners.cancel)
} else {
this.engine.removeListener("press", listeners.press)
this.engine.removeListener("move", listeners.move)
this.engine.removeListener("release", listeners.release)
this.engine.removeListener("cancel", listeners.cancel)
this.engine.removeListener(EventType.press, listeners.press)
this.engine.removeListener(EventType.move, listeners.move)
this.engine.removeListener(EventType.release, listeners.release)
this.engine.removeListener(EventType.cancel, listeners.cancel)
}
})
}

onCancel() {
this.engine.usePrevTool()
this.engine.callListeners("previewColor", { color: null })
this.engine.callListeners(EventType.previewColor, { color: null })
}

onPress({ position }: DrawingEngineEvent<"press">) {
onPress({ position }: DrawingEngineEvent<EventType.press>) {
this.pickColor(position)
}

onMove({ positions }: DrawingEngineEvent<"move">) {
onMove({ positions }: DrawingEngineEvent<EventType.move>) {
const [x, y] = positions[positions.length - 1] ?? [0, 0]
const color = BaseProgram.getColorAtPosition(this.engine.gl, [x, y])
if (!color) {
return
}
this.engine.callListeners("previewColor", { color })
this.engine.callListeners(EventType.previewColor, { color })
}

onRelease({ position }: DrawingEngineEvent<"release">) {
onRelease({ position }: DrawingEngineEvent<EventType.release>) {
if (this.pickColor(position)) {
this.engine.usePrevTool()
} else {
Expand All @@ -70,7 +70,7 @@ export class EyeDropperTool {
return false
}
this.engine.setColor(color)
this.engine.callListeners("pickColor", { color })
this.engine.callListeners(EventType.pickColor, { color })
return true
}
}
Loading

0 comments on commit 29172b1

Please sign in to comment.