This commit is contained in:
Thomas Peterson 2024-09-23 13:10:12 +02:00
parent 7756cb774b
commit b2cba00232
44 changed files with 1801 additions and 66 deletions

View File

@ -101,6 +101,11 @@ abstract class Collection implements IteratorAggregate
}
}
public function sort(callable $callback): void
{
usort($this->elements, $callback);
}
public function removeItem($item): void
{
$temp = $this->filter(function ($value, $key) use($item){

View File

@ -4,10 +4,12 @@ declare(strict_types=1);
namespace PHPNative\Framework\Application;
use PHPNative\Framework\Component\Component;
use PHPNative\UI\View;
interface Window
{
public function getTitle(): string;
public function getView(): View;
public function getView(): ?View;
}

View File

@ -0,0 +1,10 @@
<?php
namespace PHPNative\Framework\Component;
use PHPNative\UI\View;
interface Component
{
public function getComponent(): ?Component;
}

View File

@ -0,0 +1,15 @@
<?php
namespace PHPNative\Framework\Component;
use PHPNative\Core\TypedCollection;
#[Singleton]
class ComponentCollection extends TypedCollection
{
protected function type(): string
{
return Component::class;
}
}

View File

@ -0,0 +1,503 @@
<?php
namespace PHPNative\Renderer;
use PHPNative\Tailwind\Style\Color;
class GFX
{
public static function roundedBoxColor($renderer, int $x1, int $y1, int $x2, int $y2, int $rad, Color $color): void
{
self::roundedBoxRGBA($renderer, $x1, $y1, $x2, $y2, $rad, $color->red, $color->green, $color->blue, $color->alpha);
}
public static function roundedBoxRGBA($renderer, int $x1, int $y1, int $x2, int $y2, int $rad,
int $r, int $g, int $b, int $a) : void
{
$cx = 0;
$cy = $rad;
$ocx = 0xffff;
$ocy = 0xffff;
$df = 1 - $rad;
$d_e = 3;
$d_se = -2 * $rad + 5;
if ($rad <= 1) {
self::boxRGBA($renderer, $x1, $y1, $x2, $y2, $r, $g, $b, $a);
}
if ($x1 == $x2) {
if ($y1 == $y2) {
self::pixelRGBA($renderer, $x1, $y1, $r, $g, $b, $a);
} else {
self::vlineRGBA($renderer, $x1, $y1, $y2, $r, $g, $b, $a);
}
} else {
if ($y1 == $y2) {
self::hlineRGBA($renderer, $x1, $x2, $y1, $r, $g, $b, $a);
}
}
if ($x1 > $x2) {
$tmp = $x1;
$x1 = $x2;
$x2 = $tmp;
}
if ($y1 > $y2) {
$tmp = $y1;
$y1 = $y2;
$y2 = $tmp;
}
$w = $x2 - $x1 + 1;
$h = $y2 - $y1 + 1;
/*
* Maybe adjust radius
*/
$r2 = $rad + $rad;
if ($r2 > $w)
{
$rad = (int)($w / 2);
$r2 = $rad + $rad;
}
if ($r2 > $h)
{
$rad = $h / 2;
}
$x = $x1 + $rad;
$y = $y1 + $rad;
$dx = $x2 - $x1 - $rad - $rad;
$dy = $y2 - $y1 - $rad - $rad;
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255)? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
do {
$xpcx = $x + $cx;
$xmcx = $x - $cx;
$xpcy = $x + $cy;
$xmcy = $x - $cy;
if ($ocy != $cy) {
if ($cy > 0) {
$ypcy = $y + $cy;
$ymcy = $y - $cy;
self::_hline($renderer, $xmcx, $xpcx + $dx, $ypcy + $dy);
self::_hline($renderer, $xmcx, $xpcx + $dx, $ymcy);
} else {
self::_hline($renderer, $xmcx, $xpcx + $dx, $y);
}
$ocy = $cy;
}
if ($ocx != $cx) {
if ($cx != $cy) {
if ($cx > 0) {
$ypcx = $y + $cx;
$ymcx = $y - $cx;
self::_hline($renderer, $xmcy, $xpcy + $dx, $ymcx);
self::_hline($renderer, $xmcy, $xpcy + $dx, $ypcx + $dy);
} else {
self::_hline($renderer, $xmcy, $xpcy + $dx, $y);
}
}
$ocx = $cx;
}
/*
* Update
*/
if ($df < 0) {
$df += $d_e;
$d_e += 2;
$d_se += 2;
} else {
$df += $d_se;
$d_e += 2;
$d_se += 4;
$cy--;
}
$cx++;
} while ($cx <= $cy);
/* Inside */
if ($dx > 0 && $dy > 0) {
self::boxRGBA($renderer, $x1, $y1 + $rad + 1, $x2, $y2 - $rad, $r, $g, $b, $a);
}
}
public static function rectangleRGBA($renderer, int $x1, int $y1, int $x2, int $y2, int $r, int $g, int $b, int $a)
{
if ($x1 == $x2) {
if ($y1 == $y2) {
return (self::pixelRGBA($renderer, $x1, $y1, $r, $g, $b, $a));
} else {
return (self::vlineRGBA($renderer, $x1, $y1, $y2, $r, $g, $b, $a));
}
} else {
if ($y1 == $y2) {
return (self::hlineRGBA($renderer, $x1, $x2, $y1, $r, $g, $b, $a));
}
}
if ($x1 > $x2) {
$tmp = $x1;
$x1 = $x2;
$x2 = $tmp;
}
if ($y1 > $y2) {
$tmp = $y1;
$y1 = $y2;
$y2 = $tmp;
}
$rect = new \SDL_FRect($x1, $y1, $x2 - $x1, $y2 - $y1);
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255)? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
\SDL_RenderDrawRect($renderer, $rect);
}
public static function boxRGBA($renderer, int $x1, int $y1, int $x2, int $y2, int $r, int $g, int $b, int $a): void
{
if ($x1 == $x2) {
if ($y1 == $y2) {
self::pixelRGBA($renderer, $x1, $y1, $r, $g, $b, $a);
} else {
self::vlineRGBA($renderer, $x1, $y1, $y2, $r, $g, $b, $a);
}
} else {
if ($y1 == $y2) {
self::hlineRGBA($renderer, $x1, $x2, $y1, $r, $g, $b, $a);
}
}
if ($x1 > $x2) {
$tmp = $x1;
$x1 = $x2;
$x2 = $tmp;
}
if ($y1 > $y2) {
$tmp = $y1;
$y1 = $y2;
$y2 = $tmp;
}
$rect = new \SDL_FRect($x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1);
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255)? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
\SDL_RenderFillRect($renderer, $rect);
}
public static function roundedRectangleRGBA($renderer, int $x1, int $y1, int $x2, int $y2, int $rad, int $r, int $g, int $b, int $a):void
{
/*
* Special case - no rounding
*/
if ($rad <= 1) {
self::rectangleRGBA($renderer, $x1, $y1, $x2, $y2, $r, $g, $b, $a);
}
if ($x1 == $x2) {
if ($y1 == $y2) {
self::pixelRGBA($renderer, $x1, $y1, $r, $g, $b, $a);
} else {
self::vlineRGBA($renderer, $x1, $y1, $y2, $r, $g, $b, $a);
}
} else {
if ($y1 == $y2) {
self::hlineRGBA($renderer, $x1, $x2, $y1, $r, $g, $b, $a);
}
}
if ($x1 > $x2) {
$tmp = $x1;
$x1 = $x2;
$x2 = $tmp;
}
if ($y1 > $y2) {
$tmp = $y1;
$y1 = $y2;
$y2 = $tmp;
}
$w = $x2 - $x1;
$h = $y2 - $y1;
if (($rad * 2) > $w)
{
$rad = $w / 2;
}
if (($rad * 2) > $h)
{
$rad = $h / 2;
}
$xx1 = $x1 + $rad;
$xx2 = $x2 - $rad;
$yy1 = $y1 + $rad;
$yy2 = $y2 - $rad;
self::arcRGBA($renderer, $xx1, $yy1, $rad, 180, 270, $r, $g, $b, $a);
self::arcRGBA($renderer, $xx2, $yy1, $rad, 270, 360, $r, $g, $b, $a);
self::arcRGBA($renderer, $xx1, $yy2, $rad, 90, 180, $r, $g, $b, $a);
self::arcRGBA($renderer, $xx2, $yy2, $rad, 0, 90, $r, $g, $b, $a);
if ($xx1 <= $xx2) {
self::hlineRGBA($renderer, $xx1, $xx2, $y1, $r, $g, $b, $a);
self::hlineRGBA($renderer, $xx1, $xx2, $y2, $r, $g, $b, $a);
}
if ($yy1 <= $yy2) {
self::vlineRGBA($renderer, $x1, $yy1, $yy2, $r, $g, $b, $a);
self::vlineRGBA($renderer, $x2, $yy1, $yy2, $r, $g, $b, $a);
}
}
public static function _hline($renderer, int $x1, int $x2, int $y): void
{
\SDL_RenderLine($renderer, $x1, $y, $x2, $y);
}
public static function arcRGBA($renderer, int $x, int $y, int $rad, int $start, int $end, int $r, int $g, int $b, int $a): void
{
$cx = 0;
$cy = $rad;
$df = 1 - $rad;
$d_e = 3;
$d_se = -2 * $rad + 5;
$stopval_start = 0; $stopval_end = 0;
$temp = 0.;
/*
* Special case for rad=0 - draw a point
*/
if ($rad == 0) {
self::pixelRGBA($renderer, $x, $y, $r, $g, $b, $a);
}
/*
Octant labeling
\ 5 | 6 /
\ | /
4 \ | / 7
\|/
------+------ +x
/|\
3 / | \ 0
/ | \
/ 2 | 1 \
+y
Initially reset bitmask to 0x00000000
the set whether or not to keep drawing a given octant.
For example: 0x00111100 means we're drawing in octants 2-5
*/
$drawoct = 0;
/*
* Fixup angles
*/
$start %= 360;
$end %= 360;
/* 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. */
while ($start < 0) $start += 360;
while ($end < 0) $end += 360;
$start %= 360;
$end %= 360;
/* now, we find which octants we're drawing in. */
$startoct = $start / 45;
$endoct = $end / 45;
$oct = $startoct - 1;
/* stopval_start, stopval_end; what values of cx to stop at. */
do {
$oct = ($oct + 1) % 8;
if ($oct == $startoct) {
/* need to compute stopval_start for this octant. Look at picture above if this is unclear */
$dstart = (double)$start;
switch ($oct)
{
case 0:
case 3:
$temp = sin($dstart * M_PI / 180.);
break;
case 1:
case 6:
$temp = cos($dstart * M_PI / 180.);
break;
case 2:
case 5:
$temp = -cos($dstart * M_PI / 180.);
break;
case 4:
case 7:
$temp = -sin($dstart * M_PI / 180.);
break;
}
$temp *= $rad;
$stopval_start = (int)$temp;
/*
This isn't arbitrary, but requires graph paper to explain well.
The basic idea is that we're always changing drawoct after we draw, so we
stop immediately after we render the last sensible pixel at x = ((int)temp).
and whether to draw in this octant initially
*/
if ($oct % 2) $drawoct |= (1 << $oct); /* this is basically like saying drawoct[oct] = true, if drawoct were a bool array */
else $drawoct &= 255 - (1 << $oct); /* this is basically like saying drawoct[oct] = false */
}
if ($oct == $endoct) {
/* need to compute stopval_end for this octant */
$dend = (double)$end;
switch ($oct)
{
case 0:
case 3:
$temp = sin($dend * M_PI / 180);
break;
case 1:
case 6:
$temp = cos($dend * M_PI / 180);
break;
case 2:
case 5:
$temp = -cos($dend * M_PI / 180);
break;
case 4:
case 7:
$temp = -sin($dend * M_PI / 180);
break;
}
$temp *= $rad;
$stopval_end = (int)$temp;
/* and whether to draw in this octant initially */
if ($startoct == $endoct) {
/* note: we start drawing, stop, then start again in this case */
/* otherwise: we only draw in this octant, so initialize it to false, it will get set back to true */
if ($start > $end) {
/* unfortunately, if we're in the same octant and need to draw over the whole circle, */
/* we need to set the rest to true, because the while loop will end at the bottom. */
$drawoct = 255;
} else {
$drawoct &= 255 - (1 << $oct);
}
}
else if ($oct % 2) $drawoct &= 255 - (1 << $oct);
else $drawoct |= (1 << $oct);
} else if ($oct != $startoct) { /* already verified that it's != endoct */
$drawoct |= (1 << $oct); /* draw this entire segment */
}
} while ($oct != $endoct);
/* so now we have what octants to draw and when to draw them. all that's left is the actual raster code. */
/*
* Set color
*/
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255) ? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
/*
* Draw arc
*/
do {
$ypcy = $y + $cy;
$ymcy = $y - $cy;
if ($cx > 0) {
$xpcx = $x + $cx;
$xmcx = $x - $cx;
/* always check if we're drawing a certain octant before adding a pixel to that octant. */
if ($drawoct & 4) self::pixel($renderer, $xmcx, $ypcy);
if ($drawoct & 2) self::pixel($renderer, $xpcx, $ypcy);
if ($drawoct & 32) self::pixel($renderer, $xmcx, $ymcy);
if ($drawoct & 64) self::pixel($renderer, $xpcx, $ymcy);
} else {
if ($drawoct & 96) self::pixel($renderer, $x, $ymcy);
if ($drawoct & 6) self::pixel($renderer, $x, $ypcy);
}
$xpcy = $x + $cy;
$xmcy = $x - $cy;
if ($cx > 0 && $cx != $cy) {
$ypcx = $y + $cx;
$ymcx = $y - $cx;
if ($drawoct & 8) self::pixel($renderer, $xmcy, $ypcx);
if ($drawoct & 1) self::pixel($renderer, $xpcy, $ypcx);
if ($drawoct & 16) self::pixel($renderer, $xmcy, $ymcx);
if ($drawoct & 128) self::pixel($renderer, $xpcy, $ymcx);
} else if ($cx == 0) {
if ($drawoct & 24) self::pixel($renderer, $xmcy, $y);
if ($drawoct & 129) self::pixel($renderer, $xpcy, $y);
}
/*
* Update whether we're drawing an octant
*/
if ($stopval_start == $cx) {
/* works like an on-off switch. */
/* This is just in case start & end are in the same octant. */
if ($drawoct & (1 << $startoct)) $drawoct &= 255 - (1 << $startoct);
else $drawoct |= (1 << $startoct);
}
if ($stopval_end == $cx) {
if ($drawoct & (1 << $endoct)) $drawoct &= 255 - (1 << $endoct);
else $drawoct |= (1 << $endoct);
}
/*
* Update pixels
*/
if ($df < 0) {
$df += $d_e;
$d_e += 2;
$d_se += 2;
} else {
$df += $d_se;
$d_e += 2;
$d_se += 4;
$cy--;
}
$cx++;
} while ($cx <= $cy);
}
public static function pixel($renderer, int $x, int $y): void
{
\SDL_RenderPoint($renderer, $x, $y);
}
public static function hlineRGBA($renderer, int $x1, int $x2, int $y, int $r, int $g, int $b, int $a): void
{
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255) ? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
\SDL_RenderLine($renderer, $x1, $y, $x2, $y);
}
public static function vlineRGBA($renderer, int $x, int $y1, int $y2, int $r, int $g, int $b, int $a): void
{
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255) ? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
\SDL_RenderLine($renderer, $x, $y1, $x, $y2);
}
public static function pixelRGBA($renderer, int $x, int $y, int $r, int $g, int $b, int $a): void
{
\SDL_SetRenderDrawBlendMode($renderer, ($a == 255) ? \SDL_BLENDMODE_NONE: \SDL_BLENDMODE_BLEND);
\SDL_SetRenderDrawColor($renderer, $r, $g, $b, $a);
\SDL_RenderPoint($renderer, $x, $y);
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace PHPNative\Renderer;
class Item
{
public function __construct(public $texture, public \SDL_FRect $renderAt, public int $level = 0)
{
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace PHPNative\Renderer;
use PHPNative\Core\TypedCollection;
class StackCollection extends TypedCollection
{
protected function type(): string
{
// TODO: Implement type() method.
}
}

View File

@ -17,18 +17,21 @@ class Thread
private Window $window;
private StackCollection $renderStack;
private EventCollection $eventStack;
public function __construct()
{
$this->eventStack = new EventCollection();
$this->renderStack = new StackCollection();
}
public function show(Window $window): void
{
$this->window = $window;
\SDL_Init(SDL_INIT_VIDEO);
\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);
@ -53,8 +56,25 @@ class Thread
$this->startRender();
Widget::render($this, $viewPort, $this->window->getView());
$this->renderStack->sort(function(Item $itemA, Item $itemB) {
if($itemA->level == $itemB->level) {
return 0;
}
return ($itemA->level < $itemB->level) ? -1 : 1;
});
$this->renderStack->map(function(Item $item) {
\SDL_SetRenderTargetWindow($this->rendererPtr);
\SDL_RenderTexture($this->rendererPtr, $item->texture, null , $item->renderAt);
});
$this->endRender();
$this->renderStack->map(function(Item $item) {
\SDL_DestroyTexture($item->texture);
});
$this->renderStack = new StackCollection();
$this->eventStack->removeFirstItem();
}
@ -81,4 +101,10 @@ class Thread
}
return null;
}
public function addToRenderStack(Item $item): void
{
$this->renderStack->add($item);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace PHPNative\Renderer\Visuals;
use PHPNative\Renderer\GFX;
use PHPNative\Renderer\Item;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
class Border
{
public static function render(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);
\SDL_SetRenderTarget($targetViewport->renderPtr, $texture);
\SDL_SetRenderDrawColor($targetViewport->renderPtr, 255, 255, 255, 0);
\SDL_RenderClear($targetViewport->renderPtr);
// Top
if($b->enabled && $b->top > 0) {
GFX::boxRGBA($targetViewport->renderPtr, 0, 0,
$targetViewport->width, $b->top, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
}
// Bottom
if($b->enabled && $b->bottom > 0) {
GFX::boxRGBA($targetViewport->renderPtr, 0, $targetViewport->height - $b->bottom,
$targetViewport->width, $targetViewport->height, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
}
// left
if($b->enabled && $b->left > 0) {
GFX::boxRGBA($targetViewport->renderPtr, 0, 0,
$b->left, $targetViewport->height, $b->color->red, $b->color->green, $b->color->blue, $b->color->alpha);
}
// right
if($b->enabled && $b->right > 0) {
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));
}
}
}

