This commit is contained in:
Thomas Peterson 2024-09-25 19:00:43 +02:00
parent b2cba00232
commit 7d4139234f
27 changed files with 543 additions and 235 deletions

View File

@ -49,6 +49,11 @@ abstract class Collection implements IteratorAggregate
return false;
}
public function setElements($elements): void
{
$this->elements = $elements;
}
public function filter(callable $fn): static
{
return new static(array_filter($this->elements, $fn, ARRAY_FILTER_USE_BOTH));
@ -114,4 +119,5 @@ abstract class Collection implements IteratorAggregate
$this->elements = $temp->items();
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace PHPNative\Framework\Parallel;
use parallel\Events;
use parallel\Runtime;
use PHPNative\Container\Singleton;
#[Singleton]
class Worker
{
private Events $events;
private Runtime $runtime;
private array $futures = [];
public function __construct()
{
$this->events = new Events();
$this->events->setBlocking(false);
$this->runtime = new Runtime(__DIR__ . '/../../../../../../app/vendor/autoload.php');
}
public function async(callable $do, callable $finish): void
{
$uniqueId = uniqid();
$this->events->addFuture($uniqueId, $this->runtime->run($do));
$this->futures[$uniqueId] = $finish;
}
public function update(): void
{
if($data = $this->events->poll()) {
if(isset($this->futures[$data->source])) {
$this->futures[$data->source]($data->value);
unset($this->futures[$data->source]);
}
}
}
}

View File

@ -4,7 +4,7 @@ namespace PHPNative\Renderer;
class Item
{
public function __construct(public $texture, public \SDL_FRect $renderAt, public int $level = 0)
public function __construct(public string $widgetId, public $texture, public \SDL_FRect $renderAt, public int $level = 0, public ?\SDL_FRect $clipAt = null)
{
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace PHPNative\Renderer;
class Size
{
public function __construct(public int $top = 0, public int $left = 0, public int $right = 0, public int $bottom = 0)
{
}
}

View File

@ -9,6 +9,14 @@ class StackCollection extends TypedCollection
protected function type(): string
{
// TODO: Implement type() method.
return Item::class;
}
public function removeWidgetIdFromRender(string $widgetId): void
{
$temp = $this->filter(function ($value, $key) use($widgetId){
return $value->widgetId != $widgetId;
});
$this->setElements($temp->items());
}
}

View File

@ -5,6 +5,7 @@ namespace PHPNative\Renderer;
use PHPNative\Event\Event;
use PHPNative\Event\EventCollection;
use PHPNative\Framework\Application\Window;
use PHPNative\Framework\Parallel\Worker;
use PHPNative\Tailwind\Style\Background;
use PHPNative\Tailwind\Style\MediaQueryEnum;
use PHPNative\Tailwind\Style\Padding;
@ -21,7 +22,7 @@ class Thread
private EventCollection $eventStack;
public function __construct()
public function __construct(public Worker $worker)
{
$this->eventStack = new EventCollection();
$this->renderStack = new StackCollection();
@ -51,7 +52,12 @@ class Thread
$windowHeight = 0;
\SDL_GetWindowSize($this->windowId, $windowWidth, $windowHeight);
$viewPort = new Viewport($this->windowId, $this->rendererPtr, 0, 0, $windowWidth, $windowHeight, $windowWidth, $windowHeight, MediaQueryEnum::getFromPixel($windowWidth));
$viewPort = new Viewport(
windowId: $this->windowId,
renderPtr: $this->rendererPtr,
x:0, y: 0,
width: $windowWidth, height: $windowHeight, windowWidth: $windowWidth, windowHeight: $windowHeight,
windowMediaQuery: MediaQueryEnum::getFromPixel($windowWidth));
$this->startRender();
@ -65,7 +71,10 @@ class Thread
});
$this->renderStack->map(function(Item $item) {
\SDL_SetRenderTargetWindow($this->rendererPtr);
\SDL_RenderTexture($this->rendererPtr, $item->texture, null , $item->renderAt);
if($item->clipAt) {
$item->renderAt->w = $item->clipAt->w;
}
\SDL_RenderTexture($this->rendererPtr, $item->texture, $item->clipAt?? null , $item->renderAt);
});
@ -76,6 +85,8 @@ class Thread
$this->renderStack = new StackCollection();
$this->eventStack->removeFirstItem();
$this->worker->update();
}
private function startRender(): void
@ -107,4 +118,26 @@ class Thread
$this->renderStack->add($item);
}
public function removeFromStack(string $widgetId): void
{
$this->renderStack->removeWidgetIdFromRender($widgetId);
}
public function clipFromStack(string $widgetId, $x = null, $y = null): void
{
foreach($this->renderStack->items() as $item) {
if($item->widgetId == $widgetId && ($y != null || $y != null)) {
$clip = clone $item->renderAt;
if($y) {
$clip->x = 0;
$clip->y = $y;
$clip->h = $clip->h-$y;
$item->renderAt->y += $y;
$item->renderAt->h = $clip->h;
$item->clipAt = $clip;
}
}
}
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace PHPNative\Renderer\Visuals;
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
{
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_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));
}
}
}

