From a96cffedc7a9b4cec1d6308f03c5c2e7df6cd008 Mon Sep 17 00:00:00 2001 From: Aydin Hassan Date: Sun, 22 Dec 2019 19:41:14 +0100 Subject: [PATCH] Attempt to resize menu on terminal resize --- composer.json | 2 +- examples/submenu.php | 1 + src/CliMenu.php | 14 ++++++++++++++ src/MenuStyle.php | 28 ++++++++++++++++++++++++++++ src/Terminal/TerminalFactory.php | 3 ++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 9d13e359..f53074a1 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require": { "php" : ">=7.1", "beberlei/assert": "^2.4 | ^3", - "php-school/terminal": "^0.2.1", + "php-school/terminal": "dev-feature/signals", "ext-posix": "*" }, "autoload" : { diff --git a/examples/submenu.php b/examples/submenu.php index 4846f593..8620dd6d 100644 --- a/examples/submenu.php +++ b/examples/submenu.php @@ -22,6 +22,7 @@ ->addLineBreak('-'); }) ->setWidth(70) + ->setMarginAuto() ->setBackgroundColour('yellow') ->build(); diff --git a/src/CliMenu.php b/src/CliMenu.php index c57ca5ff..162f01b2 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -116,6 +116,14 @@ public function __construct( $this->radioStyle = new RadioStyle(); $this->selectableStyle = new SelectableStyle(); + $this->terminal->onSignal(SIGWINCH, function () { + $this->style->windowResize(); + + if ($this->isOpen()) { + $this->redraw(true); + } + }); + $this->selectFirstItem(); } @@ -295,6 +303,12 @@ private function display() : void while ($this->isOpen()) { $char = $reader->readCharacter(); + + if (null === $char) { + usleep(10000); + continue; + } + if (!$char->isHandledControl()) { $rawChar = $char->get(); if (isset($this->customControlMappings[$rawChar])) { diff --git a/src/MenuStyle.php b/src/MenuStyle.php index 96677bd6..837fdcf7 100644 --- a/src/MenuStyle.php +++ b/src/MenuStyle.php @@ -52,6 +52,15 @@ class MenuStyle */ private $requestedWidth; + /** + * If the window was resized, we store the original + * size, before any resizing, to attempt to restore + * it on a later resize. + * + * @var int + */ + private $widthBeforeResize; + /** * @var int */ @@ -402,6 +411,7 @@ public function setWidth(int $width) : self $this->requestedWidth = $width; $width = $this->maybeShrinkWidth($this->margin, $width); + $this->widthBeforeResize = null; $this->width = $width; if ($this->marginAuto) { $this->calculateMarginAuto($width); @@ -423,6 +433,24 @@ private function maybeShrinkWidth(int $margin, int $width) : int return $width; } + public function windowResize() : void + { + if (null === $this->widthBeforeResize) { + $this->widthBeforeResize = $this->width; + } + + $width = $this->maybeShrinkWidth($this->margin, $this->widthBeforeResize); + + $this->width = $width; + if ($this->marginAuto) { + $this->calculateMarginAuto($width); + } + + $this->calculateContentWidth(); + $this->generateBorderRows(); + $this->generatePaddingTopBottomRows(); + } + public function getPaddingTopBottom() : int { return $this->paddingTopBottom; diff --git a/src/Terminal/TerminalFactory.php b/src/Terminal/TerminalFactory.php index 6a5e589c..0f9105b3 100644 --- a/src/Terminal/TerminalFactory.php +++ b/src/Terminal/TerminalFactory.php @@ -2,6 +2,7 @@ namespace PhpSchool\CliMenu\Terminal; +use PhpSchool\Terminal\IO\NonBlockingResourceInputStream; use PhpSchool\Terminal\IO\ResourceInputStream; use PhpSchool\Terminal\IO\ResourceOutputStream; use PhpSchool\Terminal\Terminal; @@ -14,6 +15,6 @@ class TerminalFactory { public static function fromSystem() : Terminal { - return new UnixTerminal(new ResourceInputStream, new ResourceOutputStream); + return new UnixTerminal(new NonBlockingResourceInputStream, new ResourceOutputStream); } }