… | |
… | |
3 | use KGS::Constants; |
3 | use KGS::Constants; |
4 | use KGS::Game::Board; |
4 | use KGS::Game::Board; |
5 | |
5 | |
6 | use base KGS::Listener::Game; |
6 | use base KGS::Listener::Game; |
7 | use base KGS::Game; |
7 | use base KGS::Game; |
|
|
8 | |
|
|
9 | use base gtk::widget; |
8 | |
10 | |
9 | sub new { |
11 | sub new { |
10 | my $self = shift; |
12 | my $self = shift; |
11 | $self = $self->SUPER::new(@_); |
13 | $self = $self->SUPER::new(@_); |
12 | |
14 | |
13 | $self->listen($self->{conn}); |
15 | $self->listen($self->{conn}); |
14 | |
16 | |
15 | $self->{window} = new Gtk2::Window 'toplevel'; |
17 | $self->{window} = new Gtk2::Window 'toplevel'; |
16 | my $title = $self->{channel} ? $self->user0." ".$self->user1 : "Game Window"; |
18 | my $title = $self->{channel} ? $self->owner->as_string." ".$self->opponent_string : "Game Window"; |
17 | $self->{window}->set_title("KGS Game $title"); |
19 | $self->{window}->set_title("KGS Game $title"); |
18 | gtk::state $self->{window}, "game::window", undef, window_size => [600, 500]; |
20 | gtk::state $self->{window}, "game::window", undef, window_size => [600, 500]; |
19 | |
21 | |
20 | $self->{window}->signal_connect(delete_event => sub { $self->part; 1 }); |
22 | $self->{window}->signal_connect(delete_event => sub { |
|
|
23 | if ($self->{joined}) { |
|
|
24 | $self->part; |
|
|
25 | } else { |
|
|
26 | $self->event_part; |
|
|
27 | } |
|
|
28 | 1; |
|
|
29 | }); |
21 | |
30 | |
22 | $self->{window}->add(my $hpane = new Gtk2::HPaned); |
31 | $self->{window}->add($self->{hpane} = new Gtk2::HPaned); |
23 | gtk::state $hpane, "game::hpane", undef, hpane_position => 500; |
32 | gtk::state $self->{hpane}, "game::hpane", undef, position => 500; |
24 | |
33 | |
25 | $hpane->pack1((my $vbox = new Gtk2::VBox), 1, 1); |
34 | $self->{hpane}->pack1((my $vbox = new Gtk2::VBox), 1, 1); |
26 | |
35 | |
27 | $vbox->pack_start((my $frame = new Gtk2::Frame), 0, 1, 0); |
36 | $vbox->pack_start((my $frame = new Gtk2::Frame), 0, 1, 0); |
28 | |
37 | |
29 | # grrr... |
|
|
30 | { |
38 | { |
|
|
39 | # grrr... |
31 | $frame->add(my $vbox = new Gtk2::VBox); |
40 | $frame->add(my $vbox = new Gtk2::VBox); |
32 | $vbox->add($self->{title} = new Gtk2::Label $title); |
41 | $vbox->add($self->{title} = new Gtk2::Label $title); |
33 | |
42 | |
34 | $self->{moveadj} = new Gtk2::Adjustment 0, 0, 1, 0.01, 0.1, 0; |
43 | $self->{moveadj} = new Gtk2::Adjustment 1, 0, 1, 0.01, 0.1, 0; |
35 | |
44 | |
36 | $vbox->add(my $scale = new Gtk2::HScale $self->{moveadj}); |
45 | $vbox->add(my $scale = new Gtk2::HScale $self->{moveadj}); |
37 | $scale->set_draw_value (0); |
46 | $scale->set_draw_value (0); |
38 | |
47 | |
39 | $self->{moveadj}->signal_connect (value_changed => sub { |
48 | $self->{moveadj}->signal_connect (value_changed => sub { |
… | |
… | |
48 | |
57 | |
49 | $self->{text}->set_text(KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment}); |
58 | $self->{text}->set_text(KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment}); |
50 | }); |
59 | }); |
51 | } |
60 | } |
52 | |
61 | |
53 | #Gtk2::Widget->push_visual (Gtk2::Gdk::Rgb->get_visual); #d# gdk_rgb_* not yet implemented(?) |
|
|
54 | #Gtk2::Widget->push_colormap (Gtk2::Gdk::Rgb->get_cmap); |
|
|
55 | $vbox->pack_start(($self->{canvas} = new Gtk2::DrawingArea), 1, 1, 0); |
62 | $vbox->pack_start(($self->{canvas} = new Gtk2::DrawingArea), 1, 1, 0); |
56 | #Gtk2::Widget->pop_colormap; |
|
|
57 | #Gtk2::Widget->pop_visual; |
|
|
58 | |
63 | |
59 | $self->{canvas}->signal_connect(configure_event => \&configure_event, $self); |
64 | $self->{canvas}->signal_connect(configure_event => \&configure_event, $self); |
60 | $self->{canvas}->signal_connect(expose_event => \&expose_event, $self); |
65 | $self->{canvas}->signal_connect(expose_event => \&expose_event, $self); |
61 | |
66 | |
62 | $hpane->pack2((my $vpane = new Gtk2::VPaned), 0, 0); |
67 | $self->{hpane}->pack2(($self->{vpane} = new Gtk2::VPaned), 0, 0); |
|
|
68 | $self->{hpane}->set(position_set => 1); |
63 | gtk::state $vpane, "game", $self->{name}, vpane_position => 80; |
69 | gtk::state $self->{vpane}, "game::vpane", $self->{name}, position => 80; |
64 | |
70 | |
65 | $vpane->add(my $sw = new Gtk2::ScrolledWindow); |
71 | $self->{vpane}->add(my $sw = new Gtk2::ScrolledWindow); |
66 | $sw->set_policy("automatic", "always"); |
72 | $sw->set_policy("automatic", "always"); |
67 | |
73 | |
68 | if (0) { |
74 | $sw->add(($self->{userlist} = new gtk::userlist)->widget); |
69 | $sw->add($self->{userlist} = new_with_titles Gtk2::ListStore "User", "Rank", "Flags"); |
|
|
70 | ::clist_autosort $self->{userlist}; |
|
|
71 | gtk::state $self->{userlist}, "room::userlist", $self->{name}, clist_column_widths => [120, 30]; |
|
|
72 | } |
|
|
73 | |
75 | |
74 | $vpane->add(my $vbox = new Gtk2::VBox); |
76 | $self->{vpane}->add(my $vbox = new Gtk2::VBox); |
75 | |
77 | |
76 | $vbox->pack_start((my $sw = new Gtk2::ScrolledWindow), 1, 1, 0); |
78 | $vbox->pack_start((my $sw = new Gtk2::ScrolledWindow), 1, 1, 0); |
77 | $sw->set_policy("automatic", "always"); |
79 | $sw->set_policy("never", "always"); |
78 | |
80 | |
79 | $sw->add(($self->{text} = new gtk::text)->widget); |
81 | $sw->add(($self->{text} = new gtk::text)->widget); |
80 | |
82 | |
81 | $vbox->pack_start(($self->{entry} = new Gtk2::Entry), 0, 1, 0); |
83 | $vbox->pack_start(($self->{entry} = new Gtk2::Entry), 0, 1, 0); |
82 | $self->{entry}->signal_connect(activate => sub { |
84 | $self->{entry}->signal_connect(activate => sub { |
… | |
… | |
89 | } |
91 | } |
90 | |
92 | |
91 | sub event_update_users { |
93 | sub event_update_users { |
92 | my ($self) = @_; |
94 | my ($self) = @_; |
93 | |
95 | |
94 | room::event_update_users $self; |
96 | $self->{userlist}->update($self->{users}); |
95 | } |
97 | } |
96 | |
98 | |
97 | sub join { |
99 | sub join { |
98 | my ($self) = @_; |
100 | my ($self) = @_; |
99 | $self->SUPER::join; |
101 | $self->SUPER::join; |
… | |
… | |
113 | delete $self->{stack}; |
115 | delete $self->{stack}; |
114 | delete $self->{pixbuf}; |
116 | delete $self->{pixbuf}; |
115 | delete $self->{board_shown}; |
117 | delete $self->{board_shown}; |
116 | delete $self->{background}; |
118 | delete $self->{background}; |
117 | $self->repaint_board; |
119 | $self->repaint_board; |
118 | 1; |
120 | 0; |
|
|
121 | } |
|
|
122 | |
|
|
123 | sub expose_event { |
|
|
124 | my ($widget, $event, $self) = @_; |
|
|
125 | |
|
|
126 | $self->{pixbuf} or return; |
|
|
127 | |
|
|
128 | my $area = $event->area; |
|
|
129 | my ($ox, $oy, $s) = @{$self->{offsets}}; |
|
|
130 | |
|
|
131 | $self->redraw ( |
|
|
132 | (new Gtk2::Gdk::Rectangle $area->x - $ox, $area->y - $oy, $area->width, $area->height) |
|
|
133 | ->intersect(new Gtk2::Gdk::Rectangle 0, 0, $s, $s) |
|
|
134 | ); |
|
|
135 | |
|
|
136 | 0; |
119 | } |
137 | } |
120 | |
138 | |
121 | # something Gtk2 fixed |
139 | # something Gtk2 fixed |
122 | sub INTERP_NEAREST (){ 'nearest' } |
140 | sub INTERP_NEAREST (){ 'nearest' } |
123 | sub INTERP_TILES (){ 'tiles' } |
141 | sub INTERP_TILES (){ 'tiles' } |
… | |
… | |
260 | return $expose_area unless $self->{board}; |
278 | return $expose_area unless $self->{board}; |
261 | |
279 | |
262 | my ($w, $h) = ($canvas->allocation->values)[2,3]; |
280 | my ($w, $h) = ($canvas->allocation->values)[2,3]; |
263 | |
281 | |
264 | my $s = $w > $h ? $h : $w; |
282 | my $s = $w > $h ? $h : $w; |
|
|
283 | |
|
|
284 | return unless $s > 128; |
265 | |
285 | |
266 | $self->{offsets} = [int (($w - $s) / 2), int (($h - $s) / 2), $s]; |
286 | $self->{offsets} = [int (($w - $s) / 2), int (($h - $s) / 2), $s]; |
267 | |
287 | |
268 | my $size = $self->{size}; |
288 | my $size = $self->{size}; |
269 | |
289 | |
… | |
… | |
281 | if ($self->{background}) { |
301 | if ($self->{background}) { |
282 | if ($oldboard = $self->{board_shown}) { |
302 | if ($oldboard = $self->{board_shown}) { |
283 | $pixbuf = $self->{pixbuf}; |
303 | $pixbuf = $self->{pixbuf}; |
284 | } else { |
304 | } else { |
285 | $pixbuf = $self->{background}->copy; |
305 | $pixbuf = $self->{background}->copy; |
286 | $expose_area = [0, 0, $s, $s]; |
306 | $expose_area = new Gtk2::Gdk::Rectangle 0, 0, $s, $s; |
287 | } |
307 | } |
288 | } else { |
308 | } else { |
289 | $expose_area = [0, 0, $s, $s]; |
309 | $expose_area = new Gtk2::Gdk::Rectangle 0, 0, $s, $s; |
290 | |
310 | |
291 | my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); |
311 | my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); |
292 | |
312 | |
293 | if ($s < $bw && $s < $bh) { |
313 | if ($s < $bw && $s < $bh) { |
294 | $pixbuf = new_pixbuf $s, $s, 0; |
314 | $pixbuf = new_pixbuf $s, $s, 0; |
… | |
… | |
409 | $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0, |
429 | $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0, |
410 | $x + $ox - 1, $y + $oy - 1, $w + 2, $h + 2) if $::DEBUG_EXPOSE; |
430 | $x + $ox - 1, $y + $oy - 1, $w + 2, $h + 2) if $::DEBUG_EXPOSE; |
411 | } |
431 | } |
412 | } |
432 | } |
413 | |
433 | |
414 | sub expose_event { |
|
|
415 | my ($widget, $event, $self) = @_; |
|
|
416 | |
|
|
417 | $self->{pixbuf} or return; |
|
|
418 | |
|
|
419 | my $area = $event->area; |
|
|
420 | my ($ox, $oy, $s) = @{$self->{offsets}}; |
|
|
421 | |
|
|
422 | $self->redraw ( |
|
|
423 | (new Gtk2::Gdk::Rectangle $area->x - $ox, $area->x - $oy, $area->width, $area->height) |
|
|
424 | ->intersect(new Gtk2::Gdk::Rectangle 0, 0, $s, $s) |
|
|
425 | ); |
|
|
426 | |
|
|
427 | 1; |
|
|
428 | } |
|
|
429 | |
|
|
430 | sub event_update_tree { |
434 | sub event_update_tree { |
431 | my ($self) = @_; |
435 | my ($self) = @_; |
432 | |
436 | |
433 | $self->{path} = $self->get_path; |
437 | $self->{path} = $self->get_path; |
434 | |
|
|
435 | $self->{moveadj}->value_changed (); |
438 | $self->{moveadj}->value_changed if $self->{moveadj}; |
436 | } |
439 | } |
437 | |
440 | |
438 | sub event_part { |
441 | sub event_part { |
439 | my ($self) = @_; |
442 | my ($self) = @_; |
440 | $self->SUPER::event_part; |
443 | $self->SUPER::event_part; |
441 | (delete $self->{window})->destroy; # hmm.. why does this keep the object alive? puzzling.. ahh.. the callbacks ;) |
|
|
442 | delete $self->{room}{game}{$self->{channel}}; |
444 | delete $appwin::gamelist->{game}{$self->{channel}}; |
|
|
445 | $self->destroy; |
443 | } |
446 | } |
444 | |
447 | |
445 | sub event_move { |
448 | sub event_move { |
446 | my ($self, $pass) = @_; |
449 | my ($self, $pass) = @_; |
447 | sound::play 1, $pass ? "pass" : "move"; |
450 | sound::play 1, $pass ? "pass" : "move"; |
448 | } |
451 | } |
449 | |
452 | |
450 | sub DESTROY {#d# |
|
|
451 | warn "DESTROY(@_)\n";#d# |
|
|
452 | } |
|
|
453 | |
|
|
454 | 1; |
453 | 1; |
455 | |
454 | |