View File

@ -4,12 +4,13 @@ namespace PHPNative\Renderer\Visuals;
use PHPNative\Renderer\GFX;
use PHPNative\Renderer\Item;
use PHPNative\Renderer\Size;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
class Border
{
public static function render(Thread $thread, array $styles, Viewport $targetViewport): void
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): 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);
@ -37,7 +38,30 @@ 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($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), 10));
}
}
public static function changeViewport(string $widgetId, Thread $thread, array $styles, Viewport $viewport): void
{
if(isset($styles[\PHPNative\Tailwind\Style\Border::class]) && $b = $styles[\PHPNative\Tailwind\Style\Border::class]) {
// Top
if ($b->enabled && $b->top > 0) {
$viewport->y += $b->top;
}
// Bottom
if ($b->enabled && $b->bottom > 0) {
$viewport->height -= $b->bottom;
}
// left
if ($b->enabled && $b->left > 0) {
$viewport->x += $b->left;
}
// right
if ($b->enabled && $b->right > 0) {
$viewport->width -= $b->right;
}
}
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace PHPNative\Renderer\Visuals;
use PHPNative\Renderer\GFX;
use PHPNative\Renderer\Item;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
use PHPNative\Tailwind\Style\Overflow;
use PHPNative\Tailwind\Style\OverflowEnum;
class Scrollbar
{
public static function renderBackground(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
{
$texture = \SDL_CreateTexture($targetViewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, 10, $targetViewport->height);
\SDL_SetRenderTarget($targetViewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($targetViewport->renderPtr, 255, 255, 255, 0);
\SDL_RenderClear($targetViewport->renderPtr);
GFX::boxRGBA($targetViewport->renderPtr, 0, 0, $targetViewport->width - 1, $targetViewport->height, 211, 211, 211, 255);
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x + $targetViewport->width - 10, $targetViewport->y, 10, $targetViewport->height), 20));
}
public static function renderSlider(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
{
$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, 0);
\SDL_RenderClear($targetViewport->renderPtr);
GFX::boxRGBA($targetViewport->renderPtr, 1, 0, $targetViewport->width-2, $targetViewport->height, 150, 150, 150, 255);
$thread->addToRenderStack(new Item($widgetId, $texture, new \SDL_FRect($targetViewport->x, $targetViewport->y, $targetViewport->width, $targetViewport->height), 21));
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace PHPNative\Renderer\Visuals;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
class Visuals
{
public static function render(string $widgetId, Thread $thread, array $styles, Viewport $targetViewport): void
{
Background::render($widgetId, $thread, $styles, $targetViewport);
Border::render($widgetId, $thread, $styles, $targetViewport);
}
public static function changeViewport(string $widgetId, Thread $thread, array $styles, Viewport $viewport): void
{
Border::changeViewport($widgetId, $thread, $styles, $viewport);
}
}

View File

@ -36,7 +36,7 @@ class BaseView
\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($texture, $rect, 0));
$thread->addToRenderStack(new Item($view->getId(), $texture, $rect, 0));
}
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {

View File

@ -38,21 +38,16 @@ class Button
$viewport->height = $surface->h;
$textureWidth = $viewport->width;
$textureHeight = $viewport->height;
$textureX = $viewport->x;
$textureY = $viewport->y;
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);
$textureX += $m->left;
$textureY += $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 &&
@ -69,7 +64,7 @@ class Button
$thread->getEvent()->x <= $viewport->x + $viewport->width &&
$viewport->y <= $thread->getEvent()->y && $thread->getEvent()->y <=
$viewport->y + $viewport->height ) {
$view->onClick();
$view->onClick($thread->worker);
}
}
@ -78,149 +73,28 @@ class Button
$viewport->width -= ($m->right + $m->left);
$viewport->y += $m->top;
$viewport->height += ($m->bottom + $m->top);
$textureWidth -= ($m->right + $m->left);
$textureHeight += ($m->bottom + $m->top);
$backdropViewport->height += ($m->top + $m->bottom);
}
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport);
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$texture = \SDL_CreateTexture($viewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $textureWidth, $textureHeight);
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($viewport->renderPtr, 255, 255, 255, 255);
\SDL_RenderClear($viewport->renderPtr);
$rect = new \SDL_FRect(0, 0, $textureWidth, $textureHeight);
\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($texture, new \SDL_FRect($textureX, $textureY, $textureWidth, $textureHeight), 2));
}
\PHPNative\Renderer\Visuals\Border::render($thread, $styles, $viewport);
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
$thread->addToRenderStack(new Item($textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3));
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), 3));
}
}else{
}
return $viewport;
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 30);
$color = new \SDL_Color(0,0,0,0);
$surface = \SDL_TTF_RenderText_Blended($font, $view->label, $color);
$texture = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($viewport->renderPtr, 255, 255, 255, 255);
\SDL_RenderClear($viewport->renderPtr);
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
$viewport->height = $surface->h;
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
$viewport->x += $m->left;
$viewport->y += $m->top;
$viewport->width -= ($m->right + $m->left);
$viewport->height -= ($m->top + $m->bottom);
}
$orgX = $viewport->x;
$orgY = $viewport->y;
if(isset($styles[Padding::class]) && $p = $styles[Padding::class]) {
$viewport->x += $p->left;
//$viewport->width -= ($p->right + $p->left);
$viewport->y += $p->top;
$viewport->height += ($p->bottom + $p->top);
}
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$rect = new \SDL_FRect($orgX, $orgY, $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);
}
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
if( $orgX <= $thread->getEvent()->x &&
$thread->getEvent()->x <= $orgX + $viewport->width &&
$orgY <= $thread->getEvent()->y &&
$thread->getEvent()->y <= $orgY + $viewport->height ) {
$view->state = StateEnum::hover;
}else{
$view->state = StateEnum::normal;
}
}
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_UP) {
if( $orgX <= $thread->getEvent()->x &&
$thread->getEvent()->x <= $orgX + $viewport->width &&
$orgY <= $thread->getEvent()->y && $thread->getEvent()->y <=
$orgY + $viewport->height ) {
$view->onClick();
}
}
$rect = new \SDL_FRect($viewport->x,$viewport->y,$surface->w,$surface->h);
//$thread->addToRenderStack(new Item($texture, new \SDL_FRect($viewport->x, $viewport->y, $viewport->width, $viewport->height)));
}else{
/*$viewport->width = $surface->w;
$viewport->height = $surface->h;
if(isset($styles[Margin::class]) && $m = $styles[Margin::class]) {
$viewport->x += $m->left;
$viewport->y += $m->top;
}
$orgX = $viewport->x;
$orgY = $viewport->y;
if(isset($styles[Padding::class]) && $p = $styles[Padding::class]) {
$viewport->x += $p->left;
$viewport->width += ($p->right + $p->left);
$viewport->y += $p->top;
$viewport->height += ($p->bottom + $p->top);
}
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$rect = new \SDL_FRect($orgX, $orgY, $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);
}
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
if( $orgX <= $thread->getEvent()->x &&
$thread->getEvent()->x <= $orgX + $viewport->width &&
$orgY <= $thread->getEvent()->y &&
$thread->getEvent()->y <= $orgY + $viewport->height ) {
$view->state = StateEnum::hover;
}else{
$view->state = StateEnum::normal;
}
}
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_UP) {
if( $orgX <= $thread->getEvent()->x &&
$thread->getEvent()->x <= $orgX + $viewport->width &&
$orgY <= $thread->getEvent()->y && $thread->getEvent()->y <=
$orgY + $viewport->height ) {
$view->onClick();
}
}
$rect = new \SDL_FRect($viewport->x,$viewport->y,$surface->w,$surface->h);
//var_dump(\SDL_RenderTexture($viewport->renderPtr, $texture, null, $rect));*/
}
return $viewport;
}