View File

@ -6,6 +6,7 @@ use PHPNative\UI\BaseView;
use PHPNative\UI\View;
use PHPNative\UI\Widget\Button;
use PHPNative\UI\Widget\Container;
use PHPNative\UI\Widget\Label;
class Widget
{
@ -17,6 +18,9 @@ class Widget
if($view instanceof Button) {
return \PHPNative\Renderer\Widgets\Button::render($thread, $viewPort, $view);
}
if($view instanceof Label) {
return \PHPNative\Renderer\Widgets\Label::render($thread, $viewPort, $view);
}
if($view instanceof Container) {
return \PHPNative\Renderer\Widgets\Container::render($thread, $viewPort, $view);
}

View File

@ -2,6 +2,7 @@
namespace PHPNative\Renderer\Widgets;
use PHPNative\Renderer\Item;
use PHPNative\Renderer\Thread;
use PHPNative\Renderer\Viewport;
use PHPNative\Renderer\Widget;
@ -26,9 +27,16 @@ class BaseView
}
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($texture, $rect, 0));
}
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
@ -38,8 +46,8 @@ class BaseView
$viewport->height -= ($m->bottom + $m->top);
}
if($view->getView() !== null) {
Widget::render($thread, $viewport, $view->getView());
if($view->getViews()->count() > 0) {
Widget::render($thread, $viewport, $view->getViews()->first());
}
return $viewport;

View File

@ -3,14 +3,19 @@
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;
@ -20,48 +25,32 @@ class Button
public static function render(Thread $thread, Viewport $viewport, \PHPNative\UI\Widget\Button $view): Viewport
{
$styles = StyleParser::parse($view->style)->getValidStyles($viewport->windowMediaQuery, $view->state);
$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);
if(isset($styles[Width::class]) && $m = $styles[Width::class]) {
if($styles[Width::class]->unit === Unit::Pixel) {
$viewport->width = $styles[Width::class]->value;
}elseif($styles[Width::class]->unit === Unit::Percent) {
$viewport->width = $viewport->width/100*$styles[Width::class]->value;
}
$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{
$viewport->width = $surface->w;
$viewport->height = $surface->h;
$color = new \SDL_Color(0, 0, 0, 255);
}
$surface = \SDL_TTF_RenderText_Blended($font, $view->label, $color);
$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->width += $m->right;
$viewport->height += $m->bottom;
}
$viewport->height += ($m->bottom + $m->top);
$bgX = $viewport->x;
$bgY = $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($bgX, $bgY, $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);
$textureX += $m->left;
$textureY += $m->top;
}
if($thread->getEvent() && $thread->getEvent()->getType() === EventType::MOUSEMOVE) {
@ -76,13 +65,161 @@ class Button
}
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 ) {
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->onClick();
}
}
$rect = new \SDL_FRect($viewport->x,$viewport->y,$surface->w,$surface->h);
\SDL_RenderTexture($viewport->renderPtr, $texture, null, $rect);
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);
$textureWidth -= ($m->right + $m->left);
$textureHeight += ($m->bottom + $m->top);
}
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));
}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,13 +2,19 @@
namespace PHPNative\Renderer\Widgets;
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\DirectionEnum;
use PHPNative\Tailwind\Style\Flex;
use PHPNative\Tailwind\Style\Margin;
use PHPNative\Tailwind\Style\Padding;
use PHPNative\Tailwind\Style\StateEnum;
use PHPNative\Tailwind\Style\Unit;
use PHPNative\Tailwind\Style\Width;
use PHPNative\Tailwind\StyleParser;
class Container
@ -16,19 +22,24 @@ 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);
}
if(isset($styles[Background::class]) && $bg = $styles[Background::class]) {
$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);
}
\PHPNative\Renderer\Visuals\Border::render($thread, $styles, $viewport);
if(isset($styles[Padding::class]) && $m = $styles[Padding::class]) {
$viewport->x += $m->left;
@ -37,8 +48,73 @@ class Container
$viewport->height -= ($m->bottom + $m->top);
}
foreach($view->subViews as $subView) {
Widget::render($thread, clone $viewport, $subView);
$flexStyles = [];
if($view->getViews() != null) {
foreach ($view->getViews() as $subView) {
$found = false;
$stylesSubView = StyleParser::parse($subView->style)->getValidStyles($viewport->windowMediaQuery, StateEnum::normal);
if (isset($stylesSubView[Basis::class]) && $b = $stylesSubView[Basis::class]) {
if ($b->unit == Unit::Percent) {
$width = round($viewport->width / 100 * $b->value);
} else {
$width = $b->value;
}
$found = true;
}
if (isset($stylesSubView[Width::class]) && $w = $stylesSubView[Width::class]) {
if ($w->unit == Unit::Percent) {
$width = round($viewport->width / 100 * $w->value);
} else {
$width = $w->value;
}
$found = true;
}
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);
} 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);
}
$flexStyles[] = $viepo;
} else {
$flexStyles[] = $viewport;
}
}
$topHeight = 0;
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;
$vp = Widget::render($thread, $subViewPort, $subView);
$viewport->y += $vp->height;
$viewport->height -= $vp->height;
} else {
$vp = Widget::render($thread, array_shift($flexStyles), $subView);
$topHeight = max($topHeight, $vp->height);
}
}
if (isset($styles[Flex::class]) && $f = $styles[Flex::class] && $styles[Flex::class]->direction == DirectionEnum::column) {
$textureHeight = $viewport->y;
} else {
$textureHeight = $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);
$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), 1));
}
}
return $viewport;

