Accedi
IT
games/xencenter-xenadmin-xcp-jumphp / src / Gui / PopupMenu.php · commit fb1b7c9
<?phpnamespace App\Gui;use JumPHP\Gui\Theme;use JumPHP\Renderer\Renderer;/** * A drop-down list of commands (a menu of the menu bar, a right click's menu), drawn over the form. * Items: ['id' => 'vm.start', 'text' => 'Start', 'enabled' => true, 'icon' => 'power-on', 'shortcut' => 'Ctrl+B'] or '-' (a line). */final class PopupMenu{    /** @var list<array<string, mixed>|string> */    public array $items = [];    public float $x = 0;    public float $y = 0;    public float $w = 0;    public float $h = 0;    public int $hover = -1;    /** @param list<array<string, mixed>|string> $items */    public function __construct(array $items, float $x, float $y, Theme $t, float $viewW, float $viewH)    {        $this->items = array_values($items);        $font = $t->font();        $w = $t->px(160);        foreach ($this->items as $item) {            if (is_array($item)) {                $w = max($w, $font->width(\JumPHP\Util\Lang::t((string)$item['text'])) + $t->px(64) + (isset($item['shortcut']) ? $font->width((string)$item['shortcut']) + $t->px(24) : 0));            }        }        $h = $t->px(10);        foreach ($this->items as $item) {            $h += $this->rowHeight($t, $item);        }        $this->w = $w;        $this->h = $h;        $this->x = max(0, min($x, $viewW - $w - 2));        $this->y = $y + $h > $viewH ? max(0, $y - $h) : $y;    }    public function rowHeight(Theme $t, array|string $item): float    {        return is_string($item) ? $t->px(9) : $t->px(30);    }    public function contains(float $px, float $py): bool    {        return $px >= $this->x && $px < $this->x + $this->w && $py >= $this->y && $py < $this->y + $this->h;    }    public function indexAt(Theme $t, float $py): int    {        $y = $this->y + $t->px(5);        foreach ($this->items as $i => $item) {            $h = $this->rowHeight($t, $item);            if ($py >= $y && $py < $y + $h) {                return is_array($item) ? $i : -1;            }            $y += $h;        }        return -1;    }    /** @return array<string, mixed>|null the item there, when it can be chosen */    public function pick(Theme $t, float $py): ?array    {        $item = $this->items[$this->indexAt($t, $py)] ?? null;        return is_array($item) && ($item['enabled'] ?? true) ? $item : null;    }    public function render(Renderer $r, Theme $t): void    {        $t->box($r, $this->x + $t->px(2), $this->y + $t->px(4), $this->w, $this->h, [0, 0, 0, 34], $t->px(8));        $t->frame($r, $this->x, $this->y, $this->w, $this->h, '#ffffff', '#cfd6e0', $t->px(7));        $font = $t->font();        $y = $this->y + $t->px(5);        foreach ($this->items as $i => $item) {            $h = $this->rowHeight($t, $item);            if (is_string($item)) {                $r->fillRect($this->x + $t->px(10), $y + $h / 2, $this->w - $t->px(20), 1, '#e3e7ed');            } else {                $enabled = (bool)($item['enabled'] ?? true);                if ($i === $this->hover && $enabled) {                    $t->box($r, $this->x + $t->px(4), $y + $t->px(1), $this->w - $t->px(8), $h - $t->px(2), '#e3edfc', $t->px(5));                }                if (!empty($item['icon'])) {                    Icons::draw($r, (string)$item['icon'], $this->x + $t->px(10), $y + ($h - $t->px(16)) / 2, $t->px(16));                    if (!$enabled) {                        $r->fillRect($this->x + $t->px(10), $y + ($h - $t->px(16)) / 2, $t->px(16), $t->px(16), [255, 255, 255, 170]);                    }                }                if (!empty($item['checked'])) {                    $r->fillRect($this->x + $t->px(10), $y + $h / 2 - $t->px(1), $t->px(8), $t->px(3), '#333333');                }                $color = $enabled ? '#1f2329' : '#a6adb7';                $font->draw($r, \JumPHP\Util\Lang::t((string)$item['text']), $this->x + $t->px(38), $y + ($h - $font->height()) / 2, 1, $color);                if (isset($item['shortcut'])) {                    $font->draw($r, (string)$item['shortcut'], $this->x + $this->w - $t->px(12), $y + ($h - $font->height()) / 2, 1, '#707070', 'right');                }            }            $y += $h;        }    }}