View File

@ -2,6 +2,7 @@
namespace PHPNative\Renderer\Widgets;
use PHPNative\Event\EventType;
use PHPNative\Renderer\Item;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
@ -11,6 +12,8 @@ use PHPNative\Tailwind\Style\Basis;
use PHPNative\Tailwind\Style\DirectionEnum;
use PHPNative\Tailwind\Style\Flex;
use PHPNative\Tailwind\Style\Margin;
use PHPNative\Tailwind\Style\Overflow;
use PHPNative\Tailwind\Style\OverflowEnum;
use PHPNative\Tailwind\Style\Padding;
use PHPNative\Tailwind\Style\StateEnum;
use PHPNative\Tailwind\Style\Unit;
@ -22,24 +25,17 @@ class Container
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Container $view): Viewport
{
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, StateEnum::normal);
$textureWidth = $viewport->width;
$textureHeight = $viewport->height;
$textureX = $viewport->x;
$textureY = $viewport->y;
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);
$textureX += $m->left;
$textureY += $m->top;
$textureWidth -= ($m->right + $m->left);
$textureHeight -= ($m->bottom + $m->top);
}
\PHPNative\Renderer\Visuals\Border::render($thread, $styles, $viewport);
$targetViewport = clone $viewport;
\PHPNative\Renderer\Visuals\Visuals::changeViewport($view->getId(), $thread, $styles, $viewport);
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
$viewport->x += $m->left;
@ -74,7 +70,7 @@ class Container
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);
} else {
$viepo = new Viewport($viewport->windowId, $viewport->renderPtr, $viewport->x + (count($flexStyles) === 0 ? 0 : $width), $viewport->y, $width, $viewport->height, $viewport->windowWidth, $viewport->windowHeight, $viewport->windowMediaQuery);
$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);
}
$flexStyles[] = $viepo;
} else {
@ -86,8 +82,15 @@ class Container
foreach ($view->getViews() as $subView) {
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
$subViewPort = array_shift($flexStyles);
$subViewPort->y = $viewport->y;
$subViewPort->y = $viewport->y - $view->getMoveToY();
$vp = Widget::render($thread, $subViewPort, $subView);
if($vp->y < $targetViewport->y) {
$thread->clipFromStack($subView->getId(), y: $targetViewport->y-$vp->y);
}
if($vp->y + $vp->height < $targetViewport->y) {
$thread->removeFromStack($subView->getId());
}
$viewport->y += $vp->height;
$viewport->height -= $vp->height;
} else {
@ -96,24 +99,62 @@ class Container
}
}
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
$textureHeight = $viewport->y;
} else {
$textureHeight = $topHeight;
$targetViewport->height = $topHeight;
$viewport->y += $topHeight;
$viewport->height = $topHeight;
}
if (isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$texture = \SDL_CreateTexture($viewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $textureWidth, $textureHeight);
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($viewport->renderPtr, 255, 255, 255, 255);
\SDL_RenderClear($viewport->renderPtr);
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $targetViewport);
$rect = new \SDL_FRect(0, 0, $textureWidth, $textureHeight);
\SDL_SetRenderDrawColor($viewport->renderPtr, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
\SDL_RenderFillRect($viewport->renderPtr, $rect);
if (isset($styles[Overflow::class]) && $f = $styles[Overflow::class] && (
$styles[Overflow::class]->y == OverflowEnum::scroll ||
($styles[Overflow::class]->y == OverflowEnum::auto && $viewport->height < 0)
)) {
$thread->addToRenderStack(new Item($texture, new \SDL_FRect($textureX, $textureY, $textureWidth, $textureHeight), 1));
\PHPNative\Renderer\Visuals\Scrollbar::renderBackground($view->getId(), $thread, $styles, $targetViewport);
if ($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_DOWN) {
if ($targetViewport->x + $targetViewport->width - 10 <= $thread->getEvent()->x &&
$thread->getEvent()->x <= $targetViewport->x + $targetViewport->width &&
$targetViewport->y <= $thread->getEvent()->y &&
$thread->getEvent()->y <= $targetViewport->y + $targetViewport->height) {
$view->setDragMode(true);
$view->setMoveStartX($thread->getEvent()->x);
$view->setMoveStartY($thread->getEvent()->y);
}
}
if ($view->isDragMode() && $thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
$view->setMoveToX($view->getMoveEndX() + $thread->getEvent()->x - $view->getMoveStartX());
$view->setMoveToY($view->getMoveEndY() + $thread->getEvent()->y - $view->getMoveStartY());
if($view->getMoveToY() <= 0) {
$view->setMoveStartY($thread->getEvent()->y);
$view->setMoveToX($view->getMoveEndX() + $thread->getEvent()->x - $view->getMoveStartX());
$view->setMoveToY($view->getMoveEndY() + $thread->getEvent()->y - $view->getMoveStartY());
}
if($view->getMoveToY() > ($viewport->height*-1)) {
$view->setMoveToX($view->getMoveEndX() + $thread->getEvent()->x - $view->getMoveStartX());
$view->setMoveToY($viewport->height*-1);
}
}
if ($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEBUTTON_UP) {
$view->setDragMode(false);
$view->setMoveEndX($view->getMoveToX());
$view->setMoveEndY($view->getMoveToY());
}
$sliderViewport = clone $targetViewport;
$sliderViewport->width = 10;
$sliderViewport->x = $targetViewport->x + $width - 10;
$ohP = ($targetViewport->height / 100);
$ratio = ($targetViewport->height / ($viewport->height*-1+$targetViewport->height));
$sliderViewport->y = $targetViewport->y + (int)($view->getMoveToY()*$ratio);
$sliderViewport->height = (int)($ratio*100 * $ohP);
\PHPNative\Renderer\Visuals\Scrollbar::renderSlider($view->getId(), $thread, $styles, $sliderViewport);
}
}

