diff --git a/src/PHPNative/Core/src/Collection.php b/src/PHPNative/Core/src/Collection.php index 83f50ec..0e06654 100644 --- a/src/PHPNative/Core/src/Collection.php +++ b/src/PHPNative/Core/src/Collection.php @@ -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(); } + } \ No newline at end of file diff --git a/src/PHPNative/Framework/src/Parallel/Worker.php b/src/PHPNative/Framework/src/Parallel/Worker.php new file mode 100644 index 0000000..0928092 --- /dev/null +++ b/src/PHPNative/Framework/src/Parallel/Worker.php @@ -0,0 +1,39 @@ +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]); + } + } + } +} \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Item.php b/src/PHPNative/Renderer/src/Item.php index 21c143c..be7fc49 100644 --- a/src/PHPNative/Renderer/src/Item.php +++ b/src/PHPNative/Renderer/src/Item.php @@ -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) { } } \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Size.php b/src/PHPNative/Renderer/src/Size.php new file mode 100644 index 0000000..19c2685 --- /dev/null +++ b/src/PHPNative/Renderer/src/Size.php @@ -0,0 +1,10 @@ +filter(function ($value, $key) use($widgetId){ + return $value->widgetId != $widgetId; + }); + $this->setElements($temp->items()); } } \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Thread.php b/src/PHPNative/Renderer/src/Thread.php index 5c874a8..3345d68 100644 --- a/src/PHPNative/Renderer/src/Thread.php +++ b/src/PHPNative/Renderer/src/Thread.php @@ -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; + } + } + } + } + } \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Visuals/Background.php b/src/PHPNative/Renderer/src/Visuals/Background.php new file mode 100644 index 0000000..62c3bd3 --- /dev/null +++ b/src/PHPNative/Renderer/src/Visuals/Background.php @@ -0,0 +1,27 @@ +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)); + } + } +} \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Visuals/Border.php b/src/PHPNative/Renderer/src/Visuals/Border.php index 8caff3b..d8e78d8 100644 --- a/src/PHPNative/Renderer/src/Visuals/Border.php +++ b/src/PHPNative/Renderer/src/Visuals/Border.php @@ -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; + } + } + + } } \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Visuals/Scrollbar.php b/src/PHPNative/Renderer/src/Visuals/Scrollbar.php new file mode 100644 index 0000000..86b60b9 --- /dev/null +++ b/src/PHPNative/Renderer/src/Visuals/Scrollbar.php @@ -0,0 +1,40 @@ +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)); + + } +} \ No newline at end of file diff --git a/src/PHPNative/Renderer/src/Visuals/Visuals.php b/src/PHPNative/Renderer/src/Visuals/Visuals.php new file mode 100644 index 0000000..c57309d --- /dev/null +++ b/src/PHPNative/Renderer/src/Visuals/Visuals.php @@ -0,0 +1,21 @@ +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]) { diff --git a/src/PHPNative/Renderer/src/Widgets/Button.php b/src/PHPNative/Renderer/src/Widgets/Button.php index 6385a21..3c447c0 100644 --- a/src/PHPNative/Renderer/src/Widgets/Button.php +++ b/src/PHPNative/Renderer/src/Widgets/Button.php @@ -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; } diff --git a/src/PHPNative/Renderer/src/Widgets/Container.php b/src/PHPNative/Renderer/src/Widgets/Container.php index 799f4d2..8b675d4 100644 --- a/src/PHPNative/Renderer/src/Widgets/Container.php +++ b/src/PHPNative/Renderer/src/Widgets/Container.php @@ -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); } } diff --git a/src/PHPNative/Renderer/src/Widgets/Label.php b/src/PHPNative/Renderer/src/Widgets/Label.php index 0348aa7..15df5eb 100644 --- a/src/PHPNative/Renderer/src/Widgets/Label.php +++ b/src/PHPNative/Renderer/src/Widgets/Label.php @@ -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; } diff --git a/src/PHPNative/Tailwind/src/Parser/Overflow.php b/src/PHPNative/Tailwind/src/Parser/Overflow.php new file mode 100644 index 0000000..69ca2cb --- /dev/null +++ b/src/PHPNative/Tailwind/src/Parser/Overflow.php @@ -0,0 +1,39 @@ + 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; + } +} \ No newline at end of file diff --git a/src/PHPNative/Tailwind/src/Style/Overflow.php b/src/PHPNative/Tailwind/src/Style/Overflow.php new file mode 100644 index 0000000..8b774c9 --- /dev/null +++ b/src/PHPNative/Tailwind/src/Style/Overflow.php @@ -0,0 +1,14 @@ +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 diff --git a/src/PHPNative/Tailwind/tests/OverflowTest.php b/src/PHPNative/Tailwind/tests/OverflowTest.php new file mode 100644 index 0000000..f179d1d --- /dev/null +++ b/src/PHPNative/Tailwind/tests/OverflowTest.php @@ -0,0 +1,36 @@ +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); + } +} diff --git a/src/PHPNative/UI/src/BaseView.php b/src/PHPNative/UI/src/BaseView.php index c36a685..e2dd38a 100644 --- a/src/PHPNative/UI/src/BaseView.php +++ b/src/PHPNative/UI/src/BaseView.php @@ -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; } + } \ No newline at end of file diff --git a/src/PHPNative/UI/src/Trait/Action/Click.php b/src/PHPNative/UI/src/Trait/Action/Click.php index f271db5..f355cda 100644 --- a/src/PHPNative/UI/src/Trait/Action/Click.php +++ b/src/PHPNative/UI/src/Trait/Action/Click.php @@ -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); } } diff --git a/src/PHPNative/UI/src/Trait/Action/Scrollbar.php b/src/PHPNative/UI/src/Trait/Action/Scrollbar.php new file mode 100644 index 0000000..8ee3882 --- /dev/null +++ b/src/PHPNative/UI/src/Trait/Action/Scrollbar.php @@ -0,0 +1,92 @@ +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; + } + + + +} diff --git a/src/PHPNative/UI/src/Trait/Id.php b/src/PHPNative/UI/src/Trait/Id.php new file mode 100644 index 0000000..128374d --- /dev/null +++ b/src/PHPNative/UI/src/Trait/Id.php @@ -0,0 +1,17 @@ +id == null) { + $this->id = uniqid(); + } + + return $this->id; + } +} \ No newline at end of file diff --git a/src/PHPNative/UI/src/Widget/Button.php b/src/PHPNative/UI/src/Widget/Button.php index 504c694..40b3862 100644 --- a/src/PHPNative/UI/src/Widget/Button.php +++ b/src/PHPNative/UI/src/Widget/Button.php @@ -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) { diff --git a/src/PHPNative/UI/src/Widget/Container.php b/src/PHPNative/UI/src/Widget/Container.php index 6b9e6b4..823b41f 100644 --- a/src/PHPNative/UI/src/Widget/Container.php +++ b/src/PHPNative/UI/src/Widget/Container.php @@ -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 = "") { diff --git a/src/PHPNative/UI/src/Widget/Label.php b/src/PHPNative/UI/src/Widget/Label.php index e5cef33..50148ea 100644 --- a/src/PHPNative/UI/src/Widget/Label.php +++ b/src/PHPNative/UI/src/Widget/Label.php @@ -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 = '') {