sdl3/src/Ui/Widget/Label.php
2025-11-11 11:39:33 +01:00

138 lines
4.8 KiB
PHP

<?php
namespace PHPNative\Ui\Widget;
use PHPNative\Framework\TextRenderer;
use PHPNative\Tailwind\Style\Padding;
use PHPNative\Tailwind\Style\Text;
use PHPNative\Ui\Component;
class Label extends Component
{
private int $intrinsicWidth = 0;
private int $intrinsicHeight = 0;
private mixed $textTexture = null;
private int $textWidth = 0;
private int $textHeight = 0;
public function __construct(
public string $text = '',
public string $style = '',
) {
parent::__construct($style);
}
public function setText(string $text): void
{
if ($this->text === $text) {
return;
}
$this->text = $text;
$this->clearTextTexture();
// $this->markDirty(true);
}
public function layout(null|TextRenderer $textRenderer = null): void
{
// Call parent to compute styles and setup viewports
parent::layout($textRenderer);
// Measure text to get intrinsic size
if ($textRenderer !== null && $textRenderer->isInitialized()) {
$textStyle = $this->computedStyles[Text::class] ?? new Text();
[$this->intrinsicWidth, $this->intrinsicHeight] = $textRenderer->measureText($this->text, $textStyle->size);
// Adjust viewport to fit text if no explicit size
if (!isset($this->computedStyles[\PHPNative\Tailwind\Style\Width::class])) {
$this->viewport->width = $this->intrinsicWidth;
$this->contentViewport->width = $this->intrinsicWidth;
if (isset($this->computedStyles[Padding::class]) && ($pd = $this->computedStyles[Padding::class])) {
$this->viewport->width = $this->intrinsicWidth + $pd->left + $pd->right;
$this->contentViewport->width = $this->intrinsicWidth + $pd->left + $pd->right;
}
}
if (!isset($this->computedStyles[\PHPNative\Tailwind\Style\Height::class])) {
$this->viewport->height = $this->intrinsicHeight;
$this->contentViewport->height = $this->intrinsicHeight;
if (isset($this->computedStyles[Padding::class]) && ($pd = $this->computedStyles[Padding::class])) {
$this->viewport->height = $this->intrinsicHeight + $pd->top + $pd->bottom;
$this->contentViewport->height = $this->intrinsicHeight + $pd->top + $pd->bottom;
}
}
}
}
public function renderContent(&$window, null|TextRenderer $textRenderer = null): void
{
if (!$this->visible || $textRenderer === null || !$textRenderer->isInitialized()) {
return;
}
// Get text style from computed styles
$textStyle = $this->computedStyles[Text::class] ?? new Text();
// Set text color
$color = $textStyle->color;
$red = $color->red >= 0 ? $color->red : 0;
$green = $color->green >= 0 ? $color->green : 0;
$blue = $color->blue >= 0 ? $color->blue : 0;
$alpha = max(0, min(255, $color->alpha));
$textRenderer->setColor($red / 255, $green / 255, $blue / 255, $alpha / 255);
if ($this->renderDirty || $this->textTexture === null) {
$this->clearTextTexture();
$textureData = $textRenderer->createTextTexture($this->text);
if ($textureData !== null) {
$this->textTexture = $textureData['texture'];
$this->textWidth = $textureData['width'];
$this->textHeight = $textureData['height'];
if (\function_exists('sdl_set_texture_alpha_mod')) {
sdl_set_texture_alpha_mod($this->textTexture, $alpha);
}
}
}
if ($this->textTexture !== null) {
sdl_render_texture($window, $this->textTexture, [
'x' => (int) $this->contentViewport->x,
'y' => (int) $this->contentViewport->y,
'w' => $this->textWidth,
'h' => $this->textHeight,
]);
} else {
// Fallback: render text directly if texture creation failed
$textRenderer->drawText(
$this->text,
(int) $this->contentViewport->x,
(int) $this->contentViewport->y,
$textStyle->size,
);
}
$this->renderDirty = false;
// Call parent to render children if any
parent::renderContent($window, $textRenderer);
}
public function __destruct()
{
$this->clearTextTexture();
parent::__destruct();
}
private function clearTextTexture(): void
{
if ($this->textTexture !== null) {
sdl_destroy_texture($this->textTexture);
$this->textTexture = null;
$this->textWidth = 0;
$this->textHeight = 0;
}
}
}