View File

@ -25,7 +25,6 @@ class Label
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Label $view): Viewport
{
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
$font = \SDL_TTF_OpenFont(__DIR__ . DIRECTORY_SEPARATOR . '../../../../../assets/segoe-ui.ttf' , 20);
@ -38,21 +37,16 @@ class Label
$viewport->height = $surface->h;
$textureWidth = $viewport->width;
$textureHeight = $viewport->height;
$textureX = $viewport->x;
$textureY = $viewport->y;
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);
$textureX += $m->left;
$textureY += $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 &&
@ -69,61 +63,26 @@ class Label
$viewport->width -= ($m->right + $m->left);
$viewport->y += $m->top;
$viewport->height += ($m->bottom + $m->top);
$textureWidth -= ($m->right + $m->left);
$textureHeight += ($m->bottom + $m->top);
$backdropViewport->height += ($m->bottom + $m->top);
}
\PHPNative\Renderer\Visuals\Visuals::render($view->getId(), $thread, $styles, $backdropViewport);
if((isset($styles[Width::class]) && $m = $styles[Width::class]) || (isset($styles[Basis::class]) && $m = $styles[Basis::class])) {
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$texture = \SDL_CreateTexture($viewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $textureWidth, $textureHeight);
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($viewport->renderPtr, 255, 255, 255, 255);
\SDL_RenderClear($viewport->renderPtr);
$rect = new \SDL_FRect(0, 0, $textureWidth, $textureHeight);
\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($texture, new \SDL_FRect($textureX, $textureY, $textureWidth, $textureHeight), 2));
}
if(isset($styles[Border::class]) && $b = $styles[Border::class]) {
$texture = \SDL_CreateTexture($viewport->renderPtr, \SDL_PIXELFORMAT_RGBA8888, \SDL_TEXTUREACCESS_TARGET, $textureWidth, $textureHeight);
\SDL_SetRenderTarget($viewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($viewport->renderPtr, 255, 255, 255, 0);
\SDL_RenderClear($viewport->renderPtr);
// Top
GFX::boxRGBA($viewport->renderPtr, 0, 0,
$textureWidth, 1, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
// Bottom
GFX::boxRGBA($viewport->renderPtr, 0, $textureHeight-2,
$textureWidth, $textureHeight, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
// left
GFX::boxRGBA($viewport->renderPtr, 0, 0,
1, $textureHeight, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
// right
GFX::boxRGBA($viewport->renderPtr, $textureWidth-2, 0,
$textureWidth, $textureHeight, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
$thread->addToRenderStack(new Item($texture, new \SDL_FRect($textureX-1, $textureY-1, $textureWidth+2, $textureHeight+2), 10));
}
$textureFont = \SDL_CreateTextureFromSurface($viewport->renderPtr, $surface);
$thread->addToRenderStack(new Item($textureFont, new \SDL_FRect($viewport->x, $viewport->y, $surface->w, $surface->h), 3));
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), 3));
}
}else{
}
return $viewport;
}

