Jump to content

User:Btx40/Sandbox 2

From Wikipedia, the free encyclopedia

Event handling classes

[edit]
class EventArgs
{
    has Bool $.handled is rw;
}

class Event does Callable
{
    # list of handlers
    has Callable @!handlers;

    # add a handler
    our Event multi method add($event: &handler:($, EventArgs))
    {
        @!handlers.push(&handler);
        return $event;
    }
    # remove a handler
    our Event multi method remove($event: &handler:($, EventArgs))
    { 
       my Int $i = 0;
  

       loop (; $i <= @!handlers.end; $i++)
       {
           last if (@!handlers[$i] eqv &handler);
       }
       @!handlers.splice($i, 1) if $i <= @!handlers.end;
       return $event;
    }

    # remove all handlers
    our Event multi method removeall($event:)
    {
        @!handlers.splice;
        return $event;
    }

    # trigger event
    multi method trigger($event: $sender, EventArgs $args)
    {
        if (@!handlers.elems > 0)
        {
            for @!handlers
            {
                $_($sender, $args);
                last if $args.handled;
            }
        }
    }

    method &.( |$capture )
    {
        self.trigger(|$capture);
    }
}

our Event multi sub infix:<+=>(Event $event, &handler:($, EventArgs)) { return $event.add(&handler); }

our Event multi sub infix:<-=>(Event $event, &handler:($, EventArgs)) { return $event.remove(&handler); }

Test case

[edit]
my Event $ev = Event.new;
my $sample = Nil;

sub handler($sender, EventArgs $args)
{
    say "Handler 2";
}

say "----------------";
$ev.add(sub ($sender, EventArgs $args) { say "Handler 1"; });
$ev.trigger($sample, EventArgs.new);

say "----------------";
$ev.add(&handler);
$ev.trigger($sample, EventArgs.new);

say "----------------";
$ev.remove(&handler);
$ev.add(sub ($sender, EventArgs $args) { say "New handler"; });
$ev.trigger($sample, EventArgs.new);

sub blockingHandler($sender, EventArgs $args)
{
    $args.handled = True;
    say "Last handler";
}

say "----------------";
$ev.add(&blockingHandler)
$ev.add(sub ($sender, EventArgs $args) { say "should not run"; });
$ev.trigger($sample, EventArgs.new);

say "----------------";
$ev.removeall
$ev.add(sub ($sender, EventArgs $args) { say "Sole handler"; });
$ev.trigger($sample, EventArgs.new);

Test case output

[edit]
----------------
Handler 1
----------------
Handler 1
Handler 2
----------------
Handler 1
New handler
----------------
Handler 1
New handler
Last handler
----------------
Sole handler