Completed
Pull Request — master (#40)
by Michael
02:08
created

MenuStyle::getDisabledItemText()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace PhpSchool\CliMenu;
4
5
use PhpSchool\CliMenu\Exception\InvalidInstantiationException;
6
use PhpSchool\CliMenu\Terminal\TerminalFactory;
7
use PhpSchool\CliMenu\Terminal\TerminalInterface;
8
9
//TODO: B/W fallback
10
11
/**
12
 * Class MenuStyle
13
 *
14
 * @package PhpSchool\CliMenu
15
 * @author Michael Woodward <[email protected]>
16
 */
17
class MenuStyle
18
{
19
    /**
20
     * @var TerminalInterface
21
     */
22
    protected $terminal;
23
24
    /**
25
     * @var string
26
     */
27
    protected $fg;
28
29
    /**
30
     * @var string
31
     */
32
    protected $bg;
33
34
    /**
35
     * @var int
36
     */
37
    protected $width;
38
39
    /**
40
     * @var int
41
     */
42
    protected $padding;
43
44
    /**
45
     * @var int
46
     */
47
    protected $margin;
48
49
    /**
50
     * @var int
51
     */
52
    protected $contentWidth;
53
54
    /**
55
     * @var string
56
     */
57
    private $selectedMarker;
58
59
    /**
60
     * @var string
61
     */
62
    private $unselectedMarker;
63
64
    /**
65
     * @var string
66
     */
67
    private $itemExtra;
68
69
    /**
70
     * @var bool
71
     */
72
    private $displaysExtra;
73
74
    /**
75
     * @var string
76
     */
77
    private $titleSeparator;
78
79
    /**
80
     * @var string
81
     */
82
    private $allowedConsumer = 'PhpSchool\CliMenu\CliMenuBuilder';
83
84
    /**
85
     * @var array
86
     */
87
    private static $availableForegroundColors = array(
88
        'black'   => array('set' => 30, 'unset' => 39),
89
        'red'     => array('set' => 31, 'unset' => 39),
90
        'green'   => array('set' => 32, 'unset' => 39),
91
        'yellow'  => array('set' => 33, 'unset' => 39),
92
        'blue'    => array('set' => 34, 'unset' => 39),
93
        'magenta' => array('set' => 35, 'unset' => 39),
94
        'cyan'    => array('set' => 36, 'unset' => 39),
95
        'white'   => array('set' => 37, 'unset' => 39),
96
        'default' => array('set' => 39, 'unset' => 39),
97
    );
98
99
    /**
100
     * @var array
101
     */
102
    private static $availableBackgroundColors = array(
103
        'black'   => array('set' => 40, 'unset' => 49),
104
        'red'     => array('set' => 41, 'unset' => 49),
105
        'green'   => array('set' => 42, 'unset' => 49),
106
        'yellow'  => array('set' => 43, 'unset' => 49),
107
        'blue'    => array('set' => 44, 'unset' => 49),
108
        'magenta' => array('set' => 45, 'unset' => 49),
109
        'cyan'    => array('set' => 46, 'unset' => 49),
110
        'white'   => array('set' => 47, 'unset' => 49),
111
        'default' => array('set' => 49, 'unset' => 49),
112
    );
113
114
    /**
115
     * @var array
116
     */
117
    private static $availableOptions = array(
118
        'bold'       => array('set' => 1, 'unset' => 22),
119
        'dim'        => array('set' => 2, 'unset' => 22),
120
        'underscore' => array('set' => 4, 'unset' => 24),
121
        'blink'      => array('set' => 5, 'unset' => 25),
122
        'reverse'    => array('set' => 7, 'unset' => 27),
123
        'conceal'    => array('set' => 8, 'unset' => 28)
124
    );
125
126
    /**
127
     * Initialise style
128
     *
129
     * @param string $bg
130
     * @param string $fg
131
     * @param int $width
132
     * @param int $padding
133
     * @param int $margin
134
     * @param string $unselectedMarker
135
     * @param string $selectedMarker
136
     * @param string $itemExtra
137
     * @param bool $displaysExtra
138
     * @param string $titleSeparator
139
     * @param TerminalInterface $terminal
140
     * @throws InvalidInstantiationException
141
     */
142
    // TODO: Disabled marker ideally without breaking change.
143
    public function __construct(
144
        $bg = 'blue',
145
        $fg = 'white',
146
        $width = 100,
147
        $padding = 2,
148
        $margin = 2,
149
        $unselectedMarker = '○',
150
        $selectedMarker = '●',
151
        $itemExtra = '✔',
152
        $displaysExtra = false,
153
        $titleSeparator = '=',
154
        TerminalInterface $terminal = null
155
    ) {
156
        $builder = debug_backtrace();
157 View Code Duplication
        if (count($builder) < 2 || !isset($builder[1]['class']) || $builder[1]['class'] !== $this->allowedConsumer) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
            throw new InvalidInstantiationException(
159
                sprintf('The MenuStyle must be instantiated by "%s"', $this->allowedConsumer)
160
            );
161
        }
162
163
        $this->terminal        = $terminal ?: TerminalFactory::fromSystem();
164
        $this->bg              = $bg;
165
        $this->fg              = $fg;
166
        $this->padding         = $padding;
167
        $this->margin          = $margin;
168
        $this->itemExtra       = $itemExtra;
169
        $this->displaysExtra   = $displaysExtra;
170
        $this->titleSeparator  = $titleSeparator;
171
172
        $this->setUnselectedMarker($unselectedMarker);
173
        $this->setSelectedMarker($selectedMarker);
174
        $this->setWidth($width);
175
        $this->calculateContentWidth();
176
    }
177
178
    /**
179
     * @return array
180
     */
181
    public static function getAvailableColours()
182
    {
183
        return array_keys(self::$availableBackgroundColors);
184
    }
185
186
    /**
187
     * @param string $text
188
     * @return string
189
     */
190
    public function getDisabledItemText($text)
191
    {
192
        return sprintf(
193
            "\033[%sm%s\033[%sm",
194
            self::$availableOptions['dim']['set'],
195
            $text,
196
            self::$availableOptions['dim']['unset']
197
        );
198
    }
199
    
200
    /**
201
     * Get the colour code set for Bg and Fg
202
     *
203
     * @return string
204
     */
205 View Code Duplication
    public function getSelectedSetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
    {
207
        return sprintf(
208
            "\033[%sm",
209
            implode(';', [
210
                self::$availableBackgroundColors[$this->getFg()]['set'],
211
                self::$availableForegroundColors[$this->getBg()]['set'],
212
            ])
213
        );
214
    }
215
216
    /**
217
     * Get the colour unset code for Bg and Fg
218
     *
219
     * @return string
220
     */
221 View Code Duplication
    public function getSelectedUnsetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
    {
223
        return sprintf(
224
            "\033[%sm",
225
            implode(';', [
226
                self::$availableBackgroundColors[$this->getBg()]['unset'],
227
                self::$availableForegroundColors[$this->getFg()]['unset'],
228
            ])
229
        );
230
    }
231
232
    /**
233
     * Get the inverted colour code
234
     *
235
     * @return string
236
     */
237 View Code Duplication
    public function getUnselectedSetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
238
    {
239
        return sprintf(
240
            "\033[%sm",
241
            implode(';', [
242
                self::$availableBackgroundColors[$this->getBg()]['set'],
243
                self::$availableForegroundColors[$this->getFg()]['set'],
244
            ])
245
        );
246
    }
247
248
    /**
249
     * Get the inverted colour unset code
250
     *
251
     * @return string
252
     */
253 View Code Duplication
    public function getUnselectedUnsetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
254
    {
255
        return sprintf(
256
            "\033[%sm",
257
            implode(';', [
258
                self::$availableBackgroundColors[$this->getBg()]['unset'],
259
                self::$availableForegroundColors[$this->getFg()]['unset'],
260
            ])
261
        );
262
    }
263
264
    /**
265
     * Calculate the contents width
266
     */
267
    protected function calculateContentWidth()
268
    {
269
        $this->contentWidth = $this->width - ($this->padding*2) - ($this->margin*2);
270
    }
271
272
    /**
273
     * @return string
274
     */
275
    public function getFg()
276
    {
277
        return $this->fg;
278
    }
279
280
    /**
281
     * @param string $fg
282
     * @return MenuStyle
283
     */
284
    public function setFg($fg)
285
    {
286
        $this->fg = $fg;
287
288
        return $this;
289
    }
290
291
    /**
292
     * @return string
293
     */
294
    public function getBg()
295
    {
296
        return $this->bg;
297
    }
298
299
    /**
300
     * @param string $bg
301
     * @return MenuStyle
302
     */
303
    public function setBg($bg)
304
    {
305
        $this->bg = $bg;
306
307
        return $this;
308
    }
309
310
    /**
311
     * @return int
312
     */
313
    public function getWidth()
314
    {
315
        return $this->width;
316
    }
317
318
    /**
319
     * @param int $width
320
     * @return MenuStyle
321
     */
322
    public function setWidth($width)
323
    {
324
        $availableWidth = $this->terminal->getWidth() - ($this->margin * 2) - ($this->padding * 2);
325
326
        if ($width >= $availableWidth) {
327
            $width = $availableWidth;
328
        }
329
330
        $this->width = $width;
331
        $this->calculateContentWidth();
332
333
        return $this;
334
    }
335
336
    /**
337
     * @return int
338
     */
339
    public function getPadding()
340
    {
341
        return $this->padding;
342
    }
343
344
    /**
345
     * @param int $padding
346
     * @return MenuStyle
347
     */
348
    public function setPadding($padding)
349
    {
350
        $this->padding = $padding;
351
352
        $this->calculateContentWidth();
353
354
        return $this;
355
    }
356
357
    /**
358
     * @return int
359
     */
360
    public function getMargin()
361
    {
362
        return $this->margin;
363
    }
364
365
    /**
366
     * @param int $margin
367
     * @return MenuStyle
368
     */
369
    public function setMargin($margin)
370
    {
371
        $this->margin = $margin;
372
373
        $this->calculateContentWidth();
374
375
        return $this;
376
    }
377
378
    /**
379
     * @return int
380
     */
381
    public function getContentWidth()
382
    {
383
        return $this->contentWidth;
384
    }
385
386
    /**
387
     * Get padding for right had side of content
388
     *
389
     * @param $contentLength
390
     * @return int
391
     */
392
    public function getRightHandPadding($contentLength)
393
    {
394
        return $this->getContentWidth() - $contentLength + $this->getPadding();
395
    }
396
397
    /**
398
     * @return string
399
     */
400
    public function getSelectedMarker()
401
    {
402
        return $this->selectedMarker;
403
    }
404
405
    /**
406
     * @param string $marker
407
     * @return $this
408
     */
409
    public function setSelectedMarker($marker)
410
    {
411
        $this->selectedMarker = mb_substr($marker, 0, 1);
412
413
        return $this;
414
    }
415
416
    /**
417
     * @return string
418
     */
419
    public function getUnselectedMarker()
420
    {
421
        return $this->unselectedMarker;
422
    }
423
424
    /**
425
     * @param string $marker
426
     * @return $this
427
     */
428
    public function setUnselectedMarker($marker)
429
    {
430
        $this->unselectedMarker = mb_substr($marker, 0, 1);
431
432
        return $this;
433
    }
434
435
    /**
436
     * Get the correct marker for the item
437
     *
438
     * @param bool $selected
439
     * @return string
440
     */
441
    public function getMarker($selected)
442
    {
443
        // TODO: Incorperate disabled markers ?
444
        return $selected ? $this->selectedMarker : $this->unselectedMarker;
445
    }
446
447
    /**
448
     * @param string $itemExtra
449
     */
450
    public function setItemExtra($itemExtra)
451
    {
452
        $this->itemExtra = $itemExtra;
453
    }
454
455
    /**
456
     * @return string
457
     */
458
    public function getItemExtra()
459
    {
460
        return $this->itemExtra;
461
    }
462
463
    /**
464
     * @return bool
465
     */
466
    public function getDisplaysExtra()
467
    {
468
        return $this->displaysExtra;
469
    }
470
471
    /**
472
     * @param bool $displaysExtra
473
     * @return $this
474
     */
475
    public function setDisplaysExtra($displaysExtra)
476
    {
477
        $this->displaysExtra = $displaysExtra;
478
479
        return $this;
480
    }
481
482
    /**
483
     * @return string
484
     */
485
    public function getTitleSeparator()
486
    {
487
        return $this->titleSeparator;
488
    }
489
490
    /**
491
     * @param string $actionSeparator
492
     * @return $this
493
     */
494
    public function setTitleSeparator($actionSeparator)
495
    {
496
        $this->titleSeparator = $actionSeparator;
497
498
        return $this;
499
    }
500
}
501