--- kgsueme/kgsueme/game.pl 2003/05/31 09:46:51 1.1 +++ kgsueme/kgsueme/game.pl 2003/05/31 15:19:55 1.8 @@ -6,6 +6,8 @@ use base KGS::Listener::Game; use base KGS::Game; +use base gtk::widget; + sub new { my $self = shift; $self = $self->SUPER::new(@_); @@ -13,70 +15,70 @@ $self->listen($self->{conn}); $self->{window} = new Gtk2::Window 'toplevel'; - my $title = $self->{channel} ? $self->user0." ".$self->user1 : "Game Window"; + my $title = $self->{channel} ? $self->owner->as_string." ".$self->opponent_string : "Game Window"; $self->{window}->set_title("KGS Game $title"); gtk::state $self->{window}, "game::window", undef, window_size => [600, 500]; - $self->{window}->signal_connect(delete_event => sub { $self->part; 1 }); + $self->{window}->signal_connect(delete_event => sub { + if ($self->{joined}) { + $self->part; + } else { + $self->event_part; + } + 1; + }); - $self->{window}->add(my $hpane = new Gtk2::HPaned); - gtk::state $hpane, "game::hpane", undef, hpane_position => 500; + $self->{window}->add($self->{hpane} = new Gtk2::HPaned); + gtk::state $self->{hpane}, "game::hpane", undef, position => 500; - $hpane->pack1((my $vbox = new Gtk2::VBox), 1, 1); + $self->{hpane}->pack1((my $vbox = new Gtk2::VBox), 1, 1); $vbox->pack_start((my $frame = new Gtk2::Frame), 0, 1, 0); { + # grrr... $frame->add(my $vbox = new Gtk2::VBox); $vbox->add($self->{title} = new Gtk2::Label $title); - $self->{moveadj} = new Gtk2::Adjustment 0, 0, 0, 1, 10, 0; + $self->{moveadj} = new Gtk2::Adjustment 1, 0, 1, 0.01, 0.1, 0; + $vbox->add(my $scale = new Gtk2::HScale $self->{moveadj}); - $scale->set_draw_value (1); - $scale->set_digits (0); - $scale->set_value_pos('top'); + $scale->set_draw_value (0); $self->{moveadj}->signal_connect (value_changed => sub { - $self->{board} = new KGS::Game::Board $self->{size}; - $self->{board}->interpret_path ([@{$self->{path}}[0 .. $self->{moveadj}->value - 1]]); + return unless $self->{path}; - my $area = $self->repaint_board; + my $move = int (@{$self->{path}} * $_[0]->get_value); - # force a redraw (not perfect(?)) - $self->expose ($area); + $self->{board} = new KGS::Game::Board $self->{size}; + $self->{board}->interpret_path ([@{$self->{path}}[0 .. $move - 1]]); - $self->{text}->backward_delete($self->{text}->get_length); - $self->{text}->insert(undef, undef, undef, KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment}); - }); + $self->redraw ($self->repaint_board); - $self->{moveadj}->upper (scalar @{$self->{path}}) if $self->{path}; + $self->{text}->set_text(KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment}); + }); } - Gtk2::Widget->push_visual (Gtk2::Gdk::Rgb->get_visual); - Gtk2::Widget->push_colormap (Gtk2::Gdk::Rgb->get_cmap); $vbox->pack_start(($self->{canvas} = new Gtk2::DrawingArea), 1, 1, 0); - Gtk2::Widget->pop_colormap; - Gtk2::Widget->pop_visual; $self->{canvas}->signal_connect(configure_event => \&configure_event, $self); $self->{canvas}->signal_connect(expose_event => \&expose_event, $self); - $hpane->pack2((my $vpane = new Gtk2::VPaned), 0, 0); - gtk::state $vpane, "game", $self->{name}, vpane_position => 80; + $self->{hpane}->pack2(($self->{vpane} = new Gtk2::VPaned), 0, 0); + $self->{hpane}->set(position_set => 1); + gtk::state $self->{vpane}, "game::vpane", $self->{name}, position => 80; - $vpane->add(my $sw = new Gtk2::ScrolledWindow); + $self->{vpane}->add(my $sw = new Gtk2::ScrolledWindow); $sw->set_policy("automatic", "always"); - $sw->add($self->{userlist} = new_with_titles Gtk2::ListStore "User", "Rank", "Flags"); - ::clist_autosort $self->{userlist}; - gtk::state $self->{userlist}, "room::userlist", $self->{name}, clist_column_widths => [120, 30]; + $sw->add(($self->{userlist} = new gtk::userlist)->widget); - $vpane->add(my $vbox = new Gtk2::VBox); + $self->{vpane}->add(my $vbox = new Gtk2::VBox); $vbox->pack_start((my $sw = new Gtk2::ScrolledWindow), 1, 1, 0); - $sw->set_policy("automatic", "always"); + $sw->set_policy("never", "always"); - $sw->add($self->{text} = new Gtk2::Text); + $sw->add(($self->{text} = new gtk::text)->widget); $vbox->pack_start(($self->{entry} = new Gtk2::Entry), 0, 1, 0); $self->{entry}->signal_connect(activate => sub { @@ -91,7 +93,7 @@ sub event_update_users { my ($self) = @_; - room::event_update_users $self; + $self->{userlist}->update($self->{users}); } sub join { @@ -109,29 +111,42 @@ } sub configure_event { - my ($widget, $self, $event) = @_; + my ($widget, $event, $self) = @_; delete $self->{stack}; delete $self->{pixbuf}; delete $self->{board_shown}; delete $self->{background}; $self->repaint_board; - 1; + 0; } -sub INTERP_NEAREST (){ 1 } -sub INTERP_TILES (){ 1 } -sub INTERP_BILINEAR (){ 2 } -sub INTERP_HYPER (){ 3 } +sub expose_event { + my ($widget, $event, $self) = @_; + + $self->{pixbuf} or return; + + my $area = $event->area; + my ($ox, $oy, $s) = @{$self->{offsets}}; + + $self->redraw ( + (new Gtk2::Gdk::Rectangle $area->x - $ox, $area->y - $oy, $area->width, $area->height) + ->intersect(new Gtk2::Gdk::Rectangle 0, 0, $s, $s) + ); + + 0; +} + +# something Gtk2 fixed +sub INTERP_NEAREST (){ 'nearest' } +sub INTERP_TILES (){ 'tiles' } +sub INTERP_BILINEAR (){ 'bilinear' } +sub INTERP_HYPER (){ 'hyper' } sub new_pixbuf { - my ($w, $h, $alpha, $clear) = @_; + my ($w, $h, $alpha, $fill) = @_; my $pixbuf = new Gtk2::Gdk::Pixbuf 'rgb', $alpha, 8, $w, $h; - - if ($clear) { # damn, need to clear it ourselves - my $row = "\x00\x00\x00\x00" x $w; - $pixbuf->put_pixels ($row, $_, 0) for 0 .. $h - 1; - } + $pixbuf->fill ($fill) if defined $fill; $pixbuf; } @@ -159,14 +174,14 @@ my $c = \$self->{stack}{$mark}; unless ($$c) { for my $stone ($mark & (MARK_W | MARK_GRAY_W) ? @::white_img : @::black_img) { - my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 1; + my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 0x00000000; # zeroeth the shadow if ($mark & (MARK_B | MARK_W)) { $::black_img[0]->composite ( $base, $shadow, $shadow, $size, $size, $shadow-0.5, $shadow-0.5, $size / $stone->get_width, $size / $stone->get_height, - $::config->{speed} ? INTERP_NEAREST : INTERP_TILES, 128 + $::config->{speed} ? INTERP_NEAREST : INTERP_BILINEAR, 128 ); } @@ -180,7 +195,7 @@ $stone->composite ( $base, 0, 0, $size, $size, -0.5, -0.5, $size / $stone->get_width, $size / $stone->get_height, - $::config->{speed} ? INTERP_NEAREST : INTERP_HYPER, $alpha + $::config->{speed} ? INTERP_NEAREST : INTERP_BILINEAR, $alpha ); } } @@ -193,7 +208,7 @@ $img->composite ( $base, ($size / 4) x2, (int ($size / 2 + 0.5)) x2, ($size / 4 - 0.5) x 2, $size / $img->get_width / 2, $size / $img->get_height / 2, - $::config->{speed} ? INTERP_NEAREST : INTERP_HYPER, 192 + $::config->{speed} ? INTERP_NEAREST : INTERP_BILINEAR, 192 ); } } @@ -209,7 +224,7 @@ $img->composite ( $base, 0, 0, $size, $size, -0.5, -0.5, $size / $img->get_width, $size / $img->get_height, - $::config->{speed} ? INTERP_NEAREST : INTERP_HYPER, 255 + $::config->{speed} ? INTERP_NEAREST : INTERP_BILINEAR, 255 ); } } @@ -239,7 +254,7 @@ for (@c) { my $w = $_->get_width * $s; $_->composite ($pixbuf, - $x, $y, $w+0.999, $height+0.999, $x, $y, $s, $s, + $x, $y, $w+1, $height+1, $x, $y, $s, $s, $::config->{speed} ? INTERP_NEAREST : INTERP_BILINEAR, 255); $x += $w + $spacing; @@ -249,11 +264,10 @@ sub pixbuf_rect { my ($pb, $colour, $x1, $y1, $x2, $y2, $alpha) = @_; - # we fake lines by... an unspeakable method :/ - my $colour_pb = new_pixbuf 1, 1, 0, 0; - $colour_pb->put_pixels ($colour, 0, 0); - - $colour_pb->composite ($pb, $x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1, $x1, $y1, 1, 1, INTERP_NEAREST, $alpha); + # we fake lines by... a horrible method :/ + my $colour_pb = new_pixbuf 1, 1, 0, $colour; + $colour_pb->composite ($pb, $x1, $y1, $x2 - $x1 + 1, $y2 - $y1 + 1, $x1, $y1, $x2 + 1, $y2 + 1, + INTERP_NEAREST, $alpha); } sub repaint_board { @@ -263,9 +277,11 @@ return $expose_area unless $self->{board}; - my ($w, $h) = @{$canvas->allocation}[2,3]; + my ($w, $h) = ($canvas->allocation->values)[2,3]; my $s = $w > $h ? $h : $w; + + return unless $s > 128; $self->{offsets} = [int (($w - $s) / 2), int (($h - $s) / 2), $s]; @@ -287,15 +303,15 @@ $pixbuf = $self->{pixbuf}; } else { $pixbuf = $self->{background}->copy; - $expose_area = [0, 0, $s, $s]; + $expose_area = new Gtk2::Gdk::Rectangle 0, 0, $s, $s; } } else { - $expose_area = [0, 0, $s, $s]; + $expose_area = new Gtk2::Gdk::Rectangle 0, 0, $s, $s; my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); if ($s < $bw && $s < $bh) { - $pixbuf = new_pixbuf $s, $s, $::config->{conserve_memory} ? 0 : 1, 0; + $pixbuf = new_pixbuf $s, $s, 0; $::board_img->copy_area (0, 0, $s, $s, $pixbuf, 0, 0); } else { $pixbuf = scale_pixbuf $::board_img, $s, $s, $::config->{speed} ? INTERP_NEAREST : INTERP_TILES; @@ -304,14 +320,14 @@ my $linew = int ($s / 25 / $size); # ornamental border... we have time to waste :/ - pixbuf_rect $pixbuf, "\xff\xcc\x77", 0, 0, $s-1, $linew, 255; - pixbuf_rect $pixbuf, "\xff\xcc\x77", 0, 0, $linew, $s-1, 255; - pixbuf_rect $pixbuf, "\xff\xcc\x77", $s-$linew-1, 0, $s-1, $s-1, 255; - pixbuf_rect $pixbuf, "\xff\xcc\x77", 0, $s-$linew-1, $s-1, $s-1, 255; + pixbuf_rect $pixbuf, 0xffcc7700, 0, 0, $s-1, $linew, 255; + pixbuf_rect $pixbuf, 0xffcc7700, 0, 0, $linew, $s-1, 255; + pixbuf_rect $pixbuf,0xffcc7700, $s-$linew-1, 0, $s-1, $s-1, 255; + pixbuf_rect $pixbuf,0xffcc7700, 0, $s-$linew-1, $s-1, $s-1, 255; for my $i (1 .. $size) { - pixbuf_rect $pixbuf, "\x44\x11\x11", $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew, 192; - pixbuf_rect $pixbuf, "\x44\x11\x11", $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew, 192; + pixbuf_rect $pixbuf, 0x44111100, $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew, 192; + pixbuf_rect $pixbuf, 0x44111100, $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew, 192; # 38 max, but we allow a bit more my $label = (qw(- A B C D E F G H J K L M N O P Q R S T U V W X Y Z @@ -359,8 +375,8 @@ $self->{background}->copy_area (@$area, $pixbuf, $dx, $dy); $expose_area = $expose_area - ? Gtk2::Gdk::Rectangle->union ($expose_area, $area) - : $area; + ? $expose_area->union (new Gtk2::Gdk::Rectangle @$area) + : new Gtk2::Gdk::Rectangle @$area; } if ($mark) { @@ -400,62 +416,33 @@ $expose_area; } -sub expose { +sub redraw { my ($self, $area) = @_; if ($area && $self->{pixbuf}) { - my ($x, $y, $w, $h) = @$area; + my ($x, $y, $w, $h) = $area->values; my ($ox, $oy, $s) = @{$self->{offsets}}; - $self->{pixbuf}->render_to_drawable ($self->{canvas}->window, $self->{canvas}->style->white_gc, - $x, $y, $x + $ox, $y + $oy, $w, $h); + $self->{canvas}->window->draw_pixbuf ($self->{canvas}->style->white_gc, $self->{pixbuf}, + $x, $y, $x + $ox, $y + $oy, $w, $h, + "normal", 0, 0); $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0, $x + $ox - 1, $y + $oy - 1, $w + 2, $h + 2) if $::DEBUG_EXPOSE; - - #$self->{canvas}->window->draw_pixmap ( - # $self->{canvas}->style->white_gc, - # $self->{pixmap}, - # $x - $ox, $y - $oy, $x, $y, $w, $h, - #); } } -sub expose_event { - my ($widget, $self, $event) = @_; - - $self->{pixbuf} or return; - - my $area = $event->{area}; - my ($ox, $oy, $s) = @{$self->{offsets}}; - - $self->expose (Gtk2::Gdk::Rectangle->intersect ( - [$area->[0] - $ox, $area->[1] - $oy, $area->[2], $area->[3]], - [0, 0, $s, $s], - )); - - 1; -} - sub event_update_tree { my ($self) = @_; $self->{path} = $self->get_path; - - my $move = @{$self->{path}}; - - $self->{moveadj}->upper($move); - - if ($self->{moveadj}->value >= $move - 1 || !$self->{moveadj}->value) { - $self->{moveadj}->value ($move); - $self->{moveadj}->value_changed; - } + $self->{moveadj}->value_changed if $self->{moveadj}; } sub event_part { my ($self) = @_; $self->SUPER::event_part; - (delete $self->{window})->destroy; # hmm.. why does this keep the object alive? puzzling.. ahh.. the callbacks ;) - delete $self->{room}{game}{$self->{channel}}; + delete $appwin::gamelist->{game}{$self->{channel}}; + $self->destroy; } sub event_move { @@ -463,9 +450,5 @@ sound::play 1, $pass ? "pass" : "move"; } -sub DESTROY {#d# - warn "DESTROY(@_)\n";#d# -} - 1;