Skip to content

Initial SplitItem + CheckableItem support #189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
<?php

use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;

$callable = function (CliMenu $menu) {
$item = $menu->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
Expand Down Expand Up @@ -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
<?php
Expand Down Expand Up @@ -707,7 +730,7 @@ $menu->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
Expand Down Expand Up @@ -769,6 +792,19 @@ $menu = (new CliMenuBuilder)
->build();
```

You may also change the marker for `\PhpSchool\CliMenu\MenuItem\CheckableItem`:

```php
<?php

use PhpSchool\CliMenu\Builder\CliMenuBuilder;

$menu = (new CliMenuBuilder)
->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
Expand Down Expand Up @@ -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);
Expand Down
32 changes: 32 additions & 0 deletions examples/split-checkable-item.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use PhpSchool\CliMenu\Builder\SplitItemBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\MenuItem\CheckableItem;

require_once(__DIR__ . '/../vendor/autoload.php');

$itemCallable = function (CliMenu $menu) {
/** @var CheckableItem $item */
$item = $menu->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();
12 changes: 12 additions & 0 deletions src/Builder/SplitItemBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
3 changes: 1 addition & 2 deletions src/MenuItem/CheckableItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 10 additions & 1 deletion src/MenuItem/SplitItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,17 @@ 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 ($item instanceof CheckableItem) {
$markerType = $item->getChecked()
? $style->getCheckedMarker()
: $style->getUncheckedMarker();
} else {
$markerType = $style->getMarker($isSelected);
}

$marker = $item->canSelect()
? sprintf('%s', $style->getMarker($isSelected))
? sprintf('%s', $markerType)
: '';

$itemExtra = '';
Expand Down
26 changes: 26 additions & 0 deletions test/Builder/SplitItemBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
{

Expand Down