Skip to content

Commit

Permalink
Refactor window manager #58
Browse files Browse the repository at this point in the history
  • Loading branch information
Lev Z Király authored and Lev Z Király committed Oct 13, 2023
1 parent ac539ba commit 4c813f5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 76 deletions.
65 changes: 11 additions & 54 deletions components/WindowManager.vue
Original file line number Diff line number Diff line change
@@ -1,62 +1,19 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useWMStore, INewWindow, IWindow, IWindowType } from '~~/store/wm'
import { computed, ConcreteComponent, ComputedOptions, MethodOptions } from 'vue'
import { useWMStore, windowTypes } from '~~/store/wm'
import { VicavWinBox } from "./VicavWinBox.client"
const wmStore = useWMStore()
const windowList = computed(() => wmStore.windowList)
const windowTypes = {
Text: {
component: resolveComponent('Text'),
} as IWindowType,
WMap: {
component: resolveComponent('WMap'),
} as IWindowType,
DictQuery: {
component: resolveComponent('DictQuery'),
} as IWindowType,
DictEntry: {
component: resolveComponent('DictEntry'),
} as IWindowType,
}
const newWindow = computed(() => wmStore.newWindow)
watch(newWindow, (window) => {
if (window != null) {
createNewWindow(window)
}
})
function createNewWindow(newWindow: INewWindow) {
let windowType = windowTypes[newWindow.windowTypeId as keyof typeof windowTypes]
if (windowType === undefined) {
consoleWarning("Window type undefined", newWindow)
return false
}
if (typeof windowType.component === "string") {
consoleWarning("Window type '" + windowType + "' was not resolved", newWindow)
return false
}
let windowClasses = [ 'wb-vicav', 'no-min', 'no-max', 'no-full', 'no-resize', 'no-move']
if (!!newWindow.params?.customClass) {
windowClasses.push(newWindow.params.customClass)
}
let window: IWindow = {
id: newWindow.id,
ref: null,
type: windowType as IWindowType,
winBoxOptions: {
title: '[' + newWindow.windowTypeId + '] ' + newWindow.title,
top: wmStore.topMargin,
class: windowClasses,
},
params: newWindow.params,
}
wmStore.addWindowToList(window)
}
function consoleWarning(text: string, data: Object) {
console.warn("WindowManager:", text, data);
/* nuxt cannot resolve components from variables in setup, see https://github.com/nuxt/nuxt/issues/14036 */
/* otherwise this block could be deleted and only window.type be passed on to the component in the :is */
type ContentComponents = {[key: string]: string | ConcreteComponent<{}, any, any, ComputedOptions, MethodOptions>}
const contentComponents: ContentComponents = {
Text: resolveComponent('Text'),
WMap: resolveComponent('WMap'),
DictQuery: resolveComponent('DictQuery'),
DictEntry: resolveComponent('DictQuery'),
}
function registerWindowRef(i: number, ref: any) {
Expand Down Expand Up @@ -87,7 +44,7 @@
@close="removeWindowRef(i, $event)"
>
<component
:is="{...window.type.component}"
:is="contentComponents[window.type]"
:params="window.params"
/>
</VicavWinBox>
Expand Down
58 changes: 36 additions & 22 deletions store/wm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,47 @@ export const useWMStore = defineStore(
const windowMarginPx = ref(5) // must be in sync with css class .wb-vicav in WindowManager.vue
const counter = ref(0)
const windowList = ref([] as IWindow[])
const newWindow = ref(null as INewWindow|null)

const open = (windowTypeId: string, windowTitle: string, params: Object|null) => {
newWindow.value = { id: counter.value++, title: windowTitle, windowTypeId, params }
nextTick(() => {
newWindow.value = null
})
}
let windowType: WindowType
try {
windowType = validateWindowType(windowTypeId)
} catch (error: Error) {
console.warn("WindowManager: " + error.message)
return
}

let windowClasses = [ 'wb-vicav', 'no-min', 'no-max', 'no-full', 'no-resize', 'no-move']
if (!!params?.customClass) {
windowClasses.push(params.customClass)
}
let newWindow: IWindow = {
id: counter.value++,
ref: null,
type: windowType,
winBoxOptions: {
title: '[' + windowTypeId + '] ' + windowTitle,
top: topMargin,
class: windowClasses,
},
params: params,
}

const addWindowToList = (window: IWindow) => {
window.winBoxOptions.index = windowList.value.length > 0
newWindow.winBoxOptions.index = windowList.value.length > 0
? Math.max(...windowList.value.map(w => parseInt(w.ref.index))) + 1
: 1000
windowList.value.push(window)
windowList.value.push(newWindow)
arrangeWindows()
}

const validateWindowType = (windowTypeId: string): WindowType => {
const windowType = windowTypes.find(t => t === windowTypeId)
if (windowType) {
return windowType
}
throw new Error("Window type '" + windowTypeId + "' unknown")
}

const registerWindowRef = (i: number, ref: HTMLElement) => {
windowList.value[i].ref = ref
}
Expand Down Expand Up @@ -245,9 +269,7 @@ export const useWMStore = defineStore(
registerClientSize,

windowList,
newWindow,
open,
addWindowToList,
registerWindowRef,
removeWindowRef,
focus,
Expand All @@ -266,21 +288,13 @@ export const useWMStore = defineStore(
}
)

export interface INewWindow {
id: number,
title: string,
windowTypeId: string,
params: Object|null,
}

export interface IWindowType {
component: ConcreteComponent<{}, any, any, ComputedOptions, MethodOptions>,
}
export const windowTypes = ['Text', 'WMap', 'DictQuery', 'DictEntry'] as const
export type WindowType = typeof windowTypes[number]

export interface IWindow {
id: number | null
ref: any
type: IWindowType
type: WindowType
winBoxOptions: any
params: Object|null
}

0 comments on commit 4c813f5

Please sign in to comment.