View File

@ -0,0 +1,130 @@
<?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 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);
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);
}
$surface = \SDL_TTF_RenderText_Blended($font, $view->label, $color);
$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;
}
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);
$textureWidth -= ($m->right + $m->left);
$textureHeight += ($m->bottom + $m->top);
}
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));
}else{
}
return $viewport;
}
}

View File

@ -3,6 +3,7 @@
namespace PHPNative\Tailwind\Model;
use PHPNative\Core\TypedCollection;
use PHPNative\Tailwind\Style\Border;
use PHPNative\Tailwind\Style\Margin;
use PHPNative\Tailwind\Style\MediaQueryEnum;
use PHPNative\Tailwind\Style\Padding;
@ -37,6 +38,8 @@ class StyleCollection extends TypedCollection
\PHPNative\Tailwind\Parser\Padding::merge($tmp[$style->style::class], $style->style);
}elseif(isset($tmp[$style->style::class]) && $style->style::class === Margin::class) {
\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);
}else{
$tmp[$style->style::class] = $style->style;
}

View File

@ -6,7 +6,7 @@ namespace PHPNative\Tailwind\Parser;
class Background implements Parser
{
public static function parse(string $style): \PHPNative\Tailwind\Style\Background
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Background
{
$color = new \PHPNative\Tailwind\Style\Color();
@ -14,9 +14,9 @@ class Background implements Parser
if (count($output_array[0]) > 0) {
$colorStyle = $output_array[1][0];
$color = Color::parse($colorStyle);
return new \PHPNative\Tailwind\Style\Background($color);
}
return new \PHPNative\Tailwind\Style\Background($color);
return null;
}
}

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Parser;
use PHPNative\Tailwind\Style\Unit;
class Basis implements Parser
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Basis
{
$value = -1;
$unit = Unit::Pixel;
$found = false;
preg_match_all('/basis-(\d*)\/(\d*)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$value1 = (int)$output_array[1][0];
$value2 = (int)$output_array[2][0];
$unit = Unit::Percent;
$value = (int)round(100/$value2*$value1,0);
$found = true;
}
preg_match_all('/basis-(\d*)/', $style, $output_array);
if (!$found && count($output_array[0]) > 0) {
$value = (int)$output_array[1][0];
}
preg_match_all('/basis-full/', $style, $output_array);
if (!$found && count($output_array[0]) > 0) {
$value = 100;
$unit = Unit::Percent;
}
if($value != -1) {
return new \PHPNative\Tailwind\Style\Basis($unit, $value);
}
return null;
}
public static function merge(\PHPNative\Tailwind\Style\Padding $class, \PHPNative\Tailwind\Style\Padding $style)
{
if($style->left != null) {
$class->left = $style->left;
}
if($style->right != null) {
$class->right = $style->right;
}
if($style->top != null) {
$class->top = $style->top;
}
if($style->bottom != null) {
$class->bottom = $style->bottom;
}
}
}

