mirror of
https://github.com/ducbao414/win32.run.git
synced 2025-12-17 01:32:50 +09:00
init the awkward code
This commit is contained in:
258
src/lib/components/xp/Window.svelte
Normal file
258
src/lib/components/xp/Window.svelte
Normal file
@@ -0,0 +1,258 @@
|
||||
<script>
|
||||
import {onMount} from 'svelte';
|
||||
import TitleBar from './TitleBar.svelte';
|
||||
import * as utils from '../../utils';
|
||||
const {click_outside} = utils;
|
||||
import _ from 'lodash';
|
||||
import {get, set} from 'idb-keyval';
|
||||
import { zIndex, runningPrograms } from '../../store';
|
||||
|
||||
export let options = {};
|
||||
|
||||
let titlebar;
|
||||
export let node_ref;
|
||||
let saved_position;
|
||||
export let maximized;
|
||||
export let minimized;
|
||||
let translateX = '';
|
||||
let translateY = '';
|
||||
let animation_enabled = false;
|
||||
|
||||
export let on_focused = () => {
|
||||
}
|
||||
|
||||
export let z_index = 0;
|
||||
|
||||
onMount(async () => {
|
||||
if(options.exec_path != null){
|
||||
let rect = await get(options.exec_path);
|
||||
console.log(rect);
|
||||
if(rect){
|
||||
let workspace = document.querySelector('#work-space');
|
||||
if(rect.left + rect.width <= workspace.offsetWidth
|
||||
&& rect.top + rect.height <= workspace.offsetHeight){
|
||||
options.top = rect.top;
|
||||
options.left = rect.left;
|
||||
options.width = rect.width;
|
||||
options.height = rect.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(options.top == null){
|
||||
options.top = (node_ref.parentNode.offsetHeight - node_ref.offsetHeight)/2;
|
||||
}
|
||||
if(options.left == null){
|
||||
options.left = (node_ref.parentNode.offsetWidth - node_ref.offsetWidth)/2;
|
||||
}
|
||||
set_position({top: options.top, left: options.left, width: node_ref.width, height: node_ref.height});
|
||||
|
||||
if(options.resizable == null){
|
||||
options.resizable = true;
|
||||
}
|
||||
if(options.draggable == null){
|
||||
options.draggable = true;
|
||||
}
|
||||
|
||||
|
||||
setup_gestures();
|
||||
zIndex.update(value => value + 1);
|
||||
z_index = $zIndex;
|
||||
|
||||
node_ref.style.removeProperty('opacity');
|
||||
setTimeout(() => {
|
||||
animation_enabled = true;
|
||||
}, 500)
|
||||
|
||||
})
|
||||
|
||||
|
||||
export let on_click_close = () => {
|
||||
}
|
||||
|
||||
export let on_click_maximize = () => {
|
||||
if(!options.resizable) return;
|
||||
minimized = false;
|
||||
if(maximized){
|
||||
set_position(saved_position);
|
||||
maximized = false;
|
||||
} else {
|
||||
// let rect = utils.relative_rect(node_ref.parentNode.getBoundingClientRect(), node_ref.getBoundingClientRect());
|
||||
// console.log(rect);
|
||||
saved_position = {top: node_ref.offsetTop, left: node_ref.offsetLeft, width: node_ref.offsetWidth, height: node_ref.offsetHeight};
|
||||
set_position({top: 0, left: 0, width: node_ref.parentNode.offsetWidth, height: node_ref.parentNode.offsetHeight});
|
||||
maximized = true;
|
||||
}
|
||||
focus();
|
||||
}
|
||||
|
||||
export let on_click_minimize = () => {
|
||||
let window_center = get_center_point(node_ref.getBoundingClientRect());
|
||||
let tile_center = get_center_point(document.querySelector(`.program-tile[program-id="${options.id}"]`)?.getBoundingClientRect());
|
||||
|
||||
translateX = `translateX(${tile_center.x-window_center.x}px)`;
|
||||
translateY = `translateY(${tile_center.y-window_center.y}px)`;
|
||||
console.log(`${translateX} ${translateY} scale(0.1)`);
|
||||
|
||||
minimized = true;
|
||||
loose_focus();
|
||||
}
|
||||
|
||||
export function restore(){
|
||||
if(minimized){
|
||||
minimized = false;
|
||||
} else if(maximized) {
|
||||
on_click_maximize();
|
||||
}
|
||||
focus();
|
||||
}
|
||||
|
||||
export function focus(){
|
||||
if(z_index != $zIndex){
|
||||
zIndex.update(value => value + 1);
|
||||
z_index = $zIndex;
|
||||
on_focused();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function loose_focus(){
|
||||
if(z_index == $zIndex){
|
||||
console.log('loose focus');
|
||||
zIndex.update(value => value + 1);
|
||||
}
|
||||
}
|
||||
|
||||
function get_center_point(rect){
|
||||
if(rect == null){
|
||||
return {x: document.body.offsetWidth*0.5, y: document.body.offsetHeight*0.5}
|
||||
}
|
||||
return {x: rect.x + rect.width*0.5, y: rect.y+rect.height*0.5}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function set_position({top, left, width, height}){
|
||||
|
||||
node_ref.style.top = `${top}px`;
|
||||
node_ref.style.left = `${left}px`;
|
||||
node_ref.style.width = `${width}px`;
|
||||
node_ref.style.height = `${height}px`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setup_gestures(){
|
||||
if(options.draggable){
|
||||
jQuery(node_ref).draggable({
|
||||
containment: 'parent',
|
||||
handle: '.titlebar',
|
||||
stop: async () => {
|
||||
if(options.exec_path){
|
||||
await set(options.exec_path, node_ref.getBoundingClientRect())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if(options.resizable){
|
||||
jQuery(node_ref).resizable({
|
||||
minWidth: options.min_width,
|
||||
minHeight: options.min_height,
|
||||
aspectRatio: options.aspect_ratio,
|
||||
containment: 'parent',
|
||||
handles: 'all',
|
||||
classes: {
|
||||
"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se opacity-0"
|
||||
},
|
||||
stop: async () => {
|
||||
if(options.exec_path){
|
||||
await set(options.exec_path, node_ref.getBoundingClientRect())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function update_icon(icon){
|
||||
titlebar.update_icon(icon);
|
||||
}
|
||||
|
||||
export function update_title(title){
|
||||
runningPrograms.update(values => {
|
||||
let program = values.find(el => el.options.id == options.id);
|
||||
let index = values.indexOf(program);
|
||||
if(index >= 0){
|
||||
values[index].options.title = title;
|
||||
}
|
||||
|
||||
return values;
|
||||
})
|
||||
titlebar.update_title(title);
|
||||
}
|
||||
|
||||
export function show_toast({theme='dark', message}){
|
||||
let toast = document.createElement('div');
|
||||
toast.style.position = 'absolute';
|
||||
toast.style.transform = 'translate(-50%)';
|
||||
toast.style.left = '50%';
|
||||
toast.style.top = '50%';
|
||||
toast.style.padding = '10px';
|
||||
toast.innerText = message;
|
||||
toast.style.borderRadius = '7px';
|
||||
toast.style.opacity = 1;
|
||||
toast.style.fontSize = '12px';
|
||||
toast.style.minHeight = '30px';
|
||||
toast.style.minWidth = '70px';
|
||||
toast.style.zIndex = 99999;
|
||||
if(theme == 'dark'){
|
||||
toast.style.backgroundColor = '#0f172a';
|
||||
toast.style.border = '1px solid #f1f5f9';
|
||||
toast.style.color = '#f8fafc';
|
||||
} else {
|
||||
toast.style.backgroundColor = '#f1f5f9';
|
||||
toast.style.border = '1px solid #1e293b';
|
||||
toast.style.color = '#0f172a';
|
||||
}
|
||||
node_ref.append(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.remove()
|
||||
}, 3000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<div
|
||||
on:mousedown={focus}
|
||||
use:click_outside on:click_outside={loose_focus}
|
||||
bind:this={node_ref} style="
|
||||
opacity:0;
|
||||
position: absolute;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
padding: 0px;
|
||||
-webkit-font-smoothing: antialiased;"
|
||||
program-id="{options.id}"
|
||||
class="window absolute flex flex-col bg-xp-yellow {animation_enabled ? 'transition duration-300' : ''} {minimized ? `opacity-0` : ''}"
|
||||
style:width="{options.width}px" style:height="{options.height}px"
|
||||
style:min-width="{options.min_width}px" style:min-height="{options.min_height}px"
|
||||
style:transform="{minimized ? `${translateX} ${translateY} scale(0.1)` : 'none'}"
|
||||
style:background="{options.background}"
|
||||
style:z-index="{z_index}" style:box-shadow="{z_index < $zIndex ? 'var(--window-box-shadow-inactive)' : 'var(--window-box-shadow)'}">
|
||||
|
||||
<div class="shrink-0">
|
||||
<TitleBar bind:this={titlebar} options={options} inactive={z_index < $zIndex} maximized={maximized}
|
||||
on_click_close={on_click_close} on_click_maximize={on_click_maximize} on_click_minimize={on_click_minimize}>
|
||||
</TitleBar>
|
||||
</div>
|
||||
|
||||
<div class="grow shrink-0 relative shadow-xl">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<svelte:options accessors={true}></svelte:options>
|
||||
Reference in New Issue
Block a user