This commit is contained in:
Thomas Peterson 2025-11-15 09:45:52 +01:00
parent 9f95a0d630
commit 4d153aba02
5 changed files with 60 additions and 61 deletions

View File

@ -211,11 +211,7 @@ final class KanbanBoardView extends Container
$this->saveBoards(); $this->saveBoards();
$this->renderBoards(); $this->renderBoards();
$msg = sprintf( $msg = sprintf('"%s" nach "%s" verschoben.', $movedTask['title'], $this->getBoardTitle($targetBoardId));
'"%s" nach "%s" verschoben.',
$movedTask['title'],
$this->getBoardTitle($targetBoardId),
);
$this->statusLabel->setText($msg); $this->statusLabel->setText($msg);
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) { if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
error_log('[Kanban] ' . $msg); error_log('[Kanban] ' . $msg);
@ -330,7 +326,7 @@ if (empty($boards)) {
]; ];
file_put_contents($storagePath, json_encode($boards, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX); file_put_contents($storagePath, json_encode($boards, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX);
} }
define('DEBUG_EVENTS', true); define('DEBUG_EVENTS', false);
$app = new Application(); $app = new Application();
$window = new Window('Kanban Beispiel', 1200, 800); $window = new Window('Kanban Beispiel', 1200, 800);
@ -362,17 +358,13 @@ if (function_exists('sdl_get_display_content_scale')) {
$densityText .= ($densityText !== '' ? ' | ' : '') . sprintf('ContentScale: %.2f', $contentScale); $densityText .= ($densityText !== '' ? ' | ' : '') . sprintf('ContentScale: %.2f', $contentScale);
} }
// Fallback: effektiven Scale aus WindowSize vs. WindowSizeInPixels berechnen // Fallback: effektiven Scale aus WindowSize vs. WindowSizeInPixels berechnen
if ( if (function_exists('sdl_get_window_size') && function_exists('sdl_get_window_size_in_pixels')) {
function_exists('sdl_get_window_size') &&
function_exists('sdl_get_window_size_in_pixels')
) {
$logical = sdl_get_window_size($window->getWindowResource()); $logical = sdl_get_window_size($window->getWindowResource());
$pixels = sdl_get_window_size_in_pixels($window->getWindowResource()); $pixels = sdl_get_window_size_in_pixels($window->getWindowResource());
if (is_array($logical) && is_array($pixels) && $logical[0] > 0 && $logical[1] > 0) { if (is_array($logical) && is_array($pixels) && $logical[0] > 0 && $logical[1] > 0) {
$scaleX = $pixels[0] / $logical[0]; $scaleX = $pixels[0] / $logical[0];
$scaleY = $pixels[1] / $logical[1]; $scaleY = $pixels[1] / $logical[1];
$densityText .= ($densityText !== '' ? ' | ' : '') . $densityText .= ($densityText !== '' ? ' | ' : '') . sprintf('EffectiveScale: %.2f x %.2f', $scaleX, $scaleY);
sprintf('EffectiveScale: %.2f x %.2f', $scaleX, $scaleY);
} }
} }
if (function_exists('sdl_get_current_video_driver')) { if (function_exists('sdl_get_current_video_driver')) {
@ -385,7 +377,10 @@ if ($densityText !== '') {
$statusLabel->setText('Bereit. ' . $densityText); $statusLabel->setText('Bereit. ' . $densityText);
} }
$scaleInput = new TextInput('Scale (z.B. 1.0 oder 2.0)', 'w-40 border border-gray-300 rounded px-3 py-2 bg-white text-black'); $scaleInput = new TextInput(
'Scale (z.B. 1.0 oder 2.0)',
'w-40 border border-gray-300 rounded px-3 py-2 bg-white text-black',
);
$scaleInput->setOnChange(function (string $value) use ($statusLabel): void { $scaleInput->setOnChange(function (string $value) use ($statusLabel): void {
$value = trim($value); $value = trim($value);
if ($value === '') { if ($value === '') {

View File

@ -2,17 +2,23 @@
{ {
"id": "board_691661d89de624.46726087", "id": "board_691661d89de624.46726087",
"title": "Backlog", "title": "Backlog",
"tasks": []
},
{
"id": "board_691661d89de806.79123800",
"title": "In Arbeit",
"tasks": [ "tasks": [
{ {
"id": "task_691661d89de735.41071535", "id": "task_691661d89de735.41071535",
"title": "Idee sammeln", "title": "Idee sammeln",
"note": "" "note": ""
}, },
{
"id": "task_691661d89de8e0.86926319",
"title": "UI Grundlayout",
"note": ""
}
]
},
{
"id": "board_691661d89de806.79123800",
"title": "In Arbeit",
"tasks": [
{ {
"id": "task_691661d89de7a0.19655479", "id": "task_691661d89de7a0.19655479",
"title": "Mockups skizzieren", "title": "Mockups skizzieren",
@ -23,13 +29,7 @@
{ {
"id": "board_691661d89de894.20053237", "id": "board_691661d89de894.20053237",
"title": "Erledigt", "title": "Erledigt",
"tasks": [ "tasks": []
{
"id": "task_691661d89de8e0.86926319",
"title": "UI Grundlayout",
"note": ""
}
]
}, },
{ {
"id": "board_69170bcc2be8c6.34720864", "id": "board_69170bcc2be8c6.34720864",

View File

@ -403,10 +403,10 @@ abstract class Component
Profiler::start('render_cached'); Profiler::start('render_cached');
// Render cached texture // Render cached texture
sdl_render_texture($renderer, $texture, [ sdl_render_texture($renderer, $texture, [
'x' => $this->viewport->x, 'x' => $this->viewport->x * $this->viewport->uiScale,
'y' => $this->viewport->y, 'y' => $this->viewport->y * $this->viewport->uiScale,
'w' => $this->viewport->width, 'w' => $this->viewport->width * $this->viewport->uiScale,
'h' => $this->viewport->height, 'h' => $this->viewport->height * $this->viewport->uiScale,
]); ]);
Profiler::end('render_cached'); Profiler::end('render_cached');
Profiler::end('render'); Profiler::end('render');
@ -445,13 +445,12 @@ abstract class Component
// SDL3: sdl_rounded_box_ex uses (x1, y1, x2, y2) instead of (x, y, w, h) // SDL3: sdl_rounded_box_ex uses (x1, y1, x2, y2) instead of (x, y, w, h)
$x2 = $this->viewport->x + $this->viewport->width; $x2 = $this->viewport->x + $this->viewport->width;
$y2 = $this->viewport->y + $this->viewport->height; $y2 = $this->viewport->y + $this->viewport->height;
sdl_rounded_box_ex( sdl_rounded_box_ex(
$renderer, $renderer,
(int) $this->viewport->x, ((int) $this->viewport->x) * $this->viewport->uiScale,
(int) $this->viewport->y, ((int) $this->viewport->y) * $this->viewport->uiScale,
(int) $x2, ((int) $x2) * $this->viewport->uiScale,
(int) $y2, ((int) $y2) * $this->viewport->uiScale,
$border->roundTopLeft ?? 0, $border->roundTopLeft ?? 0,
$border->roundTopRight ?? 0, $border->roundTopRight ?? 0,
$border->roundBottomRight ?? 0, $border->roundBottomRight ?? 0,
@ -463,20 +462,20 @@ abstract class Component
); );
} else { } else {
sdl_render_fill_rect($renderer, [ sdl_render_fill_rect($renderer, [
'x' => $this->viewport->x, 'x' => $this->viewport->x * $this->viewport->uiScale,
'y' => $this->viewport->y, 'y' => $this->viewport->y * $this->viewport->uiScale,
'w' => $this->viewport->width, 'w' => $this->viewport->width * $this->viewport->uiScale,
'h' => $this->viewport->height, 'h' => $this->viewport->height * $this->viewport->uiScale,
]); ]);
} }
} }
if (defined('DEBUG_RENDERING') && DEBUG_RENDERING) { if (defined('DEBUG_RENDERING') && DEBUG_RENDERING) {
sdl_set_render_draw_color($renderer, rand(0, 255), rand(0, 255), rand(0, 255), 10); sdl_set_render_draw_color($renderer, rand(0, 255), rand(0, 255), rand(0, 255), 10);
sdl_render_rect($renderer, [ sdl_render_rect($renderer, [
'x' => $this->viewport->x, 'x' => $this->viewport->x * $this->viewport->uiScale,
'y' => $this->viewport->y, 'y' => $this->viewport->y * $this->viewport->uiScale,
'w' => $this->viewport->width, 'w' => $this->viewport->width * $this->viewport->uiScale,
'h' => $this->viewport->height, 'h' => $this->viewport->height * $this->viewport->uiScale,
]); ]);
} }
@ -906,7 +905,7 @@ abstract class Component
} }
} }
$temp[$y * $width + $x] = $count > 0 ? (int) ($alphaSum / $count) : 0; $temp[($y * $width) + $x] = $count > 0 ? ((int) ($alphaSum / $count)) : 0;
} }
} }
@ -916,8 +915,16 @@ abstract class Component
/** /**
* Create a blurred shadow texture * Create a blurred shadow texture
*/ */
private function createShadowTexture(&$renderer, int $width, int $height, int $blurRadius, int $alpha, int $r = 0, int $g = 0, int $b = 0): mixed private function createShadowTexture(
{ &$renderer,
int $width,
int $height,
int $blurRadius,
int $alpha,
int $r = 0,
int $g = 0,
int $b = 0,
): mixed {
if ($width <= 0 || $height <= 0) { if ($width <= 0 || $height <= 0) {
return null; return null;
} }
@ -928,9 +935,9 @@ abstract class Component
// Fill only the inner rectangle with semi-transparent color // Fill only the inner rectangle with semi-transparent color
// Leave a border for the blur to spread into // Leave a border for the blur to spread into
$margin = $blurRadius + 2; $margin = $blurRadius + 2;
for ($y = $margin; $y < $height - $margin; $y++) { for ($y = $margin; $y < ($height - $margin); $y++) {
for ($x = $margin; $x < $width - $margin; $x++) { for ($x = $margin; $x < ($width - $margin); $x++) {
$alphaMap[$y * $width + $x] = $alpha; $alphaMap[($y * $width) + $x] = $alpha;
} }
} }
@ -946,13 +953,7 @@ abstract class Component
} }
// Create texture // Create texture
$texture = sdl_create_texture( $texture = sdl_create_texture($renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, $width, $height);
$renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC,
$width,
$height
);
if (!$texture) { if (!$texture) {
return null; return null;
@ -993,7 +994,7 @@ abstract class Component
$alpha = $shadowProps['alpha']; $alpha = $shadowProps['alpha'];
if ($shadow->opacity !== null) { if ($shadow->opacity !== null) {
// Convert percentage to 0-255 range and apply to base alpha // Convert percentage to 0-255 range and apply to base alpha
$alpha = (int)(($shadow->opacity / 100) * 255); $alpha = (int) (($shadow->opacity / 100) * 255);
} }
// Get shadow color (default to black if not specified) // Get shadow color (default to black if not specified)
@ -1008,13 +1009,13 @@ abstract class Component
// Create shadow texture with blur // Create shadow texture with blur
$shadowTexture = $this->createShadowTexture( $shadowTexture = $this->createShadowTexture(
$renderer, $renderer,
(int)$this->viewport->width, (int) $this->viewport->width,
(int)$this->viewport->height, (int) $this->viewport->height,
$shadowProps['blur'], $shadowProps['blur'],
$alpha, $alpha,
$r, $r,
$g, $g,
$b $b,
); );
if (!$shadowTexture) { if (!$shadowTexture) {

View File

@ -18,5 +18,6 @@ class Viewport
public $addX = 0, public $addX = 0,
public $addY = 0, public $addY = 0,
public MediaQueryEnum $windowMediaQuery = MediaQueryEnum::normal, public MediaQueryEnum $windowMediaQuery = MediaQueryEnum::normal,
public float $uiScale = 1,
) {} ) {}
} }

View File

@ -17,7 +17,7 @@ class Window
private Viewport $viewport; private Viewport $viewport;
private bool $shouldBeReLayouted = true; private bool $shouldBeReLayouted = true;
private float $pixelRatio = 1.0; private float $pixelRatio = 1.0;
private float $uiScale = 1.0; private float $uiScale = 2.0;
private bool $shouldClose = false; private bool $shouldClose = false;
private $onResize = null; private $onResize = null;
private $onFpsChange = null; private $onFpsChange = null;
@ -51,6 +51,7 @@ class Window
$flags = SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE; $flags = SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE;
$this->window = sdl_create_window($title, $width, $height, $flags); $this->window = sdl_create_window($title, $width, $height, $flags);
if (!$this->window) { if (!$this->window) {
throw new \Exception('Failed to create window: ' . sdl_get_error()); throw new \Exception('Failed to create window: ' . sdl_get_error());
} }
@ -58,6 +59,7 @@ class Window
// Get window ID for event routing // Get window ID for event routing
$this->windowId = sdl_get_window_id($this->window); $this->windowId = sdl_get_window_id($this->window);
$this->uiScale = sdl_get_window_display_scale($this->window);
// Enable text input for this window // Enable text input for this window
sdl_start_text_input($this->window); sdl_start_text_input($this->window);
@ -82,8 +84,8 @@ class Window
windowHeight: $this->height, windowHeight: $this->height,
width: $this->width, width: $this->width,
height: $this->height, height: $this->height,
uiScale: $this->uiScale,
); );
$this->updatePixelRatio(); $this->updatePixelRatio();
$this->lastFpsUpdate = microtime(true); $this->lastFpsUpdate = microtime(true);