Skip to content

Commit

Permalink
feat: let keyboard shortcuts only affect active editor
Browse files Browse the repository at this point in the history
  • Loading branch information
robertrosman committed Jun 5, 2024
1 parent 33087e4 commit f080fe5
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 11 deletions.
7 changes: 4 additions & 3 deletions src/components/VpEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const history = defineModel<Shape[]>('history', { default: [] })
const vpImage = ref()
const { activeShape, undo, redo, save, reset } = useEditor({
const { activeShape, setTool, undo, redo, save, reset } = useEditor({
vpImage,
tools: props.tools,
history: toRef(history),
Expand All @@ -54,8 +54,9 @@ onMounted(() => {
<div class="vue-paint vp-editor" :class="`active-tool-${settings.tool}`">
<vp-image ref="vpImage" :tools :activeShape :history :width :height />

<slot name="toolbar" :undo :save :reset :settings>
<vp-toolbar v-model:settings="settings" @undo="undo" @redo="redo" @save="save" @reset="reset" :tools />
<slot name="toolbar" :set-tool :undo :save :reset :settings>
<vp-toolbar v-model:settings="settings" @set-tool="setTool" @undo="undo" @redo="redo" @save="save" @reset="reset"
:tools />
</slot>
</div>
</template>
3 changes: 2 additions & 1 deletion src/components/VpToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defineProps<{
}>()
const emit = defineEmits<{
(e: 'set-tool', tool: ToolType): void
(e: 'save'): void
(e: 'undo'): void
(e: 'redo'): void
Expand All @@ -27,7 +28,7 @@ const settings = defineModel<Settings>('settings', {
<div class="vp-tools">
<button v-for="tool in tools.filter((tool) => tool.icon)" :key="tool.type"
:class="[settings.tool === tool.type ? 'active' : '', `vp-tool-${tool.type}`]"
@click="settings.tool = tool.type as ToolType" :title="tool.type" v-html="tool.icon"></button>
@click="emit('set-tool', tool.type)" :title="tool.type" v-html="tool.icon"></button>
</div>
<div class="vp-settings">
<input type="range" min="1" max="10" v-model="settings.thickness" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Tool, BaseShape, InitializeEvent } from '@/types'
import { computed } from 'vue'
import { useActiveElement, useMagicKeys, whenever } from '@vueuse/core'
import { logicAnd } from '@vueuse/math'
import type { useEditor } from '@/composables/useEditor'
import { useActiveEditor } from '@/composables/useActiveEditor'

// Feels weird to create a Shape that will never be added to the history. Can we support Tool<undefined>?
export interface KeyboardShortcuts extends BaseShape {
Expand All @@ -22,7 +24,7 @@ interface UseKeyboardShortcutsOptions {
shortcuts?: Shortcuts
}

type Shortcuts = Record<string, (args: InitializeEvent) => void>
type Shortcuts = Record<string, (args: ReturnType<typeof useEditor>) => void>

export const defaultShortcuts: Shortcuts = {
'f': ({settings}) => settings.value.tool = 'freehand',
Expand All @@ -45,11 +47,12 @@ export function useKeyboardShortcuts({ shortcuts = defaultShortcuts }: UseKeyboa
)

const keys = useMagicKeys()
const { getActiveEditor } = useActiveEditor()

async function onInitialize(event: InitializeEvent) {
async function onInitialize() {
Object.entries(shortcuts).forEach(([keycode, callback]) => {
whenever(logicAnd(keys[keycode], notUsingInput), () => {
callback(event)
callback(getActiveEditor())
})
})
}
Expand Down
20 changes: 20 additions & 0 deletions src/composables/useActiveEditor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { useEditor } from './useEditor'

type Editor = ReturnType<typeof useEditor>
let activeEditor: Editor

export function useActiveEditor() {

function setActiveEditor(editor: Editor) {
activeEditor = editor
}

function getActiveEditor() {
return activeEditor
}

return {
setActiveEditor,
getActiveEditor
}
}
28 changes: 24 additions & 4 deletions src/composables/useEditor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useDraw } from '@/composables/useDraw'
import { randomId } from '@/utils/randomId'
import type { DrawEvent, ImageHistory, Settings, Shape, Tool } from '../types'
import type { DrawEvent, ImageHistory, Settings, Shape, Tool, ToolType } from '../types'
import { computed, ref, type ComponentPublicInstance, type Ref } from 'vue'
import { useActiveEditor } from './useActiveEditor'

export interface UseEditorOptions {
vpImage: Ref<ComponentPublicInstance>
Expand Down Expand Up @@ -46,7 +47,7 @@ export function useEditor({ vpImage, tools, history, settings, width, height, em
absoluteX: absoluteX.value,
absoluteY: absoluteY.value
}))

const {
x,
y,
Expand Down Expand Up @@ -74,36 +75,47 @@ export function useEditor({ vpImage, tools, history, settings, width, height, em
?.substring(9)
activeShape.value = getActiveTool()?.onDrawStart?.(drawEvent.value) ?? activeShape.value
emit?.('drawStart', drawEvent.value)
setActiveEditor(editor)
},
onDraw() {
activeShape.value = getActiveTool()?.onDraw?.(drawEvent.value) ?? activeShape.value
emit?.('draw', drawEvent.value)
setActiveEditor(editor)
},
async onDrawEnd() {
activeShape.value = getActiveTool()?.onDrawEnd
? await getActiveTool()?.onDrawEnd?.(drawEvent.value)
: activeShape.value
temporaryTool.value = undefined
emit?.('drawEnd', drawEvent.value)
setActiveEditor(editor)
if (activeShape.value) {
history.value.push(activeShape.value)
redoHistory.value = []
activeShape.value = undefined
}
}
})

function setTool(tool: ToolType) {
settings.value.tool = tool
setActiveEditor(editor)
}

function undo() {
if (history.value.length) {
redoHistory.value.push(...history.value.slice(-1))
history.value = history.value.slice(0, -1)
}
setActiveEditor(editor)
}

function redo() {
if (redoHistory.value.length) {
history.value.push(...redoHistory.value.slice(-1))
redoHistory.value = redoHistory.value.slice(0, -1)
}
setActiveEditor(editor)
}

function save() {
Expand All @@ -112,6 +124,7 @@ export function useEditor({ vpImage, tools, history, settings, width, height, em
throw new Error("Couldn't find the svg")
}
emit?.('save', { svg, tools, history: history.value })
setActiveEditor(editor)
}

async function reset() {
Expand All @@ -124,11 +137,13 @@ export function useEditor({ vpImage, tools, history, settings, width, height, em
)
history.value = [...shapes.filter(Boolean), ...history.value]
emit?.('reset')
setActiveEditor(editor)
}
return {

const editor = {
settings,
activeShape,
setTool,
undo,
redo,
save,
Expand All @@ -149,4 +164,9 @@ export function useEditor({ vpImage, tools, history, settings, width, height, em
absoluteX,
absoluteY
}

const { setActiveEditor } = useActiveEditor()
setActiveEditor(editor)

return editor
}

0 comments on commit f080fe5

Please sign in to comment.