-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from skoro/widget/progressbar
Implementation of progressbar widget
- Loading branch information
Showing
5 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Tkui\Layouts\Pack; | ||
use Tkui\TclTk\Variable; | ||
use Tkui\Widgets\Buttons\Button; | ||
use Tkui\Widgets\Container; | ||
use Tkui\Widgets\Frame; | ||
use Tkui\Widgets\Label; | ||
use Tkui\Widgets\LabelFrame; | ||
use Tkui\Widgets\Progressbar; | ||
|
||
require_once __DIR__ . '/DemoAppWindow.php'; | ||
|
||
$demo = new class extends DemoAppWindow | ||
{ | ||
const MAX_VALUE = 100; | ||
|
||
private Variable $progressValue; | ||
/** @var array<Progressbar> */ | ||
private array $autoincrementBars; | ||
|
||
public function __construct() | ||
{ | ||
parent::__construct('Progressbar Demo'); | ||
|
||
$this->progressValue = $this->app->registerVar('progressValue'); | ||
$this->progressValue->set(0); | ||
|
||
$this->buildActionButtons($this); | ||
|
||
$this->autoincrementBars = array_merge( | ||
$this->buildHorizontalProgressBars($this), | ||
$this->buildVerticalProgressbars($this) | ||
); | ||
} | ||
|
||
/** | ||
* @return array<Progressbar> | ||
*/ | ||
private function buildHorizontalProgressBars(Container $parent): array | ||
{ | ||
$f = new LabelFrame($parent, 'Horizontal'); | ||
|
||
$pbar1 = new Progressbar($f, [ | ||
'mode' => Progressbar::MODE_DETERMINATE, | ||
'orient' => Progressbar::ORIENT_HORIZONTAL, | ||
'variable' => $this->progressValue, | ||
'maximum' => self::MAX_VALUE, | ||
]); | ||
|
||
$pbar2 = new Progressbar($f, [ | ||
'mode' => Progressbar::MODE_INDETERMINATE, | ||
'orient' => Progressbar::ORIENT_HORIZONTAL, | ||
]); | ||
|
||
$f->grid(new Label($f, 'Determinate'), [ | ||
'row' => 0, | ||
'column' => 0, | ||
'sticky' => 'w' | ||
]); | ||
$f->grid($pbar1, [ | ||
'pady' => 4, | ||
'row' => 0, | ||
'column' => 1, | ||
]); | ||
$f->grid(new Label($f, 'Value:'), ['row' => 1, 'column' => 0, 'sticky' => 'w']); | ||
$f->grid(new Label($f, '-', ['textVariable' => $this->progressValue]), [ | ||
'row' => 1, | ||
'column' => 1, | ||
'sticky' => 'w', | ||
]); | ||
|
||
$f->grid(new Label($f, 'Indeterminate'), [ | ||
'row' => 2, | ||
'column' => 0, | ||
'sticky' => 'w', | ||
]); | ||
$f->grid($pbar2, [ | ||
'pady' => 4, | ||
'row' => 2, | ||
'column' => 1, | ||
]); | ||
|
||
$parent->pack($f, [ | ||
'side' => Pack::SIDE_LEFT, | ||
'padx' => 4, | ||
'pady' => 6, | ||
'anchor' => 'n', | ||
]); | ||
|
||
return [$pbar1, $pbar2]; | ||
} | ||
|
||
private function buildVerticalProgressbars(Container $parent): array | ||
{ | ||
$f = new LabelFrame($parent, 'Vertical'); | ||
|
||
$pbar1 = new Progressbar($f, [ | ||
'mode' => Progressbar::MODE_DETERMINATE, | ||
'orient' => Progressbar::ORIENT_VERTICAL, | ||
'variable' => $this->progressValue, | ||
'maximum' => self::MAX_VALUE, | ||
]); | ||
|
||
$pbar2 = new Progressbar($f, [ | ||
'mode' => Progressbar::MODE_INDETERMINATE, | ||
'orient' => Progressbar::ORIENT_VERTICAL, | ||
]); | ||
|
||
$f->grid(new Label($f, 'Determinate'), [ | ||
'row' => 0, | ||
'column' => 0, | ||
'sticky' => 'w' | ||
]); | ||
$f->grid($pbar1, [ | ||
'pady' => 4, | ||
'row' => 0, | ||
'column' => 1, | ||
]); | ||
$f->grid(new Label($f, '-', ['textVariable' => $this->progressValue]), [ | ||
'row' => 1, | ||
'column' => 1, | ||
]); | ||
|
||
$f->grid(new Label($f, 'Indeterminate'), [ | ||
'row' => 0, | ||
'column' => 3, | ||
'sticky' => 'w', | ||
]); | ||
$f->grid($pbar2, [ | ||
'pady' => 4, | ||
'row' => 0, | ||
'column' => 4, | ||
]); | ||
|
||
$parent->pack($f, [ | ||
'side' => Pack::SIDE_LEFT, | ||
'padx' => 4, | ||
'pady' => 6, | ||
'anchor' => 'n', | ||
]); | ||
|
||
return [$pbar1, $pbar2]; | ||
} | ||
|
||
private function buildActionButtons(Container $parent): void | ||
{ | ||
$f = new Frame($parent); | ||
|
||
$btnStep = new Button($f, 'Step'); | ||
$btnStep->onClick([$this, 'stepProgress']); | ||
|
||
$btnStart = new Button($f, 'Start'); | ||
$btnStart->onClick([$this, 'startProgress']); | ||
|
||
$btnStop = new Button($f, 'Stop'); | ||
$btnStop->onClick([$this, 'stopProgress']); | ||
|
||
$f->pack([$btnStep, $btnStart, $btnStop], [ | ||
'side' => Pack::SIDE_LEFT, | ||
]); | ||
|
||
$parent->pack($f, [ | ||
'side' => Pack::SIDE_BOTTOM, | ||
'pady' => 8, | ||
'padx' => 4, | ||
]); | ||
} | ||
|
||
public function startProgress(): void | ||
{ | ||
$this->progressValue->set(0); | ||
foreach ($this->autoincrementBars as $progressBar) { | ||
$progressBar->start(); | ||
} | ||
} | ||
|
||
public function stopProgress(): void | ||
{ | ||
foreach ($this->autoincrementBars as $progressBar) { | ||
$progressBar->stop(); | ||
} | ||
} | ||
|
||
public function stepProgress(): void | ||
{ | ||
$value = $this->progressValue->asFloat() + 5.0; | ||
if ($value >= self::MAX_VALUE) { | ||
$value = 0; | ||
} | ||
$this->progressValue->set($value); | ||
} | ||
}; | ||
|
||
$demo->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tkui\Widgets\Consts; | ||
|
||
/** | ||
* Values for 'mode' property of progressbar widget. | ||
*/ | ||
interface ProgressMode | ||
{ | ||
const MODE_DETERMINATE = 'determinate'; | ||
const MODE_INDETERMINATE = 'indeterminate'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tkui\Widgets; | ||
|
||
use Tkui\Options; | ||
use Tkui\TclTk\Variable; | ||
use Tkui\Widgets\Common\ValueInVariable; | ||
use Tkui\Widgets\Consts\Orient; | ||
use Tkui\Widgets\Consts\ProgressMode; | ||
|
||
/** | ||
* Implementation of Ttk progressbar widget. | ||
* | ||
* @link https://www.tcl.tk/man/tcl8.6/TkCmd/ttk_progressbar.html | ||
* | ||
* @property int $length | ||
* @property float $maximum | ||
* @property string $mode | ||
* @property string $orient | ||
* @property float $value | ||
* @property Variable $variable | ||
*/ | ||
class Progressbar extends TtkWidget implements ValueInVariable, Orient, ProgressMode | ||
{ | ||
protected string $widget = 'ttk::progressbar'; | ||
protected string $name = 'prbr'; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function initWidgetOptions(): Options | ||
{ | ||
return new Options([ | ||
'length' => null, | ||
'maximum' => null, | ||
'mode' => null, | ||
'orient' => Orient::ORIENT_HORIZONTAL, | ||
'phase' => null, | ||
'value' => null, | ||
'variable' => null, | ||
]); | ||
} | ||
|
||
public function getValue() | ||
{ | ||
return $this->value; | ||
} | ||
|
||
public function setValue($value): self | ||
{ | ||
$this->value = $value; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Begins autoincrement mode. | ||
* | ||
* @param int $interval Interval milliseconds. | ||
*/ | ||
public function start(int $interval = 50): self | ||
{ | ||
$this->call('start', $interval); | ||
return $this; | ||
} | ||
|
||
/** | ||
* Stops autoincrement mode. | ||
*/ | ||
public function stop(): self | ||
{ | ||
$this->call('stop'); | ||
return $this; | ||
} | ||
|
||
/** | ||
* Increments a progressbar value by amount. | ||
*/ | ||
public function step(float $amount = 1.0): self | ||
{ | ||
$this->call('step', $amount); | ||
return $this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tkui\Tests\Widgets; | ||
|
||
use Tkui\Tests\TestCase; | ||
use Tkui\Widgets\Progressbar; | ||
|
||
class ProgressbarTest extends TestCase | ||
{ | ||
/** @test */ | ||
public function it_issues_progressbar_create_command(): void | ||
{ | ||
$this->tclEvalTest(1, [ | ||
['ttk::progressbar', $this->checkWidget('.prbr')], | ||
]); | ||
|
||
new Progressbar($this->createWindowStub()); | ||
} | ||
|
||
/** @test */ | ||
public function it_issues_progressbar_with_options(): void | ||
{ | ||
$this->tclEvalTest(1, [ | ||
[ | ||
'ttk::progressbar', $this->checkWidget('.prbr'), | ||
'-maximum', '100', | ||
'-mode', 'determinate', | ||
'-orient', 'vertical', | ||
], | ||
]); | ||
|
||
new Progressbar($this->createWindowStub(), [ | ||
'mode' => Progressbar::MODE_DETERMINATE, | ||
'maximum' => 100, | ||
'orient' => Progressbar::ORIENT_VERTICAL, | ||
]); | ||
} | ||
|
||
/** @test */ | ||
public function it_issues_progressbar_start_command(): void | ||
{ | ||
$this->tclEvalTest(2, [ | ||
['ttk::progressbar', $this->checkWidget('.prbr')], | ||
[$this->checkWidget('.prbr'), 'start', '150'], | ||
]); | ||
|
||
(new Progressbar($this->createWindowStub()))->start(150); | ||
} | ||
|
||
/** @test */ | ||
public function it_issues_progressbar_stop_command(): void | ||
{ | ||
$this->tclEvalTest(2, [ | ||
['ttk::progressbar', $this->checkWidget('.prbr')], | ||
[$this->checkWidget('.prbr'), 'stop'], | ||
]); | ||
|
||
(new Progressbar($this->createWindowStub()))->stop(); | ||
} | ||
|
||
/** @test */ | ||
public function it_issues_progressbar_step_command(): void | ||
{ | ||
$this->tclEvalTest(2, [ | ||
['ttk::progressbar', $this->checkWidget('.prbr')], | ||
[$this->checkWidget('.prbr'), 'step', '1.5'], | ||
]); | ||
|
||
(new Progressbar($this->createWindowStub()))->step(1.5); | ||
} | ||
} |