Skip to content

Commit

Permalink
Merge pull request #8 from phpgl/feature/flyui
Browse files Browse the repository at this point in the history
FlyUI Basisc
  • Loading branch information
mario-deluna authored Aug 29, 2024
2 parents 95a5d85 + 2de0d07 commit 38cb7cf
Show file tree
Hide file tree
Showing 21 changed files with 1,657 additions and 34 deletions.
Binary file added resources/fonts/inter/Inter-Regular.ttf
Binary file not shown.
Binary file added resources/fonts/inter/Inter-SemiBold.ttf
Binary file not shown.
9 changes: 9 additions & 0 deletions src/FlyUI/Exception/FlyUiException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace VISU\FlyUI\Exception;

use VISU\Exception\VISUException;

class FlyUiException extends VISUException
{
}
7 changes: 7 additions & 0 deletions src/FlyUI/Exception/FlyUiInitException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace VISU\FlyUI\Exception;

class FlyUiInitException extends FlyUiException
{
}
156 changes: 156 additions & 0 deletions src/FlyUI/FUIButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?php

namespace VISU\FlyUI;

use GL\Math\Vec2;
use GL\VectorGraphics\VGAlign;
use GL\VectorGraphics\VGColor;
use VISU\OS\MouseButton;

class FUIButton extends FUIView
{
public VGColor $backgroundColor;

public VGColor $hoverBackgroundColor;

public VGColor $textColor;

public float $borderRadius;

public float $fontSize;

public string $buttonId;

/**
* Constructs a new view
*/
public function __construct(
public string $text,
public ?\Closure $onClick = null,
?string $buttonId = null
)
{
parent::__construct(FlyUI::$instance->theme->buttonPadding);

$this->backgroundColor = FlyUI::$instance->theme->buttonPrimaryBackgroundColor;
$this->hoverBackgroundColor = FlyUI::$instance->theme->buttonPrimaryHoverBackgroundColor;
$this->textColor = FlyUI::$instance->theme->buttonPrimaryTextColor;
$this->borderRadius = FlyUI::$instance->theme->buttonBorderRadius;
$this->fontSize = FlyUI::$instance->theme->buttonFontSize;

// button ID by default just the text, this means that if
// you have multiple buttons with the same text, you have to assign a custom ID
$this->buttonId = $buttonId ?? 'btn_' . $this->text;
}

/**
* Sets the button ID
*/
public function setId(string $id) : self
{
$this->buttonId = $id;
return $this;
}

/**
* Returns the height of the current view and its children
* This is used for layouting purposes
*/
public function getEstimatedHeight(FUIRenderContext $ctx) : float
{
return $this->fontSize + $this->padding->y * 2;
}

/**
* Returns the width of the current view and its children
*
* Note: This is used for layouting in some sizing modes
*/
public function getEstimatedWidth(FUIRenderContext $ctx) : float
{
$ctx->ensureFontFace('inter-semibold');
$ctx->vg->fontSize($this->fontSize);
return $ctx->vg->textBounds(0, 0, $this->text) + $this->padding->x * 2;
}

/**
* Renders the current view using the provided context
*/
public function render(FUIRenderContext $ctx) : float
{
$height = $this->getEstimatedHeight($ctx);
$width = $this->getEstimatedWidth($ctx);

// update the container size based on the determined height
$ctx->containerSize->y = $height;
$ctx->containerSize->x = $width;

// Check if the mouse is inside the button
$isInside = $ctx->isHovered();

static $fuiButtonPressStates = [];
if (!isset($fuiButtonPressStates[$this->buttonId])) {
$fuiButtonPressStates[$this->buttonId] = false;
}

if ($isInside && $ctx->input->isMouseButtonPressed(MouseButton::LEFT)) {

// render a ring around the button when pressed
$ctx->vg->beginPath();
$ctx->vg->strokeColor($this->backgroundColor);
$ctx->vg->strokeWidth(2);
$ringDistance = 2;
$ctx->vg->roundedRect(
$ctx->origin->x - $ringDistance,
$ctx->origin->y - $ringDistance,
$ctx->containerSize->x + $ringDistance * 2,
$height + $ringDistance * 2,
$this->borderRadius
);
$ctx->vg->stroke();


if (!$fuiButtonPressStates[$this->buttonId]) {
$fuiButtonPressStates[$this->buttonId] = true;
if ($this->onClick !== null) {
($this->onClick)();
}
}
} else {
$fuiButtonPressStates[$this->buttonId] = false;
}

// render the button background
$ctx->vg->beginPath();
$ctx->vg->fillColor($this->backgroundColor);

if ($isInside) {
$ctx->vg->fillColor($this->hoverBackgroundColor);
}

$ctx->vg->roundedRect(
$ctx->origin->x,
$ctx->origin->y,
$ctx->containerSize->x,
$height,
$this->borderRadius
);
$ctx->vg->fill();

// move origin to the center of the button
$ctx->origin->x = $ctx->origin->x + $ctx->containerSize->x * 0.5;
$ctx->origin->y = $ctx->origin->y + $height * 0.5;

// we cheat a little bit here, basically the technical correct center just
// doesnt look right because at least in my opinion the text should be in the center
// wile ignoring letters like 'g' or 'y' that go below the baseline
$ctx->origin->y = floor($ctx->origin->y + $this->fontSize * 0.15);

$ctx->vg->textAlign(VGAlign::CENTER | VGAlign::MIDDLE);
$ctx->vg->fillColor($this->textColor);
$ctx->vg->text($ctx->origin->x, $ctx->origin->y, $this->text);

// no pass to parent, as this is a leaf element
return $height;
}
}
68 changes: 68 additions & 0 deletions src/FlyUI/FUICard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace VISU\FlyUI;

