<template> <div ref="wall" class="fit items-center justify-evenly wall" @dragenter="onDragEnter" @dragleave="onDragLeave" @dragover="onDragOver" @drop="onDrop" style="background-color: #bce0f0" > <div id="windows" style="position: absolute"> <window @reset_geometry_offset="resetGeometryOffset" @commit_geometry="commitGeometry" @close_this_window="closeWindow" @close_other_windows="closeOtherWindows" @close_all_windows="closeAllWindows" @window_fouse_in="windowFocusIn" @dblclick="(evt) => windowDBClick(item.window_id)" @edit_volume="edit_volume" @mute_unmute="mute_unmute" :ref="'window_' + item.window_id" :id="'window_' + item.window_id" v-for="(item, index) in windows" :uuid="item.uuid" :key="index" :disable="plan_running" class="window" :signal_source_table_uuid="item.signal_source_table_uuid" :window="item" :style="{ top: (item.y * $store.state.device_screen_height) / wall_height_scaler + 'px', left: (item.x * $store.state.device_screen_width) / wall_width_scaler + 'px', width: (item.width * $store.state.device_screen_width) / wall_width_scaler + 'px', height: (item.height * $store.state.device_screen_height) / wall_height_scaler + 'px', }" /> </div> <div ref="wall_grids" @click="onWallGridsClick"> <div v-for="row in wall_rows" :key="row" class="row" :style="{ height: item_height + 'px', }" > <div :ref="'item' + (row - 1) * wall_cols * col" v-for="col in wall_cols" :key="col" class="col wall_item wall_item_flag" :style="{ width: item_witdh + 'px', height: item_height + 'px', }" > <q-popup-proxy context-menu> <q-popup-proxy context-menu /> <q-list> <q-item :disable="plan_running" clickable v-close-popup @click="closeAllWindows" > <q-item-section avatar> <q-icon name="close" color="red" /> </q-item-section> <q-item-section> {{ $t("close all windwos") }} </q-item-section> </q-item> </q-list> </q-popup-proxy> </div> </div> </div> </div> <edit-volume-dialog ref="edit_volume_dialog" /> </template> <style scoped> .wall { border: 1px solid black; } .wall_item { border: 1px solid gray; } .window { position: absolute; } .wall_item_flag { } </style> <script lang="ts"> import GlobalData from "src/common/GlobalData"; import { defineComponent, ref, Ref, computed, onMounted } from "vue"; const elementResizeDetectorMaker = require("element-resize-detector"); import { Protocol } from "src/entities/WSProtocol"; import Window from "src/components/Window.vue"; import { useI18n } from "vue-i18n"; import { useStore } from "src/store"; import EventBus, { EventNamesDefine } from "src/common/EventBus"; import { WindowOpenNotifyEntity, WindowStates, } from "src/entities/MultimediaWindowEntity"; import WindowOtherStateChangeNotifyEntity from "src/entities/WindowOtherStateChangeNotifyEntity"; import { useQuasar } from "quasar"; import { NotifyMessage } from "src/common/ClientConnection"; import EditVolumeDialog from "src/components/EditVolumeDialog.vue"; export default defineComponent({ name: "PageWall", components: { Window, EditVolumeDialog }, setup() { const $q = useQuasar(); const $store = useStore(); const $t = useI18n(); const edit_volume_dialog: Ref<any> = ref(null); const plan_running = ref(false); const windows = computed({ get: () => $store.state.windows, set: (val) => $store.commit("setWindows", val), }); const wall_rows = computed({ get: () => $store.state.wall_row, set: (val) => $store.commit("setWallRow", val), }); const wall_cols = computed({ get: () => $store.state.wall_col, set: (val) => $store.commit("setWallCol", val), }); const wall: Ref<HTMLElement | null> = ref(null); let item_witdh = ref(0); const item_height = ref(0); const wall_width_scaler = ref(0); const wall_height_scaler = ref(0); const calcWallVWScaler = (wall_width: number, wall_height: number) => { if (wall.value && wall.value.parentElement) { wall_height_scaler.value = $store.state.device_screen_height / wall_height; wall_width_scaler.value = $store.state.device_screen_width / wall_width; } }; const calcWallItemWH = () => { item_witdh.value = wall?.value?.parentElement?.offsetWidth ?? 0 / wall_cols.value; if (wall.value && wall.value.parentElement) { const wv_scaler = $store.state.device_screen_width / $store.state.device_screen_height; item_height.value = wall.value.parentElement.offsetWidth / wv_scaler / wall_rows.value; } else { item_height.value = 0; } }; EventBus.getInstance().on( EventNamesDefine.DocumentBodyClick, (evt: PointerEvent) => { if (wall.value) { let flag = false; { let item: HTMLElement | null = evt.srcElement as HTMLElement; while (item) { if (item == wall.value) { flag = true; break; } item = item.parentElement; } } if (!flag) { EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows); } } } ); EventBus.getInstance().on( EventNamesDefine.NotifyMessage, (notify: NotifyMessage) => { try { switch (notify.packet.command) { case Protocol.Commands.kCloseWindow: { const temp = JSON.parse(notify.data); if (temp && temp.window_id) { $store.commit("removeWindow", { window_id: temp.window_id, }); } } break; case Protocol.Commands.kMoveWindow: { const temp = JSON.parse(notify.data); if (temp && temp.window_id) { const window = $store.state.windows.find( (item) => item.window_id == temp.window_id ); if (window) { $store.commit("setWindowPropertys", [ { window, property_name: "x", value: temp.x ?? 0, }, { window, property_name: "y", value: temp.y ?? 0, }, ]); } } } break; case Protocol.Commands.kResizeWindow: { const temp = JSON.parse(notify.data); if (temp && temp.window_id) { const window = $store.state.windows.find( (item) => item.window_id == temp.window_id ); if (window) { $store.commit("setWindowPropertys", [ { window, property_name: "width", value: temp.width ?? 0, }, { window, property_name: "height", value: temp.height ?? 0, }, ]); } } } break; case Protocol.Commands.kOpenWindow: { const temp = JSON.parse(notify.data) as WindowOpenNotifyEntity; if (temp) { $store.commit("pushWindow", temp); } } break; case Protocol.Commands.kWindowOtherStateChanged: { const temp = JSON.parse( notify.data ) as WindowOtherStateChangeNotifyEntity; if (temp && temp.window_id) { const window = $store.state.windows.find( (item) => item.window_id == temp.window_id ); if (window) { window.window_state; // $store.commit("setWindowProperty", { window, property_name: "window_state", value: new WindowStates( temp.playing, temp.focus, temp.muted ), }); } } } break; case Protocol.Commands.kCurrentRunningPlanStateChanged: { const temp = JSON.parse( notify.data ) as Protocol.PlanRunningStateChangeNotifyEntity; if (temp && temp.plan) { plan_running.value = temp.running; } } break; } } catch {} } ); onMounted(() => { if (wall.value) { elementResizeDetectorMaker().listenTo( wall.value, (element: HTMLElement) => { if (element) { calcWallItemWH(); calcWallVWScaler(element.offsetWidth, element.offsetHeight); } } ); } }); return { windows, wall, wall_rows, wall_cols, item_witdh, item_height, wall_width_scaler, wall_height_scaler, plan_running, edit_volume_dialog, onDrop(e: DragEvent) { e.preventDefault(); let target = e.target as any; if (target) { target.classList.remove("drag-enter"); } let uuid = e.dataTransfer?.getData("uuid"); if (uuid) { let signal_sources = GlobalData.getInstance().signal_source.filter( (item) => (item as any)?.uuid == uuid ); if (signal_sources.length) { let signal_source = signal_sources[0]; if (signal_source) { let dom: HTMLElement | null = e.target as HTMLElement; if (wall.value && dom) { if (dom.classList.contains("wall_item_flag")) { GlobalData.getInstance() .getCurrentClient() ?.openWindow( new Protocol.OpenWindowRequestEntity( signal_source.uuid, (dom.offsetLeft * wall_width_scaler.value) / $store.state.device_screen_width, (dom.offsetTop * wall_height_scaler.value) / $store.state.device_screen_height, (dom.offsetWidth * wall_width_scaler.value) / $store.state.device_screen_width, (dom.offsetHeight * wall_height_scaler.value) / $store.state.device_screen_height ) ); } else if (dom.classList.contains("window_flag")) { let uuid = dom.getAttribute("uuid"); if (uuid) { let window = $store.state.windows.find( (item) => item.uuid == uuid ); if (window) { let client = GlobalData.getInstance().getCurrentClient(); if (client) { let x = window.x; let y = window.y; let width = window.width; let height = window.height; client.closeWindow(window.window_id); setTimeout(() => { client?.openWindow( new Protocol.OpenWindowRequestEntity( signal_source.uuid, x, y, width, height ) ); }, 100); } } } } } } } } }, onDragEnter(e: DragEvent) { e.stopPropagation(); let target: HTMLElement | null = e.target as HTMLElement; if (target && target.draggable !== true) { while ( target && !target.classList.contains("window_flag") && !target.classList.contains("wall_item_flag") ) { target = target.parentElement; } target?.classList.add("drag-enter"); } }, onDragLeave(e: DragEvent) { let target: HTMLElement = e.target as HTMLElement; target?.classList.remove("drag-enter"); }, onDragOver(e: DragEvent) { if (!plan_running.value) { e.preventDefault(); } }, onWallGridsClick(e: MouseEvent) { EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows); }, resetGeometryOffset( window: any, offset_x: number, offset_y: number, offset_width: number, offset_height: number ) { $store.commit("setWindowPropertys", [ { window, property_name: "x", value: window.x + (offset_x * wall_width_scaler.value) / $store.state.device_screen_width, }, { window, property_name: "y", value: window.y + (offset_y * wall_height_scaler.value) / $store.state.device_screen_height, }, { window, property_name: "width", value: Math.max( window.width + (offset_width * wall_width_scaler.value) / $store.state.device_screen_width, 32 / $store.state.device_screen_width ), }, { window, property_name: "height", value: Math.max( window.height + (offset_height * wall_height_scaler.value) / $store.state.device_screen_height, 32 / $store.state.device_screen_height ), }, ]); }, commitGeometry(window: any) { const win = window as WindowOpenNotifyEntity; if (win) { GlobalData.getInstance() .getCurrentClient() ?.moveWindow(win.window_id, win.x, win.y); GlobalData.getInstance() .getCurrentClient() ?.resizeWindow(win.window_id, win.width, win.height); } }, closeAllWindows() { for (const window of $store.state.windows) { if (window) { GlobalData.getInstance() .getCurrentClient() ?.closeWindow(window.window_id); } } }, windowFocusIn(window_id: number) { GlobalData.getInstance().getCurrentClient()?.focusIn(window_id); }, closeOtherWindows(window_id: number) { for (const window of $store.state.windows) { if (window && window.window_id != window_id) { GlobalData.getInstance() .getCurrentClient() ?.closeWindow(window.window_id); } } }, windowDBClick(window_id: number) { if (plan_running.value) { return; } GlobalData.getInstance().getCurrentClient()?.windowFitGrid(window_id); }, closeWindow(window_id: number) { GlobalData.getInstance().getCurrentClient()?.closeWindow(window_id); }, edit_volume(window_id: number) { const window = windows.value.find( (element) => element && element.window_id == window_id ); if (window) { edit_volume_dialog.value?.showDialog(window_id, window.volume); } }, mute_unmute(window_id: number) { console.log(windows.value); const window = windows.value.find( (element) => element && element.window_id == window_id ); if (window) { } }, }; }, }); </script>