This commit is contained in:
Thomas Peterson 2025-11-14 16:37:59 +01:00
parent eced006d55
commit cf9ee67f67
6 changed files with 68 additions and 136 deletions

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use PHPNative\Framework\Application;
use PHPNative\Ui\Widget\Container;
use PHPNative\Ui\Widget\Label;
use PHPNative\Ui\Window;
$app = new Application();
$window = new Window('Container Label Debug', 600, 400);
// Root with neutral background
$root = new Container('flex items-center justify-center bg-gray-100');
// Simple box with border and a single label
$box = new Container('bg-white border border-black rounded-lg p-4');
$box->addComponent(new Label('DEBUG: Label im Container', 'text-lg text-black'));
$root->addComponent($box);
$window->setRoot($root);
$app->addWindow($window);
$app->run();

View File

@ -27,7 +27,6 @@ final class KanbanTaskCard extends Container
} }
} }
#[\Override]
public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool
{ {
if ($button !== 1) { if ($button !== 1) {
@ -42,22 +41,18 @@ final class KanbanTaskCard extends Container
final class KanbanBoardView extends Container final class KanbanBoardView extends Container
{ {
private array $boards; private array $boards;
private Container $columnsContainer;
private array $boardViews = []; private array $boardViews = [];
private ?array $dragState = null; private null|array $dragState = null;
private ?string $hoverBoardId = null; private null|string $hoverBoardId = null;
public function __construct( public function __construct(
private readonly string $storagePath, private readonly string $storagePath,
array $initialBoards, array $initialBoards,
private readonly Label $statusLabel, private readonly Label $statusLabel,
) { ) {
parent::__construct('flex flex-col flex-1 overflow-hidden'); parent::__construct('flex flex-row gap-4 flex-1');
$this->boards = $initialBoards; $this->boards = $initialBoards;
$this->columnsContainer = new Container('flex flex-row gap-4 overflow-auto flex-1 pb-3');
$this->addComponent($this->columnsContainer);
$this->renderBoards(); $this->renderBoards();
} }
@ -115,7 +110,6 @@ final class KanbanBoardView extends Container
$this->statusLabel->setText('Verschiebe: ' . $task['title']); $this->statusLabel->setText('Verschiebe: ' . $task['title']);
} }
#[\Override]
public function handleMouseMove(float $mouseX, float $mouseY): void public function handleMouseMove(float $mouseX, float $mouseY): void
{ {
parent::handleMouseMove($mouseX, $mouseY); parent::handleMouseMove($mouseX, $mouseY);
@ -136,7 +130,6 @@ final class KanbanBoardView extends Container
} }
} }
#[\Override]
public function handleMouseRelease(float $mouseX, float $mouseY, int $button): void public function handleMouseRelease(float $mouseX, float $mouseY, int $button): void
{ {
parent::handleMouseRelease($mouseX, $mouseY, $button); parent::handleMouseRelease($mouseX, $mouseY, $button);
@ -151,55 +144,39 @@ final class KanbanBoardView extends Container
private function renderBoards(): void private function renderBoards(): void
{ {
$this->columnsContainer->clearChildren(); $this->clearChildren();
$this->boardViews = []; $this->boardViews = [];
foreach ($this->boards as $board) { foreach ($this->boards as $board) {
$colorHex = substr(md5($board['id']), 0, 6); $style = 'flex flex-col w-[260] flex-none bg-white border border-black rounded-lg p-3 gap-2';
$defaultStyle = 'flex flex-col w-[260] flex-none border border-gray-400 rounded-lg p-3 gap-3 shadow-sm bg-[#' . $colorHex . ']';
$highlightStyle = 'flex flex-col w-[260] flex-none bg-blue-50 border-2 border-blue-500 rounded-lg p-3 gap-3 shadow';
$debugInfo = new Label(sprintf( $column = new Container($style);
"Board %s\nID: %s\nTasks: %d", $column->addComponent(new Label('Board: ' . $board['title'], 'text-lg font-bold text-black'));
$board['title'],
$board['id'],
count($board['tasks']),
), 'text-xs text-black whitespace-pre-wrap');
$column = new Container($defaultStyle); $taskTitles = array_map(static fn($t) => $t['title'], $board['tasks']);
$header = new Container('flex flex-col gap-1 bg-white/80 rounded p-2 shadow-inner'); $tasksText = empty($taskTitles) ? '(keine Aufgaben)' : implode(', ', $taskTitles);
$header->addComponent(new Label($board['title'], 'text-lg font-semibold text-black')); $column->addComponent(new Label('Tasks: ' . $tasksText, 'text-xs text-black'));
$header->addComponent(new Label(count($board['tasks']) . ' Aufgaben', 'text-xs text-gray-500'));
$header->addComponent($debugInfo);
$column->addComponent($header);
$taskList = new Container('flex flex-col gap-2'); if (!empty($board['tasks'])) {
$taskList = new Container('flex flex-col gap-2 mt-2');
foreach ($board['tasks'] as $task) { foreach ($board['tasks'] as $task) {
$taskList->addComponent(new KanbanTaskCard($board['id'], $task, $this)); $card = new Container('bg-white border-2 border-gray-400 rounded px-2 py-1 shadow-md');
$card->addComponent(new Label($task['title'], 'text-sm text-black'));
$taskList->addComponent($card);
} }
$column->addComponent($taskList); $column->addComponent($taskList);
}
$addInput = new TextInput('Neue Aufgabe', 'flex-1 border border-gray-300 rounded px-2 py-1 bg-white text-black text-sm'); $this->addComponent($column);
$addButton = new Button('Hinzufügen', 'px-2 py-1 bg-emerald-500 text-white rounded hover:bg-emerald-600 text-sm');
$addButton->setOnClick(function () use ($board, $addInput): void {
$this->addTask($board['id'], $addInput->getValue());
$addInput->setValue('');
});
$addRow = new Container('flex flex-row gap-2');
$addRow->addComponent($addInput);
$addRow->addComponent($addButton);
$column->addComponent($addRow);
$this->columnsContainer->addComponent($column);
$this->boardViews[$board['id']] = [ $this->boardViews[$board['id']] = [
'column' => $column, 'column' => $column,
'defaultStyle' => $defaultStyle, 'defaultStyle' => $style,
'highlightStyle' => $highlightStyle, 'highlightStyle' => $style,
]; ];
} }
} }
private function findBoardAt(float $mouseX, float $mouseY): ?string private function findBoardAt(float $mouseX, float $mouseY): null|string
{ {
foreach ($this->boardViews as $boardId => $info) { foreach ($this->boardViews as $boardId => $info) {
$viewport = $info['column']->getViewport(); $viewport = $info['column']->getViewport();
@ -227,7 +204,7 @@ final class KanbanBoardView extends Container
$column->setStyle($style); $column->setStyle($style);
} }
private function completeDrag(?string $targetBoardId): void private function completeDrag(null|string $targetBoardId): void
{ {
$state = $this->dragState; $state = $this->dragState;
$this->dragState = null; $this->dragState = null;
@ -279,7 +256,11 @@ final class KanbanBoardView extends Container
$this->saveBoards(); $this->saveBoards();
$this->renderBoards(); $this->renderBoards();
$this->statusLabel->setText(sprintf('"%s" nach "%s" verschoben.', $movedTask['title'], $this->getBoardTitle($targetBoardId))); $this->statusLabel->setText(sprintf(
'"%s" nach "%s" verschoben.',
$movedTask['title'],
$this->getBoardTitle($targetBoardId),
));
} }
private function getBoardTitle(string $boardId): string private function getBoardTitle(string $boardId): string
@ -339,11 +320,7 @@ if (empty($boards)) {
], ],
], ],
]; ];
file_put_contents( file_put_contents($storagePath, json_encode($boards, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX);
$storagePath,
json_encode($boards, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE),
LOCK_EX,
);
} }
$app = new Application(); $app = new Application();
@ -352,7 +329,10 @@ $window = new Window('Kanban Beispiel', 1200, 800);
$root = new Container('flex flex-col h-full w-full bg-gray-100 gap-4 p-4'); $root = new Container('flex flex-col h-full w-full bg-gray-100 gap-4 p-4');
$title = new Label('Kanban Board', 'text-3xl font-bold text-black'); $title = new Label('Kanban Board', 'text-3xl font-bold text-black');
$subTitle = new Label('Boards hinzufügen, Aufgaben erstellen und per Drag & Drop verschieben.', 'text-base text-gray-700'); $subTitle = new Label(
'Boards hinzufügen, Aufgaben erstellen und per Drag & Drop verschieben.',
'text-base text-gray-700',
);
$root->addComponent($title); $root->addComponent($title);
$root->addComponent($subTitle); $root->addComponent($subTitle);

