44
55use PhpSchool \CliMenu \Terminal \TerminalFactory ;
66use PhpSchool \CliMenu \Util \ColourUtil ;
7+ use PhpSchool \CliMenu \Util \StringUtil as s ;
78use PhpSchool \Terminal \Terminal ;
89use Assert \Assertion ;
910
@@ -30,14 +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 /**
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.
50+ *
3851 * @var int
3952 */
40- protected $ margin ;
53+ private $ requestedWidth ;
54+
55+ /**
56+ * @var int
57+ */
58+ protected $ margin = 0 ;
4159
4260 /**
4361 * @var int
@@ -134,6 +152,11 @@ class MenuStyle
134152 */
135153 private $ marginAuto = false ;
136154
155+ /**
156+ * @var bool
157+ */
158+ private $ debugMode = false ;
159+
137160 /**
138161 * Default Values
139162 *
@@ -244,8 +267,13 @@ public function hasChangedFromDefaults() : bool
244267 $ this ->borderColour ,
245268 $ this ->marginAuto ,
246269 ];
247-
248- return $ currentValues !== array_values (self ::$ defaultStyleValues );
270+
271+ $ defaultStyleValues = self ::$ defaultStyleValues ;
272+ if ($ this ->width !== $ this ->requestedWidth ) {
273+ $ defaultStyleValues ['width ' ] = $ this ->width ;
274+ }
275+
276+ return $ currentValues !== array_values ($ defaultStyleValues );
249277 }
250278
251279 public function getDisabledItemText (string $ text ) : string
@@ -312,6 +340,8 @@ public function getColoursResetCode() : string
312340
313341 /**
314342 * Calculate the contents width
343+ *
344+ * The content width is menu width minus borders and padding.
315345 */
316346 protected function calculateContentWidth () : void
317347 {
@@ -369,13 +399,12 @@ public function setWidth(int $width) : self
369399 {
370400 Assertion::greaterOrEqualThan ($ width , 0 );
371401
372- if ($ width >= $ this ->terminal ->getWidth ()) {
373- $ width = $ this ->terminal ->getWidth ();
374- }
402+ $ this ->requestedWidth = $ width ;
403+ $ width = $ this ->maybeShrinkWidth ($ this ->margin , $ width );
375404
376405 $ this ->width = $ width ;
377406 if ($ this ->marginAuto ) {
378- $ this ->setMarginAuto ( );
407+ $ this ->calculateMarginAuto ( $ width );
379408 }
380409
381410 $ this ->calculateContentWidth ();
@@ -385,6 +414,15 @@ public function setWidth(int $width) : self
385414 return $ this ;
386415 }
387416
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+
388426 public function getPaddingTopBottom () : int
389427 {
390428 return $ this ->paddingTopBottom ;
@@ -405,7 +443,7 @@ private function generatePaddingTopBottomRows() : void
405443
406444 $ paddingRow = sprintf (
407445 "%s%s%s%s%s%s%s%s%s%s \n" ,
408- str_repeat (' ' , $ this ->margin ),
446+ $ this -> debugMode ? $ this -> getDebugString ( $ this -> margin ) : str_repeat (' ' , $ this ->margin ),
409447 $ borderColour ,
410448 str_repeat (' ' , $ this ->borderLeftWidth ),
411449 $ this ->getColoursSetCode (),
@@ -417,6 +455,15 @@ private function generatePaddingTopBottomRows() : void
417455 $ this ->coloursResetCode
418456 );
419457
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+
420467 $ this ->paddingTopBottomRows = array_fill (0 , $ this ->paddingTopBottom , $ paddingRow );
421468 }
422469
@@ -469,23 +516,28 @@ public function getMargin() : int
469516 public function setMarginAuto () : self
470517 {
471518 $ this ->marginAuto = true ;
472- $ this ->margin = ( int ) floor (( $ this -> terminal -> getWidth () - $ this -> width ) / 2 ) ;
519+ $ this ->margin = 0 ;
473520
474- $ this ->generateBorderRows ();
475- $ this ->generatePaddingTopBottomRows ();
521+ $ this ->setWidth ($ this ->requestedWidth );
476522
477523 return $ this ;
478524 }
479525
526+ private function calculateMarginAuto (int $ width ) : void
527+ {
528+ $ this ->margin = (int ) floor (($ this ->terminal ->getWidth () - ($ width )) / 2 );
529+ }
530+
480531 public function setMargin (int $ margin ) : self
481532 {
482533 Assertion::greaterOrEqualThan ($ margin , 0 );
483534
484535 $ this ->marginAuto = false ;
485536 $ this ->margin = $ margin ;
486537
487- $ this ->generateBorderRows ();
488- $ 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 );
489541
490542 return $ this ;
491543 }
@@ -549,12 +601,20 @@ private function generateBorderRows() : void
549601 {
550602 $ borderRow = sprintf (
551603 "%s%s%s%s \n" ,
552- str_repeat (' ' , $ this ->margin ),
604+ $ this -> debugMode ? $ this -> getDebugString ( $ this -> margin ) : str_repeat (' ' , $ this ->margin ),
553605 $ this ->getBorderColourCode (),
554606 str_repeat (' ' , $ this ->width ),
555- $ this ->coloursResetCode
607+ $ this ->getColoursResetCode ()
556608 );
557609
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+
558618 $ this ->borderTopRows = array_fill (0 , $ this ->borderTopWidth , $ borderRow );
559619 $ this ->borderBottomRows = array_fill (0 , $ this ->borderBottomWidth , $ borderRow );
560620 }
@@ -696,4 +756,22 @@ public function getBorderColourCode() : string
696756
697757 return sprintf ("\033[%sm " , $ borderColourCode );
698758 }
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+ }
699777}
0 commit comments