From a83d9f85325fa8855df914911a3f587647219f8a Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Mon, 16 Dec 2019 12:35:31 -0600 Subject: [PATCH 1/4] Initial SplitItem + CheckableItem support --- examples/split-checkable-item.php | 32 +++++++++++++++++++++++++++++++ src/Builder/SplitItemBuilder.php | 12 ++++++++++++ src/MenuItem/SplitItem.php | 12 +++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 examples/split-checkable-item.php diff --git a/examples/split-checkable-item.php b/examples/split-checkable-item.php new file mode 100644 index 00000000..862c4beb --- /dev/null +++ b/examples/split-checkable-item.php @@ -0,0 +1,32 @@ +getSelectedItem(); + + $item->toggle(); + + $menu->redraw(); +}; + +$menu = (new CliMenuBuilder) + ->setTitle('Select a Language') + ->addSplitItem(function (SplitItemBuilder $b) use ($itemCallable) { + $b->setGutter(5) + ->addCheckableItem('Rust', $itemCallable) + ->addCheckableItem('C++', $itemCallable) + ->addCheckableItem('Go', $itemCallable) + ->addCheckableItem('Java', $itemCallable) + ->addCheckableItem('C', $itemCallable) + ; + }) + ->build(); + +$menu->open(); diff --git a/src/Builder/SplitItemBuilder.php b/src/Builder/SplitItemBuilder.php index 61fac5de..99014b61 100644 --- a/src/Builder/SplitItemBuilder.php +++ b/src/Builder/SplitItemBuilder.php @@ -3,6 +3,7 @@ namespace PhpSchool\CliMenu\Builder; use PhpSchool\CliMenu\CliMenu; +use PhpSchool\CliMenu\MenuItem\CheckableItem; use PhpSchool\CliMenu\MenuItem\LineBreakItem; use PhpSchool\CliMenu\MenuItem\MenuMenuItem; use PhpSchool\CliMenu\MenuItem\SelectableItem; @@ -57,6 +58,17 @@ public function addItem( return $this; } + public function addCheckableItem( + string $text, + callable $itemCallable, + bool $showItemExtra = false, + bool $disabled = false + ) : self { + $this->splitItem->addItem(new CheckableItem($text, $itemCallable, $showItemExtra, $disabled)); + + return $this; + } + public function addStaticItem(string $text) : self { $this->splitItem->addItem(new StaticItem($text)); diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index bc5d27fe..5db63fa6 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -129,8 +129,18 @@ public function getRows(MenuStyle $style, bool $selected = false) : array return $this->buildRows( array_map(function ($index, $item) use ($selected, $length, $style) { $isSelected = $selected && $index === $this->selectedItemIndex; + + if (is_a($item, CheckableItem::class)) { + /** @var CheckableItem $item */ + $markerType = $item->getChecked() + ? $style->getCheckedMarker() + : $style->getUncheckedMarker(); + } else { + $markerType = $style->getMarker($isSelected); + } + $marker = $item->canSelect() - ? sprintf('%s', $style->getMarker($isSelected)) + ? sprintf('%s', $markerType) : ''; $itemExtra = ''; From 80550ffc506993c25971a135ed26c65edb1fe5b9 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Tue, 17 Dec 2019 09:07:31 -0600 Subject: [PATCH 2/4] PR changes --- src/MenuItem/CheckableItem.php | 3 +-- src/MenuItem/SplitItem.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/MenuItem/CheckableItem.php b/src/MenuItem/CheckableItem.php index 93f021d7..e8fded5d 100644 --- a/src/MenuItem/CheckableItem.php +++ b/src/MenuItem/CheckableItem.php @@ -2,11 +2,10 @@ namespace PhpSchool\CliMenu\MenuItem; -use PhpSchool\CliMenu\MenuItem; use PhpSchool\CliMenu\MenuStyle; use PhpSchool\CliMenu\Util\StringUtil; -class CheckableItem implements MenuItem\MenuItemInterface +class CheckableItem implements MenuItemInterface { /** * @var callable diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 5db63fa6..ea362cda 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -130,8 +130,7 @@ public function getRows(MenuStyle $style, bool $selected = false) : array array_map(function ($index, $item) use ($selected, $length, $style) { $isSelected = $selected && $index === $this->selectedItemIndex; - if (is_a($item, CheckableItem::class)) { - /** @var CheckableItem $item */ + if ($item instanceof CheckableItem) { $markerType = $item->getChecked() ? $style->getCheckedMarker() : $style->getUncheckedMarker(); From 8dbcee9a5b4fbeca103e9d13c2e270a1b30f64af Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Tue, 17 Dec 2019 09:13:12 -0600 Subject: [PATCH 3/4] Tests for SplitItem + CheckableItem support --- test/Builder/SplitItemBuilderTest.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/Builder/SplitItemBuilderTest.php b/test/Builder/SplitItemBuilderTest.php index 6d2d10fe..3450c35f 100644 --- a/test/Builder/SplitItemBuilderTest.php +++ b/test/Builder/SplitItemBuilderTest.php @@ -4,6 +4,7 @@ use PhpSchool\CliMenu\Builder\SplitItemBuilder; use PhpSchool\CliMenu\CliMenu; +use PhpSchool\CliMenu\MenuItem\CheckableItem; use PhpSchool\CliMenu\MenuItem\MenuMenuItem; use PhpSchool\CliMenu\MenuItem\SelectableItem; use PhpSchool\CliMenu\MenuItem\SplitItem; @@ -37,6 +38,31 @@ public function testAddItem() : void $this->checkItemItems($item, $expected); } + public function testAddCheckableItem() : void + { + $callable = function () { + }; + + $menu = new CliMenu(null, []); + $builder = new SplitItemBuilder($menu); + $builder->addCheckableItem('Item 1', $callable); + $builder->addCheckableItem('Item 2', $callable); + $item = $builder->build(); + + $expected = [ + [ + 'class' => CheckableItem::class, + 'text' => 'Item 1', + ], + [ + 'class' => CheckableItem::class, + 'text' => 'Item 2', + ], + ]; + + $this->checkItemItems($item, $expected); + } + public function testAddStaticItem() : void { From d25a1b3270a0d548b0087817cb3ab673e6810437 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Tue, 17 Dec 2019 09:27:27 -0600 Subject: [PATCH 4/4] Adds CheckableItem to README. Needs fancy screenshot example --- README.md | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0cea2d90..0ec66fd4 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ * [Remove Exit Button](#remove-exit-button) * [Items](#appearance) * [Selectable Item](#selectable-item) + * [Checkable Item](#checkable-item) * [Line Break Item](#line-break-item) * [Static Item](#static-item) * [Ascii Art Item](#ascii-art-item) @@ -499,6 +500,7 @@ $menu = (new CliMenuBuilder) There a few different types of items you can add to your menu * Selectable Item - This is the type of item you need for something to be selectable (you can hit enter and it will invoke your callable) +* Checkable Item - This is a checkbox type of item that keeps track of its toggled state to show a different marker. * Line Break Item - This is used to break up areas, it can span multiple lines and will be the width of Menu. Whatever string is passed will be repeated. * Static Item - This will print whatever text is passed, useful for headings. * Ascii Art Item - Special item which allows usage of Ascii art. It takes care of padding and alignment. @@ -544,6 +546,27 @@ $menu = (new CliMenuBuilder) Note: You can add as many items as you want and they can all have a different action. The action is the second parameter and must be a valid PHP `callable`. Try using an `Invokable` class to keep your actions easily testable. +### Checkable Item + +```php +getSelectedItem(); + $item->toggle(); + $menu->redraw(); +}; + +$menu = (new CliMenuBuilder) + ->addCheckableItem('Item 1', $callable) + ->addCheckableItem('Item 2', $callable) + ->addCheckableItem('Item 3', $callable) + ->build(); +``` + ### Line Break Item ```php @@ -674,7 +697,7 @@ Split Items allows you to add multiple items on the same row. The full width of You can set the number of spaces separating items using `->setGutter()` (defaults to 2). -Only Selectable, Static and SubMenu items are currently allowed inside a Split Item. +Only Selectable, Checkable, Static and SubMenu items are currently allowed inside a Split Item. ```php open(); There are a few things to note about the syntax and builder process here: 1. The first parameter to `addSplitItem` is a closure, which will be invoked with a new instance of `SplitItemBuilder` which you can use to add items to the split item. -2. You can call `addItem`, `addSubMenu` and `addStaticItem` on the `SplitItemBuilder`. +2. You can call `addItem`, `addCheckableItem`, `addSubMenu` and `addStaticItem` on the `SplitItemBuilder`. 3. `SplitItemBuilder` has a fluent interface so you can chain method calls. Note: The closure used to build the split item is also binded with the `SplitItemBuilder` instance so you can add items and such using `$this->addItem()` rather than using the function @@ -769,6 +792,19 @@ $menu = (new CliMenuBuilder) ->build(); ``` +You may also change the marker for `\PhpSchool\CliMenu\MenuItem\CheckableItem`: + +```php +setUncheckedMarker('[○] ') + ->setCheckedMarker('[●] ') + ->build(); +``` + ### Item Extra You can optionally display some arbitrary text on the right hand side of an item. You can customise this text and @@ -904,7 +940,7 @@ $exit = function(CliMenu $menu) { }; $menu = (new CliMenuBuilder) - ->addItem('Item 1') + ->addItem('Item 1', function(CliMenu $menu) {}) ->build(); $menu->addCustomControlMapping("x", $exit);