Backup
This commit is contained in:
parent
7d4139234f
commit
401287a2a1
BIN
assets/symbol.ttf
Normal file
BIN
assets/symbol.ttf
Normal file
Binary file not shown.
@ -11,7 +11,9 @@
|
||||
"require": {
|
||||
"ext-parallel": "*",
|
||||
"ext-sdl": "*",
|
||||
"php": "^8.3"
|
||||
"php": "^8.3",
|
||||
"symfony/serializer": "^7",
|
||||
"zumba/json-serializer": "^3"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.21",
|
||||
@ -28,6 +30,7 @@
|
||||
"phpnative/event": "self.version",
|
||||
"phpnative/framework": "self.version",
|
||||
"phpnative/renderer": "self.version",
|
||||
"phpnative/storage": "self.version",
|
||||
"phpnative/support": "self.version",
|
||||
"phpnative/tailwind": "self.version",
|
||||
"phpnative/ui": "self.version"
|
||||
@ -39,6 +42,7 @@
|
||||
"PHPNative\\Event\\": "src/PHPNative/Event/src",
|
||||
"PHPNative\\Framework\\": "src/PHPNative/Framework/src",
|
||||
"PHPNative\\Renderer\\": "src/PHPNative/Renderer/src",
|
||||
"PHPNative\\Storage\\": "src/PHPNative/Storage/src",
|
||||
"PHPNative\\Support\\": "src/PHPNative/Support/src",
|
||||
"PHPNative\\Tailwind\\": "src/PHPNative/Tailwind/src",
|
||||
"PHPNative\\UI\\": "src/PHPNative/UI/src"
|
||||
@ -51,6 +55,7 @@
|
||||
"PHPNative\\Event\\Tests\\": "src/PHPNative/Event/tests",
|
||||
"PHPNative\\Framework\\Tests\\": "src/PHPNative/Framework/tests",
|
||||
"PHPNative\\Renderer\\Tests\\": "src/PHPNative/Renderer/tests",
|
||||
"PHPNative\\Storage\\Tests\\": "src/PHPNative/Storage/tests",
|
||||
"PHPNative\\Support\\Tests\\": "src/PHPNative/Support/tests",
|
||||
"PHPNative\\Tailwind\\Tests\\": "src/PHPNative/Tailwind/tests",
|
||||
"PHPNative\\UI\\Tests\\": "src/PHPNative/UI/tests"
|
||||
|
||||
@ -120,4 +120,9 @@ abstract class Collection implements IteratorAggregate
|
||||
$this->elements = $temp->items();
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
$this->elements = [];
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,11 +12,17 @@ class Driver
|
||||
public function pollEvent(): Event
|
||||
{
|
||||
\SDL_PollEvent($this->event);
|
||||
if($this->event->type == \SDL_EVENT_KEY_UP) {
|
||||
var_dump($this->event->key->key);
|
||||
}
|
||||
return match($this->event->type) {
|
||||
\SDL_EVENT_QUIT => new \PHPNative\Event\SystemEvent(EventType::QUIT),
|
||||
\SDL_EVENT_MOUSE_BUTTON_DOWN => new MouseDown(EventType::MOUSEBUTTON_DOWN, $this->event->button->x, $this->event->button->y ),
|
||||
\SDL_EVENT_MOUSE_BUTTON_UP => new MouseUp(EventType::MOUSEBUTTON_UP, $this->event->button->x, $this->event->button->y ),
|
||||
\SDL_EVENT_MOUSE_MOTION => new MouseMove(EventType::MOUSEMOVE, $this->event->motion->x, $this->event->motion->y ),
|
||||
\SDL_EVENT_WINDOW_CLOSE_REQUESTED => new \PHPNative\Event\SystemEvent(EventType::WINDOW_CLOSE, $this->event->window->windowID),
|
||||
\SDL_EVENT_KEY_UP => new \PHPNative\Event\KeyUp(EventType::KEYUP, $this->event->window->windowID, Key::tryFrom($this->event->key->key)),
|
||||
\SDL_EVENT_TEXT_INPUT => new \PHPNative\Event\TextInput(EventType::TEXTINPUT, $this->event->window->windowID, mb_convert_encoding($this->event->text->text, 'ISO-8859-1', 'UTF-8')),
|
||||
\SDL_EVENT_MOUSE_BUTTON_DOWN => new MouseDown(EventType::MOUSEBUTTON_DOWN, $this->event->window->windowID, $this->event->button->x, $this->event->button->y ),
|
||||
\SDL_EVENT_MOUSE_BUTTON_UP => new MouseUp(EventType::MOUSEBUTTON_UP, $this->event->window->windowID, $this->event->button->x, $this->event->button->y ),
|
||||
\SDL_EVENT_MOUSE_MOTION => new MouseMove(EventType::MOUSEMOVE, $this->event->window->windowID, $this->event->motion->x, $this->event->motion->y ),
|
||||
default => new \PHPNative\Event\SystemEvent(EventType::NOOP)
|
||||
};
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ enum EventType: int
|
||||
{
|
||||
case NOOP = 0;
|
||||
case QUIT = 1;
|
||||
case CLOSE_WINDOW = 2;
|
||||
case WINDOW_FOCUS_LOST = 1000;
|
||||
case WINDOW_FOCUS_GAINED = 1001;
|
||||
case WINDOW_RESIZED = 1002;
|
||||
|
||||
15
src/PHPNative/Event/src/Key.php
Normal file
15
src/PHPNative/Event/src/Key.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Event;
|
||||
|
||||
enum Key: int
|
||||
{
|
||||
|
||||
case BACKSPACE = 8;
|
||||
|
||||
case SDLK_RIGHT = 1073741903;
|
||||
case SDLK_LEFT = 1073741904;
|
||||
case SDLK_UP = 1073741906;
|
||||
case SDLK_DOWN = 1073741905;
|
||||
|
||||
}
|
||||
17
src/PHPNative/Event/src/KeyUp.php
Normal file
17
src/PHPNative/Event/src/KeyUp.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PHPNative\Event;
|
||||
|
||||
class KeyUp implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::MOUSEBUTTON_UP, public int $windowId = 0, public ?Key $key = null)
|
||||
{
|
||||
}
|
||||
|
||||
public function getType(): EventType
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@ namespace PHPNative\Event;
|
||||
|
||||
class MouseDown implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::MOUSEBUTTON_DOWN, public int $x = 0, public int $y = 0)
|
||||
public function __construct(public EventType $type = EventType::MOUSEBUTTON_DOWN, public int $windowId = 0, public int $x = 0, public int $y = 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ namespace PHPNative\Event;
|
||||
|
||||
class MouseMove implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::MOUSEMOVE, public int $x = 0, public int $y = 0)
|
||||
public function __construct(public EventType $type = EventType::MOUSEMOVE, public int $windowId = 0, public int $x = 0, public int $y = 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ namespace PHPNative\Event;
|
||||
|
||||
class MouseUp implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::MOUSEBUTTON_UP, public int $x = 0, public int $y = 0)
|
||||
public function __construct(public EventType $type = EventType::MOUSEBUTTON_UP, public int $windowId = 0, public int $x = 0, public int $y = 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ namespace PHPNative\Event;
|
||||
|
||||
class SystemEvent implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::NOOP)
|
||||
public function __construct(public EventType $type = EventType::NOOP, public int $windowId = 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
17
src/PHPNative/Event/src/TextInput.php
Normal file
17
src/PHPNative/Event/src/TextInput.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PHPNative\Event;
|
||||
|
||||
class TextInput implements Event
|
||||
{
|
||||
public function __construct(public EventType $type = EventType::TEXTINPUT, public int $windowId = 0, public string $text = "")
|
||||
{
|
||||
}
|
||||
|
||||
public function getType(): EventType
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,6 @@ namespace PHPNative\Framework\Application;
|
||||
interface Application
|
||||
{
|
||||
|
||||
public function run(string|null $start): void;
|
||||
public function run(): void;
|
||||
|
||||
}
|
||||
7
src/PHPNative/Framework/src/Application/Config.php
Normal file
7
src/PHPNative/Framework/src/Application/Config.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace PHPNative\Framework\Application;
|
||||
|
||||
class Config
|
||||
{
|
||||
}
|
||||
@ -18,25 +18,29 @@ final readonly class Gui implements Application
|
||||
}
|
||||
|
||||
public static function boot(
|
||||
string $name = 'PHPNative',
|
||||
?string $app = null,
|
||||
?string $root = null,
|
||||
array $discoveryLocations = [],
|
||||
): self {
|
||||
$container = PHPNative::boot($root);
|
||||
|
||||
$container = PHPNative::boot($root);
|
||||
$container->register(App::class, function () use ($app, $container) {
|
||||
return $container->get($app);
|
||||
});
|
||||
$application = $container->get(Gui::class);
|
||||
|
||||
return $application;
|
||||
}
|
||||
|
||||
|
||||
public function run(string|null $start): void
|
||||
public function run(): void
|
||||
{
|
||||
try {
|
||||
$application = $this->container->get(App::class);
|
||||
$lifeCycle = $this->container->get(Lifecycle::class);
|
||||
|
||||
try {
|
||||
$lifeCycle->show($this->container->get($start));
|
||||
$lifeCycle->show($this->container->get($application->getStartWindow()));
|
||||
$lifeCycle->run();
|
||||
} catch (ArgumentCountError $e) {
|
||||
var_dump($e->getMessage());
|
||||
|
||||
@ -6,9 +6,9 @@ namespace PHPNative\Framework\Application;
|
||||
|
||||
use PHPNative\Container\Container;
|
||||
use PHPNative\Container\GenericContainer;
|
||||
use PHPNative\Framework\Discovery\DiscoveryLocationBootstrap;
|
||||
use PHPNative\Framework\Discovery\LoadDiscoveryClasses;
|
||||
use PHPNative\Framework\Discovery\LoadDiscoveryLocations;
|
||||
use Zumba\JsonSerializer\JsonSerializer;
|
||||
|
||||
final class Kernel
|
||||
{
|
||||
@ -34,6 +34,9 @@ final class Kernel
|
||||
private function registerKernel(): self
|
||||
{
|
||||
$this->container->singleton(self::class, $this);
|
||||
$this->container->register(JsonSerializer::class, function () {
|
||||
return new JsonSerializer();
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace PHPNative\Framework\Lifecycle;
|
||||
|
||||
use Closure;
|
||||
use PHPNative\Event\Event;
|
||||
use PHPNative\Framework\Application\Window;
|
||||
use PHPNative\Renderer\Thread;
|
||||
@ -9,7 +10,7 @@ use PHPNative\Renderer\Thread;
|
||||
class Context
|
||||
{
|
||||
|
||||
public function __construct(private Thread $thread)
|
||||
public function __construct(public Thread $thread, public ?Closure $onClose = null)
|
||||
{
|
||||
|
||||
}
|
||||
@ -26,7 +27,9 @@ class Context
|
||||
|
||||
public function event(Event $event): void
|
||||
{
|
||||
$this->thread->addEvent($event);
|
||||
if($event->windowId == $this->thread->windowId) {
|
||||
$this->thread->addEvent($event);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(float $delta): void
|
||||
@ -36,7 +39,10 @@ class Context
|
||||
|
||||
public function unload(): void
|
||||
{
|
||||
//TODO: unload
|
||||
if($this->onClose) {
|
||||
($this->onClose)();
|
||||
}
|
||||
$this->thread->close();
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,4 +12,15 @@ class ContextCollection extends TypedCollection
|
||||
{
|
||||
return Context::class;
|
||||
}
|
||||
|
||||
public function removeWindowFrom(string $windowId): void
|
||||
{
|
||||
$temp = $this->filter(function ($value, $key) use($windowId){
|
||||
if($value->thread->windowId == $windowId) {
|
||||
$value->unload();
|
||||
}
|
||||
return $value->thread->windowId != $windowId;
|
||||
});
|
||||
$this->setElements($temp->items());
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
namespace PHPNative\Framework\Lifecycle;
|
||||
|
||||
use PHPNative\Container\Container;
|
||||
use PHPNative\Container\Singleton;
|
||||
use PHPNative\Event\Event;
|
||||
use PHPNative\Event\EventType;
|
||||
use PHPNative\Framework\Application\Window;
|
||||
@ -10,6 +11,7 @@ use PHPNative\Framework\Loop\OrderedEventLoop;
|
||||
use PHPNative\Framework\Loop\WorkerInterface;
|
||||
use PHPNative\Renderer\Thread;
|
||||
|
||||
#[Singleton]
|
||||
class Lifecycle implements WorkerInterface
|
||||
{
|
||||
public function __construct(
|
||||
@ -20,14 +22,15 @@ class Lifecycle implements WorkerInterface
|
||||
$this->loop->use($this);
|
||||
}
|
||||
|
||||
public function show(Window $window, array $arguments = []): void
|
||||
public function show(Window $window, array $arguments = [], ?callable $onClose = null): void
|
||||
{
|
||||
|
||||
$context = $this->container->get(
|
||||
Context::class,
|
||||
thread: $this->container->get(Thread::class)
|
||||
null
|
||||
);
|
||||
|
||||
$context->onClose = $onClose;
|
||||
$context->show($window);
|
||||
|
||||
$this->contextCollection->add($context);
|
||||
@ -45,7 +48,9 @@ class Lifecycle implements WorkerInterface
|
||||
|
||||
public function onRender(float $delta): void
|
||||
{
|
||||
$this->contextCollection->map(fn(Context $context) => $context->render($delta));
|
||||
$this->contextCollection->map(
|
||||
fn(Context $context) => $context->render($delta)
|
||||
);
|
||||
}
|
||||
|
||||
public function onEvent( $event): void
|
||||
@ -60,6 +65,9 @@ class Lifecycle implements WorkerInterface
|
||||
case EventType::WINDOW_FOCUS_LOST:
|
||||
$this->loop->pause();
|
||||
break;
|
||||
case EventType::WINDOW_CLOSE:
|
||||
$this->closeWindow($event->windowId);
|
||||
break;
|
||||
case EventType::WINDOW_FOCUS_GAINED:
|
||||
$this->loop->resume();
|
||||
break;
|
||||
@ -67,6 +75,7 @@ class Lifecycle implements WorkerInterface
|
||||
$this->contextCollection->map(fn(Context $context) => $context->unload());
|
||||
$this->contextCollection = new ContextCollection();
|
||||
$this->loop->stop();
|
||||
\SDL_Quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -84,4 +93,13 @@ class Lifecycle implements WorkerInterface
|
||||
$this->context->resume();
|
||||
}
|
||||
}
|
||||
|
||||
private function closeWindow($windowId)
|
||||
{
|
||||
if($this->contextCollection->count() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->contextCollection->removeWindowFrom($windowId);
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,8 @@ final class PHPNative
|
||||
): Container {
|
||||
$root ??= getcwd();
|
||||
|
||||
\SDL_Init(\SDL_INIT_VIDEO);
|
||||
\SDL_TTF_Init();
|
||||
// Kernel
|
||||
return (new Kernel(
|
||||
root: $root,
|
||||
|
||||
8
src/PHPNative/Renderer/src/Cache/Image.php
Normal file
8
src/PHPNative/Renderer/src/Cache/Image.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Renderer\Cache;
|
||||
|
||||
class Image
|
||||
{
|
||||
|
||||
}
|
||||
@ -13,10 +13,13 @@ use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class Thread
|
||||
{
|
||||
private ?\SDL_Window $windowId = null;
|
||||
public ?\SDL_Window $windowPtr = null;
|
||||
public ?int $windowId = null;
|
||||
private $rendererPtr = null;
|
||||
|
||||
private Window $window;
|
||||
private bool $shouldRenderd = true;
|
||||
|
||||
public Window $window;
|
||||
|
||||
private StackCollection $renderStack;
|
||||
|
||||
@ -32,28 +35,32 @@ class Thread
|
||||
{
|
||||
$this->window = $window;
|
||||
|
||||
\SDL_Init(\SDL_INIT_VIDEO);
|
||||
\SDL_TTF_Init();
|
||||
$this->windowId = \SDL_CreateWindow($this->window->getTitle(), 800, 600, \SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
$this->rendererPtr = \SDL_CreateRenderer($this->windowId);
|
||||
$this->windowPtr = \SDL_CreateWindow($this->window->getTitle(), 1000, 600, \SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
$this->rendererPtr = \SDL_CreateRenderer($this->windowPtr);
|
||||
$this->windowId = \SDL_GetWindowID($this->windowPtr);
|
||||
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$this->shouldRenderd = false;
|
||||
\SDL_DestroyRenderer($this->rendererPtr);
|
||||
\SDL_DestroyWindow($this->windowId);
|
||||
\SDL_Quit();
|
||||
\SDL_DestroyWindow($this->windowPtr);
|
||||
|
||||
}
|
||||
|
||||
public function render(): void
|
||||
{
|
||||
if(!$this->shouldRenderd) {
|
||||
return;
|
||||
}
|
||||
$windowWidth = 0;
|
||||
$windowHeight = 0;
|
||||
\SDL_GetWindowSize($this->windowId, $windowWidth, $windowHeight);
|
||||
\SDL_GetWindowSize($this->windowPtr, $windowWidth, $windowHeight);
|
||||
|
||||
$viewPort = new Viewport(
|
||||
windowId: $this->windowId,
|
||||
windowPtr: $this->windowPtr,
|
||||
renderPtr: $this->rendererPtr,
|
||||
x:0, y: 0,
|
||||
width: $windowWidth, height: $windowHeight, windowWidth: $windowWidth, windowHeight: $windowHeight,
|
||||
@ -74,6 +81,7 @@ class Thread
|
||||
if($item->clipAt) {
|
||||
$item->renderAt->w = $item->clipAt->w;
|
||||
}
|
||||
|
||||
\SDL_RenderTexture($this->rendererPtr, $item->texture, $item->clipAt?? null , $item->renderAt);
|
||||
});
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ class Viewport
|
||||
{
|
||||
|
||||
public function __construct(public $windowId,
|
||||
public $windowPtr,
|
||||
public $renderPtr,
|
||||
public int $x = 0,
|
||||
public int $y = 0,
|
||||
@ -16,6 +17,8 @@ class Viewport
|
||||
public $height = 0,
|
||||
public $windowWidth = 0,
|
||||
public $windowHeight = 0,
|
||||
public $addX = 0,
|
||||
public $addY = 0,
|
||||
public MediaQueryEnum $windowMediaQuery = MediaQueryEnum::normal)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2,26 +2,37 @@
|
||||
|
||||
namespace PHPNative\Renderer\Visuals;
|
||||
|
||||
use PHPNative\Renderer\GFX;
|
||||
use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
|
||||
class Background
|
||||
{
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport, int $index = 0): void
|
||||
{
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Background::class]) && $bg = $styles[\PHPNative\Tailwind\Style\Background::class]) {
|
||||
|
||||
$texture = \SDL_CreateTexture($targetViewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $targetViewport->width, $targetViewport->height);
|
||||
\SDL_SetRenderTarget($targetViewport->renderPtr, $texture);
|
||||
\SDL_SetRenderDrawColor($targetViewport->renderPtr, 255, 255, 255, 255);
|
||||
\SDL_SetRenderDrawColor($targetViewport->renderPtr, 0, 0, 0, 0);
|
||||
\SDL_RenderClear($targetViewport->renderPtr);
|
||||
|
||||
$rect = new \SDL_FRect(0, 0, $targetViewport->width, $targetViewport->height);
|
||||
\SDL_SetRenderDrawColor($targetViewport->renderPtr, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||
\SDL_RenderFillRect($targetViewport->renderPtr, $rect);
|
||||
|
||||
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, $targetViewport->width, $targetViewport->height), 2));
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Border::class]) && $border = $styles[\PHPNative\Tailwind\Style\Border::class]) {
|
||||
if($border->roundTop > 0) {
|
||||
GFX::roundedBoxRGBA($targetViewport->renderPtr, 0, 0,
|
||||
$targetViewport->width, $targetViewport->height, $border->roundTop, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||
}else{
|
||||
GFX::boxRGBA($targetViewport->renderPtr, 0, 0,
|
||||
$targetViewport->width, $targetViewport->height, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||
}
|
||||
}else{
|
||||
GFX::boxRGBA($targetViewport->renderPtr, 0, 0,
|
||||
$targetViewport->width, $targetViewport->height, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||
}
|
||||
|
||||
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, $targetViewport->width, $targetViewport->height), $index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ use PHPNative\Renderer\Viewport;
|
||||
|
||||
class Border
|
||||
{
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport, int $index): void
|
||||
{
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Border::class]) && $b = $styles[\PHPNative\Tailwind\Style\Border::class]) {
|
||||
$texture = \SDL_CreateTexture($targetViewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $targetViewport->width, $targetViewport->height);
|
||||
@ -38,7 +38,7 @@ class Border
|
||||
GFX::boxRGBA($targetViewport->renderPtr, $targetViewport->width - $b->right, 0,
|
||||
$targetViewport->width, $targetViewport->height, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
|
||||
}
|
||||
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, $targetViewport->width, $targetViewport->height), 10));
|
||||
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, $targetViewport->width, $targetViewport->height), $index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
23
src/PHPNative/Renderer/src/Visuals/Cursor.php
Normal file
23
src/PHPNative/Renderer/src/Visuals/Cursor.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Renderer\Visuals;
|
||||
|
||||
use PHPNative\Renderer\GFX;
|
||||
use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
|
||||
class Cursor
|
||||
{
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport, int $index = 0): void
|
||||
{
|
||||
$texture = \SDL_CreateTexture($targetViewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, 4, $targetViewport->height);
|
||||
\SDL_SetRenderTarget($targetViewport->renderPtr, $texture);
|
||||
\SDL_SetRenderDrawColor($targetViewport->renderPtr, 0, 0, 0, 255);
|
||||
\SDL_RenderClear($targetViewport->renderPtr);
|
||||
|
||||
GFX::boxRGBA($targetViewport->renderPtr, 0, 0, 4, $targetViewport->height, 128,128,128,255);
|
||||
|
||||
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, 4, $targetViewport->height), $index));
|
||||
}
|
||||
}
|
||||
@ -7,10 +7,10 @@ use PHPNative\Renderer\Viewport;
|
||||
|
||||
class Visuals
|
||||
{
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
|
||||
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport, int $index = 0): void
|
||||
{
|
||||
Background::render($widgetId, $thread, $styles, $targetViewport);
|
||||
Border::render($widgetId, $thread, $styles, $targetViewport);
|
||||
Background::render($widgetId, $thread, $styles, $targetViewport, $index);
|
||||
Border::render($widgetId, $thread, $styles, $targetViewport, $index);
|
||||
}
|
||||
|
||||
public static function changeViewport(string $widgetId, Thread $thread, array $styles, Viewport $viewport): void
|
||||
|
||||
@ -2,29 +2,40 @@
|
||||
|
||||
namespace PHPNative\Renderer;
|
||||
|
||||
use PHPNative\UI\Widget\Icon;
|
||||
use PHPNative\UI\Widget\Image;
|
||||
use PHPNative\UI\Widget\TextEdit;
|
||||
use PHPNative\UI\BaseView;
|
||||
use PHPNative\UI\View;
|
||||
use PHPNative\UI\Widget\Button;
|
||||
use PHPNative\UI\Widget\Container;
|
||||
use PHPNative\UI\Widget\Label;
|
||||
use PHPNative\UI\Widget\Text;
|
||||
|
||||
class Widget
|
||||
{
|
||||
public static function render(Thread $thread, ViewPort $viewPort, View $view): Viewport {
|
||||
public static function render(Thread $thread, ViewPort $viewPort, View $view, int $index = 1): Viewport {
|
||||
|
||||
if($view instanceof BaseView) {
|
||||
return \PHPNative\Renderer\Widgets\BaseView::render($thread, $viewPort, $view);
|
||||
return \PHPNative\Renderer\Widgets\BaseView::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof Button) {
|
||||
return \PHPNative\Renderer\Widgets\Button::render($thread, $viewPort, $view);
|
||||
return \PHPNative\Renderer\Widgets\Container::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof Label) {
|
||||
return \PHPNative\Renderer\Widgets\Label::render($thread, $viewPort, $view);
|
||||
if($view instanceof Text) {
|
||||
return \PHPNative\Renderer\Widgets\Text::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof TextEdit) {
|
||||
return \PHPNative\Renderer\Widgets\TextEdit::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof Container) {
|
||||
return \PHPNative\Renderer\Widgets\Container::render($thread, $viewPort, $view);
|
||||
return \PHPNative\Renderer\Widgets\Container::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof Image) {
|
||||
return \PHPNative\Renderer\Widgets\Image::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
if($view instanceof Icon) {
|
||||
return \PHPNative\Renderer\Widgets\Icon::render($thread, $viewPort, $view, $index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,43 +13,7 @@ use PHPNative\Tailwind\Style\Padding;
|
||||
use PHPNative\Tailwind\Style\StateEnum;
|
||||
use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class BaseView
|
||||
class BaseView extends Container
|
||||
{
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\BaseView $view): Viewport
|
||||
{
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, StateEnum::normal);
|
||||
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height -= ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
|
||||
$texture = \SDL_CreateTexture($viewport->renderPtr, \SDL_PIXELFORMAT_ARGB8888, \SDL_TEXTUREACCESS_TARGET, 200, 100);
|
||||
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
|
||||
\SDL_SetRenderDrawColor($viewport->renderPtr, 0, 0, 0, 255);
|
||||
\SDL_RenderClear($viewport->renderPtr);
|
||||
$rect = new \SDL_FRect($viewport->x, $viewport->y, $viewport->width, $viewport->height);
|
||||
|
||||
\SDL_SetRenderDrawColor($viewport->renderPtr, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||
\SDL_RenderFillRect($viewport->renderPtr, $rect);
|
||||
|
||||
$thread->addToRenderStack(new Item($view->getId(), $texture, $rect, 0));
|
||||
}
|
||||
|
||||
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height -= ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
if($view->getViews()->count() > 0) {
|
||||
Widget::render($thread, $viewport, $view->getViews()->first());
|
||||
}
|
||||
|
||||
return $viewport;
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
use PHPNative\Renderer\Widget;
|
||||
use PHPNative\Tailwind\Style\AlignEnum;
|
||||
use PHPNative\Tailwind\Style\Background;
|
||||
use PHPNative\Tailwind\Style\Basis;
|
||||
use PHPNative\Tailwind\Style\Border;
|
||||
@ -23,15 +24,20 @@ use PHPNative\Tailwind\StyleParser;
|
||||
class Button
|
||||
{
|
||||
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Button $view): Viewport
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Button $view, int $index = 0): Viewport
|
||||
{
|
||||
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 20);
|
||||
if(isset($styles[Text::class]) && $t = $styles[Text::class]) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , $t->size);
|
||||
if($t->color->red != -1) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
}else{
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
}else{
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 16);
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
$surface = \SDL_TTF_RenderText_Blended($font, $view->label, $color);
|
||||
@ -76,7 +82,7 @@ class Button
|
||||
$backdropViewport->height += ($m->top + $m->bottom);
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport);
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport, $index);
|
||||
|
||||
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
|
||||
|
||||
@ -87,10 +93,15 @@ class Button
|
||||
new \SDL_FRect(0, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3));
|
||||
if(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::center) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + (($viewport->width - $surface->w) /2), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}elseif(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::right) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + ($viewport->width - $surface->w), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
}
|
||||
|
||||
@ -22,9 +22,9 @@ use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class Container
|
||||
{
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Container $view): Viewport
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Container $view, int $index = 0): Viewport
|
||||
{
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, StateEnum::normal);
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->x += $m->left;
|
||||
@ -46,6 +46,7 @@ class Container
|
||||
|
||||
$flexStyles = [];
|
||||
if($view->getViews() != null) {
|
||||
|
||||
foreach ($view->getViews() as $subView) {
|
||||
$found = false;
|
||||
$stylesSubView = StyleParser::parse($subView->style)->getValidStyles($viewport->windowMediaQuery, StateEnum::normal);
|
||||
@ -68,13 +69,13 @@ class Container
|
||||
|
||||
if ($found) {
|
||||
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
|
||||
$viepo = new Viewport($viewport->windowId, $viewport->renderPtr, $viewport->x, $viewport->y, $width, $viewport->height, $viewport->windowWidth, $viewport->windowHeight, $viewport->windowMediaQuery);
|
||||
$viepo = new Viewport($viewport->windowId, $viewport->windowPtr, $viewport->renderPtr, $viewport->x, $viewport->y, $width, $viewport->height, $viewport->windowWidth, $viewport->windowHeight, $viewport->windowMediaQuery);
|
||||
} else {
|
||||
$viepo = new Viewport($viewport->windowId, $viewport->renderPtr, $viewport->x + (count($flexStyles) === 0 ? 0 : end($flexStyles)->x+end($flexStyles)->width), $viewport->y, $width, $viewport->height, $viewport->windowWidth, $viewport->windowHeight, $viewport->windowMediaQuery);
|
||||
$viepo = new Viewport($viewport->windowId, $viewport->windowPtr, $viewport->renderPtr, $viewport->x + (count($flexStyles) === 0 ? 0 : end($flexStyles)->x+end($flexStyles)->width), $viewport->y, $width, $viewport->height, $viewport->windowWidth, $viewport->windowHeight, $viewport->windowMediaQuery);
|
||||
}
|
||||
$flexStyles[] = $viepo;
|
||||
} else {
|
||||
$flexStyles[] = $viewport;
|
||||
$flexStyles[] = clone $viewport;
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +84,7 @@ class Container
|
||||
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
|
||||
$subViewPort = array_shift($flexStyles);
|
||||
$subViewPort->y = $viewport->y - $view->getMoveToY();
|
||||
$vp = Widget::render($thread, $subViewPort, $subView);
|
||||
$vp = Widget::render($thread, $subViewPort, $subView, $index+1);
|
||||
if($vp->y < $targetViewport->y) {
|
||||
$thread->clipFromStack($subView->getId(), y: $targetViewport->y-$vp->y);
|
||||
}
|
||||
@ -93,9 +94,19 @@ class Container
|
||||
|
||||
$viewport->y += $vp->height;
|
||||
$viewport->height -= $vp->height;
|
||||
} else {
|
||||
$vp = Widget::render($thread, array_shift($flexStyles), $subView);
|
||||
} elseif(isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::row) {
|
||||
$vp = Widget::render($thread, array_shift($flexStyles), $subView, $index+1);
|
||||
$topHeight = max($topHeight, $vp->height);
|
||||
} else{
|
||||
$sfs = array_shift($flexStyles);
|
||||
$vp = Widget::render($thread, $sfs, $subView, $index+1);
|
||||
$topHeight = max($topHeight, $vp->height);
|
||||
if(count($flexStyles) > 0) {
|
||||
if($vp->addX > 0) {
|
||||
$flexStyles[0]->x += $vp->addX;
|
||||
$flexStyles[0]->width -= $vp->addX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
|
||||
@ -104,16 +115,43 @@ class Container
|
||||
$targetViewport->height = $topHeight;
|
||||
$viewport->y += $topHeight;
|
||||
$viewport->height = $topHeight;
|
||||
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
|
||||
$targetViewport->height += ($m->bottom + $m->top);
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $targetViewport);
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
|
||||
if( $targetViewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $targetViewport->x + $targetViewport->width &&
|
||||
$targetViewport->y <= $thread->getEvent()->y &&
|
||||
$thread->getEvent()->y <= $targetViewport->y + $targetViewport->height ) {
|
||||
$view->state = StateEnum::hover;
|
||||
}else{
|
||||
$view->state = StateEnum::normal;
|
||||
}
|
||||
}
|
||||
|
||||
if($view instanceof \PHPNative\UI\Widget\Button && $thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_UP) {
|
||||
if( $targetViewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $targetViewport->x + $targetViewport->width &&
|
||||
$targetViewport->y <= $thread->getEvent()->y && $thread->getEvent()->y <=
|
||||
$targetViewport->y + $targetViewport->height ) {
|
||||
$view->onClick($thread->worker);
|
||||
}
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $targetViewport, $index);
|
||||
|
||||
if (isset($styles[Overflow::class]) && $f = $styles[Overflow::class] && (
|
||||
$styles[Overflow::class]->y == OverflowEnum::scroll ||
|
||||
($styles[Overflow::class]->y == OverflowEnum::auto && $viewport->height < 0)
|
||||
)) {
|
||||
|
||||
\PHPNative\Renderer\Visuals\Scrollbar::renderBackground($view->getId(), $thread, $styles, $targetViewport);
|
||||
\PHPNative\Renderer\Visuals\Scrollbar::renderBackground($view->getId(), $thread, $styles, $targetViewport, $index);
|
||||
|
||||
if ($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_DOWN) {
|
||||
if ($targetViewport->x + $targetViewport->width - 10 <= $thread->getEvent()->x &&
|
||||
@ -154,7 +192,7 @@ class Container
|
||||
$sliderViewport->y = $targetViewport->y + (int)($view->getMoveToY()*$ratio);
|
||||
$sliderViewport->height = (int)($ratio*100 * $ohP);
|
||||
|
||||
\PHPNative\Renderer\Visuals\Scrollbar::renderSlider($view->getId(), $thread, $styles, $sliderViewport);
|
||||
\PHPNative\Renderer\Visuals\Scrollbar::renderSlider($view->getId(), $thread, $styles, $sliderViewport, $index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
103
src/PHPNative/Renderer/src/Widgets/Icon.php
Normal file
103
src/PHPNative/Renderer/src/Widgets/Icon.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Renderer\Widgets;
|
||||
|
||||
use PHPNative\Event\EventType;
|
||||
use PHPNative\Renderer\GFX;
|
||||
use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
use PHPNative\Renderer\Widget;
|
||||
use PHPNative\Tailwind\Style\Background;
|
||||
use PHPNative\Tailwind\Style\Basis;
|
||||
use PHPNative\Tailwind\Style\Border;
|
||||
use PHPNative\Tailwind\Style\Margin;
|
||||
use PHPNative\Tailwind\Style\MediaQueryEnum;
|
||||
use PHPNative\Tailwind\Style\Padding;
|
||||
use PHPNative\Tailwind\Style\StateEnum;
|
||||
use PHPNative\Tailwind\Style\Text;
|
||||
use PHPNative\Tailwind\Style\Unit;
|
||||
use PHPNative\Tailwind\Style\Width;
|
||||
use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class Icon
|
||||
{
|
||||
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Icon $view, int $index = 0): Viewport
|
||||
{
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Text::class]) && $t = $styles[\PHPNative\Tailwind\Style\Text::class]) {
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/symbol.ttf' , $view->size);
|
||||
if($t->color->red != -1) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
}else{
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
}else{
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/symbol.ttf' , $view->size);
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
|
||||
$surface = \SDL_TTF_RenderGlyph_Blended($font, $view->icon->value, $color);
|
||||
|
||||
if(!isset($styles[Basis::class]) && !isset($styles[Width::class])) {
|
||||
$viewport->width = $surface->w;
|
||||
}
|
||||
$viewport->height = $surface->h;
|
||||
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
$backdropViewport = clone $viewport;
|
||||
$backdropViewport->height = $surface->h;
|
||||
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
|
||||
if( $viewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $viewport->x + $viewport->width &&
|
||||
$viewport->y <= $thread->getEvent()->y &&
|
||||
$thread->getEvent()->y <= $viewport->y + $viewport->height ) {
|
||||
$view->state = StateEnum::hover;
|
||||
}else{
|
||||
$view->state = StateEnum::normal;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
$backdropViewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport, $index);
|
||||
|
||||
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
|
||||
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
if($surface->w > $viewport->width) {
|
||||
$thread->addToRenderStack(new Item($textureFont,
|
||||
new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3,
|
||||
new \SDL_FRect(0, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}else{
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
|
||||
if(!isset($styles[Basis::class]) && !isset($styles[Width::class])) {
|
||||
$viewport->addX = $viewport->width;
|
||||
}
|
||||
|
||||
return $viewport;
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,20 +20,17 @@ use PHPNative\Tailwind\Style\Unit;
|
||||
use PHPNative\Tailwind\Style\Width;
|
||||
use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class Label
|
||||
class Image
|
||||
{
|
||||
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Label $view): Viewport
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Image $view, int $index = 0): Viewport
|
||||
{
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 20);
|
||||
if(isset($styles[Text::class]) && $t = $styles[Text::class]) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
}else{
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
if(!file_exists($view->src)) {
|
||||
return $viewport;
|
||||
}
|
||||
$surface = \SDL_TTF_RenderText_Blended($font, $view->label, $color);
|
||||
$surface = \SDL_IMG_Load($view->src);
|
||||
|
||||
$viewport->height = $surface->h;
|
||||
|
||||
@ -66,7 +63,7 @@ class Label
|
||||
$backdropViewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport);
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport, $index);
|
||||
|
||||
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
|
||||
|
||||
@ -77,10 +74,11 @@ class Label
|
||||
new \SDL_FRect(0, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3));
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}else{
|
||||
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
|
||||
return $viewport;
|
||||
119
src/PHPNative/Renderer/src/Widgets/Text.php
Normal file
119
src/PHPNative/Renderer/src/Widgets/Text.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Renderer\Widgets;
|
||||
|
||||
use PHPNative\Event\EventType;
|
||||
use PHPNative\Renderer\GFX;
|
||||
use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
use PHPNative\Tailwind\Style\AlignEnum;
|
||||
use PHPNative\Tailwind\Style\Basis;
|
||||
use PHPNative\Tailwind\Style\Border;
|
||||
use PHPNative\Tailwind\Style\Margin;
|
||||
use PHPNative\Tailwind\Style\MediaQueryEnum;
|
||||
use PHPNative\Tailwind\Style\Padding;
|
||||
use PHPNative\Tailwind\Style\StateEnum;
|
||||
use PHPNative\Tailwind\Style\Width;
|
||||
use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class Text
|
||||
{
|
||||
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Text $view, int $index = 0): Viewport
|
||||
{
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Text::class]) && $t = $styles[\PHPNative\Tailwind\Style\Text::class]) {
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , $t->size);
|
||||
if($t->color->red != -1) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
}else{
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
}else{
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 16);
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
$surface = \SDL_TTF_RenderText_Blended($font, $view->text, $color);
|
||||
|
||||
if(!isset($styles[Basis::class]) && !isset($styles[Width::class])) {
|
||||
$viewport->width = $surface->w;
|
||||
}
|
||||
$viewport->height = $surface->h;
|
||||
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->x += $m->left;
|
||||
if(!isset($styles[Basis::class]) && !isset($styles[Width::class])) {
|
||||
$viewport->width += ($m->right + $m->left);
|
||||
}else{
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
}
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
$backdropViewport = clone $viewport;
|
||||
$backdropViewport->height = $surface->h;
|
||||
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
|
||||
if( $viewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $viewport->x + $viewport->width &&
|
||||
$viewport->y <= $thread->getEvent()->y &&
|
||||
$thread->getEvent()->y <= $viewport->y + $viewport->height ) {
|
||||
$view->state = StateEnum::hover;
|
||||
}else{
|
||||
$view->state = StateEnum::normal;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
$backdropViewport->height += ($m->top + $m->bottom);
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport, $index);
|
||||
|
||||
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
|
||||
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
if($surface->w > $viewport->width) {
|
||||
$thread->addToRenderStack(new Item($textureFont,
|
||||
new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3,
|
||||
new \SDL_FRect(0, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else {
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Text::class]) && $styles[\PHPNative\Tailwind\Style\Text::class]->align == AlignEnum::center) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + (($viewport->width - $surface->w) /2), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}elseif(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::right) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + ($viewport->width - $surface->w), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
if($surface->w > $viewport->width) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont,
|
||||
new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3,
|
||||
new \SDL_FRect(0, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else {
|
||||
if(isset($styles[\PHPNative\Tailwind\Style\Text::class]) && $styles[\PHPNative\Tailwind\Style\Text::class]->align == AlignEnum::center) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + (($viewport->width - $surface->w) /2), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}elseif(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::right) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + ($viewport->width - $surface->w), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $viewport;
|
||||
}
|
||||
|
||||
}
|
||||
179
src/PHPNative/Renderer/src/Widgets/TextEdit.php
Normal file
179
src/PHPNative/Renderer/src/Widgets/TextEdit.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Renderer\Widgets;
|
||||
|
||||
use PHPNative\Event\EventType;
|
||||
use PHPNative\Event\Key;
|
||||
use PHPNative\Renderer\GFX;
|
||||
use PHPNative\Renderer\Item;
|
||||
use PHPNative\Renderer\Thread;
|
||||
use PHPNative\Renderer\Viewport;
|
||||
use PHPNative\Renderer\Visuals\Cursor;
|
||||
use PHPNative\Renderer\Widget;
|
||||
use PHPNative\Tailwind\Style\AlignEnum;
|
||||
use PHPNative\Tailwind\Style\Background;
|
||||
use PHPNative\Tailwind\Style\Basis;
|
||||
use PHPNative\Tailwind\Style\Border;
|
||||
use PHPNative\Tailwind\Style\Margin;
|
||||
use PHPNative\Tailwind\Style\MediaQueryEnum;
|
||||
use PHPNative\Tailwind\Style\Padding;
|
||||
use PHPNative\Tailwind\Style\StateEnum;
|
||||
use PHPNative\Tailwind\Style\Text;
|
||||
use PHPNative\Tailwind\Style\Unit;
|
||||
use PHPNative\Tailwind\Style\Width;
|
||||
use PHPNative\Tailwind\StyleParser;
|
||||
|
||||
class TextEdit
|
||||
{
|
||||
|
||||
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\TextEdit $view, int $index = 0): Viewport
|
||||
{
|
||||
|
||||
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
|
||||
|
||||
if(isset($styles[Text::class]) && $t = $styles[Text::class]) {
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , $t->size);
|
||||
if($t->color->red != -1) {
|
||||
$color = new \SDL_Color($t->color->red, $t->color->green, $t->color->blue, $t->color->alpha);
|
||||
}else{
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
}else{
|
||||
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 16);
|
||||
$color = new \SDL_Color(0, 0, 0, 255);
|
||||
}
|
||||
if($view->value == "" && $view->placeholder != null) {
|
||||
$color = new \SDL_Color(0, 0, 0, 128);
|
||||
$surface = \SDL_TTF_RenderText_Blended($font, $view->placeholder, $color);
|
||||
$cursorWidth = 0;
|
||||
}else{
|
||||
$surface = \SDL_TTF_RenderText_Blended($font, $view->value, $color);
|
||||
$surfaceCursor = \SDL_TTF_RenderText_Blended($font, mb_substr($view->value, 0, $view->textEditIndex), $color);
|
||||
$cursorWidth = $surfaceCursor->w;
|
||||
|
||||
}
|
||||
|
||||
$viewport->height = $surface->h;
|
||||
|
||||
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
}
|
||||
|
||||
$backdropViewport = clone $viewport;
|
||||
$backdropViewport->height = $surface->h;
|
||||
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
|
||||
if( $viewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $viewport->x + $viewport->width &&
|
||||
$viewport->y <= $thread->getEvent()->y &&
|
||||
$thread->getEvent()->y <= $viewport->y + $viewport->height ) {
|
||||
if($view->state == StateEnum::focus || $view->state == StateEnum::hoverfocus) {
|
||||
$view->state = StateEnum::hoverfocus;
|
||||
}else{
|
||||
$view->state = StateEnum::hover;
|
||||
}
|
||||
}else{
|
||||
if($view->state == StateEnum::hoverfocus ) {
|
||||
$view->state = StateEnum::focus;
|
||||
}
|
||||
if($view->state != StateEnum::focus ) {
|
||||
$view->state = StateEnum::normal;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_UP) {
|
||||
if( $viewport->x <= $thread->getEvent()->x &&
|
||||
$thread->getEvent()->x <= $viewport->x + $viewport->width &&
|
||||
$viewport->y <= $thread->getEvent()->y && $thread->getEvent()->y <=
|
||||
$viewport->y + $viewport->height ) {
|
||||
$view->state = StateEnum::focus;
|
||||
\SDL_StartTextInput($thread->windowPtr);
|
||||
}else{
|
||||
\SDL_StopTextInput($thread->windowPtr);
|
||||
$view->state = StateEnum::normal;
|
||||
}
|
||||
}
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::KEYUP && $thread->getEvent()->key == Key::BACKSPACE) {
|
||||
if($view->textEditIndex > 0) {
|
||||
$view->value = self::str_delete($view->value, $view->textEditIndex);
|
||||
$view->textEditIndex -= 1;
|
||||
}
|
||||
}
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::TEXTINPUT && $view->state === StateEnum::focus) {
|
||||
if($view->value != "") {
|
||||
$view->value = self::str_insert($view->value, $thread->getEvent()->text, $view->textEditIndex);
|
||||
}else {
|
||||
$view->value = $view->value . $thread->getEvent()->text;
|
||||
}
|
||||
$view->textEditIndex += mb_strlen($thread->getEvent()->text);
|
||||
}
|
||||
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::KEYUP && $thread->getEvent()->key == Key::SDLK_LEFT) {
|
||||
if($view->textEditIndex > 0) {
|
||||
$view->textEditIndex -= 1;
|
||||
}
|
||||
}
|
||||
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::KEYUP && $thread->getEvent()->key == Key::SDLK_RIGHT) {
|
||||
if($view->textEditIndex < mb_strlen($view->value)) {
|
||||
$view->textEditIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
|
||||
$viewport->x += $m->left;
|
||||
$viewport->width -= ($m->right + $m->left);
|
||||
$viewport->y += $m->top;
|
||||
$viewport->height += ($m->bottom + $m->top);
|
||||
$backdropViewport->height += ($m->top + $m->bottom);
|
||||
}
|
||||
|
||||
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport, $index);
|
||||
|
||||
$currentTime = \SDL_GetTicks() / 500;
|
||||
|
||||
if (((int)$currentTime & 1) && ($view->state == StateEnum::focus || $view->state == StateEnum::hoverfocus)) {
|
||||
$viewportCorsor = clone $viewport;
|
||||
$viewportCorsor->height = $surface->h;
|
||||
$viewportCorsor->x += $cursorWidth;
|
||||
Cursor::render($view->getId(), $thread, $styles, $viewportCorsor, $index);
|
||||
}
|
||||
|
||||
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
|
||||
|
||||
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
|
||||
if($surface->w > $viewport->width) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont,
|
||||
new \SDL_FRect($viewport->x, $viewport->y, $viewport->width, $surface->h), 3,
|
||||
new \SDL_FRect($surface->w - $viewport->width, 0, $viewport->width, $surface->h)
|
||||
));
|
||||
}else {
|
||||
if(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::center) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + (($viewport->width - $surface->w) /2), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}elseif(isset($styles[Text::class]) && $styles[Text::class]->align == AlignEnum::right) {
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x + ($viewport->width - $surface->w), $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}else{
|
||||
$thread->addToRenderStack(new Item($view->getId(), $textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), ++$index));
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
}
|
||||
|
||||
return $viewport;
|
||||
}
|
||||
|
||||
private static function str_delete(string $str, int $pos = 0) {
|
||||
return mb_substr($str, 0, $pos-1) . mb_substr($str, $pos);
|
||||
}
|
||||
|
||||
private static function str_insert(string $oldString, string $newString, int $pos = 0) {
|
||||
return mb_substr($oldString, 0, $pos) . $newString . mb_substr($oldString, $pos);
|
||||
}
|
||||
}
|
||||
18
src/PHPNative/Storage/composer.json
Normal file
18
src/PHPNative/Storage/composer.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "phpnative/storage",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.3",
|
||||
"zumba/json-serializer": "^3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHPNative\\Storage\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"PHPNative\\Storage\\Tests\\": "tests"
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/PHPNative/Storage/src/Storage.php
Normal file
67
src/PHPNative/Storage/src/Storage.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace PHPNative\Storage;
|
||||
|
||||
use PHPNative\Framework\App;
|
||||
use Zumba\JsonSerializer\JsonSerializer;
|
||||
|
||||
class Storage
|
||||
{
|
||||
public function __construct(private JsonSerializer $jsonSerializer, private App $appConfig)
|
||||
{
|
||||
}
|
||||
|
||||
public function saveModel(object $model): void
|
||||
{
|
||||
$path = $this->getLocalAppData() . DIRECTORY_SEPARATOR . md5($model::class). '.json';
|
||||
if(!file_exists($this->getLocalAppData())) {
|
||||
mkdir($this->getLocalAppData(), 0777, true);
|
||||
}
|
||||
file_put_contents($path, $this->jsonSerializer->serialize($model));
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param class-string<T> $className
|
||||
* @return T
|
||||
*/
|
||||
public function loadModel(string $className): object
|
||||
{
|
||||
$path = $this->getLocalAppData() . DIRECTORY_SEPARATOR . md5($className). '.json';
|
||||
if(file_exists($path)) {
|
||||
return $this->jsonSerializer->unserialize(file_get_contents($path));
|
||||
}else{
|
||||
return new $className();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getLocalAppData() {
|
||||
$homeDir = $_SERVER['HOME'] ?? '';
|
||||
|
||||
if(empty($homeDir)) {
|
||||
$homeDir = getenv('HOME');
|
||||
}
|
||||
|
||||
if(empty($homeDir) && $this->is_windows()) {
|
||||
$homeData = $_SERVER['LOCALAPPDATA'] ?? '';
|
||||
|
||||
$homeDir = $homeData;
|
||||
}
|
||||
|
||||
if(empty($homeDir) && function_exists('exec')) {
|
||||
if($this->is_windows()) {
|
||||
$homeDir = exec('echo %userprofile%');
|
||||
} else {
|
||||
$homeDir = exec('echo ~');
|
||||
}
|
||||
}
|
||||
|
||||
return implode(DIRECTORY_SEPARATOR ,[$homeDir, $this->appConfig->getName()]);
|
||||
}
|
||||
|
||||
private function is_windows() {
|
||||
return strncasecmp(PHP_OS, "WIN", 3) === 0;
|
||||
}
|
||||
|
||||
}
|
||||
8
src/PHPNative/Tailwind/src/Data/Icon.php
Normal file
8
src/PHPNative/Tailwind/src/Data/Icon.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Tailwind\Data;
|
||||
|
||||
enum Icon:int
|
||||
{
|
||||
case plus = 57669;
|
||||
}
|
||||
@ -8,6 +8,7 @@ use PHPNative\Tailwind\Style\Margin;
|
||||
use PHPNative\Tailwind\Style\MediaQueryEnum;
|
||||
use PHPNative\Tailwind\Style\Padding;
|
||||
use PHPNative\Tailwind\Style\StateEnum;
|
||||
use PHPNative\Tailwind\Style\Text;
|
||||
|
||||
class StyleCollection extends TypedCollection
|
||||
{
|
||||
@ -40,6 +41,8 @@ class StyleCollection extends TypedCollection
|
||||
\PHPNative\Tailwind\Parser\Margin::merge($tmp[$style->style::class], $style->style);
|
||||
}elseif(isset($tmp[$style->style::class]) && $style->style::class === Border::class) {
|
||||
\PHPNative\Tailwind\Parser\Border::merge($tmp[$style->style::class], $style->style);
|
||||
}elseif(isset($tmp[$style->style::class]) && $style->style::class === Text::class) {
|
||||
\PHPNative\Tailwind\Parser\Text::merge($tmp[$style->style::class], $style->style);
|
||||
}else{
|
||||
$tmp[$style->style::class] = $style->style;
|
||||
}
|
||||
|
||||
@ -4,12 +4,43 @@ declare(strict_types=1);
|
||||
|
||||
namespace PHPNative\Tailwind\Parser;
|
||||
|
||||
use PHPNative\Tailwind\Style\AlignEnum;
|
||||
|
||||
class Text implements Parser
|
||||
{
|
||||
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Text
|
||||
{
|
||||
$color = new \PHPNative\Tailwind\Style\Color();
|
||||
|
||||
preg_match_all('/text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)/', $style, $output_array);
|
||||
if (count($output_array[0]) > 0) {
|
||||
$size = match ((string)$output_array[1][0]) {
|
||||
'xs' => 12,
|
||||
'sm' => 14,
|
||||
'base' => 16,
|
||||
'lg' => 18,
|
||||
'xl' => 20,
|
||||
'2xl' => 24,
|
||||
'3xl' => 30,
|
||||
'4xl' => 36,
|
||||
'5xl' => 48,
|
||||
'6xl' => 60,
|
||||
'7xl' => 72,
|
||||
'8xl' => 96,
|
||||
'9xl' => 128,
|
||||
};
|
||||
return new \PHPNative\Tailwind\Style\Text(size: $size);
|
||||
}
|
||||
|
||||
preg_match_all('/text-(center|right|left)/', $style, $output_array);
|
||||
if (count($output_array[0]) > 0) {
|
||||
return match ((string)$output_array[1][0]) {
|
||||
'left' => new \PHPNative\Tailwind\Style\Text(align: AlignEnum::left),
|
||||
'right' => new \PHPNative\Tailwind\Style\Text(align: AlignEnum::right),
|
||||
'center' => new \PHPNative\Tailwind\Style\Text(align: AlignEnum::center),
|
||||
};
|
||||
}
|
||||
|
||||
preg_match_all('/text-(.*)/', $style, $output_array);
|
||||
if (count($output_array[0]) > 0) {
|
||||
$colorStyle = $output_array[1][0];
|
||||
@ -19,4 +50,26 @@ class Text implements Parser
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function merge(\PHPNative\Tailwind\Style\Text $style1, \PHPNative\Tailwind\Style\Text $style2): void
|
||||
{
|
||||
if($style2->color->red != -1) {
|
||||
$style1->color->red = $style2->color->red;
|
||||
}
|
||||
if($style2->color->green != -1) {
|
||||
$style1->color->green = $style2->color->green;
|
||||
}
|
||||
if($style2->color->blue != -1) {
|
||||
$style1->color->blue = $style2->color->blue;
|
||||
}
|
||||
if($style2->color->alpha != -1) {
|
||||
$style1->color->alpha = $style2->color->alpha;
|
||||
}
|
||||
if($style2->size != 16) {
|
||||
$style1->size = $style2->size;
|
||||
}
|
||||
if($style2->align != AlignEnum::left) {
|
||||
$style1->align = $style2->align;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/PHPNative/Tailwind/src/Style/AlignEnum.php
Normal file
10
src/PHPNative/Tailwind/src/Style/AlignEnum.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\Tailwind\Style;
|
||||
|
||||
enum AlignEnum
|
||||
{
|
||||
case left;
|
||||
case center;
|
||||
case right;
|
||||
}
|
||||
@ -6,6 +6,7 @@ enum StateEnum
|
||||
{
|
||||
case normal;
|
||||
case hover;
|
||||
case hoverfocus;
|
||||
case focus;
|
||||
case active;
|
||||
}
|
||||
@ -6,7 +6,7 @@ namespace PHPNative\Tailwind\Style;
|
||||
|
||||
class Text implements Style
|
||||
{
|
||||
public function __construct(public Color $color = new Color())
|
||||
public function __construct(public Color $color = new Color(), public AlignEnum $align = AlignEnum::left, public int $size = 16)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace PHPNative\Tailwind\Tests;
|
||||
|
||||
use PHPNative\Tailwind\Parser\Text;
|
||||
use PHPNative\Tailwind\Style\AlignEnum;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -32,4 +33,18 @@ class TextTest extends TestCase
|
||||
$this->assertSame(219, $text->color->blue);
|
||||
$this->assertSame(255, $text->color->alpha);
|
||||
}
|
||||
|
||||
public function test_text_align(): void
|
||||
{
|
||||
/** @var \PHPNative\Tailwind\Style\Text $text */
|
||||
$text = Text::parse("flex text-center");
|
||||
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Text::class, $text);
|
||||
$this->assertSame(AlignEnum::center, $text->align);
|
||||
$text = Text::parse("flex text-left");
|
||||
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Text::class, $text);
|
||||
$this->assertSame(AlignEnum::left, $text->align);
|
||||
$text = Text::parse("flex text-right");
|
||||
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Text::class, $text);
|
||||
$this->assertSame(AlignEnum::right, $text->align);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,18 +5,15 @@ namespace PHPNative\UI;
|
||||
use PHPNative\UI\Collection\Views;
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\Widget\Container;
|
||||
|
||||
class BaseView implements View
|
||||
class BaseView extends Container
|
||||
{
|
||||
use Style;
|
||||
use Id;
|
||||
|
||||
public ?Views $views = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function getViews(): ?Views
|
||||
{
|
||||
return $this->views;
|
||||
|
||||
@ -4,24 +4,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace PHPNative\UI\Widget;
|
||||
|
||||
use PHPNative\UI\Collection\Views;
|
||||
use PHPNative\UI\Trait\Action\Click;
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
class Button implements View
|
||||
class Button extends Container implements View
|
||||
{
|
||||
use Style;
|
||||
use Click;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public function __construct(public string $label)
|
||||
public function __construct(public ?Views $views = null, string $style = "")
|
||||
{
|
||||
parent::__construct($style);
|
||||
}
|
||||
|
||||
public function getViews(): ?\PHPNative\UI\Collection\Views
|
||||
{
|
||||
return $this->views;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ namespace PHPNative\UI\Widget;
|
||||
use PHPNative\UI\Collection\Views;
|
||||
use PHPNative\UI\Trait\Action\Scrollbar;
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
@ -14,6 +15,7 @@ class Container implements View
|
||||
{
|
||||
use Style;
|
||||
use Scrollbar;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public function __construct(string $style = "")
|
||||
|
||||
26
src/PHPNative/UI/src/Widget/Icon.php
Normal file
26
src/PHPNative/UI/src/Widget/Icon.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\UI\Widget;
|
||||
|
||||
use PHPNative\UI\Collection\Views;
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
class Icon implements View
|
||||
{
|
||||
use Style;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public function __construct(public \PHPNative\Tailwind\Data\Icon $icon = \PHPNative\Tailwind\Data\Icon::plus, public int $size = 30, string $style = '')
|
||||
{
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
public function getViews(): ?Views
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
26
src/PHPNative/UI/src/Widget/Image.php
Normal file
26
src/PHPNative/UI/src/Widget/Image.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace PHPNative\UI\Widget;
|
||||
|
||||
use PHPNative\UI\Collection\Views;
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
class Image implements View
|
||||
{
|
||||
use Style;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public function __construct(public string $src = "", string $style = '')
|
||||
{
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
public function getViews(): ?Views
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -9,13 +9,13 @@ use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
class Label implements View
|
||||
class Text implements View
|
||||
{
|
||||
use Style;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public function __construct(public string $label, string $style = '')
|
||||
public function __construct(public ?string $text, string $style = '')
|
||||
{
|
||||
$this->style = $style;
|
||||
}
|
||||
28
src/PHPNative/UI/src/Widget/TextEdit.php
Normal file
28
src/PHPNative/UI/src/Widget/TextEdit.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PHPNative\UI\Widget;
|
||||
|
||||
use PHPNative\UI\Trait\Id;
|
||||
use PHPNative\UI\Trait\State;
|
||||
use PHPNative\UI\Trait\Style;
|
||||
use PHPNative\UI\View;
|
||||
|
||||
class TextEdit implements View
|
||||
{
|
||||
use Style;
|
||||
use State;
|
||||
use Id;
|
||||
|
||||
public int $textEditIndex = 0;
|
||||
|
||||
public function __construct(public string $value = "", public ?string $placeholder = null, string $style = '')
|
||||
{
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
public function getViews(): ?\PHPNative\UI\Collection\Views
|
||||
{
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user