Skip to content

Commit

Permalink
Add first cut at heat-ping example
Browse files Browse the repository at this point in the history
  • Loading branch information
japhb committed Mar 26, 2024
1 parent 67f14b7 commit 4bf4d1c
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions examples/heat-ping
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# ABSTRACT: Heat ping example based on Terminal::Widgets::Viz::SmokeChart

use Terminal::Widgets::Events;
use Terminal::Widgets::Simple;
use Terminal::Widgets::Viz::SmokeChart;


#| A top level UI container based on Terminal::Widgets::Simple::TopLevel
class HeatPingUI is TopLevel {
has Form:D $.form .= new;
has Channel:D $.stop .= new;
has UInt:D $.ms-per-pixel = 2;

method initial-layout($builder, $width, $height) {
with $builder {
.text-input(:$.form, id => 'target', prompt-string => 'Ping Target >'),
.node(
.button(:$.form, id => 'start', label => 'Start',
process-input => { self.start-ping }),
.button(:$.form, id => 'stop', label => 'Stop', :!enabled,
process-input => { self.stop-ping }),
.button(:$.form, id => 'clear', label => 'Clear',
process-input => { self.clear-chart }),
.button(:$.form, id => 'quit', label => 'Quit',
process-input => { self.stop-ping;
$.terminal.quit }),
),
.divider(line-style => 'light1', style => %(set-h => 1)),
.smoke-chart(id => 'chart',
val-scale => 1 / ($.ms-per-pixel || 1)),
}
}

method start-ping() {
# Disable the Start button and enable the Stop button
%.by-id<start>.set-enabled(False);
%.by-id<stop>.set-enabled(True);

# Focus on the chart
self.focus-on(%.by-id<chart>);

# Prepare a `ping` child process that the reactor will listen to
my $target = %.by-id<target>.input-field.buffer.contents || '8.8.8.8';
my $ping = Proc::Async.new('ping', $target);

# Update window title to indicate target
my $title = "$target - heat-ping";
self.terminal.set-window-title($title);

# Run ping event reactor until interrupt signal or `ping` exits
start react {
# Parse `ping` results
whenever $ping.stderr.lines { .note }
whenever $ping.stdout.lines {
if $_ ~~ / 'seq=' (\d+) .*? 'time=' (\d+ ['.' \d+]?) / -> $/ {
self.update-chart(+$0, +$1);
}
}

# Quit on stop requested or child process exit
whenever $.stop { done }
whenever $ping.start { self.stop-ping }
}
}

method stop-ping() {
# Disable the Stop button and enable the Start button
%.by-id<stop>.set-enabled(False);
%.by-id<start>.set-enabled(True);

# Stop any existing reactor
$.stop.send('stop');

# Update window title to indicate ping is now idle
my $title = "idle - heat-ping";
self.terminal.set-window-title($title);
}

method clear-chart() {
%.by-id<chart>.clear-frame;
%.by-id<chart>.start-slice(0);
}

method update-chart($id, $time) {
%.by-id<chart>.add-entry($id, $time);
}

# Make a ^C targeting the chart stop the ping reactor
multi method handle-event(Terminal::Widgets::Events::KeyboardEvent:D $event
where *.keyname eq 'Ctrl-C', BubbleUp) {
self.stop-ping if self.focused-child === %.by-id<chart>;
}
}


sub MAIN() {
# Boot a Terminal::Widgets::App and jump right to the UI screen
App.new.boot-to-screen('heat-ping', HeatPingUI, title => 'Smoke Chart Example');
}

0 comments on commit 4bf4d1c

Please sign in to comment.