Files
RFP_Infinity-Vis/app/ui/preview_layout.py

69 lines
2.8 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from app.qt_compat import QRectF
from app.config.models import InfinityMirrorConfig, TileConfig
@dataclass(frozen=True)
class PreviewLayout:
canvas_rect: QRectF
tile_rects: dict[str, QRectF]
def compute_preview_layout(widget_rect: QRectF, config: InfinityMirrorConfig) -> PreviewLayout:
rows = config.logical_display.rows
cols = config.logical_display.cols
outer = QRectF(widget_rect).adjusted(28, 28, -28, -28)
gap = min(22.0, max(10.0, min(outer.width() / 48.0, outer.height() / 22.0)))
tile_aspect = tile_aspect_ratio(config)
usable_width = max(1.0, outer.width() - gap * (cols - 1))
usable_height = max(1.0, outer.height() - gap * (rows - 1))
tile_width = usable_width / max(1, cols)
tile_height = tile_width / tile_aspect
if tile_height * rows > usable_height:
tile_height = usable_height / max(1, rows)
tile_width = tile_height * tile_aspect
shell_padding = max(18.0, min(tile_width, tile_height) * 0.16)
grid_width = tile_width * cols + gap * (cols - 1)
grid_height = tile_height * rows + gap * (rows - 1)
left = outer.left() + (outer.width() - grid_width) / 2.0
top = outer.top() + (outer.height() - grid_height) / 2.0
canvas_rect = QRectF(left - shell_padding, top - shell_padding, grid_width + shell_padding * 2.0, grid_height + shell_padding * 2.0)
tile_rects: dict[str, QRectF] = {}
for tile in config.sorted_tiles():
x = left + (tile.col - 1) * (tile_width + gap)
y = top + (tile.row - 1) * (tile_height + gap)
tile_rects[tile.tile_id] = QRectF(x, y, tile_width, tile_height)
return PreviewLayout(canvas_rect=canvas_rect, tile_rects=tile_rects)
def tile_aspect_ratio(config: InfinityMirrorConfig) -> float:
logical_display = config.logical_display
tile_width = max(1.0, float(logical_display.tile_width))
tile_height = max(1.0, float(logical_display.tile_height))
return max(0.55, min(1.8, tile_width / tile_height))
def segment_display_rect(tile: TileConfig, rect: QRectF) -> QRectF:
tile_width = max(0.001, tile.x1 - tile.x0)
tile_height = max(0.001, tile.y1 - tile.y0)
aspect_ratio = max(0.5, min(1.8, tile_width / tile_height))
base = min(rect.width(), rect.height())
margin = max(6.0, base * 0.07)
available_rect = rect.adjusted(margin, margin, -margin, -margin)
fitted_width = available_rect.width()
fitted_height = fitted_width / aspect_ratio
if fitted_height > available_rect.height():
fitted_height = available_rect.height()
fitted_width = fitted_height * aspect_ratio
left = available_rect.left() + (available_rect.width() - fitted_width) / 2.0
top = available_rect.top() + (available_rect.height() - fitted_height) / 2.0
return QRectF(left, top, fitted_width, fitted_height)