View File

@ -36,5 +36,10 @@
"note": "" "note": ""
} }
] ]
},
{
"id": "board_69170bcc2be8c6.34720864",
"title": "asd",
"tasks": []
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

View File

@ -1,36 +0,0 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PHPNative\Framework\Application;
use PHPNative\Ui\Widget\Container;
use PHPNative\Ui\Widget\Label;
use PHPNative\Ui\Window;
$app = new Application();
$window = new Window('Scroll Test', 400, 300);
// Main container
$mainContainer = new Container('flex flex-col bg-white');
// Create a scrollable container with fixed height
$scrollContainer = new Container('flex flex-col w-full h-48 overflow-auto bg-gray-100 border-2 border-red-500');
// Add many labels to force scrolling
for ($i = 1; $i <= 30; $i++) {
$label = new Label("Item $i", 'px-4 py-2 border-b border-gray-300 text-black bg-white');
$scrollContainer->addComponent($label);
}
$mainContainer->addComponent(new Label('Scroll Test (red box should be scrollable)', 'text-xl font-bold p-4 text-black'));
$mainContainer->addComponent($scrollContainer);
$mainContainer->addComponent(new Label('Try scrolling with mouse wheel over the red box', 'p-4 text-black'));
$window->setRoot($mainContainer);
$app->addWindow($window);
echo "Scroll Test started!\n";
echo "- Red box should show scrollbar\n";
echo "- Try scrolling with mouse wheel\n\n";
$app->run();

View File

@ -1,44 +0,0 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PHPNative\Framework\Application;
use PHPNative\Ui\Widget\Container;
use PHPNative\Ui\Widget\Table;
use PHPNative\Ui\Window;
$app = new Application();
$window = new Window('Table Scroll Test', 800, 600);
// Simple container with limited height
$mainContainer = new Container('flex flex-col bg-gray-100 p-4');
// Table with max height
$table = new Table('h-96'); // 384px max height
$table->setColumns([
['key' => 'id', 'title' => 'ID', 'width' => 100],
['key' => 'name', 'title' => 'Name', 'width' => 400],
['key' => 'status', 'title' => 'Status', 'width' => 120],
]);
// Test data with 63 entries (same as your example)
$testData = [];
for ($i = 1; $i <= 63; $i++) {
$testData[] = [
'id' => $i,
'name' => "Server-{$i}",
'status' => ($i % 3 === 0) ? 'stopped' : 'running',
];
}
$table->setData($testData);
$mainContainer->addComponent($table);
$window->setRoot($mainContainer);
$app->addWindow($window);
echo "Table Scroll Test started!\n";
echo "- Table should show scrollbar\n";
echo "- Try scrolling with mouse wheel over the table\n\n";
$app->run();