… | |
… | |
218 | |
218 | |
219 | use POSIX qw(ceil); |
219 | use POSIX qw(ceil); |
220 | |
220 | |
221 | sub new { |
221 | sub new { |
222 | my ($self, %arg) = @_; |
222 | my ($self, %arg) = @_; |
|
|
223 | |
223 | $self = $self->Glib::Object::new; |
224 | $self = $self->Glib::Object::new; |
224 | $self->{$_} = delete $arg{$_} for keys %arg; |
225 | $self->{$_} = delete $arg{$_} for keys %arg; |
225 | |
226 | |
226 | gtk::state $self, "game::window", undef, window_size => [600, 500]; |
227 | gtk::state $self, "game::window", undef, window_size => [620, 460]; |
|
|
228 | $self->set (allow_shrink => 1); |
227 | |
229 | |
228 | $self->signal_connect (destroy => sub { |
230 | $self->signal_connect (destroy => sub { |
229 | $self->unlisten; |
231 | $self->unlisten; |
230 | delete $self->{app}{game}{$self->{channel}}; |
232 | delete $self->{app}{game}{$self->{channel}}; |
231 | %{$_[0]} = (); |
233 | %{$_[0]} = (); |
232 | });#d# |
234 | });#d# |
233 | |
235 | |
234 | $self->add (my $hpane = new Gtk2::HPaned); |
236 | $self->add (my $hpane = new Gtk2::HPaned); |
235 | gtk::state $hpane, "game::hpane", undef, position => 500; |
237 | gtk::state $hpane, "game::hpane", undef, position => 420; |
236 | |
238 | |
237 | # LEFT PANE |
239 | # LEFT PANE |
238 | |
240 | |
239 | $hpane->pack1 (($self->{left} = new Gtk2::VBox), 1, 0); |
241 | $hpane->pack1 (($self->{left} = new Gtk2::VBox), 1, 0); |
240 | |
242 | |
… | |
… | |
275 | for COLOUR_WHITE, COLOUR_BLACK; |
277 | for COLOUR_WHITE, COLOUR_BLACK; |
276 | |
278 | |
277 | $vbox->pack_start ((my $buttonbox = new Gtk2::HButtonBox), 0, 1, 0); |
279 | $vbox->pack_start ((my $buttonbox = new Gtk2::HButtonBox), 0, 1, 0); |
278 | |
280 | |
279 | $buttonbox->add ($self->{button_pass} = |
281 | $buttonbox->add ($self->{button_pass} = |
280 | Gtk2::Button->Glib::Object::new (label => "Pass", no_show_all => 1, visible => 0)); |
282 | Gtk2::Button->Glib::Object::new (label => "Pass", visible => 0)); |
281 | $self->{button_pass}->signal_connect (clicked => sub { |
283 | $self->{button_pass}->signal_connect (clicked => sub { |
282 | $self->{board_click}->(255, 255) if $self->{board_click}; |
284 | $self->{board_click}->(255, 255) if $self->{board_click}; |
283 | }); |
285 | }); |
|
|
286 | eval { $self->{button_pass}->set (no_show_all => 1) }; # workaround for gtk+-2.2 |
284 | $buttonbox->add ($self->{button_undo} = |
287 | $buttonbox->add ($self->{button_undo} = |
285 | Gtk2::Button->Glib::Object::new (label => "Undo", no_show_all => 1, visible => 0)); |
288 | Gtk2::Button->Glib::Object::new (label => "Undo", visible => 0)); |
286 | $self->{button_undo}->signal_connect (clicked => sub { |
289 | $self->{button_undo}->signal_connect (clicked => sub { |
287 | $self->send (req_undo => channel => $self->{channel}); |
290 | $self->send (req_undo => channel => $self->{channel}); |
288 | }); |
291 | }); |
|
|
292 | eval { $self->{button_undo}->set (no_show_all => 1) }; # workaround for gtk+-2.2 |
289 | $buttonbox->add ($self->{button_resign} = |
293 | $buttonbox->add ($self->{button_resign} = |
290 | Gtk2::Button->Glib::Object::new (label => "Resign", no_show_all => 1, visible => 0)); |
294 | Gtk2::Button->Glib::Object::new (label => "Resign", visible => 0)); |
291 | $self->{button_resign}->signal_connect (clicked => sub { |
295 | $self->{button_resign}->signal_connect (clicked => sub { |
292 | $self->send (resign_game => channel => $self->{channel}, player => $self->{colour}); |
296 | $self->send (resign_game => channel => $self->{channel}, player => $self->{colour}); |
293 | }); |
297 | }); |
|
|
298 | eval { $self->{button_resign}->set (no_show_all => 1) }; # workaround for gtk+-2.2 |
294 | |
299 | |
295 | $vbox->pack_start (($self->{chat} = new superchat), 1, 1, 0); |
300 | $vbox->pack_start (($self->{chat} = new chat), 1, 1, 0); |
296 | |
301 | |
297 | $self->set_channel ($self->{channel}); |
302 | $self->set_channel ($self->{channel}); |
298 | |
303 | |
299 | $self->show_all; |
304 | $self->show_all; |
300 | |
305 | |
… | |
… | |
331 | return if $self->{joined}; |
336 | return if $self->{joined}; |
332 | |
337 | |
333 | $self->SUPER::join; |
338 | $self->SUPER::join; |
334 | } |
339 | } |
335 | |
340 | |
|
|
341 | sub part { |
|
|
342 | my ($self) = @_; |
|
|
343 | |
|
|
344 | $self->hide; |
|
|
345 | $self->SUPER::part; |
|
|
346 | } |
|
|
347 | |
336 | sub event_join { |
348 | sub event_join { |
337 | my ($self) = @_; |
349 | my ($self) = @_; |
338 | |
350 | |
339 | $self->SUPER::event_join (@_); |
351 | $self->SUPER::event_join (@_); |
340 | $self->init_tree; |
352 | $self->init_tree; |
… | |
… | |
379 | $important{$self->{black}{name}}++; |
391 | $important{$self->{black}{name}}++; |
380 | $important{$self->{white}{name}}++; |
392 | $important{$self->{white}{name}}++; |
381 | $important{$self->{owner}{name}}++; |
393 | $important{$self->{owner}{name}}++; |
382 | |
394 | |
383 | if (my @users = grep $important{$_->{name}}, @$add) { |
395 | if (my @users = grep $important{$_->{name}}, @$add) { |
384 | $self->{chat}->append_text ("\n<header>Joins:</header>"); |
396 | $self->{chat}->append_text ("\n<leader>Joins:</leader>"); |
385 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
397 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
386 | } |
398 | } |
387 | if (my @users = grep $important{$_->{name}}, @$remove) { |
399 | if (my @users = grep $important{$_->{name}}, @$remove) { |
388 | $self->{chat}->append_text ("\n<header>Parts:</header>"); |
400 | $self->{chat}->append_text ("\n<leader>Parts:</leader>"); |
389 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
401 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
390 | } |
402 | } |
391 | } |
403 | } |
392 | |
404 | |
393 | ### GAME INFO ############################################################### |
405 | ### GAME INFO ############################################################### |
… | |
… | |
554 | |
566 | |
555 | my $running = $self->{showmove} == @{$self->{path}} && $self->is_active; |
567 | my $running = $self->{showmove} == @{$self->{path}} && $self->is_active; |
556 | |
568 | |
557 | delete $self->{board_click}; |
569 | delete $self->{board_click}; |
558 | |
570 | |
559 | $self->{colour} = COLOUR_BLACK;#d# |
|
|
560 | $self->{whosemove} = COLOUR_BLACK;#d# |
|
|
561 | $running = 1;#d# |
|
|
562 | if ($self->{teacher} eq $self->{app}{conn}) { |
571 | if ($self->{teacher} eq $self->{app}{conn}) { |
563 | #TODO# # teaching mode not implemented |
572 | #TODO# # teaching mode not implemented |
564 | $self->{button_pass}->set (label => "Pass", visible => 1, sensitive => 1); |
573 | $self->{button_pass}->set (label => "Pass", visible => 1, sensitive => 1); |
565 | $self->{button_undo}->hide; |
574 | $self->{button_undo}->hide; |
566 | $self->{button_resign}->hide; |
575 | $self->{button_resign}->hide; |
… | |
… | |
628 | sub update_board { |
637 | sub update_board { |
629 | my ($self) = @_; |
638 | my ($self) = @_; |
630 | |
639 | |
631 | return unless $self->{path}; |
640 | return unless $self->{path}; |
632 | |
641 | |
|
|
642 | $self->{board_label}->set_text ("Move " . ($self->{showmove} - 1)); |
|
|
643 | |
|
|
644 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
|
|
645 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
|
|
646 | |
633 | if ($self->{rules}{ruleset} == RULESET_JAPANESE) { |
647 | if ($self->{rules}{ruleset} == RULESET_JAPANESE) { |
634 | if ($self->{curnode}{move} == 0) { |
648 | if ($self->{curnode}{move} == 0) { |
635 | $self->{whosemove} = $self->{handicap} ? COLOUR_WHITE : COLOUR_BLACK; |
649 | $self->{whosemove} = $self->{handicap} ? COLOUR_WHITE : COLOUR_BLACK; |
636 | } else { |
650 | } else { |
637 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
651 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
… | |
… | |
645 | } else { |
659 | } else { |
646 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
660 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
647 | } |
661 | } |
648 | } |
662 | } |
649 | |
663 | |
650 | $self->{board_label}->set_text ("Move " . ($self->{showmove} - 1)); |
|
|
651 | |
|
|
652 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
|
|
653 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
|
|
654 | |
|
|
655 | $self->update_cursor; |
|
|
656 | |
|
|
657 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
664 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
658 | for COLOUR_WHITE, COLOUR_BLACK; |
665 | for COLOUR_WHITE, COLOUR_BLACK; |
659 | |
666 | |
660 | my $start_time = $self->{rules}{time}; |
667 | my $start_time = $self->{rules}{time}; |
661 | |
668 | |
… | |
… | |
683 | . "Black: $self->{cur_board}{score}[COLOUR_BLACK]" |
690 | . "Black: $self->{cur_board}{score}[COLOUR_BLACK]" |
684 | . "</score>"); |
691 | . "</score>"); |
685 | } elsif ($self->{score_inlay}) { |
692 | } elsif ($self->{score_inlay}) { |
686 | (delete $self->{score_inlay})->clear; |
693 | (delete $self->{score_inlay})->clear; |
687 | } |
694 | } |
|
|
695 | |
|
|
696 | $self->update_cursor; |
|
|
697 | |
688 | } |
698 | } |
689 | |
699 | |
690 | sub event_update_tree { |
700 | sub event_update_tree { |
691 | my ($self) = @_; |
701 | my ($self) = @_; |
692 | |
702 | |
… | |
… | |
784 | } |
794 | } |
785 | |
795 | |
786 | sub event_owner_left { |
796 | sub event_owner_left { |
787 | my ($self) = @_; |
797 | my ($self) = @_; |
788 | |
798 | |
789 | sound::play 2, "info"; |
|
|
790 | $self->{chat}->append_text ("\n<infoblock><header>Owner left</header>" |
799 | $self->{chat}->append_text ("\n<infoblock><header>Owner left</header>" |
791 | . "\nThe owner of this game left.</infoblock>"); |
800 | . "\nThe owner of this game left.</infoblock>"); |
792 | } |
801 | } |
793 | |
802 | |
794 | sub event_teacher_left { |
803 | sub event_teacher_left { |
795 | my ($self) = @_; |
804 | my ($self) = @_; |
796 | |
805 | |
797 | sound::play 2, "info"; |
|
|
798 | $self->{chat}->append_text ("\n<infoblock><header>Teacher left</header>" |
806 | $self->{chat}->append_text ("\n<infoblock><header>Teacher left</header>" |
799 | . "\nThe teacher left the game.</infoblock>"); |
807 | . "\nThe teacher left the game.</infoblock>"); |
800 | } |
808 | } |
801 | |
809 | |
802 | sub event_done { |
810 | sub event_done { |
… | |
… | |
878 | |
886 | |
879 | my ($size, $time, $interval, $count, $type); |
887 | my ($size, $time, $interval, $count, $type); |
880 | |
888 | |
881 | if (!$self->{channel}) { |
889 | if (!$self->{channel}) { |
882 | $inlay->append_text ("\nNotes: "); |
890 | $inlay->append_text ("\nNotes: "); |
883 | $inlay->append_entry (\$info->{notes}, 20, ""); |
891 | $inlay->append_widget (gtk::textentry \$info->{notes}, 20, ""); |
884 | $inlay->append_text ("\nGlobal Offer: "); |
892 | $inlay->append_text ("\nGlobal Offer: "); |
885 | $inlay->append_optionmenu (\$info->{flags}, |
893 | $inlay->append_optionmenu (\$info->{flags}, |
886 | 0 => "No", |
894 | 0 => "No", |
887 | 2 => "Yes", |
895 | 2 => "Yes", |
888 | ); |
896 | ); |
… | |
… | |
941 | if ($self->{channel}) { |
949 | if ($self->{channel}) { |
942 | $inlay->append_text ("\nHandicap: "); |
950 | $inlay->append_text ("\nHandicap: "); |
943 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
951 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
944 | |
952 | |
945 | $inlay->append_text ("\nKomi: "); |
953 | $inlay->append_text ("\nKomi: "); |
946 | $inlay->append_entry (\$info->{rules}{komi}, 5); |
954 | $inlay->append_widget (gtk::numentry \$info->{rules}{komi}, 5); |
947 | } |
955 | } |
948 | |
956 | |
949 | $inlay->append_text ("\nTimesys: "); |
957 | $inlay->append_text ("\nTimesys: "); |
950 | $inlay->append_optionmenu ( |
958 | $inlay->append_optionmenu ( |
951 | \$info->{rules}{timesys}, |
959 | \$info->{rules}{timesys}, |
… | |
… | |
980 | } |
988 | } |
981 | } |
989 | } |
982 | ); |
990 | ); |
983 | |
991 | |
984 | $inlay->append_text ("\nMain Time: "); |
992 | $inlay->append_text ("\nMain Time: "); |
985 | $time = $inlay->append_entry (\$info->{rules}{time}, 5); |
993 | $time = $inlay->append_widget (gtk::timeentry \$info->{rules}{time}, 5); |
986 | $inlay->append_text ("\nInterval: "); |
994 | $inlay->append_text ("\nInterval: "); |
987 | $interval = $inlay->append_entry (\$info->{rules}{interval}, 3); |
995 | $interval = $inlay->append_widget (gtk::timeentry \$info->{rules}{interval}, 5); |
988 | $inlay->append_text ("\nPeriods/Stones: "); |
996 | $inlay->append_text ("\nPeriods/Stones: "); |
989 | $count = $inlay->append_entry (\$info->{rules}{count}, 2); |
997 | $count = $inlay->append_widget (gtk::numentry \$info->{rules}{count}, 5); |
990 | |
998 | |
991 | $inlay->append_text ("\n"); |
999 | $inlay->append_text ("\n"); |
992 | |
1000 | |
993 | if (!$self->{channel}) { |
1001 | if (!$self->{channel}) { |
994 | $inlay->append_button ("Create Challenge", sub { |
1002 | $inlay->append_button ("Create Challenge", sub { |