ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/kgsueme/bin/kgsueme
(Generate patch)

Comparing kgsueme/bin/kgsueme (file contents):
Revision 1.22 by pcg, Fri May 30 11:39:56 2003 UTC vs.
Revision 1.26 by pcg, Sat May 31 03:11:58 2003 UTC

1#!/usr/bin/perl -I../lib/ 1#!/usr/bin/perl
2 2
3use Gtk; 3use Gtk;
4use Gtk::Gdk; 4use Gtk::Gdk;
5use Gtk::Gdk::Pixbuf; 5use Gtk::Gdk::Pixbuf;
6#use Gtk::Gdk::ImlibImage; 6#use Gtk::Gdk::ImlibImage;
10 10
11use Audio::Data; 11use Audio::Data;
12use Audio::Play; 12use Audio::Play;
13 13
14use IO::Socket::INET; 14use IO::Socket::INET;
15 15use List::Util;
16use Errno; 16use Errno;
17 17
18init Gtk; 18init Gtk;
19 19
20$HACK = 1; # do NEVER enable. ;) 20our $HACK = 1; # do NEVER enable. ;)
21our $DEBUG_EXPOSE = 1;
22
23if ($HACK) {
24 $KGS::debug = 1;
25}
26
27our $VERSION = "0.1";
21 28
22our $config; 29our $config;
23our $LIBDIR = "."; 30our $LIBDIR = ".";
24our $IMGDIR = "$LIBDIR/images"; 31our $IMGDIR = "$LIBDIR/images";
25our $SNDDIR = "$LIBDIR/sounds"; 32our $SNDDIR = "$LIBDIR/sounds";
80 87
81 my $state = -r $staterc ? Storable::retrieve($staterc) : {}; 88 my $state = -r $staterc ? Storable::retrieve($staterc) : {};
82 my @widgets; 89 my @widgets;
83 90
84 $config = $state->{config} ||= {}; 91 $config = $state->{config} ||= {};
92
93 $config{speed} = 0;#d# optimize for speed or memory?
94 $config{conserve_memory} = 0;
85 95
86 # grr... more gtk+ brokenness 96 # grr... more gtk+ brokenness
87 my %get = ( 97 my %get = (
88 hpane_position => sub { ($_[0]->children)[0]->allocation->[2] }, 98 hpane_position => sub { ($_[0]->children)[0]->allocation->[2] },
89 vpane_position => sub { ($_[0]->children)[0]->allocation->[3] }, 99 vpane_position => sub { ($_[0]->children)[0]->allocation->[3] },
179} 189}
180 190
181if (0) { 191if (0) {
182 use KGS::Constants; 192 use KGS::Constants;
183 193
184 my $board = new game size => 5; 194 for (19) {
195 my $board = new game %{Storable::retrieve "testboard.storable"};
196
197 if (0) {
185 $board->{board} = new KGS::Game::Board; 198 $board->{board} = new KGS::Game::Board;
186 $board->{board}{board}[0][0] = MARK_B; 199 $board->{board}{board}[0][0] = MARK_B;
187 $board->{board}{board}[1][1] = MARK_GRAY_B | MARK_SMALL_W; 200 $board->{board}{board}[1][1] = MARK_GRAY_B | MARK_SMALL_W;
188 $board->{board}{board}[2][2] = MARK_W | MARK_TRIANGLE; 201 $board->{board}{board}[2][2] = MARK_W | MARK_TRIANGLE;
202 $board->{board}{board}[1][2] = MARK_B | MARK_LABEL;
203 $board->{board}{label}[1][2] = "198";
204 $board->{board}{board}[0][2] = MARK_W | MARK_LABEL;
205 $board->{board}{label}[0][2] = "AWA";
206 }
189 $board->{window}->show_all; 207 $board->{window}->show_all;
208 }
190} 209}
191 210
192main Gtk; 211main Gtk;
193 212
194############################################################################# 213#############################################################################
203 222
204 $self->{conn} = new KGS::Protocol; 223 $self->{conn} = new KGS::Protocol;
205 224
206 KGS::Listener::Debug->new->listen($self->{conn}); #d# debug only :) 225 KGS::Listener::Debug->new->listen($self->{conn}); #d# debug only :)
207 226
208 $self->listen($self->{conn}); 227 $self->listen($self->{conn}, "login");
209 228
210 $self->{roomlist} = new roomlist conn => $self->{conn}; 229 $self->{roomlist} = new roomlist conn => $self->{conn};
211 230
212 $self->{window} = new Gtk::Window 'toplevel'; 231 $self->{window} = new Gtk::Window 'toplevel';
213 $self->{window}->set_title('kgsueme'); 232 $self->{window}->set_title('kgsueme');
276 } 295 }
277 $self->{conn}->feed_data($buf); 296 $self->{conn}->feed_data($buf);
278 }; 297 };
279 298
280 # now login 299 # now login
281 $self->{conn}->login($self->{login}->get_text, $self->{password}->get_text); 300 $self->{conn}->login("kgsueme $VERSION $^O", $self->{login}->get_text, $self->{password}->get_text);
282} 301}
283 302
284sub inject_login { 303sub inject_login {
285 my ($self, $msg) = @_; 304 my ($self, $msg) = @_;
286 305
380 399
381sub new { 400sub new {
382 my $self = shift; 401 my $self = shift;
383 $self = $self->SUPER::new(@_); 402 $self = $self->SUPER::new(@_);
384 403
385 $self->listen($self->{conn}); 404 $self->listen($self->{conn}, qw(msg_room:));
386 405
387 $self->{window} = new Gtk::Window 'toplevel'; 406 $self->{window} = new Gtk::Window 'toplevel';
388 $self->{window}->set_title("KGS Room $self->{name}"); 407 $self->{window}->set_title("KGS Room $self->{name}");
389 ::state $self->{window}, "room::window", $self->{name}, window_size => [600, 400]; 408 ::state $self->{window}, "room::window", $self->{name}, window_size => [600, 400];
390 409
433 ::state $self->{userlist}, "room::userlist", $self->{name}, clist_column_widths => [120, 30]; 452 ::state $self->{userlist}, "room::userlist", $self->{name}, clist_column_widths => [120, 30];
434 453
435 $self; 454 $self;
436} 455}
437 456
457sub join {
458 my ($self) = @_;
459 $self->SUPER::join;
460
461 $self->{window}->show_all;
462}
463
464sub part {
465 my ($self) = @_;
466 $self->SUPER::part;
467
468 delete $::config->{rooms}{$self->{channel}};
469 $self->{window}->hide_all;
470 $self->event_update_users;
471 $self->event_update_games;
472}
473
474sub inject_msg_room {
475 my ($self, $msg) = @_;
476
477 $self->{text}->insert(undef, undef, undef, "\n$msg->{name}: $msg->{message}");
478}
479
438sub event_update_users { 480sub event_update_users {
439 my ($self) = @_; 481 my ($self) = @_;
440 482
441 $self->{event_update} ||= Gtk->timeout_add(200, sub { 483 $self->{event_update} ||= Gtk->timeout_add(200, sub {
442 my $l = $self->{userlist}; 484 my $l = $self->{userlist};
481 delete $self->{event_update_games}; 523 delete $self->{event_update_games};
482 0; 524 0;
483 }); 525 });
484} 526}
485 527
486sub join {
487 my ($self) = @_;
488 $self->SUPER::join;
489
490 $self->{window}->show_all;
491}
492
493sub part {
494 my ($self) = @_;
495 $self->SUPER::part;
496
497 delete $::config->{rooms}{$self->{channel}};
498 $self->{window}->hide_all;
499 $self->event_update_users;
500 $self->event_update_games;
501}
502
503sub event_join { 528sub event_join {
504 my ($self) = @_; 529 my ($self) = @_;
505 $self->SUPER::event_join; 530 $self->SUPER::event_join;
506 531
507 $::config->{rooms}{$self->{channel}} = 1; 532 $::config->{rooms}{$self->{channel}} = 1;
509 534
510sub event_update_roominfo { 535sub event_update_roominfo {
511 my ($self) = @_; 536 my ($self) = @_;
512 537
513 $self->{text}->insert(undef, undef, undef, "\n$self->{owner}: $self->{description}\n"); 538 $self->{text}->insert(undef, undef, undef, "\n$self->{owner}: $self->{description}\n");
514}
515
516sub inject_msg_room {
517 my ($self, $msg) = @_;
518 return unless $self->{channel} == $msg->{channel};
519
520 $self->{text}->insert(undef, undef, undef, "\n$msg->{name}: $msg->{message}");
521} 539}
522 540
523############################################################################# 541#############################################################################
524 542
525package game; 543package game;
535 $self = $self->SUPER::new(@_); 553 $self = $self->SUPER::new(@_);
536 554
537 $self->listen($self->{conn}); 555 $self->listen($self->{conn});
538 556
539 $self->{window} = new Gtk::Window 'toplevel'; 557 $self->{window} = new Gtk::Window 'toplevel';
540 $self->{window}->set_title("KGS Game ".$self->user0." ".$self->user1) if $self->{channel};#d# 558 my $title = $self->{channel} ? $self->user0." ".$self->user1 : "Game Window";
559 $self->{window}->set_title("KGS Game $title");
541 ::state $self->{window}, "game::window", undef, window_size => [600, 500]; 560 ::state $self->{window}, "game::window", undef, window_size => [600, 500];
542 561
543 $self->{window}->signal_connect(delete_event => sub { $self->part; 1 }); 562 $self->{window}->signal_connect(delete_event => sub { $self->part; 1 });
544 563
545 $self->{window}->add(my $hpane = new Gtk::HPaned); 564 $self->{window}->add(my $hpane = new Gtk::HPaned);
546 ::state $hpane, "game::hpane", undef, hpane_position => 500; 565 ::state $hpane, "game::hpane", undef, hpane_position => 500;
547 566
567 $hpane->pack1(my $vbox = new Gtk::VBox);
568
569 $vbox->pack_start((my $frame = new Gtk::Frame), 0, 1, 0);
570
571 {
572 $frame->add(my $vbox = new Gtk::VBox);
573 $vbox->add($self->{title} = new Gtk::Label $title);
574
575 $self->{moveadj} = new Gtk::Adjustment 0, 0, 0, 1, 10, 0;
576 $vbox->add(my $scale = new Gtk::HScale $self->{moveadj});
577 $scale->set_draw_value (1);
578 $scale->set_digits (0);
579 $scale->set_value_pos('top');
580
581 $self->{moveadj}->signal_connect (value_changed => sub {
582 $self->{board} = new KGS::Game::Board $self->{size};
583 $self->{board}->interpret_path ([@{$self->{path}}[0 .. $self->{moveadj}->value - 1]]);
584
585 my $area = $self->repaint_board;
586
587 # force a redraw (not perfect(?))
588 $self->expose ($area);
589
590 $self->{text}->backward_delete($self->{text}->get_length);
591 $self->{text}->insert(undef, undef, undef, KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment});
592 });
593
594 $self->{moveadj}->upper (scalar @{$self->{path}}) if $self->{path};
595 }
596
548 Gtk::Widget->push_visual (Gtk::Gdk::Rgb->get_visual); 597 Gtk::Widget->push_visual (Gtk::Gdk::Rgb->get_visual);
549 Gtk::Widget->push_colormap (Gtk::Gdk::Rgb->get_cmap); 598 Gtk::Widget->push_colormap (Gtk::Gdk::Rgb->get_cmap);
550 $hpane->pack1(($self->{canvas} = new Gtk::DrawingArea), 1, 1); 599 $vbox->pack_start(($self->{canvas} = new Gtk::DrawingArea), 1, 1, 0);
551 Gtk::Widget->pop_colormap; 600 Gtk::Widget->pop_colormap;
552 Gtk::Widget->pop_visual; 601 Gtk::Widget->pop_visual;
553 602
554 $self->{canvas}->signal_connect(configure_event => \&configure_event, $self); 603 $self->{canvas}->signal_connect(configure_event => \&configure_event, $self);
555 $self->{canvas}->signal_connect(expose_event => \&expose_event, $self); 604 $self->{canvas}->signal_connect(expose_event => \&expose_event, $self);
602} 651}
603 652
604sub configure_event { 653sub configure_event {
605 my ($widget, $self, $event) = @_; 654 my ($widget, $self, $event) = @_;
606 delete $self->{stack}; 655 delete $self->{stack};
656 delete $self->{pixbuf};
657 delete $self->{board_shown};
607 delete $self->{background}; 658 delete $self->{background};
608 $self->repaint_board; 659 $self->repaint_board;
609 1; 660 1;
610} 661}
611 662
643 694
644# create a stack of stones 695# create a stack of stones
645sub create_stack { 696sub create_stack {
646 my ($self, $mark, $size, $rand) = @_; 697 my ($self, $mark, $size, $rand) = @_;
647 698
648 my $shadow = $size * 0.06; 699 my $shadow = $size * 0.05;
649 700
650 my $c = \$self->{stack}{$mark}; 701 my $c = \$self->{stack}{$mark};
651 unless ($$c) { 702 unless ($$c) {
652 for my $stone ($mark & (MARK_W | MARK_GRAY_W) ? @::white_img : @::black_img) { 703 for my $stone ($mark & (MARK_W | MARK_GRAY_W) ? @::white_img : @::black_img) {
653 my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 1; 704 my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 1;
654 705
655 # zeroeth the shadow 706 # zeroeth the shadow
707 if ($mark & (MARK_B | MARK_W)) {
656 $::black_img[0]->composite ( 708 $::black_img[0]->composite (
657 $base, $shadow, $shadow, $size, $size, $shadow-0.5, $shadow-0.5, 709 $base, $shadow, $shadow, $size, $size, $shadow-0.5, $shadow-0.5,
658 $size / $stone->get_width, $size / $stone->get_height, 710 $size / $stone->get_width, $size / $stone->get_height,
659 INTERP_TILES, 128 711 $::config{speed} ? INTERP_NEAREST : INTERP_TILES, 128
660 ); 712 );
713 }
661 714
662 # first the big stones 715 # first the big stones
663 for ([MARK_B, 255], 716 for ([MARK_B, 255],
664 [MARK_W, 255], 717 [MARK_W, 255],
665 [MARK_GRAY_B, 128], 718 [MARK_GRAY_B, 128],
667 my ($mask, $alpha) = @$_; 720 my ($mask, $alpha) = @$_;
668 if ($mark & $mask) { 721 if ($mark & $mask) {
669 $stone->composite ( 722 $stone->composite (
670 $base, 0, 0, $size, $size, -0.5, -0.5, 723 $base, 0, 0, $size, $size, -0.5, -0.5,
671 $size / $stone->get_width, $size / $stone->get_height, 724 $size / $stone->get_width, $size / $stone->get_height,
672 INTERP_HYPER, $alpha 725 $::config{speed} ? INTERP_NEAREST : INTERP_HYPER, $alpha
673 ); 726 );
674 } 727 }
675 } 728 }
676 729
677 # then the samll stones 730 # then the samll stones
680 my ($mask, $img) = @$_; 733 my ($mask, $img) = @$_;
681 if ($mark & $mask) { 734 if ($mark & $mask) {
682 $img->composite ( 735 $img->composite (
683 $base, ($size / 4) x2, (int ($size / 2 + 0.5)) x2, ($size / 4 - 0.5) x 2, 736 $base, ($size / 4) x2, (int ($size / 2 + 0.5)) x2, ($size / 4 - 0.5) x 2,
684 $size / $img->get_width / 2, $size / $img->get_height / 2, 737 $size / $img->get_width / 2, $size / $img->get_height / 2,
685 INTERP_HYPER, 192 738 $::config{speed} ? INTERP_NEAREST : INTERP_HYPER, 192
686 ); 739 );
687 } 740 }
688 } 741 }
689 742
690 # and lastly any markers (labels NYI) 743 # and lastly any markers
691 my $dark_bg = ! ! ($mark & (MARK_B | MARK_GRAY_B)); 744 my $dark_bg = ! ! ($mark & (MARK_B | MARK_GRAY_B));
692 745
693 for ([MARK_CIRCLE, $::circle_img[$dark_bg]], 746 for ([MARK_CIRCLE, $::circle_img[$dark_bg]],
694 [MARK_TRIANGLE, $::triangle_img[$dark_bg]], 747 [MARK_TRIANGLE, $::triangle_img[$dark_bg]],
695 [MARK_SQUARE, $::square_img[$dark_bg]]) { 748 [MARK_SQUARE, $::square_img[$dark_bg]]) {
696 my ($mask, $img) = @$_; 749 my ($mask, $img) = @$_;
697 if ($mark & $mask) { 750 if ($mark & $mask) {
698 $img->composite ( 751 $img->composite (
699 $base, 0, 0, $size, $size, -0.5, -0.5, 752 $base, 0, 0, $size, $size, -0.5, -0.5,
700 $size / $img->get_width, $size / $img->get_height, 753 $size / $img->get_width, $size / $img->get_height,
701 INTERP_HYPER, 255 754 $::config{speed} ? INTERP_NEAREST : INTERP_HYPER, 255
702 ); 755 );
703 } 756 }
704 } 757 }
705 758
706 push @$$c, $base; 759 push @$$c, $base;
711} 764}
712 765
713sub pixbuf_text { 766sub pixbuf_text {
714 my ($pixbuf, $colour, $x, $y, $height, $text) = @_; 767 my ($pixbuf, $colour, $x, $y, $height, $text) = @_;
715 768
716 my $c = $::font[$colour][$::fontmap{substr $text, 0, 1}]; 769 my @c = grep $_,
770 map $::font[$colour][$::fontmap{$_}],
771 split //, $text;
717 772
718 if ($c) { 773 if (@c) {
719 my ($w, $h) = ($c->get_width, $c->get_height); 774 my $spacing = $height * 0.1;
720 my $s = ($height-1) / ($h-1); 775 my $s = $height / List::Util::max map $_->get_height, @c;
776 my $W = List::Util::sum map $_->get_width, @c;
721 777
722 $x -= $w * $s * 0.5; 778 $x -= ($W * $s + $spacing * (@c - 1)) * 0.5;
723 $y -= $height * 0.5; 779 $y -= $height * 0.5;
724 780
781 for (@c) {
782 my $w = $_->get_width * $s;
725 $c->composite ($pixbuf, 783 $_->composite ($pixbuf,
726 $x, $y, $w*$s+0.5, $height+0.5, $x-0.5, $y-0.5, $s, $s, 784 $x, $y, $w+0.999, $height+0.999, $x, $y, $s, $s,
727 INTERP_BILINEAR, 192); 785 $::config{speed} ? INTERP_NEAREST : INTERP_BILINEAR, 255);
728 786
729 } else { 787 $x += $w + $spacing;
730 warn "unable to render character '$text'"; 788 }
731 } 789 }
732} 790}
733 791
734my $black_pb; 792my $black_pb;
735 793
745} 803}
746 804
747sub repaint_board { 805sub repaint_board {
748 my ($self) = @_; 806 my ($self) = @_;
749 my $canvas = $self->{canvas}; 807 my $canvas = $self->{canvas};
808 my $expose_area = undef;
750 809
751 return unless $self->{board}; 810 return $expose_area unless $self->{board};
752 811
753 my ($w, $h) = @{$canvas->allocation}[2,3]; 812 my ($w, $h) = @{$canvas->allocation}[2,3];
754 813
755 my $s = $w > $h ? $h : $w; 814 my $s = $w > $h ? $h : $w;
756 815
757 $self->{offsets} = [int (($w - $s) / 2), int (($h - $s) / 2), $s]; 816 $self->{offsets} = [int (($w - $s) / 2), int (($h - $s) / 2), $s];
758 817
759 my $size = $self->{size}; 818 my $size = $self->{size};
760 819
761 my $border = int ($s / $size); 820 my $border = int ($s / ($size + 3) * 0.5);
762 my $s2 = $s - $border * 2; 821 my $s2 = $s - $border * 2;
763 my $edge = int ($s2 / $size * 0.97); 822 my $edge = int ($s2 / ($size + 1) * 0.95);
764 my $ofs = int ($edge / 2); 823 my $ofs = int ($edge / 2);
765 824
766 my @k = map int ($s2 * $_ / $size - $ofs + $border + 0.5), 0 .. $size; 825 my @k = map int ($s2 * $_ / ($size+1) + $border + 0.5), 0 .. $size;
767 826
768 unless ($self->{background}) {
769 my $pixbuf; 827 my $pixbuf;
828
829 my $oldboard;
830
831 if ($self->{background}) {
832 if ($oldboard = $self->{board_shown}) {
833 $pixbuf = $self->{pixbuf};
834 } else {
835 $pixbuf = $self->{background}->copy;
836 $expose_area = [0, 0, $s, $s];
837 }
838 } else {
839 $expose_area = [0, 0, $s, $s];
770 840
771 my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); 841 my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height);
772 842
773 if ($s < $bw && $s < $bh) { 843 if ($s < $bw && $s < $bh) {
774 $pixbuf = new_pixbuf $s, $s, 1, 0; 844 $pixbuf = new_pixbuf $s, $s, $::config{conserve_memory} ? 0 : 1, 0;
775 $::board_img->copy_area (0, 0, $s, $s, $pixbuf, 0, 0); 845 $::board_img->copy_area (0, 0, $s, $s, $pixbuf, 0, 0);
776 } else { 846 } else {
777 $pixbuf = scale_pixbuf $::board_img, $s, $s, INTERP_TILES; 847 $pixbuf = scale_pixbuf $::board_img, $s, $s, $::config{speed} ? INTERP_NEAREST : INTERP_TILES;
778 } 848 }
779 849
780 my $linew = int ($s / 500); 850 my $linew = int ($s / 25 / $size);
781 851
782 my $a = "A";
783 for my $i (1 .. $size) { 852 for my $i (1 .. $size) {
784 pixbuf_rect $pixbuf, $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew; 853 pixbuf_rect $pixbuf, $k[$i] - $linew, $k[1] - $linew, $k[$i] + $linew, $k[$size] + $linew;
785 pixbuf_rect $pixbuf, $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew; 854 pixbuf_rect $pixbuf, $k[1] - $linew, $k[$i] - $linew, $k[$size] + $linew, $k[$i] + $linew;
786 855
856 # 38 max, but we allow a bit more
857 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
858 AA BB CC DD EE FF GG HH JJ KK LL MM NN OO PP QQ RR SS TT UU VV WW XX YY ZZ))[$i];
859
787 pixbuf_text $pixbuf, 0, $k[$i], ($ofs +$border) / 2, $ofs, $a; 860 pixbuf_text $pixbuf, 0, $k[$i], $border, $ofs, $label;
788 pixbuf_text $pixbuf, 0, $k[$i], $s2 + $border + $ofs / 2, $ofs, $a; 861 pixbuf_text $pixbuf, 0, $k[$i], $s2 + $border, $ofs, $label;
789 pixbuf_text $pixbuf, 0, ($ofs + $border) / 2, $k[$i], $ofs, $size - $i + 1; 862 pixbuf_text $pixbuf, 0, $border, $k[$i], $ofs, $size - $i + 1;
790 pixbuf_text $pixbuf, 0, $s2 + $border + $ofs / 2, $k[$i], $ofs, $size - $i + 1; 863 pixbuf_text $pixbuf, 0, $s2 + $border, $k[$i], $ofs, $size - $i + 1;
791 864
792 $a++; 865 $a++;
793 $a++ if $a eq "I"; # not correct, instead of AA AB, we should get HH JJ KK... 866 $a++ if $a eq "I"; # not correct, instead of AA AB, we should get HH JJ KK...
794 } 867 }
795 868
869 unless ($::config->{conserve_memory}) {
796 $self->{background} = $pixbuf; 870 $self->{background} = $pixbuf;
871 $pixbuf = $pixbuf->copy;
872 }
797 } 873 }
798 874
799 my $pixbuf = $self->{pixbuf} = $self->{background}->copy; 875 $self->{pixbuf} = $pixbuf;
800 876
801 # hoshi-points(!)#d# 877 # hoshi-points(!)#d#
802 # caching of empty board gfx(!)#d# 878 # caching of empty board gfx(!)#d#
803 879
804 for my $x (1 .. $size) { 880 for my $x (1 .. $size) {
805 for my $y (1 .. $size) { 881 for my $y (1 .. $size) {
882 my ($dx, $dy) = ($k[$x] - $ofs, $k[$y] - $ofs);
806 my $mark = $self->{board}{board}[$x-1][$y-1]; 883 my $mark = $self->{board}{board}[$x-1][$y-1];
884 my $old = $oldboard ? $oldboard->{board}[$x-1][$y-1] : 0;
885
886 if ($oldboard && $old != $mark) {
887 my $shadow = $edge * 0.05;
888 my $new_expose = [$dx, $dy, $edge + $shadow, $edge + $shadow];
889 $self->{background}->copy_area (@$new_expose, $pixbuf, $dx, $dy);
890 $expose_area = $expose_area
891 ? Gtk::Gdk::Rectangle->union ($expose_area, $new_expose)
892 : $new_expose;
893 }
807 894
808 if ($mark) { 895 if ($mark) {
809 my ($dx, $dy) = ($k[$x] - $ofs, $k[$y] - $ofs);
810 my $pb = $self->create_stack($mark, $edge, $x * 17 + $y * 11 ); 896 my $pb = $self->create_stack($mark, $edge, $x * 17 + $y * 11 );
811 897
812 $pb->composite ($pixbuf, $dx, $dy, $pb->get_width, $pb->get_height, 898 $pb->composite ($pixbuf, $dx, $dy, $pb->get_width, $pb->get_height,
813 $dx, $dy, 1, 1, INTERP_NEAREST, 255); 899 $dx, $dy, 1, 1, $::config{speed} ? INTERP_NEAREST : INTERP_NEAREST, 255);
900
901 # labels are handled here because they are quite rare
902 if ($mark & MARK_LABEL) {
903 my $white = $mark & (MARK_W | MARK_GRAY_W) ? 0 : 1;
904
905 if ($white) {
906 pixbuf_text $pixbuf, 0,
907 $k[$x] + $ofs * 0.1, $k[$y] + $ofs * 0.1, $ofs * 0.7,
908 $self->{board}{label}[$x-1][$y-1];
909 }
910 pixbuf_text $pixbuf, $white,
911 $k[$x], $k[$y], $ofs * 0.7,
912 $self->{board}{label}[$x-1][$y-1];
913 }
814 914
915 # old pixmap&mask-way. that was fast ;(
815 #my ($pm, $bm) = $self->create_stack($gc, $mark, $edge, $x * 17 + $y * 11 ); 916 #my ($pm, $bm) = $self->create_stack($gc, $mark, $edge, $x * 17 + $y * 11 );
816 917
817 #$gc->set_clip_mask ($bm); 918 #$gc->set_clip_mask ($bm);
818 #$gc->set_clip_origin ($dx, $dy); 919 #$gc->set_clip_origin ($dx, $dy);
819 #$pixmap->draw_pixmap ($gc, $pm, 0, 0, $dx, $dy, $edge, $edge); 920 #$pixmap->draw_pixmap ($gc, $pm, 0, 0, $dx, $dy, $edge, $edge);
820 } 921 }
821 } 922 }
822 } 923 }
823}
824 924
925 $self->{board_shown} = Storable::dclone $self->{board};
926 #d# save
927 #Storable::nstore { board => $self->{board}, size => $self->{size}, path => $self->{path}}, "testboard.storable";
928
929 $expose_area;
930}
931
825sub expose_event { 932sub expose {
826 my ($widget, $self, $event) = @_; 933 my ($self, $area) = @_;
827 934
828 $self->{pixbuf} or return; 935 if ($area && $self->{pixbuf}) {
829 936 my ($x, $y, $w, $h) = @$area;
830 my ($ox, $oy, $s) = @{$self->{offsets}}; 937 my ($ox, $oy, $s) = @{$self->{offsets}};
831 938
832 my ($x, $y, $w, $h) =
833 @{Gtk::Gdk::Rectangle->intersect(
834 $event->{area},
835 [$ox, $oy, $s, $s]
836 )};
837
838 if (defined $x) {
839 $self->{pixbuf}->render_to_drawable ($self->{canvas}->window, $self->{canvas}->style->white_gc, 939 $self->{pixbuf}->render_to_drawable ($self->{canvas}->window, $self->{canvas}->style->white_gc,
840 $x - $ox, $y - $oy, $x, $y, $w, $h); 940 $x, $y, $x + $ox, $y + $oy, $w, $h);
941 $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0,
942 $x + $ox, $y + $oy, $w, $h) if $::DEBUG_EXPOSE;
943
841 #$self->{canvas}->window->draw_pixmap ( 944 #$self->{canvas}->window->draw_pixmap (
842 # $self->{canvas}->style->white_gc, 945 # $self->{canvas}->style->white_gc,
843 # $self->{pixmap}, 946 # $self->{pixmap},
844 # $x - $ox, $y - $oy, $x, $y, $w, $h, 947 # $x - $ox, $y - $oy, $x, $y, $w, $h,
845 #); 948 #);
846 } 949 }
950}
951
952sub expose_event {
953 my ($widget, $self, $event) = @_;
954
955 $self->{pixbuf} or return;
956
957 my $area = $event->{area};
958 my ($ox, $oy, $s) = @{$self->{offsets}};
959
960 $self->expose (Gtk::Gdk::Rectangle->intersect (
961 [$area->[0] - $ox, $area->[1] - $oy, $area->[2], $area->[3]],
962 [0, 0, $s, $s],
963 ));
964
847 1; 965 1;
848} 966}
849 967
850sub event_update_tree { 968sub event_update_tree {
851 my ($self) = @_; 969 my ($self) = @_;
852 970
853 $self->{board} = new KGS::Game::Board $self->{size}; 971 $self->{path} = $self->get_path;
854 $self->{board}->interpret_path ($self->get_path); 972
973 my $move = @{$self->{path}};
855 974
856 $self->repaint_board; 975 $self->{moveadj}->upper($move);
857 976
858 # force a redraw (not perfect(?)) 977 if ($self->{moveadj}->value >= $move - 1 || !$self->{moveadj}->value) {
859 expose_event $self->{canvas}, $self, { area => $self->{canvas}->allocation }; 978 $self->{moveadj}->set_value ($move);
860 979 }
861 $self->{text}->backward_delete($self->{text}->get_length);
862 $self->{text}->insert(undef, undef, undef, KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment});
863} 980}
864 981
865sub event_move { 982sub event_move {
866 ::play_sound "move"; 983 ::play_sound "move";
867} 984}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines