From e58bb70b4d4f137d7f63a133de99446753686a4e Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 12:47:22 -0600 Subject: [PATCH 1/7] Item styling for Checkbox and Radio items --- .../{checkable-item.php => checkbox-item.php} | 7 +- examples/radio-item.php | 7 +- ...kable-item.php => split-checkbox-item.php} | 4 + src/Builder/CliMenuBuilder.php | 102 ++++++++++++------ src/Builder/SplitItemBuilder.php | 67 +++++++++++- src/CliMenu.php | 67 +++++++++++- src/MenuItem/CheckboxItem.php | 102 ++++++++---------- src/MenuItem/RadioItem.php | 102 ++++++++---------- src/MenuItem/SplitItem.php | 22 ++-- src/MenuItem/ToggableTrait.php | 100 +++++++++-------- src/MenuStyle.php | 80 -------------- src/Style/CheckboxStyle.php | 45 ++++++++ src/Style/ItemStyleTrait.php | 85 +++++++++++++++ src/Style/RadioStyle.php | 45 ++++++++ test/Builder/CliMenuBuilderTest.php | 4 - ...kableItemTest.php => CheckboxItemTest.php} | 8 +- test/MenuItem/RadioItemTest.php | 10 +- test/MenuItem/SplitItemTest.php | 50 ++++----- test/MenuStyleTest.php | 8 -- 19 files changed, 581 insertions(+), 334 deletions(-) rename examples/{checkable-item.php => checkbox-item.php} (83%) rename examples/{split-checkable-item.php => split-checkbox-item.php} (88%) create mode 100644 src/Style/CheckboxStyle.php create mode 100644 src/Style/ItemStyleTrait.php create mode 100644 src/Style/RadioStyle.php rename test/MenuItem/{CheckableItemTest.php => CheckboxItemTest.php} (96%) diff --git a/examples/checkable-item.php b/examples/checkbox-item.php similarity index 83% rename from examples/checkable-item.php rename to examples/checkbox-item.php index 75618775..d4070f07 100644 --- a/examples/checkable-item.php +++ b/examples/checkbox-item.php @@ -2,6 +2,7 @@ use PhpSchool\CliMenu\CliMenu; use PhpSchool\CliMenu\Builder\CliMenuBuilder; +use PhpSchool\CliMenu\Style\CheckboxStyle; require_once(__DIR__ . '/../vendor/autoload.php'); @@ -22,8 +23,10 @@ }) ->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) { $b->setTitle('Interpreted Languages') - ->setUncheckedMarker('[○] ') - ->setCheckedMarker('[●] ') + ->checkboxStyle(function (CheckboxStyle $style) { + $style->setMarkerOff('[○] ') + ->setMarkerOn('[●] '); + }) ->addCheckboxItem('PHP', $itemCallable) ->addCheckboxItem('Javascript', $itemCallable) ->addCheckboxItem('Ruby', $itemCallable) diff --git a/examples/radio-item.php b/examples/radio-item.php index d3b7f0c9..c50f030f 100644 --- a/examples/radio-item.php +++ b/examples/radio-item.php @@ -2,6 +2,7 @@ use PhpSchool\CliMenu\CliMenu; use PhpSchool\CliMenu\Builder\CliMenuBuilder; +use PhpSchool\CliMenu\Style\RadioStyle; require_once(__DIR__ . '/../vendor/autoload.php'); @@ -22,8 +23,10 @@ }) ->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) { $b->setTitle('Interpreted Languages') - ->setUnradioMarker('[ ] ') - ->setRadioMarker('[✔] ') + ->radioStyle(function (RadioStyle $style) { + $style->setMarkerOff('[ ] ') + ->setMarkerOn('[✔] '); + }) ->addRadioItem('PHP', $itemCallable) ->addRadioItem('Javascript', $itemCallable) ->addRadioItem('Ruby', $itemCallable) diff --git a/examples/split-checkable-item.php b/examples/split-checkbox-item.php similarity index 88% rename from examples/split-checkable-item.php rename to examples/split-checkbox-item.php index 9597540f..d05dbfaa 100644 --- a/examples/split-checkable-item.php +++ b/examples/split-checkbox-item.php @@ -6,6 +6,10 @@ require_once(__DIR__ . '/../vendor/autoload.php'); +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + $itemCallable = function (CliMenu $menu) { echo $menu->getSelectedItem()->getText(); }; diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index fb7cbfad..33fa324f 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -16,6 +16,8 @@ use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\CliMenu\MenuStyle; +use PhpSchool\CliMenu\Style\CheckboxStyle; +use PhpSchool\CliMenu\Style\RadioStyle; use PhpSchool\CliMenu\Terminal\TerminalFactory; use PhpSchool\Terminal\Terminal; @@ -138,7 +140,10 @@ public function addCheckboxItem( bool $showItemExtra = false, bool $disabled = false ) : self { - $this->addMenuItem(new CheckboxItem($text, $itemCallable, $showItemExtra, $disabled)); + $item = (new CheckboxItem($text, $itemCallable, $showItemExtra, $disabled)) + ->setStyle($this->menu->getCheckboxStyle()); + + $this->addMenuItem($item); return $this; } @@ -149,7 +154,10 @@ public function addRadioItem( bool $showItemExtra = false, bool $disabled = false ) : self { - $this->addMenuItem(new RadioItem($text, $itemCallable, $showItemExtra, $disabled)); + $item = (new RadioItem($text, $itemCallable, $showItemExtra, $disabled)) + ->setStyle($this->menu->getRadioStyle()); + + $this->addMenuItem($item); return $this; } @@ -194,6 +202,18 @@ public function addSubMenu(string $text, \Closure $callback) : self $menu->setStyle($this->menu->getStyle()); } + if (!$menu->getCheckboxStyle()->getIsCustom()) { + $menu->checkboxStyle(function (CheckboxStyle $style) { + $style->fromArray($this->menu->getCheckboxStyle()->toArray()); + }); + } + + if (!$menu->getRadioStyle()->getIsCustom()) { + $menu->radioStyle(function (RadioStyle $style) { + $style->fromArray($this->menu->getRadioStyle()->toArray()); + }); + } + $this->menu->addItem($item = new MenuMenuItem( $text, $menu, @@ -216,6 +236,14 @@ public function addSubMenuFromBuilder(string $text, CliMenuBuilder $builder) : s $menu->setStyle($this->menu->getStyle()); } + $menu->checkboxStyle(function (CheckboxStyle $style) { + $style->fromArray($this->menu->getCheckboxStyle()->toArray()); + }); + + $menu->radioStyle(function (RadioStyle $style) { + $style->fromArray($this->menu->getRadioStyle()->toArray()); + }); + $this->menu->addItem($item = new MenuMenuItem( $text, $menu, @@ -302,6 +330,14 @@ public function addSplitItem(\Closure $callback) : self } $callback($builder); + + $builder->checkboxStyle(function (CheckboxStyle $style) { + $style->fromArray($this->menu->getCheckboxStyle()->toArray()); + }); + + $builder->radioStyle(function (RadioStyle $style) { + $style->fromArray($this->menu->getRadioStyle()->toArray()); + }); $this->menu->addItem($splitItem = $builder->build()); @@ -417,34 +453,6 @@ public function setSelectedMarker(string $marker) : self return $this; } - public function setUncheckedMarker(string $marker) : self - { - $this->style->setUncheckedMarker($marker); - - return $this; - } - - public function setCheckedMarker(string $marker) : self - { - $this->style->setCheckedMarker($marker); - - return $this; - } - - public function setUnradioMarker(string $marker) : self - { - $this->style->setUnradioMarker($marker); - - return $this; - } - - public function setRadioMarker(string $marker) : self - { - $this->style->setRadioMarker($marker); - - return $this; - } - public function setItemExtra(string $extra) : self { $this->style->setItemExtra($extra); @@ -558,4 +566,38 @@ public function build() : CliMenu return $this->menu; } + + /** + * Use as + * + ->checkboxStyle(function (CheckboxStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function checkboxStyle(callable $itemCallable) : self + { + $this->menu->checkboxStyle($itemCallable); + + return $this; + } + + /** + * Use as + * + ->radioStyle(function (RadioStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function radioStyle(callable $itemCallable) : self + { + $this->menu->radioStyle($itemCallable); + + return $this; + } } diff --git a/src/Builder/SplitItemBuilder.php b/src/Builder/SplitItemBuilder.php index c5da6531..fb6abd55 100644 --- a/src/Builder/SplitItemBuilder.php +++ b/src/Builder/SplitItemBuilder.php @@ -10,6 +10,8 @@ use PhpSchool\CliMenu\MenuItem\SelectableItem; use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; +use PhpSchool\CliMenu\Style\CheckboxStyle; +use PhpSchool\CliMenu\Style\RadioStyle; /** * @author Aydin Hassan @@ -42,10 +44,23 @@ class SplitItemBuilder */ private $autoShortcutsRegex = '/\[(.)\]/'; + /** + * @var CheckboxStyle + */ + private $checkboxStyle; + + /** + * @var RadioStyle + */ + private $radioStyle; + public function __construct(CliMenu $menu) { $this->menu = $menu; $this->splitItem = new SplitItem(); + + $this->checkboxStyle = new CheckboxStyle(); + $this->radioStyle = new RadioStyle(); } public function addItem( @@ -65,7 +80,10 @@ public function addCheckboxItem( bool $showItemExtra = false, bool $disabled = false ) : self { - $this->splitItem->addItem(new CheckboxItem($text, $itemCallable, $showItemExtra, $disabled)); + $item = (new CheckboxItem($text, $itemCallable, $showItemExtra, $disabled)) + ->setStyle($this->menu->getCheckboxStyle()); + + $this->splitItem->addItem($item); return $this; } @@ -76,7 +94,10 @@ public function addRadioItem( bool $showItemExtra = false, bool $disabled = false ) : self { - $this->splitItem->addItem(new RadioItem($text, $itemCallable, $showItemExtra, $disabled)); + $item = (new RadioItem($text, $itemCallable, $showItemExtra, $disabled)) + ->setStyle($this->menu->getRadioStyle()); + + $this->splitItem->addItem($item); return $this; } @@ -108,6 +129,14 @@ public function addSubMenu(string $text, \Closure $callback) : self $menu = $builder->build(); $menu->setParent($this->menu); + $menu->checkboxStyle(function (CheckboxStyle $style) { + $style->fromArray($this->menu->getCheckboxStyle()->toArray()); + }); + + $menu->radioStyle(function (RadioStyle $style) { + $style->fromArray($this->menu->getRadioStyle()->toArray()); + }); + $this->splitItem->addItem(new MenuMenuItem( $text, $menu, @@ -139,4 +168,38 @@ public function build() : SplitItem { return $this->splitItem; } + + /** + * Use as + * + ->checkboxStyle(function (CheckboxStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function checkboxStyle(callable $itemCallable) : self + { + $this->menu->checkboxStyle($itemCallable); + + return $this; + } + + /** + * Use as + * + ->radioStyle(function (RadioStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function radioStyle(callable $itemCallable) : self + { + $this->menu->radioStyle($itemCallable); + + return $this; + } } diff --git a/src/CliMenu.php b/src/CliMenu.php index 5b7631ba..9736d864 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -8,12 +8,15 @@ use PhpSchool\CliMenu\Input\Number; use PhpSchool\CliMenu\Input\Password; use PhpSchool\CliMenu\Input\Text; +use PhpSchool\CliMenu\MenuItem\CheckboxItem; use PhpSchool\CliMenu\MenuItem\LineBreakItem; use PhpSchool\CliMenu\MenuItem\MenuItemInterface; use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\CliMenu\Dialogue\Confirm; use PhpSchool\CliMenu\Dialogue\Flash; +use PhpSchool\CliMenu\Style\CheckboxStyle; +use PhpSchool\CliMenu\Style\RadioStyle; use PhpSchool\CliMenu\Terminal\TerminalFactory; use PhpSchool\CliMenu\Util\StringUtil as s; use PhpSchool\Terminal\InputCharacter; @@ -35,6 +38,16 @@ class CliMenu */ protected $style; + /** + * @var CheckboxStyle + */ + private $checkboxStyle; + + /** + * @var RadioStyle + */ + private $radioStyle; + /** * @var ?string */ @@ -90,10 +103,12 @@ public function __construct( Terminal $terminal = null, MenuStyle $style = null ) { - $this->title = $title; - $this->items = $items; - $this->terminal = $terminal ?: TerminalFactory::fromSystem(); - $this->style = $style ?: new MenuStyle($this->terminal); + $this->title = $title; + $this->items = $items; + $this->terminal = $terminal ?: TerminalFactory::fromSystem(); + $this->style = $style ?: new MenuStyle($this->terminal); + $this->checkboxStyle = new CheckboxStyle(); + $this->radioStyle = new RadioStyle(); $this->selectFirstItem(); } @@ -640,6 +655,50 @@ public function setStyle(MenuStyle $style) : void $this->style = $style; } + public function getCheckboxStyle() : CheckboxStyle + { + return $this->checkboxStyle; + } + + /** + * Use as + * + ->checkboxStyle(function (CheckboxStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function checkboxStyle(callable $itemCallable) : self + { + $itemCallable($this->checkboxStyle); + + return $this; + } + + public function getRadioStyle() : RadioStyle + { + return $this->radioStyle; + } + + /** + * Use as + * + ->radioStyle(function (RadioStyle $style) { + $style->setMarkerOff('- '); + }) + * + * @param callable $itemCallable + * @return $this + */ + public function radioStyle(callable $itemCallable) : self + { + $itemCallable($this->radioStyle); + + return $this; + } + public function getCurrentFrame() : Frame { return $this->currentFrame; diff --git a/src/MenuItem/CheckboxItem.php b/src/MenuItem/CheckboxItem.php index f0278bbf..9a958688 100644 --- a/src/MenuItem/CheckboxItem.php +++ b/src/MenuItem/CheckboxItem.php @@ -3,30 +3,18 @@ namespace PhpSchool\CliMenu\MenuItem; use PhpSchool\CliMenu\CliMenu; +use PhpSchool\CliMenu\MenuStyle; +use PhpSchool\CliMenu\Util\StringUtil; +use PhpSchool\CliMenu\Style\CheckboxStyle; class CheckboxItem implements MenuItemInterface, ToggableItemInterface { use ToggableTrait; /** - * @var callable + * @var CheckboxStyle; */ - private $selectAction; - - /** - * @var string - */ - private $text = ''; - - /** - * @var bool - */ - private $showItemExtra = false; - - /** - * @var bool - */ - private $disabled = false; + private $style; public function __construct( string $text, @@ -38,6 +26,43 @@ public function __construct( $this->selectAction = $selectAction; $this->showItemExtra = $showItemExtra; $this->disabled = $disabled; + + $this->style = new CheckboxStyle(); + } + + /** + * The output text for the item + */ + public function getRows(MenuStyle $style, bool $selected = false) : array + { + $marker = sprintf("%s", $this->style->getMarker($this->checked)); + + $itemExtra = $this->style->getItemExtra(); + + $length = $this->style->getDisplaysExtra() + ? $style->getContentWidth() - (mb_strlen($itemExtra) + 2) + : $style->getContentWidth(); + + $rows = explode( + "\n", + StringUtil::wordwrap( + sprintf('%s%s', $marker, $this->text), + $length, + sprintf("\n%s", str_repeat(' ', mb_strlen($marker))) + ) + ); + + return array_map(function ($row, $key) use ($style, $length, $itemExtra) { + $text = $this->disabled ? $style->getDisabledItemText($row) : $row; + + if ($key === 0) { + return $this->showItemExtra + ? sprintf('%s%s %s', $text, str_repeat(' ', $length - mb_strlen($row)), $itemExtra) + : $text; + } + + return $text; + }, $rows, array_keys($rows)); } /** @@ -53,48 +78,15 @@ public function getSelectAction() : ?callable }; } - /** - * Return the raw string of text - */ - public function getText() : string - { - return $this->text; - } - - /** - * Set the raw string of text - */ - public function setText(string $text) : void - { - $this->text = $text; - } - - /** - * Can the item be selected - */ - public function canSelect() : bool - { - return !$this->disabled; - } - - public function showsItemExtra() : bool + public function getStyle() : CheckboxStyle { - return $this->showItemExtra; + return $this->style; } - /** - * Enable showing item extra - */ - public function showItemExtra() : void + public function setStyle(CheckboxStyle $style) : self { - $this->showItemExtra = true; - } + $this->style = $style; - /** - * Disable showing item extra - */ - public function hideItemExtra() : void - { - $this->showItemExtra = false; + return $this; } } diff --git a/src/MenuItem/RadioItem.php b/src/MenuItem/RadioItem.php index d4129699..711732f6 100644 --- a/src/MenuItem/RadioItem.php +++ b/src/MenuItem/RadioItem.php @@ -3,30 +3,18 @@ namespace PhpSchool\CliMenu\MenuItem; use PhpSchool\CliMenu\CliMenu; +use PhpSchool\CliMenu\MenuStyle; +use PhpSchool\CliMenu\Util\StringUtil; +use PhpSchool\CliMenu\Style\RadioStyle; class RadioItem implements MenuItemInterface, ToggableItemInterface { use ToggableTrait; /** - * @var callable + * @var RadioStyle; */ - private $selectAction; - - /** - * @var string - */ - private $text = ''; - - /** - * @var bool - */ - private $showItemExtra = false; - - /** - * @var bool - */ - private $disabled = false; + private $style; public function __construct( string $text, @@ -38,6 +26,43 @@ public function __construct( $this->selectAction = $selectAction; $this->showItemExtra = $showItemExtra; $this->disabled = $disabled; + + $this->style = new RadioStyle(); + } + + /** + * The output text for the item + */ + public function getRows(MenuStyle $style, bool $selected = false) : array + { + $marker = sprintf("%s", $this->style->getMarker($this->checked)); + + $itemExtra = $this->style->getItemExtra(); + + $length = $this->style->getDisplaysExtra() + ? $style->getContentWidth() - (mb_strlen($itemExtra) + 2) + : $style->getContentWidth(); + + $rows = explode( + "\n", + StringUtil::wordwrap( + sprintf('%s%s', $marker, $this->text), + $length, + sprintf("\n%s", str_repeat(' ', mb_strlen($marker))) + ) + ); + + return array_map(function ($row, $key) use ($style, $length, $itemExtra) { + $text = $this->disabled ? $style->getDisabledItemText($row) : $row; + + if ($key === 0) { + return $this->showItemExtra + ? sprintf('%s%s %s', $text, str_repeat(' ', $length - mb_strlen($row)), $itemExtra) + : $text; + } + + return $text; + }, $rows, array_keys($rows)); } /** @@ -73,48 +98,15 @@ function (RadioItem $item) { }; } - /** - * Return the raw string of text - */ - public function getText() : string - { - return $this->text; - } - - /** - * Set the raw string of text - */ - public function setText(string $text) : void - { - $this->text = $text; - } - - /** - * Can the item be selected - */ - public function canSelect() : bool - { - return !$this->disabled; - } - - public function showsItemExtra() : bool + public function getStyle() : RadioStyle { - return $this->showItemExtra; + return $this->style; } - /** - * Enable showing item extra - */ - public function showItemExtra() : void + public function setStyle(RadioStyle $style) : self { - $this->showItemExtra = true; - } + $this->style = $style; - /** - * Disable showing item extra - */ - public function hideItemExtra() : void - { - $this->showItemExtra = false; + return $this; } } diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 6369d8fe..4b96b7cd 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -130,16 +130,14 @@ public function getRows(MenuStyle $style, bool $selected = false) : array array_map(function ($index, $item) use ($selected, $length, $style) { $isSelected = $selected && $index === $this->selectedItemIndex; - if ($item instanceof CheckboxItem) { - $markerType = $item->getChecked() - ? $style->getCheckedMarker() - : $style->getUncheckedMarker(); - } elseif ($item instanceof RadioItem) { - $markerType = $item->getChecked() - ? $style->getRadioMarker() - : $style->getUnradioMarker(); + if ($item instanceof CheckboxItem || $item instanceof RadioItem) { + $markerType = $item->getStyle()->getMarker($item->getChecked()); + $displaysExtra = $item->getStyle()->getDisplaysExtra(); + $itemExtraVal = $item->getStyle()->getItemExtra(); } else { - $markerType = $style->getMarker($isSelected); + $markerType = $style->getMarker($isSelected); + $displaysExtra = $style->getDisplaysExtra(); + $itemExtraVal = $style->getItemExtra(); } $marker = $item->canSelect() @@ -147,10 +145,10 @@ public function getRows(MenuStyle $style, bool $selected = false) : array : ''; $itemExtra = ''; - if ($style->getDisplaysExtra()) { + if ($displaysExtra) { $itemExtra = $item->showsItemExtra() - ? sprintf(' %s', $style->getItemExtra()) - : sprintf(' %s', str_repeat(' ', mb_strlen($style->getItemExtra()))); + ? sprintf(' %s', $itemExtraVal) + : sprintf(' %s', str_repeat(' ', mb_strlen($itemExtraVal))); } return $this->buildCell( diff --git a/src/MenuItem/ToggableTrait.php b/src/MenuItem/ToggableTrait.php index a56f77d0..e176d420 100644 --- a/src/MenuItem/ToggableTrait.php +++ b/src/MenuItem/ToggableTrait.php @@ -2,57 +2,20 @@ namespace PhpSchool\CliMenu\MenuItem; -use PhpSchool\CliMenu\MenuStyle; -use PhpSchool\CliMenu\Util\StringUtil; - trait ToggableTrait { /** - * @var bool + * @var callable */ - private $checked = false; + private $selectAction; - /** - * The output text for the item - */ - public function getRows(MenuStyle $style, bool $selected = false) : array - { - $markerTypes = [ - true => $this instanceof CheckboxItem - ? $style->getCheckedMarker() - : $style->getRadioMarker(), - false => $this instanceof CheckboxItem - ? $style->getUncheckedMarker() - : $style->getUnradioMarker(), - ]; - - $marker = sprintf("%s", $markerTypes[$this->checked]); - - $length = $style->getDisplaysExtra() - ? $style->getContentWidth() - (mb_strlen($style->getItemExtra()) + 2) - : $style->getContentWidth(); - - $rows = explode( - "\n", - StringUtil::wordwrap( - sprintf('%s%s', $marker, $this->text), - $length, - sprintf("\n%s", str_repeat(' ', mb_strlen($marker))) - ) - ); - - return array_map(function ($row, $key) use ($style, $length) { - $text = $this->disabled ? $style->getDisabledItemText($row) : $row; - - if ($key === 0) { - return $this->showItemExtra - ? sprintf('%s%s %s', $text, str_repeat(' ', $length - mb_strlen($row)), $style->getItemExtra()) - : $text; - } - - return $text; - }, $rows, array_keys($rows)); - } + private $text = ''; + + private $showItemExtra = false; + + private $disabled = false; + + private $checked = false; /** * Toggles checked state @@ -85,4 +48,49 @@ public function getChecked() : bool { return $this->checked; } + + /** + * Return the raw string of text + */ + public function getText() : string + { + return $this->text; + } + + /** + * Set the raw string of text + */ + public function setText(string $text) : void + { + $this->text = $text; + } + + /** + * Can the item be selected + */ + public function canSelect() : bool + { + return !$this->disabled; + } + + public function showsItemExtra() : bool + { + return $this->showItemExtra; + } + + /** + * Enable showing item extra + */ + public function showItemExtra() : void + { + $this->showItemExtra = true; + } + + /** + * Disable showing item extra + */ + public function hideItemExtra() : void + { + $this->showItemExtra = false; + } } diff --git a/src/MenuStyle.php b/src/MenuStyle.php index f2139bca..47329f9d 100644 --- a/src/MenuStyle.php +++ b/src/MenuStyle.php @@ -69,26 +69,6 @@ class MenuStyle */ private $unselectedMarker; - /** - * @var string - */ - private $checkedMarker; - - /** - * @var string - */ - private $uncheckedMarker; - - /** - * @var string - */ - private $radioMarker; - - /** - * @var string - */ - private $unradioMarker; - /** * @var string */ @@ -178,10 +158,6 @@ class MenuStyle 'margin' => 2, 'selectedMarker' => '● ', 'unselectedMarker' => '○ ', - 'checkedMarker' => '[✔] ', - 'uncheckedMarker' => '[ ] ', - 'radioMarker' => '[●] ', - 'unradioMarker' => '[○] ', 'itemExtra' => '✔', 'displaysExtra' => false, 'titleSeparator' => '=', @@ -253,10 +229,6 @@ public function __construct(Terminal $terminal = null) $this->setMargin(self::$defaultStyleValues['margin']); $this->setSelectedMarker(self::$defaultStyleValues['selectedMarker']); $this->setUnselectedMarker(self::$defaultStyleValues['unselectedMarker']); - $this->setCheckedMarker(self::$defaultStyleValues['checkedMarker']); - $this->setUncheckedMarker(self::$defaultStyleValues['uncheckedMarker']); - $this->setRadioMarker(self::$defaultStyleValues['radioMarker']); - $this->setUnradioMarker(self::$defaultStyleValues['unradioMarker']); $this->setItemExtra(self::$defaultStyleValues['itemExtra']); $this->setDisplaysExtra(self::$defaultStyleValues['displaysExtra']); $this->setTitleSeparator(self::$defaultStyleValues['titleSeparator']); @@ -278,10 +250,6 @@ public function hasChangedFromDefaults() : bool $this->margin, $this->selectedMarker, $this->unselectedMarker, - $this->checkedMarker, - $this->uncheckedMarker, - $this->radioMarker, - $this->unradioMarker, $this->itemExtra, $this->displaysExtra, $this->titleSeparator, @@ -589,54 +557,6 @@ public function getMarker(bool $selected) : string return $selected ? $this->selectedMarker : $this->unselectedMarker; } - public function getCheckedMarker() : string - { - return $this->checkedMarker; - } - - public function setCheckedMarker(string $marker) : self - { - $this->checkedMarker = $marker; - - return $this; - } - - public function getUncheckedMarker() : string - { - return $this->uncheckedMarker; - } - - public function setUncheckedMarker(string $marker) : self - { - $this->uncheckedMarker = $marker; - - return $this; - } - - public function getRadioMarker() : string - { - return $this->radioMarker; - } - - public function setRadioMarker(string $marker) : self - { - $this->radioMarker = $marker; - - return $this; - } - - public function getUnradioMarker() : string - { - return $this->unradioMarker; - } - - public function setUnradioMarker(string $marker) : self - { - $this->unradioMarker = $marker; - - return $this; - } - public function setItemExtra(string $itemExtra) : self { $this->itemExtra = $itemExtra; diff --git a/src/Style/CheckboxStyle.php b/src/Style/CheckboxStyle.php new file mode 100644 index 00000000..c095603d --- /dev/null +++ b/src/Style/CheckboxStyle.php @@ -0,0 +1,45 @@ + '[✔] ', + 'markerOff' => '[ ] ', + 'itemExtra' => '✔', + 'displaysExtra' => false, + ]; + + public function __construct() + { + $this->setMarkerOn(self::DEFAULT_STYLES['markerOn']); + $this->setMarkerOff(self::DEFAULT_STYLES['markerOff']); + $this->setItemExtra(self::DEFAULT_STYLES['itemExtra']); + $this->setDisplaysExtra(self::DEFAULT_STYLES['displaysExtra']); + + $this->custom = false; + } + + public function toArray() : array + { + return [ + 'markerOn' => $this->markerOn, + 'markerOff' => $this->markerOff, + 'itemExtra' => $this->itemExtra, + 'displaysExtra' => $this->displaysExtra, + ]; + } + + public function fromArray(array $style) : self + { + $this->markerOn = $style['markerOn'] ?? $this->markerOn; + $this->markerOff = $style['markerOff'] ?? $this->markerOff; + $this->itemExtra = $style['itemExtra'] ?? $this->itemExtra; + $this->displaysExtra = $style['displaysExtra'] ?? $this->displaysExtra; + + return $this; + } +} diff --git a/src/Style/ItemStyleTrait.php b/src/Style/ItemStyleTrait.php new file mode 100644 index 00000000..d65deb91 --- /dev/null +++ b/src/Style/ItemStyleTrait.php @@ -0,0 +1,85 @@ +custom; + } + + public function getMarker(bool $selected) : string + { + return $selected ? $this->markerOn : $this->markerOff; + } + + public function getMarkerOn() : string + { + return $this->markerOn; + } + + public function setMarkerOn(string $marker) : self + { + $this->custom = true; + + $this->markerOn = $marker; + + return $this; + } + + public function getMarkerOff() : string + { + return $this->markerOff; + } + + public function setMarkerOff(string $marker) : self + { + $this->custom = true; + + $this->markerOff = $marker; + + return $this; + } + + public function getItemExtra() : string + { + return $this->itemExtra; + } + + public function setItemExtra(string $itemExtra) : self + { + $this->custom = true; + + $this->itemExtra = $itemExtra; + + // if we customise item extra, it means we most likely want to display it + $this->setDisplaysExtra(true); + + return $this; + } + + public function getDisplaysExtra() : bool + { + return $this->displaysExtra; + } + + public function setDisplaysExtra(bool $displaysExtra) : self + { + $this->custom = true; + + $this->displaysExtra = $displaysExtra; + + return $this; + } +} diff --git a/src/Style/RadioStyle.php b/src/Style/RadioStyle.php new file mode 100644 index 00000000..6317c6fd --- /dev/null +++ b/src/Style/RadioStyle.php @@ -0,0 +1,45 @@ + '[●] ', + 'markerOff' => '[○] ', + 'itemExtra' => '✔', + 'displaysExtra' => false, + ]; + + public function __construct() + { + $this->setMarkerOn(self::DEFAULT_STYLES['markerOn']); + $this->setMarkerOff(self::DEFAULT_STYLES['markerOff']); + $this->setItemExtra(self::DEFAULT_STYLES['itemExtra']); + $this->setDisplaysExtra(self::DEFAULT_STYLES['displaysExtra']); + + $this->custom = false; + } + + public function toArray() : array + { + return [ + 'markerOn' => $this->markerOn, + 'markerOff' => $this->markerOff, + 'itemExtra' => $this->itemExtra, + 'displaysExtra' => $this->displaysExtra, + ]; + } + + public function fromArray(array $style) : self + { + $this->markerOn = $style['markerOn'] ?? $this->markerOn; + $this->markerOff = $style['markerOff'] ?? $this->markerOff; + $this->itemExtra = $style['itemExtra'] ?? $this->itemExtra; + $this->displaysExtra = $style['displaysExtra'] ?? $this->displaysExtra; + + return $this; + } +} diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 55df7f49..d4cc7372 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -67,8 +67,6 @@ public function testModifyStyles() : void $builder->setMargin(4); $builder->setUnselectedMarker('>'); $builder->setSelectedMarker('x'); - $builder->setUncheckedMarker('-'); - $builder->setCheckedMarker('+'); $builder->setItemExtra('*'); $builder->setTitleSeparator('-'); @@ -83,8 +81,6 @@ public function testModifyStyles() : void self::assertEquals(4, $style->getMargin()); self::assertEquals('>', $style->getUnselectedMarker()); self::assertEquals('x', $style->getSelectedMarker()); - self::assertEquals('-', $style->getUncheckedMarker()); - self::assertEquals('+', $style->getCheckedMarker()); self::assertEquals('*', $style->getItemExtra()); self::assertEquals('-', $style->getTitleSeparator()); } diff --git a/test/MenuItem/CheckableItemTest.php b/test/MenuItem/CheckboxItemTest.php similarity index 96% rename from test/MenuItem/CheckableItemTest.php rename to test/MenuItem/CheckboxItemTest.php index 98649b0e..8a9a1d49 100644 --- a/test/MenuItem/CheckableItemTest.php +++ b/test/MenuItem/CheckboxItemTest.php @@ -141,11 +141,12 @@ public function testGetRowsWithItemExtra() : void $menuStyle = new MenuStyle($terminal); $menuStyle->setPaddingLeftRight(0); $menuStyle->setWidth(20); - $menuStyle->setItemExtra('[EXTRA]'); - $menuStyle->setDisplaysExtra(true); $item = new CheckboxItem('Item', function () { }, true); + $item->getStyle() + ->setItemExtra('[EXTRA]') + ->setDisplaysExtra(true); $this->assertEquals(['[ ] Item [EXTRA]'], $item->getRows($menuStyle)); } @@ -162,6 +163,9 @@ public function testGetRowsWithMultipleLinesWithItemExtra() : void $item = new CheckboxItem('LONG ITEM LINE', function () { }, true); + $item->getStyle() + ->setItemExtra('[EXTRA]') + ->setDisplaysExtra(true); $this->assertEquals( [ "[ ] LONG [EXTRA]", diff --git a/test/MenuItem/RadioItemTest.php b/test/MenuItem/RadioItemTest.php index 00f667df..92475352 100644 --- a/test/MenuItem/RadioItemTest.php +++ b/test/MenuItem/RadioItemTest.php @@ -175,11 +175,12 @@ public function testGetRowsWithItemExtra() : void $menuStyle = new MenuStyle($terminal); $menuStyle->setPaddingLeftRight(0); $menuStyle->setWidth(20); - $menuStyle->setItemExtra('[EXTRA]'); - $menuStyle->setDisplaysExtra(true); $item = new RadioItem('Item', function () { }, true); + $item->getStyle() + ->setItemExtra('[EXTRA]') + ->setDisplaysExtra(true); $this->assertEquals(['[○] Item [EXTRA]'], $item->getRows($menuStyle)); } @@ -191,11 +192,12 @@ public function testGetRowsWithMultipleLinesWithItemExtra() : void $menuStyle = new MenuStyle($terminal); $menuStyle->setPaddingLeftRight(0); $menuStyle->setWidth(20); - $menuStyle->setItemExtra('[EXTRA]'); - $menuStyle->setDisplaysExtra(true); $item = new RadioItem('LONG ITEM LINE', function () { }, true); + $item->getStyle() + ->setItemExtra('[EXTRA]') + ->setDisplaysExtra(true); $this->assertEquals( [ "[○] LONG [EXTRA]", diff --git a/test/MenuItem/SplitItemTest.php b/test/MenuItem/SplitItemTest.php index bd85791b..34940b67 100644 --- a/test/MenuItem/SplitItemTest.php +++ b/test/MenuItem/SplitItemTest.php @@ -12,6 +12,8 @@ use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\CliMenu\MenuStyle; +use PhpSchool\CliMenu\Style\CheckboxStyle; +use PhpSchool\CliMenu\Style\RadioStyle; use PhpSchool\Terminal\Terminal; use PHPUnit\Framework\TestCase; @@ -479,21 +481,17 @@ public function testCheckboxItem() : void ->method('getContentWidth') ->will($this->returnValue(30)); - $menuStyle - ->expects($this->any()) - ->method('getCheckedMarker') - ->willReturn('[✔] '); - - $menuStyle - ->expects($this->any()) - ->method('getUncheckedMarker') - ->willReturn('[ ] '); - $checkboxItem1 = new CheckboxItem('Item One', function () { }); + $checkboxItem1->getStyle() + ->setMarkerOff('[ ] ') + ->setMarkerOn('[✔] '); $checkboxItem2 = new CheckboxItem('Item Two', function () { }); + $checkboxItem2->getStyle() + ->setMarkerOff('[ ] ') + ->setMarkerOn('[✔] '); $item = new SplitItem( [ @@ -520,26 +518,22 @@ public function testRadioItem() : void ->method('getContentWidth') ->will($this->returnValue(30)); - $menuStyle - ->expects($this->any()) - ->method('getRadioMarker') - ->willReturn('[●] '); - - $menuStyle - ->expects($this->any()) - ->method('getUnradioMarker') - ->willReturn('[○] '); + $radioStyle = new RadioStyle(); + $radioStyle->setMarkerOn('[+] ') + ->setMarkerOff('[-] '); - $checkboxItem1 = new RadioItem('Item One', function () { + $radioItem1 = new RadioItem('Item One', function () { }); + $radioItem1->setStyle($radioStyle); - $checkboxItem2 = new RadioItem('Item Two', function () { + $radioItem2 = new RadioItem('Item Two', function () { }); + $radioItem2->setStyle($radioStyle); $item = new SplitItem( [ - $checkboxItem1, - $checkboxItem2, + $radioItem1, + $radioItem2, ] ); @@ -561,14 +555,14 @@ public function testRadioItem() : void $item->setSelectedItemIndex(0); - self::assertEquals(['[○] Item One [○] Item Two '], $item->getRows($menuStyle, true)); + self::assertEquals(['[-] Item One [-] Item Two '], $item->getRows($menuStyle, true)); - $checkboxItem1->getSelectAction()($cliMenu); + $radioItem1->getSelectAction()($cliMenu); - self::assertEquals(['[●] Item One [○] Item Two '], $item->getRows($menuStyle, true)); + self::assertEquals(['[+] Item One [-] Item Two '], $item->getRows($menuStyle, true)); - $checkboxItem2->getSelectAction()($cliMenu); + $radioItem2->getSelectAction()($cliMenu); - self::assertEquals(['[○] Item One [●] Item Two '], $item->getRows($menuStyle, true)); + self::assertEquals(['[-] Item One [+] Item Two '], $item->getRows($menuStyle, true)); } } diff --git a/test/MenuStyleTest.php b/test/MenuStyleTest.php index 6294f351..1c954cc3 100644 --- a/test/MenuStyleTest.php +++ b/test/MenuStyleTest.php @@ -100,10 +100,6 @@ public function testGetterAndSetters() : void $style->setFg('yellow'); $style->setUnselectedMarker('-'); $style->setSelectedMarker('>'); - $style->setUncheckedMarker('/'); - $style->setCheckedMarker('+'); - $style->setUnradioMarker('O'); - $style->setRadioMarker('X'); $style->setItemExtra('EXTRA!'); $style->setDisplaysExtra(true); $style->setTitleSeparator('+'); @@ -121,10 +117,6 @@ public function testGetterAndSetters() : void self::assertSame('yellow', $style->getFg()); self::assertSame('-', $style->getUnselectedMarker()); self::assertSame('>', $style->getSelectedMarker()); - self::assertEquals('/', $style->getUncheckedMarker()); - self::assertEquals('+', $style->getCheckedMarker()); - self::assertEquals('O', $style->getUnradioMarker()); - self::assertEquals('X', $style->getRadioMarker()); self::assertSame('EXTRA!', $style->getItemExtra()); self::assertTrue($style->getDisplaysExtra()); self::assertSame('+', $style->getTitleSeparator()); From 34ea4b3847d5388bff047bfa79bffb53adaf6fd6 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 12:50:25 -0600 Subject: [PATCH 2/7] Updates README --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8af5be97..573fd943 100644 --- a/README.md +++ b/README.md @@ -817,10 +817,13 @@ You may also change the marker for `\PhpSchool\CliMenu\MenuItem\CheckboxItem`: setUncheckedMarker('[○] ') - ->setCheckedMarker('[●] ') + ->checkboxStyle(function (CheckboxStyle $style) { + $style->setMarkerOff('[○] ') + ->setMarkerOn('[●] '); + }) ->build(); ``` @@ -830,10 +833,13 @@ and for `\PhpSchool\CliMenu\MenuItem\RadioItem`: setUnradioMarker('[ ] ') - ->setRadioMarker('[✔] ') + ->radioStyle(function (RadioStyle $style) { + $style->setMarkerOff('[ ] ') + ->setMarkerOn('[✔] '); + }) ->build(); ``` From 6b7299271f667d51c95c188c4c59c57a93e0f229 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 12:53:39 -0600 Subject: [PATCH 3/7] Removes extra code --- examples/split-checkbox-item.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/split-checkbox-item.php b/examples/split-checkbox-item.php index d05dbfaa..9597540f 100644 --- a/examples/split-checkbox-item.php +++ b/examples/split-checkbox-item.php @@ -6,10 +6,6 @@ require_once(__DIR__ . '/../vendor/autoload.php'); -ini_set('display_errors', 1); -ini_set('display_startup_errors', 1); -error_reporting(E_ALL); - $itemCallable = function (CliMenu $menu) { echo $menu->getSelectedItem()->getText(); }; From 0c483118feb9b7effc0f888b3c6f6ec438e43889 Mon Sep 17 00:00:00 2001 From: Aydin Hassan Date: Thu, 19 Dec 2019 21:58:27 +0100 Subject: [PATCH 4/7] Drop comments --- src/Builder/CliMenuBuilder.php | 20 -------------------- src/Builder/SplitItemBuilder.php | 20 -------------------- src/CliMenu.php | 20 -------------------- 3 files changed, 60 deletions(-) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index 33fa324f..d12e66a3 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -567,16 +567,6 @@ public function build() : CliMenu return $this->menu; } - /** - * Use as - * - ->checkboxStyle(function (CheckboxStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function checkboxStyle(callable $itemCallable) : self { $this->menu->checkboxStyle($itemCallable); @@ -584,16 +574,6 @@ public function checkboxStyle(callable $itemCallable) : self return $this; } - /** - * Use as - * - ->radioStyle(function (RadioStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function radioStyle(callable $itemCallable) : self { $this->menu->radioStyle($itemCallable); diff --git a/src/Builder/SplitItemBuilder.php b/src/Builder/SplitItemBuilder.php index fb6abd55..3ee819a4 100644 --- a/src/Builder/SplitItemBuilder.php +++ b/src/Builder/SplitItemBuilder.php @@ -169,16 +169,6 @@ public function build() : SplitItem return $this->splitItem; } - /** - * Use as - * - ->checkboxStyle(function (CheckboxStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function checkboxStyle(callable $itemCallable) : self { $this->menu->checkboxStyle($itemCallable); @@ -186,16 +176,6 @@ public function checkboxStyle(callable $itemCallable) : self return $this; } - /** - * Use as - * - ->radioStyle(function (RadioStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function radioStyle(callable $itemCallable) : self { $this->menu->radioStyle($itemCallable); diff --git a/src/CliMenu.php b/src/CliMenu.php index 9736d864..0ea9b71c 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -660,16 +660,6 @@ public function getCheckboxStyle() : CheckboxStyle return $this->checkboxStyle; } - /** - * Use as - * - ->checkboxStyle(function (CheckboxStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function checkboxStyle(callable $itemCallable) : self { $itemCallable($this->checkboxStyle); @@ -682,16 +672,6 @@ public function getRadioStyle() : RadioStyle return $this->radioStyle; } - /** - * Use as - * - ->radioStyle(function (RadioStyle $style) { - $style->setMarkerOff('- '); - }) - * - * @param callable $itemCallable - * @return $this - */ public function radioStyle(callable $itemCallable) : self { $itemCallable($this->radioStyle); From 8179b35a4f8f4f1e3cf2fc63264224fb3e7449be Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 15:42:10 -0600 Subject: [PATCH 5/7] CR changes --- examples/checkbox-item.php | 2 +- examples/radio-item.php | 2 +- src/Builder/CliMenuBuilder.php | 68 ++++++++++++++-------- src/Builder/SplitItemBuilder.php | 44 +++++++++++---- src/CliMenu.php | 8 +-- src/MenuItem/CheckboxItem.php | 90 +++++++++++++++++++++++++++++- src/MenuItem/RadioItem.php | 90 +++++++++++++++++++++++++++++- src/MenuItem/ToggableTrait.php | 96 -------------------------------- src/Style/CheckboxStyle.php | 85 +++++++++++++++++++++++----- src/Style/ItemStyleTrait.php | 85 ---------------------------- src/Style/RadioStyle.php | 85 +++++++++++++++++++++++----- 11 files changed, 404 insertions(+), 251 deletions(-) delete mode 100644 src/MenuItem/ToggableTrait.php delete mode 100644 src/Style/ItemStyleTrait.php diff --git a/examples/checkbox-item.php b/examples/checkbox-item.php index d4070f07..09d65860 100644 --- a/examples/checkbox-item.php +++ b/examples/checkbox-item.php @@ -23,7 +23,7 @@ }) ->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) { $b->setTitle('Interpreted Languages') - ->checkboxStyle(function (CheckboxStyle $style) { + ->modifyCheckboxStyle(function (CheckboxStyle $style) { $style->setMarkerOff('[○] ') ->setMarkerOn('[●] '); }) diff --git a/examples/radio-item.php b/examples/radio-item.php index c50f030f..7f7ff5ff 100644 --- a/examples/radio-item.php +++ b/examples/radio-item.php @@ -23,7 +23,7 @@ }) ->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) { $b->setTitle('Interpreted Languages') - ->radioStyle(function (RadioStyle $style) { + ->modifyRadioStyle(function (RadioStyle $style) { $style->setMarkerOff('[ ] ') ->setMarkerOn('[✔] '); }) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index d12e66a3..dd6d45f5 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -202,16 +202,12 @@ public function addSubMenu(string $text, \Closure $callback) : self $menu->setStyle($this->menu->getStyle()); } - if (!$menu->getCheckboxStyle()->getIsCustom()) { - $menu->checkboxStyle(function (CheckboxStyle $style) { - $style->fromArray($this->menu->getCheckboxStyle()->toArray()); - }); + if (!$menu->getCheckboxStyle()->hasChangedFromDefaults()) { + $menu->setCheckboxStyle(clone $this->menu->getCheckboxStyle()); } - if (!$menu->getRadioStyle()->getIsCustom()) { - $menu->radioStyle(function (RadioStyle $style) { - $style->fromArray($this->menu->getRadioStyle()->toArray()); - }); + if (!$menu->getRadioStyle()->hasChangedFromDefaults()) { + $menu->setRadioStyle(clone $this->menu->getRadioStyle()); } $this->menu->addItem($item = new MenuMenuItem( @@ -236,13 +232,13 @@ public function addSubMenuFromBuilder(string $text, CliMenuBuilder $builder) : s $menu->setStyle($this->menu->getStyle()); } - $menu->checkboxStyle(function (CheckboxStyle $style) { - $style->fromArray($this->menu->getCheckboxStyle()->toArray()); - }); + if (!$menu->getCheckboxStyle()->hasChangedFromDefaults()) { + $menu->setCheckboxStyle(clone $this->menu->getCheckboxStyle()); + } - $menu->radioStyle(function (RadioStyle $style) { - $style->fromArray($this->menu->getRadioStyle()->toArray()); - }); + if (!$menu->getRadioStyle()->hasChangedFromDefaults()) { + $menu->setRadioStyle(clone $this->menu->getRadioStyle()); + } $this->menu->addItem($item = new MenuMenuItem( $text, @@ -331,13 +327,13 @@ public function addSplitItem(\Closure $callback) : self $callback($builder); - $builder->checkboxStyle(function (CheckboxStyle $style) { - $style->fromArray($this->menu->getCheckboxStyle()->toArray()); - }); + if (!$builder->getCheckboxStyle()->hasChangedFromDefaults()) { + $builder->setCheckboxStyle(clone $this->menu->getCheckboxStyle()); + } - $builder->radioStyle(function (RadioStyle $style) { - $style->fromArray($this->menu->getRadioStyle()->toArray()); - }); + if (!$builder->getRadioStyle()->hasChangedFromDefaults()) { + $builder->setRadioStyle(clone $this->menu->getRadioStyle()); + } $this->menu->addItem($splitItem = $builder->build()); @@ -567,16 +563,40 @@ public function build() : CliMenu return $this->menu; } - public function checkboxStyle(callable $itemCallable) : self + public function getCheckboxStyle() : CheckboxStyle + { + return $this->menu->getCheckboxStyle(); + } + + public function setCheckboxStyle(CheckboxStyle $style) : self + { + $this->menu->setCheckboxStyle($style); + + return $this; + } + + public function modifyCheckboxStyle(callable $itemCallable) : self + { + $itemCallable($this->menu->getCheckboxStyle()); + + return $this; + } + + public function getRadioStyle() : RadioStyle + { + return $this->menu->getRadioStyle(); + } + + public function setRadioStyle(RadioStyle $style) : self { - $this->menu->checkboxStyle($itemCallable); + $this->menu->setRadioStyle($style); return $this; } - public function radioStyle(callable $itemCallable) : self + public function modifyRadioStyle(callable $itemCallable) : self { - $this->menu->radioStyle($itemCallable); + $itemCallable($this->menu->getRadioStyle()); return $this; } diff --git a/src/Builder/SplitItemBuilder.php b/src/Builder/SplitItemBuilder.php index 3ee819a4..c71bbfe1 100644 --- a/src/Builder/SplitItemBuilder.php +++ b/src/Builder/SplitItemBuilder.php @@ -129,13 +129,13 @@ public function addSubMenu(string $text, \Closure $callback) : self $menu = $builder->build(); $menu->setParent($this->menu); - $menu->checkboxStyle(function (CheckboxStyle $style) { - $style->fromArray($this->menu->getCheckboxStyle()->toArray()); - }); + if (!$menu->getCheckboxStyle()->hasChangedFromDefaults()) { + $menu->setCheckboxStyle(clone $this->menu->getCheckboxStyle()); + } - $menu->radioStyle(function (RadioStyle $style) { - $style->fromArray($this->menu->getRadioStyle()->toArray()); - }); + if (!$menu->getRadioStyle()->hasChangedFromDefaults()) { + $menu->setRadioStyle(clone $this->menu->getRadioStyle()); + } $this->splitItem->addItem(new MenuMenuItem( $text, @@ -169,16 +169,40 @@ public function build() : SplitItem return $this->splitItem; } - public function checkboxStyle(callable $itemCallable) : self + public function getCheckboxStyle() : CheckboxStyle + { + return $this->checkboxStyle; + } + + public function setCheckboxStyle(CheckboxStyle $style) : self + { + $this->checkboxStyle = $style; + + return $this; + } + + public function modifyCheckboxStyle(callable $itemCallable) : self + { + $itemCallable($this->menu->getCheckboxStyle()); + + return $this; + } + + public function getRadioStyle() : RadioStyle + { + return $this->radioStyle; + } + + public function setRadioStyle(RadioStyle $style) : self { - $this->menu->checkboxStyle($itemCallable); + $this->radioStyle = $style; return $this; } - public function radioStyle(callable $itemCallable) : self + public function modifyRadioStyle(callable $itemCallable) : self { - $this->menu->radioStyle($itemCallable); + $itemCallable($this->menu->getRadioStyle()); return $this; } diff --git a/src/CliMenu.php b/src/CliMenu.php index 0ea9b71c..1e743ba4 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -660,9 +660,9 @@ public function getCheckboxStyle() : CheckboxStyle return $this->checkboxStyle; } - public function checkboxStyle(callable $itemCallable) : self + public function setCheckboxStyle(CheckboxStyle $style) : self { - $itemCallable($this->checkboxStyle); + $this->checkboxStyle = $style; return $this; } @@ -672,9 +672,9 @@ public function getRadioStyle() : RadioStyle return $this->radioStyle; } - public function radioStyle(callable $itemCallable) : self + public function setRadioStyle(RadioStyle $style) : self { - $itemCallable($this->radioStyle); + $this->radioStyle = $style; return $this; } diff --git a/src/MenuItem/CheckboxItem.php b/src/MenuItem/CheckboxItem.php index 9a958688..be2b3398 100644 --- a/src/MenuItem/CheckboxItem.php +++ b/src/MenuItem/CheckboxItem.php @@ -9,7 +9,18 @@ class CheckboxItem implements MenuItemInterface, ToggableItemInterface { - use ToggableTrait; + /** + * @var callable + */ + private $selectAction; + + private $text = ''; + + private $showItemExtra = false; + + private $disabled = false; + + private $checked = false; /** * @var CheckboxStyle; @@ -89,4 +100,81 @@ public function setStyle(CheckboxStyle $style) : self return $this; } + + /** + * Toggles checked state + */ + public function toggle() : void + { + $this->checked = !$this->checked; + } + + /** + * Sets checked state to true + */ + public function setChecked() : void + { + $this->checked = true; + } + + /** + * Sets checked state to false + */ + public function setUnchecked() : void + { + $this->checked = false; + } + + /** + * Whether or not the item is checked + */ + public function getChecked() : bool + { + return $this->checked; + } + + /** + * Return the raw string of text + */ + public function getText() : string + { + return $this->text; + } + + /** + * Set the raw string of text + */ + public function setText(string $text) : void + { + $this->text = $text; + } + + /** + * Can the item be selected + */ + public function canSelect() : bool + { + return !$this->disabled; + } + + public function showsItemExtra() : bool + { + return $this->showItemExtra; + } + + /** + * Enable showing item extra + */ + public function showItemExtra() : void + { + $this->showItemExtra = true; + } + + /** + * Disable showing item extra + */ + public function hideItemExtra() : void + { + $this->showItemExtra = false; + } } diff --git a/src/MenuItem/RadioItem.php b/src/MenuItem/RadioItem.php index 711732f6..d6017d60 100644 --- a/src/MenuItem/RadioItem.php +++ b/src/MenuItem/RadioItem.php @@ -9,7 +9,18 @@ class RadioItem implements MenuItemInterface, ToggableItemInterface { - use ToggableTrait; + /** + * @var callable + */ + private $selectAction; + + private $text = ''; + + private $showItemExtra = false; + + private $disabled = false; + + private $checked = false; /** * @var RadioStyle; @@ -109,4 +120,81 @@ public function setStyle(RadioStyle $style) : self return $this; } + + /** + * Toggles checked state + */ + public function toggle() : void + { + $this->checked = !$this->checked; + } + + /** + * Sets checked state to true + */ + public function setChecked() : void + { + $this->checked = true; + } + + /** + * Sets checked state to false + */ + public function setUnchecked() : void + { + $this->checked = false; + } + + /** + * Whether or not the item is checked + */ + public function getChecked() : bool + { + return $this->checked; + } + + /** + * Return the raw string of text + */ + public function getText() : string + { + return $this->text; + } + + /** + * Set the raw string of text + */ + public function setText(string $text) : void + { + $this->text = $text; + } + + /** + * Can the item be selected + */ + public function canSelect() : bool + { + return !$this->disabled; + } + + public function showsItemExtra() : bool + { + return $this->showItemExtra; + } + + /** + * Enable showing item extra + */ + public function showItemExtra() : void + { + $this->showItemExtra = true; + } + + /** + * Disable showing item extra + */ + public function hideItemExtra() : void + { + $this->showItemExtra = false; + } } diff --git a/src/MenuItem/ToggableTrait.php b/src/MenuItem/ToggableTrait.php deleted file mode 100644 index e176d420..00000000 --- a/src/MenuItem/ToggableTrait.php +++ /dev/null @@ -1,96 +0,0 @@ -checked = !$this->checked; - } - - /** - * Sets checked state to true - */ - public function setChecked() : void - { - $this->checked = true; - } - - /** - * Sets checked state to false - */ - public function setUnchecked() : void - { - $this->checked = false; - } - - /** - * Whether or not the item is checked - */ - public function getChecked() : bool - { - return $this->checked; - } - - /** - * Return the raw string of text - */ - public function getText() : string - { - return $this->text; - } - - /** - * Set the raw string of text - */ - public function setText(string $text) : void - { - $this->text = $text; - } - - /** - * Can the item be selected - */ - public function canSelect() : bool - { - return !$this->disabled; - } - - public function showsItemExtra() : bool - { - return $this->showItemExtra; - } - - /** - * Enable showing item extra - */ - public function showItemExtra() : void - { - $this->showItemExtra = true; - } - - /** - * Disable showing item extra - */ - public function hideItemExtra() : void - { - $this->showItemExtra = false; - } -} diff --git a/src/Style/CheckboxStyle.php b/src/Style/CheckboxStyle.php index c095603d..38fe2d99 100644 --- a/src/Style/CheckboxStyle.php +++ b/src/Style/CheckboxStyle.php @@ -4,8 +4,6 @@ class CheckboxStyle { - use ItemStyleTrait; - protected const DEFAULT_STYLES = [ 'markerOn' => '[✔] ', 'markerOff' => '[ ] ', @@ -13,6 +11,16 @@ class CheckboxStyle 'displaysExtra' => false, ]; + protected $markerOn = ''; + + protected $markerOff = ''; + + protected $itemExtra = ''; + + protected $displaysExtra = false; + + protected $custom = false; + public function __construct() { $this->setMarkerOn(self::DEFAULT_STYLES['markerOn']); @@ -23,22 +31,71 @@ public function __construct() $this->custom = false; } - public function toArray() : array + public function hasChangedFromDefaults() : bool + { + return $this->custom; + } + + public function getMarker(bool $selected) : string + { + return $selected ? $this->markerOn : $this->markerOff; + } + + public function getMarkerOn() : string + { + return $this->markerOn; + } + + public function setMarkerOn(string $marker) : self + { + $this->custom = true; + + $this->markerOn = $marker; + + return $this; + } + + public function getMarkerOff() : string { - return [ - 'markerOn' => $this->markerOn, - 'markerOff' => $this->markerOff, - 'itemExtra' => $this->itemExtra, - 'displaysExtra' => $this->displaysExtra, - ]; + return $this->markerOff; } - public function fromArray(array $style) : self + public function setMarkerOff(string $marker) : self { - $this->markerOn = $style['markerOn'] ?? $this->markerOn; - $this->markerOff = $style['markerOff'] ?? $this->markerOff; - $this->itemExtra = $style['itemExtra'] ?? $this->itemExtra; - $this->displaysExtra = $style['displaysExtra'] ?? $this->displaysExtra; + $this->custom = true; + + $this->markerOff = $marker; + + return $this; + } + + public function getItemExtra() : string + { + return $this->itemExtra; + } + + public function setItemExtra(string $itemExtra) : self + { + $this->custom = true; + + $this->itemExtra = $itemExtra; + + // if we customise item extra, it means we most likely want to display it + $this->setDisplaysExtra(true); + + return $this; + } + + public function getDisplaysExtra() : bool + { + return $this->displaysExtra; + } + + public function setDisplaysExtra(bool $displaysExtra) : self + { + $this->custom = true; + + $this->displaysExtra = $displaysExtra; return $this; } diff --git a/src/Style/ItemStyleTrait.php b/src/Style/ItemStyleTrait.php deleted file mode 100644 index d65deb91..00000000 --- a/src/Style/ItemStyleTrait.php +++ /dev/null @@ -1,85 +0,0 @@ -custom; - } - - public function getMarker(bool $selected) : string - { - return $selected ? $this->markerOn : $this->markerOff; - } - - public function getMarkerOn() : string - { - return $this->markerOn; - } - - public function setMarkerOn(string $marker) : self - { - $this->custom = true; - - $this->markerOn = $marker; - - return $this; - } - - public function getMarkerOff() : string - { - return $this->markerOff; - } - - public function setMarkerOff(string $marker) : self - { - $this->custom = true; - - $this->markerOff = $marker; - - return $this; - } - - public function getItemExtra() : string - { - return $this->itemExtra; - } - - public function setItemExtra(string $itemExtra) : self - { - $this->custom = true; - - $this->itemExtra = $itemExtra; - - // if we customise item extra, it means we most likely want to display it - $this->setDisplaysExtra(true); - - return $this; - } - - public function getDisplaysExtra() : bool - { - return $this->displaysExtra; - } - - public function setDisplaysExtra(bool $displaysExtra) : self - { - $this->custom = true; - - $this->displaysExtra = $displaysExtra; - - return $this; - } -} diff --git a/src/Style/RadioStyle.php b/src/Style/RadioStyle.php index 6317c6fd..c798a98a 100644 --- a/src/Style/RadioStyle.php +++ b/src/Style/RadioStyle.php @@ -4,8 +4,6 @@ class RadioStyle { - use ItemStyleTrait; - protected const DEFAULT_STYLES = [ 'markerOn' => '[●] ', 'markerOff' => '[○] ', @@ -13,6 +11,16 @@ class RadioStyle 'displaysExtra' => false, ]; + protected $markerOn = ''; + + protected $markerOff = ''; + + protected $itemExtra = ''; + + protected $displaysExtra = false; + + protected $custom = false; + public function __construct() { $this->setMarkerOn(self::DEFAULT_STYLES['markerOn']); @@ -23,22 +31,71 @@ public function __construct() $this->custom = false; } - public function toArray() : array + public function hasChangedFromDefaults() : bool + { + return $this->custom; + } + + public function getMarker(bool $selected) : string + { + return $selected ? $this->markerOn : $this->markerOff; + } + + public function getMarkerOn() : string + { + return $this->markerOn; + } + + public function setMarkerOn(string $marker) : self + { + $this->custom = true; + + $this->markerOn = $marker; + + return $this; + } + + public function getMarkerOff() : string { - return [ - 'markerOn' => $this->markerOn, - 'markerOff' => $this->markerOff, - 'itemExtra' => $this->itemExtra, - 'displaysExtra' => $this->displaysExtra, - ]; + return $this->markerOff; } - public function fromArray(array $style) : self + public function setMarkerOff(string $marker) : self { - $this->markerOn = $style['markerOn'] ?? $this->markerOn; - $this->markerOff = $style['markerOff'] ?? $this->markerOff; - $this->itemExtra = $style['itemExtra'] ?? $this->itemExtra; - $this->displaysExtra = $style['displaysExtra'] ?? $this->displaysExtra; + $this->custom = true; + + $this->markerOff = $marker; + + return $this; + } + + public function getItemExtra() : string + { + return $this->itemExtra; + } + + public function setItemExtra(string $itemExtra) : self + { + $this->custom = true; + + $this->itemExtra = $itemExtra; + + // if we customise item extra, it means we most likely want to display it + $this->setDisplaysExtra(true); + + return $this; + } + + public function getDisplaysExtra() : bool + { + return $this->displaysExtra; + } + + public function setDisplaysExtra(bool $displaysExtra) : self + { + $this->custom = true; + + $this->displaysExtra = $displaysExtra; return $this; } From 7a8a9631f8c6199f40ea81f03ce3a62be8a73b4f Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 15:50:27 -0600 Subject: [PATCH 6/7] Updates README radioStyle -> modifyRadioStyle --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 573fd943..dc5e1ef4 100644 --- a/README.md +++ b/README.md @@ -820,7 +820,7 @@ use PhpSchool\CliMenu\Builder\CliMenuBuilder; use PhpSchool\CliMenu\Style\CheckboxStyle; $menu = (new CliMenuBuilder) - ->checkboxStyle(function (CheckboxStyle $style) { + ->modifyCheckboxStyle(function (CheckboxStyle $style) { $style->setMarkerOff('[○] ') ->setMarkerOn('[●] '); }) @@ -836,7 +836,7 @@ use PhpSchool\CliMenu\Builder\CliMenuBuilder; use PhpSchool\CliMenu\Style\RadioStyle; $menu = (new CliMenuBuilder) - ->radioStyle(function (RadioStyle $style) { + ->modifyRadioStyle(function (RadioStyle $style) { $style->setMarkerOff('[ ] ') ->setMarkerOn('[✔] '); }) From 0f1db5f75e89bef2772cc08818ddf796b6257983 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 16:17:45 -0600 Subject: [PATCH 7/7] SplitItemBuilder should reference menu styles --- src/Builder/CliMenuBuilder.php | 10 ++-------- src/Builder/SplitItemBuilder.php | 21 ++++----------------- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index dd6d45f5..469f27be 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -320,6 +320,8 @@ private function processIndividualShortcut(MenuItemInterface $item, callable $ca public function addSplitItem(\Closure $callback) : self { $builder = new SplitItemBuilder($this->menu); + $builder->setCheckboxStyle(clone $this->menu->getCheckboxStyle()) + ->setRadioStyle(clone $this->menu->getRadioStyle()); if ($this->autoShortcuts) { $builder->enableAutoShortcuts($this->autoShortcutsRegex); @@ -327,14 +329,6 @@ public function addSplitItem(\Closure $callback) : self $callback($builder); - if (!$builder->getCheckboxStyle()->hasChangedFromDefaults()) { - $builder->setCheckboxStyle(clone $this->menu->getCheckboxStyle()); - } - - if (!$builder->getRadioStyle()->hasChangedFromDefaults()) { - $builder->setRadioStyle(clone $this->menu->getRadioStyle()); - } - $this->menu->addItem($splitItem = $builder->build()); $this->processSplitItemShortcuts($splitItem); diff --git a/src/Builder/SplitItemBuilder.php b/src/Builder/SplitItemBuilder.php index c71bbfe1..1f6112a6 100644 --- a/src/Builder/SplitItemBuilder.php +++ b/src/Builder/SplitItemBuilder.php @@ -44,23 +44,10 @@ class SplitItemBuilder */ private $autoShortcutsRegex = '/\[(.)\]/'; - /** - * @var CheckboxStyle - */ - private $checkboxStyle; - - /** - * @var RadioStyle - */ - private $radioStyle; - public function __construct(CliMenu $menu) { $this->menu = $menu; $this->splitItem = new SplitItem(); - - $this->checkboxStyle = new CheckboxStyle(); - $this->radioStyle = new RadioStyle(); } public function addItem( @@ -171,12 +158,12 @@ public function build() : SplitItem public function getCheckboxStyle() : CheckboxStyle { - return $this->checkboxStyle; + return $this->menu->getCheckboxStyle(); } public function setCheckboxStyle(CheckboxStyle $style) : self { - $this->checkboxStyle = $style; + $this->menu->setCheckboxStyle($style); return $this; } @@ -190,12 +177,12 @@ public function modifyCheckboxStyle(callable $itemCallable) : self public function getRadioStyle() : RadioStyle { - return $this->radioStyle; + return $this->menu->getRadioStyle(); } public function setRadioStyle(RadioStyle $style) : self { - $this->radioStyle = $style; + $this->menu->setRadioStyle($style); return $this; }