package LifeWidget; use Qt 2.0; use Qt::slots ('nextGeneration()', 'clear()'); @ISA = qw(Qt::Frame); $SCALE = 10; $MAXSIZE = 50; $MINSIZE = 10; $BORDER = 5; sub pos2index { my $x = shift; return int(($x - $BORDER) / $SCALE + 1); } sub index2pos { my $i = shift; return int(($i - 1) * $SCALE + $BORDER); } sub maxCol { shift->{'maxi'} } sub maxRow { shift->{'maxj'} } sub new { my $self = shift->SUPER::new(@_); $self->{'maxi'} = $self->{'maxj'} = 50; $self->setMinimumSize($MINSIZE * $SCALE + 2 * $BORDER, $MINSIZE * $SCALE + 2 * $BORDER); $self->setMaximumSize($MAXSIZE * $SCALE + 2 * $BORDER, $MAXSIZE * $SCALE + 2 * $BORDER ); $self->setSizeIncrement($SCALE, $SCALE); $self->clear(); $self->resize($self->{'maxi'} * $SCALE + 2 * $BORDER, $self->{'maxj'} * $SCALE + 2 * $BORDER); return $self; } sub clear { my $self = shift; $self->{'current'} = 0; for(my $t = 0; $t < 2; $t++) { for(my $i = 0; $i < $MAXSIZE + 2; $i++) { for (my $j = 0; $j < $MAXSIZE + 2; $j++) { $self->{'cells'}[$t][$i][$j] = 0; } } } $self->repaint(); } sub resizeEvent { my $self = shift; my $e = shift; $self->{'maxi'} = ($e->size()->width() - 2 * $BORDER) / $SCALE; $self->{'maxj'} = ($e->size()->height() - 2 * $BORDER) / $SCALE; } sub setPoint { my $self = shift; my($i, $j) = @_; return if $i < 1 || $i > $self->{'maxi'} || $j < 1 || $j > $self->{'maxi'}; $self->{'cells'}[$self->{'current'}][$i][$j] = 1; $self->repaint(index2pos($i), index2pos($j), $SCALE, $SCALE, 0); } sub mouseHandle { my $self = shift; my $pos = shift; my $i = pos2index($pos->x()); my $j = pos2index($pos->y()); $self->setPoint($i, $j); } sub mouseMoveEvent { my $self = shift; my $e = shift; $self->mouseHandle($e->pos()); } sub mousePressEvent { my $self = shift; my $e = shift; $self->mouseHandle($e->pos()) if $e->button() == Qt::LeftButton; } sub nextGeneration() { my $self = shift; my(@cells) = @{$self->{'cells'}}; my $current = $self->{'current'}; for(my $i = 1; $i <= $MAXSIZE; $i++) { for (my $j = 1; $j <= $MAXSIZE; $j++ ) { my $t = $cells[$current][$i - 1][$j - 1] + $cells[$current][$i - 1][$j] + $cells[$current][$i - 1][$j + 1] + $cells[$current][$i][$j - 1] + $cells[$current][$i][$j + 1] + $cells[$current][$i + 1][$j - 1] + $cells[$current][$i + 1][$j] + $cells[$current][$i + 1][$j + 1]; $cells[!$current][$i][$j] = ( $t == 3 || $t == 2 && $cells[$current][$i][$j]); } } $self->{'current'} = !$current; $self->repaint(0); } sub paintEvent { my $self = shift; my $cells = $self->{'cells'}; my $e = shift; my $starti = pos2index($e->rect()->left()); my $stopi = pos2index($e->rect()->right()); my $startj = pos2index($e->rect()->top()); my $stopj = pos2index($e->rect()->bottom()); $stopi = $self->{'maxi'} if $stopi > $self->{'maxi'}; $stopj = $self->{'maxj'} if $stopj > $self->{'maxj'}; my $paint = Qt::Painter->new($self); for(my $i = $starti; $i <= $stopi; $i++) { for(my $j = $startj; $j <= $stopj; $j++) { # print "getting [$self->{'current'}][$i][$j]\n"; if($cells->[$self->{'current'}][$i][$j]) { my $ipos = index2pos($i); my $jpos = index2pos($j); $paint->drawShadePanel($ipos, $jpos, $SCALE - 1, $SCALE - 1, $self->colorGroup()); #,0,1,undef); } elsif($cells->[!$self->{'current'}][$i][$j]) { $paint->eraseRect(index2pos($i), index2pos($j), $SCALE - 1, $SCALE - 1); } } } $self->drawFrame($paint); }