Skip to content

Item-level style example; fixes disappearing styles for nested #203

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

Closed
wants to merge 8 commits into from
Closed

Item-level style example; fixes disappearing styles for nested #203

wants to merge 8 commits into from

Conversation

jtreminio
Copy link
Contributor

Not ready for merge. Needs feedback, unit tests and general cleanup.

@jtreminio
Copy link
Contributor Author

jtreminio commented Dec 18, 2019

Basically what I've changed is created three new style objects:

  • CheckableStyle
  • RadioStyle
  • SelectableStyle

Each CliMenu keeps a copy of each of these styles to use as its base for all current-level and children items (checkable, radio and selectable items).

So an example CheckableItem would be:

<?php

use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Style\CheckableStyle;

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

$itemCallable = function (CliMenu $menu) {
    echo $menu->getSelectedItem()->getText();
};

$menu = (new CliMenuBuilder)
    ->setTitle('Select a Language')
    ->addSubMenu('Compiled', function (CliMenuBuilder $b) use ($itemCallable) {
        $b->setTitle('Compiled Languages')
            ->addCheckableItem('Rust', $itemCallable)
            ->addCheckableItem('C++', $itemCallable)
            ->addCheckableItem('Go', $itemCallable)
            ->addCheckableItem('Java', $itemCallable)
            ->addCheckableItem('C', $itemCallable)
        ;
    })
    ->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) {
        $b->setTitle('Interpreted Languages')
            ->checkableStyle(function (CheckableStyle $style) {
                $style->setMarkerOff('[○] ')
                    ->setMarkerOn('[●] ');
            })
            ->addCheckableItem('PHP', $itemCallable)
            ->addCheckableItem('Javascript', $itemCallable)
            ->addCheckableItem('Ruby', $itemCallable)
            ->addCheckableItem('Python', $itemCallable)
        ;
    })
    ->build();

$menu->open();

The style classes only care about styles related to their item type. Right now they're identical, only difference are the marker texts.

You'll be able to deprecate the following in MenuStyle:

  • $selectedMarker
  • $unselectedMarker
  • $itemExtra
  • $displaysExtra

since these are item-level styles. Note that not all item types have moved off of MenuStyle - this is just the start of the PR, pending feedback.

Since the style classes all share the same interface, we're able to get rid of setUncheckedMarker, getUnchecked and similar.


Aside from this, I was able to fix the #201 issue.

CliMenuBuilder::addSubMenu() and CliMenuBuilder::addSubMenuFromBuilder() now inject a closure to MenuMenuItem(). Then, when the menu is first opened and MenuMenuItem::showSubMenu() is called then the closure is unpackaged and the menu generated.

This helps avoid creating the menu code ahead of time, and uses style values that are set after all PHP code has been read.

@codecov-io
Copy link

codecov-io commented Dec 18, 2019

Codecov Report

Merging #203 into master will decrease coverage by 2.05%.
The diff coverage is 85.04%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #203      +/-   ##
============================================
- Coverage     93.91%   91.85%   -2.06%     
- Complexity      516      554      +38     
============================================
  Files            29       35       +6     
  Lines          1561     1744     +183     
============================================
+ Hits           1466     1602     +136     
- Misses           95      142      +47
Impacted Files Coverage Δ Complexity Δ
src/MenuItem/RadioItem.php 100% <100%> (ø) 6 <2> (-4) ⬇️
src/MenuItem/SelectableTrait.php 100% <100%> (ø) 11 <2> (+2) ⬆️
src/Style/SelectableStyle.php 100% <100%> (ø) 3 <3> (?)
src/Style/RadioStyle.php 100% <100%> (ø) 3 <3> (?)
src/CliMenu.php 95.34% <100%> (+0.29%) 115 <6> (+6) ⬆️
src/MenuItem/CheckableItem.php 100% <100%> (ø) 5 <4> (-4) ⬇️
src/Style/CheckableStyle.php 100% <100%> (ø) 3 <3> (?)
src/MenuItem/ToggableTrait.php 100% <100%> (ø) 15 <6> (+4) ⬆️
src/MenuStyle.php 96.61% <100%> (-0.67%) 60 <0> (-18)
src/MenuItem/SplitItem.php 100% <100%> (ø) 46 <1> (-1) ⬇️
... and 15 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a9e6a34...b08a081. Read the comment docs.

