4
4
5
5
use PhpSchool \CliMenu \Terminal \TerminalFactory ;
6
6
use PhpSchool \CliMenu \Util \ColourUtil ;
7
+ use PhpSchool \CliMenu \Util \StringUtil as s ;
7
8
use PhpSchool \Terminal \Terminal ;
8
9
use Assert \Assertion ;
9
10
@@ -30,23 +31,31 @@ class MenuStyle
30
31
protected $ bg ;
31
32
32
33
/**
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
+ *
33
41
* @var int
34
42
*/
35
43
protected $ width ;
36
44
37
45
/**
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.
41
50
*
42
- * @var bool
51
+ * @var int
43
52
*/
44
- private $ widthShrunkTo ;
53
+ private $ requestedWidth ;
45
54
46
55
/**
47
56
* @var int
48
57
*/
49
- protected $ margin ;
58
+ protected $ margin = 0 ;
50
59
51
60
/**
52
61
* @var int
@@ -143,6 +152,11 @@ class MenuStyle
143
152
*/
144
153
private $ marginAuto = false ;
145
154
155
+ /**
156
+ * @var bool
157
+ */
158
+ private $ debugMode = false ;
159
+
146
160
/**
147
161
* Default Values
148
162
*
@@ -255,10 +269,10 @@ public function hasChangedFromDefaults() : bool
255
269
];
256
270
257
271
$ defaultStyleValues = self ::$ defaultStyleValues ;
258
- if ($ this ->widthShrunkTo ) {
259
- $ defaultStyleValues ['width ' ] = $ this ->widthShrunkTo ;
272
+ if ($ this ->width !== $ this -> requestedWidth ) {
273
+ $ defaultStyleValues ['width ' ] = $ this ->width ;
260
274
}
261
-
275
+
262
276
return $ currentValues !== array_values ($ defaultStyleValues );
263
277
}
264
278
@@ -326,13 +340,14 @@ public function getColoursResetCode() : string
326
340
327
341
/**
328
342
* Calculate the contents width
343
+ *
344
+ * The content width is menu width minus borders and padding.
329
345
*/
330
346
protected function calculateContentWidth () : void
331
347
{
332
348
$ this ->contentWidth = $ this ->width
333
349
- ($ this ->paddingLeftRight * 2 )
334
- - ($ this ->borderRightWidth + $ this ->borderLeftWidth )
335
- - $ this ->margin ;
350
+ - ($ this ->borderRightWidth + $ this ->borderLeftWidth );
336
351
337
352
if ($ this ->contentWidth < 0 ) {
338
353
$ this ->contentWidth = 0 ;
@@ -384,14 +399,12 @@ public function setWidth(int $width) : self
384
399
{
385
400
Assertion::greaterOrEqualThan ($ width , 0 );
386
401
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 );
391
404
392
405
$ this ->width = $ width ;
393
406
if ($ this ->marginAuto ) {
394
- $ this ->setMarginAuto ( );
407
+ $ this ->calculateMarginAuto ( $ width );
395
408
}
396
409
397
410
$ this ->calculateContentWidth ();
@@ -401,6 +414,15 @@ public function setWidth(int $width) : self
401
414
return $ this ;
402
415
}
403
416
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
+
404
426
public function getPaddingTopBottom () : int
405
427
{
406
428
return $ this ->paddingTopBottom ;
@@ -421,7 +443,7 @@ private function generatePaddingTopBottomRows() : void
421
443
422
444
$ paddingRow = sprintf (
423
445
"%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 ),
425
447
$ borderColour ,
426
448
str_repeat (' ' , $ this ->borderLeftWidth ),
427
449
$ this ->getColoursSetCode (),
@@ -433,6 +455,15 @@ private function generatePaddingTopBottomRows() : void
433
455
$ this ->coloursResetCode
434
456
);
435
457
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
+
436
467
$ this ->paddingTopBottomRows = array_fill (0 , $ this ->paddingTopBottom , $ paddingRow );
437
468
}
438
469
@@ -485,24 +516,28 @@ public function getMargin() : int
485
516
public function setMarginAuto () : self
486
517
{
487
518
$ this ->marginAuto = true ;
488
- $ this ->margin = ( int ) floor (( $ this -> terminal -> getWidth () - $ this -> width ) / 2 ) ;
519
+ $ this ->margin = 0 ;
489
520
490
- $ this ->generateBorderRows ();
491
- $ this ->generatePaddingTopBottomRows ();
521
+ $ this ->setWidth ($ this ->requestedWidth );
492
522
493
523
return $ this ;
494
524
}
495
525
526
+ private function calculateMarginAuto (int $ width ) : void
527
+ {
528
+ $ this ->margin = (int ) floor (($ this ->terminal ->getWidth () - ($ width )) / 2 );
529
+ }
530
+
496
531
public function setMargin (int $ margin ) : self
497
532
{
498
533
Assertion::greaterOrEqualThan ($ margin , 0 );
499
534
500
535
$ this ->marginAuto = false ;
501
536
$ this ->margin = $ margin ;
502
537
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 );
506
541
507
542
return $ this ;
508
543
}
@@ -566,12 +601,20 @@ private function generateBorderRows() : void
566
601
{
567
602
$ borderRow = sprintf (
568
603
"%s%s%s%s \n" ,
569
- str_repeat (' ' , $ this ->margin ),
604
+ $ this -> debugMode ? $ this -> getDebugString ( $ this -> margin ) : str_repeat (' ' , $ this ->margin ),
570
605
$ this ->getBorderColourCode (),
571
- str_repeat (' ' , $ this ->width - $ this -> margin ),
572
- $ this ->coloursResetCode
606
+ str_repeat (' ' , $ this ->width ),
607
+ $ this ->getColoursResetCode ()
573
608
);
574
609
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
+
575
618
$ this ->borderTopRows = array_fill (0 , $ this ->borderTopWidth , $ borderRow );
576
619
$ this ->borderBottomRows = array_fill (0 , $ this ->borderBottomWidth , $ borderRow );
577
620
}
@@ -713,4 +756,22 @@ public function getBorderColourCode() : string
713
756
714
757
return sprintf ("\033[%sm " , $ borderColourCode );
715
758
}
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
+ }
716
777
}
0 commit comments