-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from phpgl/feature/flyui
FlyUI Basisc
- Loading branch information
Showing
21 changed files
with
1,657 additions
and
34 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace VISU\FlyUI\Exception; | ||
|
||
class FlyUiInitException extends FlyUiException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
{ | ||
} |
Oops, something went wrong.