media_player_client/src/components/WindowRectEditDialog.vue

517 lines
15 KiB
Vue

<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 50vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-auto text-h6">
{{ $t("window rect") }}
</div>
<q-space />
<div>
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 40vh; width: 50vw" class="scroll">
<q-list>
<q-item class="text-center text-h6">
<q-item-section>
<q-item-label>
<span>{{ $t("desktop width") }}: </span>
<span>
{{ screen_width }}
</span>
<span>{{ $t("px") }}</span>
</q-item-label>
</q-item-section>
<q-item-section>
<q-item-label>
<span>{{ $t("desktop height") }}: </span>
<span>
{{ screen_height }}
</span>
<span>{{ $t("px") }}</span>
</q-item-label>
</q-item-section>
</q-item>
<q-separator />
<q-item>
<q-item-section>
<q-item>
<q-item-section avatar>
<span class="q-mb-md">{{ $t("X") }}:</span>
</q-item-section>
<q-item-section>
<q-input
autofocus
type="number"
min="0"
v-model="window_rect.x"
:rules="[
(val) =>
(val != null &&
val != undefined &&
val.toString().length > 0) ||
$t('Please type something'),
(val) =>
parseInt(val) >= 0 ||
$t('the number must be greater than 0'),
]"
lazy-rules
>
<template v-slot:append>
<span class="input_append">{{ $t("px") }}</span>
</template>
</q-input>
</q-item-section>
</q-item>
</q-item-section>
<q-item-section>
<q-item>
<q-item-section avatar>
<span class="q-mb-md">{{ $t("Y") }}:</span>
</q-item-section>
<q-item-section>
<q-input
type="number"
min="0"
v-model="window_rect.y"
:rules="[
(val) =>
(val != null &&
val != undefined &&
val.toString().length > 0) ||
$t('Please type something'),
(val) =>
parseInt(val) >= 0 ||
$t('the number must be greater than 0'),
]"
lazy-rules
>
<template v-slot:append>
<span class="input_append">{{ $t("px") }}</span>
</template>
</q-input>
</q-item-section>
</q-item>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item>
<q-item-section avatar>
<span class="q-mb-md">{{ $t("width") }}:</span>
</q-item-section>
<q-item-section>
<q-input
type="number"
min="1"
v-model="window_rect.width"
:rules="[
(val) =>
(val != null &&
val != undefined &&
val.toString().length > 0) ||
$t('Please type something'),
(val) =>
parseInt(val) >= 1 ||
$t('the number must be greater than 1'),
]"
lazy-rules
>
<template v-slot:append>
<span class="input_append">{{ $t("px") }}</span>
</template>
</q-input>
</q-item-section>
</q-item>
</q-item-section>
<q-item-section>
<q-item>
<q-item-section avatar>
<span class="q-mb-md">{{ $t("height") }}:</span>
</q-item-section>
<q-item-section>
<q-input
type="number"
min="1"
v-model="window_rect.height"
:rules="[
(val) =>
(val != null &&
val != undefined &&
val.toString().length > 0) ||
$t('Please type something'),
(val) =>
parseInt(val) >= 1 ||
$t('the number must be greater than 1'),
]"
lazy-rules
>
<template v-slot:append>
<span class="input_append">{{ $t("px") }}</span>
</template>
</q-input>
</q-item-section>
</q-item>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
v-if="mod == 'sync'"
:loading="loading"
flat
:label="$t('revert')"
no-caps
color="primary"
@click="revertWindowRect"
/>
<q-btn
:loading="loading"
flat
:label="$t('Close')"
no-caps
:disable="loading"
color="primary"
v-close-popup
/>
<q-btn
v-if="mod == 'async'"
ref="accept"
flat
:label="$t('Accept')"
no-caps
:loading="loading"
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped>
.input_append {
font-size: 1rem;
}
</style>
<script lang="ts">
import { defineComponent, ref, watch, computed, reactive } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { SpecialVideoHelper } from "src/common/SpecialVideoHelper";
export default defineComponent({
name: "ComponentWindowRectEditDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let loading = ref(false);
const screen_width = ref($store.state.device_screen_width);
const screen_height = ref($store.state.device_screen_height);
if ($store.state.isSpecialVideo()) {
const screen_info = SpecialVideoHelper.getScreenInfo(
$store.state.wall_col,
$store.state.wall_row
);
screen_width.value = screen_info.screen_width;
screen_height.value = screen_info.screen_height;
}
const window_rect = reactive({
x: 0,
y: 0,
width: 0,
height: 0,
clean: function () {
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
},
formartNumber: function () {
this.x = parseInt(<any>this.x);
this.y = parseInt(<any>this.y);
this.width = parseInt(<any>this.width);
this.height = parseInt(<any>this.height);
},
getRealRect: function (screen_height: number, screen_width: number) {
const result = {
x: this.x,
y: this.y,
width: this.width,
height: this.height,
};
result.x /= screen_width;
result.y /= screen_height;
result.width /= screen_width;
result.height /= screen_height;
return result;
},
});
let back_window_rect = {
x: 0,
y: 0,
width: 0,
height: 0,
};
// async 为异步模式,不发送窗口指令,只返回坐标
// sync 为同步模式,坐标修改后直接发送窗口指令,不返回任何数据
const mod = ref("async"); // sync
let _resolve: any = null;
let _reject: any = null;
const clean_promise = () => {
try {
if (_resolve && typeof _resolve == "function") {
_resolve(null);
} else if (_reject && typeof _reject == "function") {
_reject(null);
}
_resolve = null;
_reject = null;
} catch {}
};
let current_window_id = 0;
const sendSetWindowGeometryMessage = () => {
if (mod.value == "async") {
return;
}
const rect = window_rect.getRealRect(
screen_height.value,
screen_width.value
);
GlobalData.getInstance()
.getCurrentClient()
?.setWindowGeometry(
current_window_id,
rect.x,
rect.y,
rect.width,
rect.height
);
};
watch(
() => window_rect.x,
() => {
sendSetWindowGeometryMessage();
}
);
watch(
() => window_rect.y,
() => {
sendSetWindowGeometryMessage();
}
);
watch(
() => window_rect.width,
() => {
sendSetWindowGeometryMessage();
}
);
watch(
() => window_rect.height,
() => {
sendSetWindowGeometryMessage();
}
);
return {
show_dialog,
loading,
window_rect,
screen_height,
screen_width,
mod,
showDialog(window_id: number) {
const window = $store.state.windows.find(
(e) => e && e.window_id == window_id
);
if (window) {
screen_width.value = $store.state.device_screen_width;
screen_height.value = $store.state.device_screen_height;
if ($store.state.isSpecialVideo()) {
const screen_info = SpecialVideoHelper.getScreenInfo(
$store.state.wall_col,
$store.state.wall_row
);
screen_width.value = screen_info.screen_width;
screen_height.value = screen_info.screen_height;
}
window_rect.clean();
window_rect.x = Math.round(window.x * screen_width.value);
window_rect.y = Math.round(window.y * screen_height.value);
window_rect.width = Math.round(window.width * screen_width.value);
window_rect.height = Math.round(window.height * screen_height.value);
back_window_rect.x = window_rect.x;
back_window_rect.y = window_rect.y;
back_window_rect.width = window_rect.width;
back_window_rect.height = window_rect.height;
current_window_id = window_id;
mod.value = "sync";
show_dialog.value = true;
} else {
console.error("can't find window.", window_id);
}
},
showDialogAsync(x: number, y: number, width: number, height: number) {
return new Promise((resolve, reject) => {
clean_promise();
screen_width.value = $store.state.device_screen_width;
screen_height.value = $store.state.device_screen_height;
if ($store.state.isSpecialVideo()) {
const screen_info = SpecialVideoHelper.getScreenInfo(
$store.state.wall_col,
$store.state.wall_row
);
screen_width.value = screen_info.screen_width;
screen_height.value = screen_info.screen_height;
}
window_rect.clean();
window_rect.x = Math.round(x);
window_rect.y = Math.round(y);
window_rect.width = Math.round(width);
window_rect.height = Math.round(height);
_resolve = resolve;
_reject = reject;
mod.value = "async";
show_dialog.value = true;
});
},
resetData() {
show_dialog.value = false;
loading.value = false;
current_window_id = 0;
back_window_rect = { x: 0, y: 0, height: 0, width: 0 };
if (_reject) {
try {
_reject(null);
} catch {}
}
_resolve = null;
_reject = null;
},
onSubmit() {
loading.value = true;
window_rect.formartNumber();
const resolve_data = () => {
if (_resolve) {
try {
_resolve(window_rect);
} catch {}
}
_resolve = null;
_reject = null;
loading.value = false;
show_dialog.value = false;
};
if (
window_rect.x + window_rect.width > screen_width.value ||
window_rect.y + window_rect.height > screen_height.value
) {
$q.dialog({
title: $t.t("Warning"),
message:
$t.t(
"set the window rectangle beyond the desktop rectangle, the window rectangle will be clipped, are you sure to use this window rectangle"
) + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => resolve_data())
.onCancel(() => (loading.value = false));
} else {
resolve_data();
}
},
revertWindowRect() {
window_rect.x = back_window_rect.x;
window_rect.y = back_window_rect.y;
window_rect.width = back_window_rect.width;
window_rect.height = back_window_rect.height;
sendSetWindowGeometryMessage();
},
};
},
});
</script>