View File

@ -0,0 +1,121 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Parser;
class Border implements Parser
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Border
{
$color = new \PHPNative\Tailwind\Style\Color();
preg_match_all('/rounded-(t|b|l|r)-(none|sm|md|lg|xl|2xl|3xl)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$size = match ((string)$output_array[2][0]) {
'none' => 0,
'sm' => 2,
'md' => 6,
'lg' => 8,
'xl' => 12,
'2xl' => 16,
'3xl' => 24
};
return match ((string)$output_array[1][0]) {
't' => new \PHPNative\Tailwind\Style\Border(roundTop: $size),
'b' => new \PHPNative\Tailwind\Style\Border(roundBottom: $size),
'r' => new \PHPNative\Tailwind\Style\Border(roundRight: $size),
'l' => new \PHPNative\Tailwind\Style\Border(roundLeft: $size),
};
}
preg_match_all('/rounded-(none|sm|md|lg|xl|2xl|3xl)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$size = match ((string)$output_array[1][0]) {
'none' => 0,
'sm' => 2,
'md' => 6,
'lg' => 8,
'xl' => 12,
'2xl' => 16,
'3xl' => 24
};
return new \PHPNative\Tailwind\Style\Border(roundTop: $size, roundLeft: $size, roundRight: $size, roundBottom: $size);
}
preg_match_all('/rounded/', $style, $output_array);
if (count($output_array[0]) > 0) {
$size = 4;
return new \PHPNative\Tailwind\Style\Border(roundTop: $size, roundLeft: $size, roundRight: $size, roundBottom: $size);
}
preg_match_all('/border-([tblr])-(.*)/', $style, $output_array);
if (count($output_array[0]) > 0) {
return match ((string)$output_array[1][0]) {
't' => new \PHPNative\Tailwind\Style\Border(true, top: (int)$output_array[2][0]),
'b' => new \PHPNative\Tailwind\Style\Border(true, bottom: (int)$output_array[2][0]),
'r' => new \PHPNative\Tailwind\Style\Border(true, right: (int)$output_array[2][0]),
'l' => new \PHPNative\Tailwind\Style\Border(true, left: (int)$output_array[2][0])
};
}
preg_match_all('/border-(.*)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$colorStyle = $output_array[1][0];
$color = Color::parse($colorStyle);
return new \PHPNative\Tailwind\Style\Border(false, $color);
}
preg_match_all('/border/', $style, $output_array);
if (count($output_array[0]) > 0) {
return new \PHPNative\Tailwind\Style\Border(enabled: true, left: 1, right: 1, top: 1, bottom: 1);
}
return null;
}
public static function merge(\PHPNative\Tailwind\Style\Border $style1, \PHPNative\Tailwind\Style\Border $style2): void
{
if($style2->enabled && !$style1->enabled) {
$style1->enabled = true;
}
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->top != -1) {
$style1->top = $style2->top;
}
if($style2->bottom != -1) {
$style1->bottom = $style2->bottom;
}
if($style2->left != -1) {
$style1->left = $style2->left;
}
if($style2->right != -1) {
$style1->right = $style2->right;
}
if($style2->roundTop != -1) {
$style1->roundTop = $style2->roundTop;
}
if($style2->roundBottom != -1) {
$style1->roundBottom = $style2->roundBottom;
}
if($style2->roundRight != -1) {
$style1->roundRight = $style2->roundRight;
}
if($style2->roundLeft != -1) {
$style1->roundLeft = $style2->roundLeft;
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace PHPNative\Tailwind\Parser;
use PHPNative\Tailwind\Style\DirectionEnum;
class Flex implements Parser
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Style
{
preg_match_all('/flex-col/', $style, $output_array);
if (count($output_array[0]) > 0) {
return new \PHPNative\Tailwind\Style\Flex(DirectionEnum::column);
}
preg_match_all('/(?!flex-col)(flex-row|flex)/', $style, $output_array);
if (count($output_array[0]) > 0) {
return new \PHPNative\Tailwind\Style\Flex(DirectionEnum::row);
}
return null;
}
}

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Parser;
use PHPNative\Tailwind\Style\Unit;
class Height implements Parser
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Height
{
$value = -1;
$unit = Unit::Pixel;
$found = false;
preg_match_all('/h-(\d*)\/(\d*)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$value1 = (int)$output_array[1][0];
$value2 = (int)$output_array[2][0];
$unit = Unit::Percent;
$value = 100/$value2*$value1;
$found = true;
}
preg_match_all('/h-(\d*)/', $style, $output_array);
if (!$found && count($output_array[0]) > 0) {
$value = (int)$output_array[1][0];
}
preg_match_all('/(h-full|h-screen)/', $style, $output_array);
if (!$found && count($output_array[0]) > 0) {
$value = 100;
$unit = Unit::Percent;
}
if($value != -1) {
return new \PHPNative\Tailwind\Style\Height($unit, $value);
}
return null;
}
public static function merge(\PHPNative\Tailwind\Style\Padding $class, \PHPNative\Tailwind\Style\Padding $style)
{
if($style->left != null) {
$class->left = $style->left;
}
if($style->right != null) {
$class->right = $style->right;
}
if($style->top != null) {
$class->top = $style->top;
}
if($style->bottom != null) {
$class->bottom = $style->bottom;
}
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Parser;
class Text implements Parser
{
public static function parse(string $style): ?\PHPNative\Tailwind\Style\Text
{
$color = new \PHPNative\Tailwind\Style\Color();
preg_match_all('/text-(.*)/', $style, $output_array);
if (count($output_array[0]) > 0) {
$colorStyle = $output_array[1][0];
$color = Color::parse($colorStyle);
return new \PHPNative\Tailwind\Style\Text($color);
}
return null;
}
}

View File

@ -27,14 +27,12 @@ class Width implements Parser
$value = (int)$output_array[1][0];
}
preg_match_all('/w-full/', $style, $output_array);
preg_match_all('/(w-screen|w-full)/', $style, $output_array);
if (!$found && count($output_array[0]) > 0) {
$value = 100;
$unit = Unit::Percent;
}
if($value != -1) {
return new \PHPNative\Tailwind\Style\Width($unit, $value);
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
class Basis implements Style
{
public function __construct(public Unit $unit = Unit::Pixel, public int $value = 0)
{
}
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
class Border implements Style
{
public function __construct(public bool $enabled = false, public Color $color = new Color(),
public int $left = -1, public int $right = -1, public int $top = -1, public int $bottom = -1,
public int $roundLeft = -1, public int $roundRight = -1, public int $roundTop = -1, public int $roundBottom = -1)
{
}
}

View File

@ -6,7 +6,7 @@ namespace PHPNative\Tailwind\Style;
class Color implements Style
{
public function __construct(public int $red = 255, public int $green = 255, public int $blue = 255, public int $alpha = 0)
public function __construct(public int $red = -1, public int $green = -1, public int $blue = -1, public int $alpha = 255)
{
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace PHPNative\Tailwind\Style;
enum DirectionEnum
{
case row;
case column;
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
class Flex implements Style
{
public function __construct(public DirectionEnum $direction = DirectionEnum::row)
{
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
class Height implements Style
{
public function __construct(public Unit $unit = Unit::Pixel, public int $value = 0)
{
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Style;
class Text implements Style
{
public function __construct(public Color $color = new Color())
{
}
}

View File

@ -15,6 +15,9 @@ class StyleParser
public static function parse($style, int $width = 0): StyleCollection
{
$computed = new StyleCollection();
if($style === null || strlen(trim($style)) === 0) {
return $computed;
}
$styles = explode(" ", $style);
foreach($styles as $styleStr) {
@ -46,9 +49,21 @@ class StyleParser
if($w = \PHPNative\Tailwind\Parser\Width::parse($style)) {
return $w;
}
if($b = \PHPNative\Tailwind\Parser\Basis::parse($style)) {
return $b;
}
if($f = \PHPNative\Tailwind\Parser\Flex::parse($style)) {
return $f;
}
if($bg = \PHPNative\Tailwind\Parser\Background::parse($style)) {
return $bg;
}
if($t = \PHPNative\Tailwind\Parser\Text::parse($style)) {
return $t;
}
if($b = \PHPNative\Tailwind\Parser\Border::parse($style)) {
return $b;
}
return null;
}

View File

@ -20,6 +20,16 @@ class BackgroundTest extends TestCase
$this->assertSame(203, $bg->color->red);
$this->assertSame(213, $bg->color->green);
$this->assertSame(225, $bg->color->blue);
$this->assertSame(0, $bg->color->alpha);
$this->assertSame(255, $bg->color->alpha);
}
public function test_gray_background(): void
{
$bg = Background::parse("flex bg-gray-300");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Background::class, $bg);
$this->assertSame(209, $bg->color->red);
$this->assertSame(213, $bg->color->green);
$this->assertSame(219, $bg->color->blue);
$this->assertSame(255, $bg->color->alpha);
}
}

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Basis;
use PHPNative\Tailwind\Style\Unit;
use PHPUnit\Framework\TestCase;
class BasisTest extends TestCase
{
public function test_basis_pixel(): void
{
$basis = Basis::parse("basis-10");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Basis::class, $basis);
$this->assertSame(10, $basis->value);
$this->assertSame(Unit::Pixel, $basis->unit);
}
public function test_basis_percent_full(): void
{
$basis = Basis::parse("basis-full");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Basis::class, $basis);
$this->assertSame(100, $basis->value);
$this->assertSame(Unit::Percent, $basis->unit);
}
public function test_basis_percent_one_half(): void
{
$basis = Basis::parse("basis-1/2");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Basis::class, $basis);
$this->assertSame(50, $basis->value);
$this->assertSame(Unit::Percent, $basis->unit);
}
public function test_basis_percent_second_third(): void
{
$basis = Basis::parse("basis-3/4");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Basis::class, $basis);
$this->assertSame(75, $basis->value);
$this->assertSame(Unit::Percent, $basis->unit);
}
}

View File

@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Border;
use PHPNative\Tailwind\Style\MediaQueryEnum;
use PHPNative\Tailwind\Style\StateEnum;
use PHPNative\Tailwind\StyleParser;
use PHPUnit\Framework\TestCase;
/**
* @internal
* @small
*/
class BorderTest extends TestCase
{
public function test_border(): void
{
$border = Border::parse("border-slate-300");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $border);
$this->assertSame(203, $border->color->red);
$this->assertSame(213, $border->color->green);
$this->assertSame(225, $border->color->blue);
$this->assertSame(255, $border->color->alpha);
$this->assertSame(false, $border->enabled);
}
public function test_gray_border(): void
{
$border = Border::parse("flex border-gray-300");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $border);
$this->assertSame(209, $border->color->red);
$this->assertSame(213, $border->color->green);
$this->assertSame(219, $border->color->blue);
$this->assertSame(255, $border->color->alpha);
$this->assertSame(-1, $border->left);
$this->assertSame(-1, $border->right);
$this->assertSame(-1, $border->top);
$this->assertSame(-1, $border->bottom);
$this->assertSame(false, $border->enabled);
}
public function test_enabled(): void
{
$border = Border::parse("flex border");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $border);
$this->assertSame(true, $border->enabled);
}
public function test_border_complex(): void
{
$styles = StyleParser::parse("flex border border-gray-300 hover:border-lime-400")->getValidStyles(MediaQueryEnum::lx, StateEnum::normal);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(209, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(213, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(219, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
public function test_border_complex_hover(): void
{
$styles = StyleParser::parse("flex border border-gray-300 hover:border-lime-400")->getValidStyles(MediaQueryEnum::lx, StateEnum::hover);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(163, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(230, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(53, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
public function test_border_top(): void
{
$styles = StyleParser::parse("flex border-t-4 border-gray-300")->getValidStyles(MediaQueryEnum::lx, StateEnum::normal);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(209, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(213, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(219, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
public function test_border_rounded(): void
{
$styles = StyleParser::parse("flex rounded border-t-4 border-gray-300")->getValidStyles(MediaQueryEnum::lx, StateEnum::normal);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(209, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(213, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(219, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->roundLeft);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->roundRight);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
public function test_border_rounded_xl(): void
{
$styles = StyleParser::parse("flex rounded-xl border-t-4 border-gray-300")->getValidStyles(MediaQueryEnum::lx, StateEnum::normal);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(209, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(213, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(219, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(12, $styles[\PHPNative\Tailwind\Style\Border::class]->roundLeft);
$this->assertSame(12, $styles[\PHPNative\Tailwind\Style\Border::class]->roundRight);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
public function test_border_rounded_top_xl(): void
{
$styles = StyleParser::parse("flex rounded-t-xl border-t-4 border-gray-300")->getValidStyles(MediaQueryEnum::lx, StateEnum::normal);
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Border::class, $styles[\PHPNative\Tailwind\Style\Border::class]);
$this->assertSame(209, $styles[\PHPNative\Tailwind\Style\Border::class]->color->red);
$this->assertSame(213, $styles[\PHPNative\Tailwind\Style\Border::class]->color->green);
$this->assertSame(219, $styles[\PHPNative\Tailwind\Style\Border::class]->color->blue);
$this->assertSame(255, $styles[\PHPNative\Tailwind\Style\Border::class]->color->alpha);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->left);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->right);
$this->assertSame(4, $styles[\PHPNative\Tailwind\Style\Border::class]->top);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->bottom);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->roundLeft);
$this->assertSame(12, $styles[\PHPNative\Tailwind\Style\Border::class]->roundTop);
$this->assertSame(-1, $styles[\PHPNative\Tailwind\Style\Border::class]->roundRight);
$this->assertSame(true, $styles[\PHPNative\Tailwind\Style\Border::class]->enabled);
}
}

View File

@ -20,7 +20,7 @@ class ColorTest extends TestCase
$this->assertSame(239, $color->red);
$this->assertSame(68, $color->green);
$this->assertSame(68, $color->blue);
$this->assertSame(0, $color->alpha);
$this->assertSame(255, $color->alpha);
}
public function test_name_variant(): void
@ -30,7 +30,7 @@ class ColorTest extends TestCase
$this->assertSame(190, $color->red);
$this->assertSame(242, $color->green);
$this->assertSame(100, $color->blue);
$this->assertSame(0, $color->alpha);
$this->assertSame(255, $color->alpha);
}
public function test_white(): void
@ -40,7 +40,7 @@ class ColorTest extends TestCase
$this->assertSame(255, $color->red);
$this->assertSame(255, $color->green);
$this->assertSame(255, $color->blue);
$this->assertSame(0, $color->alpha);
$this->assertSame(255, $color->alpha);
}
public function test_black(): void
@ -50,6 +50,6 @@ class ColorTest extends TestCase
$this->assertSame(0, $color->red);
$this->assertSame(0, $color->green);
$this->assertSame(0, $color->blue);
$this->assertSame(0, $color->alpha);
$this->assertSame(255, $color->alpha);
}
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Flex;
use PHPNative\Tailwind\Style\DirectionEnum;
use PHPUnit\Framework\TestCase;
class FlexTest extends TestCase
{
public function test_container_flex(): void
{
$flex = Flex::parse("flex");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Flex::class, $flex);
$this->assertSame(DirectionEnum::row, $flex->direction);
}
public function test_container_flex_row(): void
{
$flex = Flex::parse("flex flex-row");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Flex::class, $flex);
$this->assertSame(DirectionEnum::row, $flex->direction);
}
public function test_container_flex_col(): void
{
$flex = Flex::parse("flex flex-col");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Flex::class, $flex);
$this->assertSame(DirectionEnum::column, $flex->direction);
}
}

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Height;
use PHPNative\Tailwind\Style\Unit;
use PHPUnit\Framework\TestCase;
class HeightTest extends TestCase
{
public function test_height_pixel(): void
{
$height = Height::parse("h-10");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Height::class, $height);
$this->assertSame(10, $height->value);
$this->assertSame(Unit::Pixel, $height->unit);
}
public function test_height_percent_full(): void
{
$height = Height::parse("h-full");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Height::class, $height);
$this->assertSame(100, $height->value);
$this->assertSame(Unit::Percent, $height->unit);
}
public function test_height_percent_screen(): void
{
$height = Height::parse("h-screen");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Height::class, $height);
$this->assertSame(100, $height->value);
$this->assertSame(Unit::Percent, $height->unit);
}
public function test_height_percent_one_half(): void
{
$height = Height::parse("h-1/2");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Height::class, $height);
$this->assertSame(50, $height->value);
$this->assertSame(Unit::Percent, $height->unit);
}
public function test_height_percent_second_third(): void
{
$height = Height::parse("h-3/4");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Height::class, $height);
$this->assertSame(75, $height->value);
$this->assertSame(Unit::Percent, $height->unit);
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace PHPNative\Tailwind\Tests;
use PHPNative\Tailwind\Parser\Text;
use PHPUnit\Framework\TestCase;
/**
* @internal
* @small
*/
class TextTest extends TestCase
{
public function test_text(): void
{
$text = Text::parse("text-slate-300");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Text::class, $text);
$this->assertSame(203, $text->color->red);
$this->assertSame(213, $text->color->green);
$this->assertSame(225, $text->color->blue);
$this->assertSame(255, $text->color->alpha);
}
public function test_gray_text(): void
{
$text = Text::parse("flex text-gray-300");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Text::class, $text);
$this->assertSame(209, $text->color->red);
$this->assertSame(213, $text->color->green);
$this->assertSame(219, $text->color->blue);
$this->assertSame(255, $text->color->alpha);
}
}

View File

@ -26,6 +26,14 @@ class WidthTest extends TestCase
$this->assertSame(Unit::Percent, $width->unit);
}
public function test_width_percent_screen(): void
{
$width = Width::parse("w-screen");
$this->assertInstanceOf(\PHPNative\Tailwind\Style\Width::class, $width);
$this->assertSame(100, $width->value);
$this->assertSame(Unit::Percent, $width->unit);
}
public function test_width_percent_one_half(): void
{
$width = Width::parse("w-1/2");

View File

@ -2,20 +2,21 @@
namespace PHPNative\UI;
use PHPNative\UI\Collection\Views;
use PHPNative\UI\Trait\Style;
class BaseView implements View
{
use Style;
public ?View $view = null;
public ?Views $views = null;
public function __construct()
{
}
public function getView(): ?View
public function getViews(): ?Views
{
return $this->view;
return $this->views;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace PHPNative\UI\Collection;
use PHPNative\Core\TypedCollection;
class Views extends TypedCollection
{
protected function type(): string
{
return \PHPNative\UI\View::class;
}
}

View File

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace PHPNative\UI;
use PHPNative\UI\Collection\Views;
interface View
{
public function getView(): ?View;
public function getViews(): ?Views;
}

View File

@ -19,7 +19,7 @@ class Button implements View
{
}
public function getView(): ?View
public function getViews(): ?\PHPNative\UI\Collection\Views
{
}
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace PHPNative\UI\Widget;
use PHPNative\UI\Collection\Views;
use PHPNative\UI\Trait\Style;
use PHPNative\UI\View;
@ -11,11 +12,12 @@ class Container implements View
{
use Style;
public function __construct(public array $subViews)
public function __construct(string $style = "")
{
$this->style = $style;
}
public function getView(): ?View
public function getViews(): ?Views
{
return null;
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace PHPNative\UI\Widget;
use PHPNative\UI\Trait\Action\Click;
use PHPNative\UI\Trait\State;
use PHPNative\UI\Trait\Style;
use PHPNative\UI\View;
class Label implements View
{
use Style;
use State;
public function __construct(public string $label, string $style = '')
{
$this->style = $style;
}
public function getViews(): ?\PHPNative\UI\Collection\Views
{
}
}