Skip to content

Commit 938ca67

Browse files
committed
Fix changing margins when menu has been shrunk
1 parent 830eba1 commit 938ca67

File tree

1 file changed

+87
-26
lines changed

1 file changed

+87
-26
lines changed

src/MenuStyle.php

Lines changed: 87 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpSchool\CliMenu\Terminal\TerminalFactory;
66
use PhpSchool\CliMenu\Util\ColourUtil;
7+
use PhpSchool\CliMenu\Util\StringUtil as s;
78
use PhpSchool\Terminal\Terminal;
89
use Assert\Assertion;
910

@@ -30,23 +31,31 @@ class MenuStyle
3031
protected $bg;
3132

3233
/**
34+
* The width of the menu. Including borders and padding.
35+
* Does not include margin.
36+
*
37+
* May not be the value that was requested in the
38+
* circumstance that the terminal is smaller then the
39+
* requested width.
40+
*
3341
* @var int
3442
*/
3543
protected $width;
3644

3745
/**
38-
* In case the menu is wider than the terminal
39-
* The value that we originally shrunk it to
40-
* (the width of the terminal)
46+
* In case the requested width is wider than the terminal
47+
* then we shrink the width to fit the terminal. We keep
48+
* the requested size in case the margins are changed and
49+
* we need to recalculate the width.
4150
*
42-
* @var bool
51+
* @var int
4352
*/
44-
private $widthShrunkTo;
53+
private $requestedWidth;
4554

4655
/**
4756
* @var int
4857
*/
49-
protected $margin;
58+
protected $margin = 0;
5059

5160
/**
5261
* @var int
@@ -143,6 +152,11 @@ class MenuStyle
143152
*/
144153
private $marginAuto = false;
145154