View File

@ -0,0 +1,39 @@
<?php
namespace PHPNative\Tailwind\Parser;
use PHPNative\Tailwind\Style\OverflowEnum;
class Overflow
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Overflow
{
preg_match_all("/overflow-auto/", $style, $output_array);
if (count($output_array[0]) > 0) {
return new \PHPNative\Tailwind\Style\Overflow(x: OverflowEnum::auto, y: OverflowEnum::auto);
}
preg_match_all("/overflow-x-(auto|scroll|hidden|clip)/", $style, $output_array);
if (count($output_array[0]) > 0) {
$value = match($output_array[1][0]) {
'auto' => OverflowEnum::auto,
'scroll' => OverflowEnum::scroll,
'hidden' => OverflowEnum::hidden,
'clip' => OverflowEnum::clip
};
return new \PHPNative\Tailwind\Style\Overflow(x: $value);
}
preg_match_all("/overflow-y-(auto|scroll|hidden|clip)/", $style, $output_array);
if (count($output_array[0]) > 0) {
$value = match($output_array[1][0]) {
'auto' => OverflowEnum::auto,
'scroll' => OverflowEnum::scroll,
'hidden' => OverflowEnum::hidden,
'clip' => OverflowEnum::clip
};
return new \PHPNative\Tailwind\Style\Overflow(y: $value);
}
return null;
}
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
use PHPNative\Tailwind\Style\OverflowEnum;
class Overflow implements Style
{
public function __construct(public OverflowEnum $x = OverflowEnum::hidden, public OverflowEnum $y = OverflowEnum::hidden)
{
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace PHPNative\Tailwind\Style;
enum OverflowEnum
{
case hidden;
case clip;
case scroll;
case auto;
}

View File

@ -6,8 +6,6 @@ namespace PHPNative\Tailwind;
use PHPNative\Tailwind\Model\Size;
use PHPNative\Tailwind\Model\StyleCollection;
use PHPNative\Tailwind\Style\Margin;
use PHPNative\Tailwind\Style\Padding;
use PHPNative\Tailwind\Style\Style;
class StyleParser
@ -46,9 +44,15 @@ class StyleParser
if($m = \PHPNative\Tailwind\Parser\Margin::parse($style)) {
return $m;
}
if($o = \PHPNative\Tailwind\Parser\Overflow::parse($style)) {
return $o;
}
if($w = \PHPNative\Tailwind\Parser\Width::parse($style)) {
return $w;
}
if($h = \PHPNative\Tailwind\Parser\Height::parse($style)) {
return $h;
}
if($b = \PHPNative\Tailwind\Parser\Basis::parse($style)) {
return $b;
}

View File

@ -2,10 +2,11 @@
namespace PHPNative\Tailwind\Tests;
use PHPNative\Renderer\Viewport;
use PHPNative\Tailwind\Model\Size;
use PHPNative\Tailwind\Style\Margin;
use PHPNative\Tailwind\Style\MediaQueryEnum;
use PHPNative\Tailwind\Style\Overflow;
use PHPNative\Tailwind\Style\OverflowEnum;
use PHPNative\Tailwind\Style\Padding;
use PHPNative\Tailwind\Style\StateEnum;
use PHPNative\Tailwind\StyleParser;
@ -15,13 +16,14 @@ class ComplexTest extends TestCase
{
public function testComplex(): void
{
$computed = StyleParser::parse("bg-lime-300 p-2 pb-3 m-2 ml-10 mr-10")->getValidStyles(MediaQueryEnum::normal, StateEnum::normal);
$this->assertCount(3, $computed);
$computed = StyleParser::parse("bg-lime-300 p-2 pb-3 m-2 ml-10 mr-10 overflow-y-scroll")->getValidStyles(MediaQueryEnum::normal, StateEnum::normal);
$this->assertCount(4, $computed);
$this->assertEquals(2, $computed[Padding::class]->left);
$this->assertEquals(3, $computed[Padding::class]->bottom);
$this->assertEquals(2, $computed[Margin::class]->top);
$this->assertEquals(10, $computed[Margin::class]->left);
$this->assertEquals(10, $computed[Margin::class]->right);
$this->assertEquals(OverflowEnum::scroll, $computed[Overflow::class]->y);
}
public function testComplexWithModifier(): void

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Overflow;
use PHPNative\Tailwind\Style\OverflowEnum;
use PHPUnit\Framework\TestCase;
class OverflowTest extends TestCase
{
public function test_overflow_y(): void
{
$overflow = Overflow::parse("overflow-y-scroll");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Overflow::class, $overflow);
$this->assertSame(OverflowEnum::hidden, $overflow->x);
$this->assertSame(OverflowEnum::scroll, $overflow->y);
}
public function test_overflow_x(): void
{
$overflow = Overflow::parse("overflow-x-scroll");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Overflow::class, $overflow);
$this->assertSame(OverflowEnum::scroll, $overflow->x);
$this->assertSame(OverflowEnum::hidden, $overflow->y);
}
public function test_overflow_xy(): void
{
$overflow = Overflow::parse("overflow-auto");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Overflow::class, $overflow);
$this->assertSame(OverflowEnum::auto, $overflow->x);
$this->assertSame(OverflowEnum::auto, $overflow->y);
}
}