use GL\VectorGraphics\VGColor;

class FUICard extends FUILayout
{
public VGColor $backgroundColor;

public float $borderRadius;

public ?VGColor $borderColor;

public float $borderWidth;

/**
* Constructs a new view
*/
public function __construct()
{
parent::__construct(FlyUI::$instance->theme->cardPadding);

$this->backgroundColor = FlyUI::$instance->theme->cardBackgroundColor;
$this->borderRadius = FlyUI::$instance->theme->cardBorderRadius;
$this->borderColor = FlyUI::$instance->theme->cardBorderColor;
$this->borderWidth = FlyUI::$instance->theme->cardBorderWidth;
$this->spacingY = FlyUI::$instance->theme->cardSpacing;
}

/**
* Renders the current view using the provided context
*/
public function renderContent(FUIRenderContext $ctx) : void
{
$finalPos = $ctx->origin;
$finalSize = $ctx->containerSize;

// borders are always drawn inset in FlyUI, as VG draws them in the middle
// we have to adjust the position and size of the rectangle
if ($this->borderColor) {
$finalPos->x = $finalPos->x + $this->borderWidth * 0.5;
$finalPos->y = $finalPos->y + $this->borderWidth * 0.5;
$finalSize->x = $finalSize->x - $this->borderWidth;
$finalSize->y = $finalSize->y - $this->borderWidth;
}

$ctx->vg->beginPath();
$ctx->vg->fillColor($this->backgroundColor);
$ctx->vg->roundedRect(
$finalPos->x,
$finalPos->y,
$finalSize->x,
$finalSize->y,
$this->borderRadius
);
$ctx->vg->fill();

if ($this->borderColor) {
$ctx->vg->strokeColor($this->borderColor);
$ctx->vg->strokeWidth($this->borderWidth);
$ctx->vg->stroke();
}

// pass to children
parent::renderContent($ctx);
}
}
100 changes: 100 additions & 0 deletions src/FlyUI/FUICheckbox.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace VISU\FlyUI;

use GL\Math\Vec2;
use GL\VectorGraphics\VGAlign;
use GL\VectorGraphics\VGColor;
use VISU\OS\MouseButton;

class FUICheckbox extends FUIView
{
private const FUI_HEIGHT = 24.0;

/**
* Constructs a new view
*/
public function __construct(
public string $text,
public bool &$checked,
)
{
parent::__construct();
}

/**
* Returns the height of the current view and its children
* This is used for layouting purposes
*/
public function getEstimatedHeight(FUIRenderContext $ctx) : float
{
return self::FUI_HEIGHT;
}

/**
* Renders the current view using the provided context
*/
public function render(FUIRenderContext $ctx) : float
{
$height = $this->getEstimatedHeight($ctx);

$ctx->containerSize->y = $height;

$isInside = $ctx->isHovered();

if ($ctx->triggeredOnce('swt_' . $this->text, $isInside && $ctx->input->isMouseButtonPressed(MouseButton::LEFT))) {
$this->checked = !$this->checked;
}

$switchWidth = self::FUI_HEIGHT * 2;

// first a background
$bgColor = $this->checked ? FlyUI::$instance->theme->checkboxActiveBackgroundColor : FlyUI::$instance->theme->checkboxBackgroundColor;
if ($isInside) {
$bgColor = $this->checked ? $bgColor->lighten(0.05) : $bgColor->darken(0.05);
}

// border
$ctx->vg->strokeColor($bgColor->darken(0.1));
$ctx->vg->strokeWidth(1.0);

$ctx->vg->beginPath();
$ctx->vg->fillColor($bgColor);
$ctx->vg->roundedRect(
$ctx->origin->x,
$ctx->origin->y + 1,
$switchWidth,
self::FUI_HEIGHT - 2,
(self::FUI_HEIGHT - 2) * 0.5
);
$ctx->vg->stroke();
$ctx->vg->fill();

$knobX = $ctx->origin->x + ($this->checked ? $switchWidth - self::FUI_HEIGHT : 0);

// render a little circle in the middle
$ctx->vg->beginPath();
$ctx->vg->fillColor(VGColor::white());
$ctx->vg->circle(
$knobX + self::FUI_HEIGHT * 0.5,
$ctx->origin->y + self::FUI_HEIGHT * 0.5,
self::FUI_HEIGHT * 0.35
);
$ctx->vg->fill();
$ctx->vg->stroke();

// render the text next to the switch
$ctx->ensureFontFace('inter-regular');
$ctx->vg->textAlign(VGAlign::LEFT | VGAlign::MIDDLE);
$ctx->vg->fontSize(FlyUI::$instance->theme->fontSize);
$ctx->vg->fillColor(VGColor::black());
$ctx->vg->text(
$ctx->origin->x + $switchWidth + FlyUI::$instance->theme->padding,
$ctx->origin->y + self::FUI_HEIGHT * 0.5,
$this->text
);

// no pass to parent, as this is a leaf element
return $height;
}
}
9 changes: 9 additions & 0 deletions src/FlyUI/FUIException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace VISU\FlyUI;

use VISU\Exception\VISUException;

class FUIException extends VISUException
{
}
Loading

0 comments on commit 38cb7cf

Please sign in to comment.