155+
/**
156+
* @var bool
157+
*/
158+
private $debugMode = false;
159+
146160
/**
147161
* Default Values
148162
*
@@ -255,10 +269,10 @@ public function hasChangedFromDefaults() : bool
255269
];
256270

257271
$defaultStyleValues = self::$defaultStyleValues;
258-
if ($this->widthShrunkTo) {
259-
$defaultStyleValues['width'] = $this->widthShrunkTo;
272+
if ($this->width !== $this->requestedWidth) {
273+
$defaultStyleValues['width'] = $this->width;
260274
}
261-
275+
262276
return $currentValues !== array_values($defaultStyleValues);
263277
}
264278

@@ -326,13 +340,14 @@ public function getColoursResetCode() : string
326340

327341
/**
328342
* Calculate the contents width
343+
*
344+
* The content width is menu width minus borders and padding.
329345
*/
330346
protected function calculateContentWidth() : void
331347
{
332348
$this->contentWidth = $this->width
333349
- ($this->paddingLeftRight * 2)
334-
- ($this->borderRightWidth + $this->borderLeftWidth)
335-
- $this->margin;
350+
- ($this->borderRightWidth + $this->borderLeftWidth);
336351

337352
if ($this->contentWidth < 0) {
338353
$this->contentWidth = 0;
@@ -384,14 +399,12 @@ public function setWidth(int $width) : self
384399
{
385400
Assertion::greaterOrEqualThan($width, 0);
386401

387-
if ($width >= $this->terminal->getWidth()) {
388-
$width = $this->terminal->getWidth();
389-
$this->widthShrunkTo = $width;
390-
}
402+
$this->requestedWidth = $width;
403+
$width = $this->maybeShrinkWidth($this->margin, $width);
391404

392405
$this->width = $width;
393406
if ($this->marginAuto) {
394-
$this->setMarginAuto();
407+
$this->calculateMarginAuto($width);
395408
}
396409

397410
$this->calculateContentWidth();
@@ -401,6 +414,15 @@ public function setWidth(int $width) : self
401414
return $this;
402415
}
403416

417+
private function maybeShrinkWidth(int $margin, int $width) : int
418+
{
419+
if ($width + $margin >= $this->terminal->getWidth()) {
420+
$width = $this->terminal->getWidth() - $margin;
421+
}
422+
423+
return $width;
424+
}
425+
404426
public function getPaddingTopBottom() : int
405427
{
406428
return $this->paddingTopBottom;
@@ -421,7 +443,7 @@ private function generatePaddingTopBottomRows() : void
421443

422444
$paddingRow = sprintf(
423445
"%s%s%s%s%s%s%s%s%s%s\n",
424-
str_repeat(' ', $this->margin),
446+
$this->debugMode ? $this->getDebugString($this->margin) : str_repeat(' ', $this->margin),
425447
$borderColour,
426448
str_repeat(' ', $this->borderLeftWidth),
427449
$this->getColoursSetCode(),
@@ -433,6 +455,15 @@ private function generatePaddingTopBottomRows() : void
433455
$this->coloursResetCode
434456
);
435457

458+
459+
if ($this->debugMode && s::length($paddingRow) <= $this->terminal->getWidth()) {
460+
$paddingRow = substr_replace(
461+
$paddingRow,
462+
sprintf("%s\n", $this->getDebugString($this->terminal->getWidth() - (s::length($paddingRow) - 1))),
463+
-1
464+
);
465+
}
466+
436467
$this->paddingTopBottomRows = array_fill(0, $this->paddingTopBottom, $paddingRow);
437468
}
438469

@@ -485,24 +516,28 @@ public function getMargin() : int
485516
public function setMarginAuto() : self
486517
{
487518
$this->marginAuto = true;
488-
$this->margin = (int) floor(($this->terminal->getWidth() - $this->width) / 2);
519+
$this->margin = 0;
489520

490-
$this->generateBorderRows();
491-
$this->generatePaddingTopBottomRows();
521+
$this->setWidth($this->requestedWidth);
492522

493523
return $this;
494524
}
495525

526+
private function calculateMarginAuto(int $width) : void
527+
{
528+
$this->margin = (int) floor(($this->terminal->getWidth() - ($width)) / 2);
529+
}
530+
496531
public function setMargin(int $margin) : self
497532
{
498533
Assertion::greaterOrEqualThan($margin, 0);
499534

500535
$this->marginAuto = false;
501536
$this->margin = $margin;
502537

503-
$this->calculateContentWidth();
504-
$this->generateBorderRows();
505-
$this->generatePaddingTopBottomRows();
538+
//margin + width may now exceed terminal size
539+
//so set width again to trigger width check + maybe resize
540+
$this->setWidth($this->requestedWidth);
506541

507542
return $this;
508543
}
@@ -566,12 +601,20 @@ private function generateBorderRows() : void
566601
{
567602
$borderRow = sprintf(
568603
"%s%s%s%s\n",
569-
str_repeat(' ', $this->margin),
604+
$this->debugMode ? $this->getDebugString($this->margin) : str_repeat(' ', $this->margin),
570605
$this->getBorderColourCode(),
571-
str_repeat(' ', $this->width - $this->margin),
572-
$this->coloursResetCode
606+
str_repeat(' ', $this->width),
607+
$this->getColoursResetCode()
573608
);
574609

610+
if ($this->debugMode && s::length($borderRow) <= $this->terminal->getWidth()) {
611+
$borderRow = substr_replace(
612+
$borderRow,
613+
sprintf("%s\n", $this->getDebugString($this->terminal->getWidth() - (s::length($borderRow) - 1))),
614+
-1
615+
);
616+
}
617+
575618
$this->borderTopRows = array_fill(0, $this->borderTopWidth, $borderRow);
576619
$this->borderBottomRows = array_fill(0, $this->borderBottomWidth, $borderRow);
577620
}
@@ -713,4 +756,22 @@ public function getBorderColourCode() : string
713756

714757
return sprintf("\033[%sm", $borderColourCode);
715758
}
759+
760+
/**
761+
* Get a string of given length consisting of 0-9
762+
* eg $length = 15 : 012345678901234
763+
*/
764+
private function getDebugString(int $length) : string
765+
{
766+
$nums = [];
767+
for ($i = 0, $j = 0; $i < $length; $i++, $j++) {
768+
if ($j === 10) {
769+
$j = 0;
770+
}
771+
772+
$nums[] = $j;
773+
}
774+
775+
return implode('', $nums);
776+
}
716777
}

0 commit comments

Comments
 (0)