View File

@ -3,11 +3,13 @@
namespace PHPNative\UI;
use PHPNative\UI\Collection\Views;
use PHPNative\UI\Trait\Id;
use PHPNative\UI\Trait\Style;
class BaseView implements View
{
use Style;
use Id;
public ?Views $views = null;
@ -19,4 +21,5 @@ class BaseView implements View
{
return $this->views;
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PHPNative\UI\Trait\Action;
use Closure;
use PHPNative\Framework\Parallel\Worker;
trait Click
{
@ -16,10 +17,10 @@ trait Click
return $this;
}
public function onClick(): void
public function onClick(Worker $worker): void
{
if($this->click instanceof Closure) {
($this->click)();
($this->click)($worker);
}
}

View File

@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
namespace PHPNative\UI\Trait\Action;
use Closure;
use PHPNative\Framework\Parallel\Worker;
trait Scrollbar
{
private bool $dragMode = false;
private int $moveStartX = 0;
private int $moveEndX = 0;
private int $moveToX = 0;
private int $moveStartY = 0;
private int $moveEndY = 0;
private int $moveToY = 0;
public function isDragMode(): bool
{
return $this->dragMode;
}
public function setDragMode(bool $dragMode): void
{
$this->dragMode = $dragMode;
}
public function getMoveStartX(): int
{
return $this->moveStartX;
}
public function setMoveStartX(int $moveStartX): void
{
$this->moveStartX = $moveStartX;
}
public function getMoveEndX(): int
{
return $this->moveEndX;
}
public function setMoveEndX(int $moveEndX): void
{
$this->moveEndX = $moveEndX;
}
public function getMoveToX(): int
{
return $this->moveToX;
}
public function setMoveToX(int $moveToX): void
{
$this->moveToX = $moveToX;
}
public function getMoveStartY(): int
{
return $this->moveStartY;
}
public function setMoveStartY(int $moveStartY): void
{
$this->moveStartY = $moveStartY;
}
public function getMoveEndY(): int
{
return $this->moveEndY;
}
public function setMoveEndY(int $moveEndY): void
{
$this->moveEndY = $moveEndY;
}
public function getMoveToY(): int
{
return $this->moveToY;
}
public function setMoveToY(int $moveToY): void
{
$this->moveToY = $moveToY;
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace PHPNative\UI\Trait;
trait Id
{
private ?string $id = null;
public function getId(): string
{
if($this->id == null) {
$this->id = uniqid();
}
return $this->id;
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PHPNative\UI\Widget;
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;
@ -14,6 +15,7 @@ class Button implements View
use Style;
use Click;
use State;
use Id;
public function __construct(public string $label)
{

View File

@ -5,12 +5,16 @@ declare(strict_types=1);
namespace PHPNative\UI\Widget;
use PHPNative\UI\Collection\Views;
use PHPNative\UI\Trait\Action\Scrollbar;
use PHPNative\UI\Trait\Id;
use PHPNative\UI\Trait\Style;
use PHPNative\UI\View;
class Container implements View
{
use Style;
use Scrollbar;
use Id;
public function __construct(string $style = "")
{

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace PHPNative\UI\Widget;
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;
@ -13,6 +13,7 @@ class Label implements View
{
use Style;
use State;
use Id;
public function __construct(public string $label, string $style = '')
{