
    package MainWindow;
    sub Signal {
        my ($self) = shift;
        return SignalView->new(-main=>$self);
    }
    package SignalView;
    use Signal;
    use Tk;
    sub new {
        my $type = shift;
        my %params = @_;
        my $self = {};
        my $signal = Signal->new(%params);
        my $main = $params{-main};
        my $canvas;
        my $states = $signal->{'States'};
        my %views = ();
        $self->{'Interval'} = 500;
        $canvas = $main->Canvas(-width=>50,-height=>150);
        $x = 5; $y = 5;
        $r = 40;
        for $state ( @$states ) {
            $views{$state} = 
                $canvas->create('oval', $x, $y, $x+$r, $y+$r, 
                    -width => 1, -outline => 'black', -fill => 'black');
            $y += 50;
        }
        $canvas->pack(-side=>left);
        $self->{'MainWindow'}  = $main;
        $self->{'Canvas'}  = $canvas;
        $self->{'Views'}  = \%views;
        $self->{'Signal'}  = $signal;
        bless $self;
    }
    sub next {
        my ($self) = shift;
        my $state = $self->{'Signal'}->{'State'};
        my $view = $self->{'Views'}->{$state};
        my $canvas = $self->{'Canvas'};
        $canvas->itemconfigure($view,-fill=>'black');
        $state = $self->{'Signal'}->next();
        $view = $self->{'Views'}->{$state};
        $canvas->itemconfigure($view,-fill=>$state);
    }
    sub update {
        my ($self) = shift;
        $self->{'MainWindow'}->update();
    }
    sub run {
        my ($self) = shift;
        my %params = @_;
        my $main=$self->{'MainWindow'};
        if(defined($params{'Interval'})) {
            $self->{'Interval'} = $params{'Interval'};
        }
        if(! $self->{'Running'})  {
            $self->{'Running'} = 1;
            $main->after($self->{'Interval'},sub {$self->running()});
        }
    }
    sub running {
        my ($self) = shift;
        my $interval = $self->{'Interval'};
        if($self->{'Running'}) {
            $self->next();
            $self->update();
            $self->{'MainWindow'}->after($interval,sub {$self->running()});
        } 
    }
    sub stop {
        my ($self) = shift;
        $self->{'Running'} = 0;
    }

    sub controller {
        my ($self) = shift;
        my $main=$self->{'MainWindow'};
        # my $c= $main->Toplevel();
        my $c= $main->Frame();
        my $int= $c->Frame();
        my $int_entry = $int->Entry(-relief => 'sunken',-width=>5);
        my $int_label= $int->Label(-text=>"Interval:");
        my $quit = $c->Button( 
            -text => 'Quit', -width => 10, -command => sub {$main->destroy});
        my $run = $c->Button( 
            -text => 'Run', -width => 10, -command => 
                sub { $self->run(Interval=>($int_entry->get())) }
            );
        my $stop = $c->Button( 
            -text => 'Stop', -width => 10, -command => sub {$self->stop});
        $int->pack(-side => 'top', -fill => 'x');
        $int_entry->pack(-side => 'right');
        $int_label->pack(-side => 'left');
        $c->pack( -side => 'right', -expand => 'no', -pady => 2);
        $int->pack(-side => 'top', -expand => 'no', -pady => 2);
        $run->pack( -side => 'top', -expand => 'no', -pady => 2);
        $stop->pack(-side => 'top', -expand => 'no', -pady => 2);
        $quit->pack(-side => 'top', -expand => 'no', -pady => 2);
        # set default value
        $int_entry->insert(0,$self->{'Interval'});
        $self->{'Controller'}=$c;
        $self->update();
    }
    # end

    package Main;
    use Tk;
    $main = MainWindow->new();
    $signal = $main->Signal();
    $signal->run();
    $signal->controller();
    &MainLoop();


