/** * Where a tab's window sits (#371). Nothing of it is kept: a window opens in the middle of the * screen every time, and is held on the screen while it is moved, sized, or the page shrinks. */ export interface WindowBox { x: number; y: number; w: number; h: number; } /** Below this a tab's controls no longer fit in a row, and the title bar loses its buttons. */ export const MIN_WINDOW_WIDTH = 320; export const MIN_WINDOW_HEIGHT = 200; /** The least a window is sized to; a pane that needs more says so (#378). */ const LEAST = { w: MIN_WINDOW_WIDTH, h: MIN_WINDOW_HEIGHT }; /** The least size of a window around a pane that needs `w` by `h`, never below the usual least. */ export function leastBox(w: number, h: number): { w: number; h: number } { return { w: Math.max(MIN_WINDOW_WIDTH, Math.ceil(w)), h: Math.max(MIN_WINDOW_HEIGHT, Math.ceil(h)) }; } /** How far each further window opens down and to the right, so it does not hide the one before. */ const WINDOW_STEP = 24; /** Half the screen's width and 60 % of its height, in the middle; the `count`-th one a step further. */ export function openingBox(screenW: number, screenH: number, count: number): WindowBox { const w = Math.min(screenW, Math.max(MIN_WINDOW_WIDTH, Math.round(screenW * 0.5))); const h = Math.min(screenH, Math.max(MIN_WINDOW_HEIGHT, Math.round(screenH * 0.6))); const step = count * WINDOW_STEP; return onScreen( { x: Math.round((screenW - w) / 2) + step, y: Math.round((screenH - h) / 2) + step, w, h }, screenW, screenH, ); } /** `box` whole on the screen: no larger than it, and moved in where it sticks out. */ export function onScreen(box: WindowBox, screenW: number, screenH: number, least = LEAST): WindowBox { const w = Math.min(Math.max(box.w, least.w), screenW); const h = Math.min(Math.max(box.h, least.h), screenH); const x = Math.max(0, Math.min(box.x, screenW - w)); const y = Math.max(0, Math.min(box.y, screenH - h)); return { x: Math.round(x), y: Math.round(y), w: Math.round(w), h: Math.round(h) }; } /** `box` with its lower right corner pulled by `dx`, `dy`: at least the minimum, at most to the screen's edge. */ export function sized( box: WindowBox, dx: number, dy: number, screenW: number, screenH: number, least = LEAST, ): WindowBox { const w = Math.max(least.w, Math.min(box.w + dx, screenW - box.x)); const h = Math.max(least.h, Math.min(box.h + dy, screenH - box.y)); return { ...box, w: Math.round(w), h: Math.round(h) }; }