@jtreminio
Copy link
Contributor Author

createMenuClosure() should be refactored into a trait or something else. IT's identical between CliMenuBuilder and SplitItemBuilder.

@jtreminio
Copy link
Contributor Author

This PR provides item-level styles, and completely removes these same styles from MenuStyle.

To run a quick test:

<?php

use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\MenuItem\SelectableItem;

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

$itemCallable = function (CliMenu $menu) {
    echo $menu->getSelectedItem()->getText();
};

$item1 = new SelectableItem('Item 1', function () {});
$item1->getStyle()
    ->setMarkerOff('! ')
    ->setMarkerOn('1 ');

$item2 = new SelectableItem('Item 2', function () {});
$item2->getStyle()
    ->setMarkerOff('@ ')
    ->setMarkerOn('2 ');

$item3 = new SelectableItem('Item 3', function () {});
$item3->getStyle()
    ->setMarkerOff('# ')
    ->setMarkerOn('3 ');

$menu = (new CliMenuBuilder)
    ->setTitle('Basic CLI Menu')
    ->addMenuItem($item1)
    ->addMenuItem($item2)
    ->addMenuItem($item3)
    ->addLineBreak('-')
    ->build();

$menu->open();

Peek 2019-12-18 22-20

@jtreminio jtreminio mentioned this pull request Dec 19, 2019
@@ -22,8 +23,10 @@
})
->addSubMenu('Interpreted', function (CliMenuBuilder $b) use ($itemCallable) {
$b->setTitle('Interpreted Languages')
->setUncheckedMarker('[○] ')
->setCheckedMarker('[●] ')
->setCheckableStyle(function (CheckableStyle $style) {
Copy link
Member

@AydinHassan AydinHassan Dec 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is irking me a little. Can we change CheckableItem to CheckboxItem to match RadioItem please, then possibly change this to CheckboxStyle and ->setCheckboxStyle. Can we rename the checkbox as a separate PR though. This one in a bit unruly!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, removing the able from items makes sense and it was bothering me as well.

As for this being unruly - I can yank out the bits with Closure that fixes nested styles not being applied, and put it into a separate PR. Anything else you think isn't clear, though?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be very helpful, I'll try pick out and comment on things I think can be separated. Appreciate all the work though!


use PhpSchool\CliMenu\Style;

interface ItemStyleInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this StyleableItem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StyleableItem or StyleableItemInterface?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just go with StyleableItem

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it again, we also don't need this. I think we can drop it. Each item can still implement getStyle and setStyle but should type hint on the concrete style they need. If it turns out that a few different types of item use basically the same styles then we can introduce an interface but I think until then there is no benefit.


namespace PhpSchool\CliMenu\Style;

interface ItemStyleInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather get rid of the interfaces for each item style type. Each item renders itself so therefore can just hint on the concrete. I don't think we need interfaces for that.

@AydinHassan
Copy link
Member

What I'd like to see here (after changing the checkableitem to checkbox item) a PR just changing checkbox item to this new individual style design. And then we can PR each item type one by one making it easier to review. I think it makes it easier to discuss the design that way. What do you think?

@jtreminio jtreminio closed this Dec 19, 2019
@jtreminio
Copy link
Contributor Author

What I'd like to see here (after changing the checkableitem to checkbox item) a PR just changing checkbox item to this new individual style design. And then we can PR each item type one by one making it easier to review. I think it makes it easier to discuss the design that way. What do you think?

I'll redo the PR to slim it down in scope, but doing only Checkbox styling and leaving Radio and Selectable will be ugly as will need to do a bunch if if (... instanceof ...) checks.

I'll create the minimum for the Selectable and Radio styles and include in PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants