ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/kgsueme/kgsueme/appwin.pl
Revision: 1.5
Committed: Tue Jun 3 15:08:41 2003 UTC (21 years ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +3 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 package appwin;
2
3 use Scalar::Util;
4
5 use base KGS::Listener;
6 use base gtk::widget;
7
8 my %context_id;
9
10 # static method to request the userimage and call the cb when it's available.
11 sub userpic {
12 my ($name, $cb) = @_;
13 $self->get_userpic ($name, $cb);
14 }
15
16 sub status {
17 my ($type, $text) = @_;
18
19 $self->{status}->pop($context_id{$type}) if $context_id{$type};
20 $self->{status}->push($context_id{$type} ||= $self->{status}->get_context_id($type), $text) if $text;
21 }
22
23 sub new {
24 my $self = shift;
25 $self = $self->SUPER::new(@_);
26
27 $appwin::self = $self; # singleton
28 Scalar::Util::weaken $appwin::self;
29
30 $self->{conn} = new KGS::Protocol;
31
32 KGS::Listener::Debug->new->listen($self->{conn}, "any"); #d# debug only :)
33
34 $self->listen($self->{conn}, qw(login userpic));
35
36 $self->{roomlist} = new roomlist conn => $self->{conn};
37
38 $self->{window} = new Gtk2::Window 'toplevel';
39 $self->{window}->set_title('kgsueme');
40 gtk::state $self->{window}, "main::window", undef, window_size => [400, 400];
41 $self->{window}->signal_connect(delete_event => sub { main_quit Gtk2; 1 });
42
43 $self->{window}->add(my $vbox = new Gtk2::VBox);
44
45 $vbox->pack_start(($buttonbox = new Gtk2::HButtonBox), 0, 1, 0);
46 $buttonbox->set_spacing(0);
47
48 my $button = sub {
49 $buttonbox->add(my $button = new Gtk2::Button $_[0]);
50 signal_connect $button clicked => $_[1];
51 };
52
53 $button->("Login", sub { $self->login; });
54 $button->("Roomlist", sub { $self->{roomlist}->show; });
55 $button->("Save Config & Layout", \&util::save_config);
56 $button->("Quit", sub { main_quit Gtk2 });
57
58 $vbox->pack_start((my $hbox = new Gtk2::HBox), 0, 1, 0);
59
60 $hbox->add(new Gtk2::Label "Login");
61
62 $hbox->add($self->{login} = new_with_max_length Gtk2::Entry 12);
63 $self->{login}->set_text($::config->{login});
64
65 if ($::HACK) {
66 $self->{login}->signal_connect(activate => sub {
67 $self->{conn}{name} = $self->{login}->get_text;
68 });
69 }
70
71 $hbox->add(new Gtk2::Label "Password");
72 $hbox->add($self->{password} = new Gtk2::Entry);
73 $self->{password}->set_visibility(0);
74
75 $self->{gamelist} = new gamelist conn => $self->{conn};
76 $vbox->pack_start ($self->{gamelist}->widget, 1, 1, 0);
77
78 $appwin::gamelist = $self->{gamelist};
79 Scalar::Util::weaken $appwin::gamelist;
80
81 $vbox->pack_start(($self->{status} = new Gtk2::Statusbar), 0, 1, 0);
82
83 $self->{window}->show_all;
84
85 $self;
86 }
87
88 sub login {
89 my ($self) = @_;
90
91 $self->{conn}->disconnect;
92
93 # initialize new socket and connection
94 my $sock = new IO::Socket::INET PeerHost => "kgs.kiseido.com", PeerPort => "2379"
95 or die;
96
97 $sock->blocking(1);
98 $self->{conn}->handshake($sock);
99 $sock->blocking(0);
100
101 my $input; $input = add_watch Glib::IO fileno $sock, [G_IO_IN, G_IO_ERR, G_IO_HUP], sub {
102 # this is dorked
103 my $buf;
104 if (0 >= sysread $sock, $buf, 16384
105 and !$!{EINTR} and !$!{EAGAIN}) {
106 remove Glib::Source $input;
107 $self->event_disconnect;
108 }
109 $self->{conn}->feed_data($buf);
110 1;
111 }, G_PRIORITY_HIGH;
112
113 # now login
114 $self->{conn}->login($ENV{KGSUEME_CLIENTVER} || "kgsueme $VERSION $^O", # allow users to overwrite
115 $self->{login}->get_text,
116 $self->{password}->get_text);
117 }
118
119 sub inject_login {
120 my ($self, $msg) = @_;
121
122 appwin::status("login", "logged in as '$self->{conn}{name}' with status '$msg->{result}'");
123 $::config->{login} = $self->{conn}{name};
124
125 if ($msg->{success}) {
126 # auto-join
127 for (values %{$::config->{rooms}}) {
128 $self->{roomlist}->join_room($_);
129 }
130 sound::play 3, "connect";
131 } elsif ($msg->{result} eq "user unknown") {
132 sound::play 2, "user_unknown";
133 } else {
134 sound::play 2, "warning";
135 }
136 }
137
138 my %userpic;
139 my %userpic_cb;
140
141 sub get_userpic {
142 my ($self, $name, $cb) = @_;
143
144 if (exists $userpic{$name}) {
145 $cb->($userpic{$name});
146 } else {
147 if (!exists $userpic_cb{$name}) {
148 # after 10 seconds, flush callbacks
149 $self->msg (pic_req => name => $name);
150 add Glib::Timeout 10000, sub {
151 $_->() for @{delete $userpic_cb{$name} || []};
152 0;
153 };
154 }
155 push @{$userpic_cb{$name}}, $cb;
156 }
157 }
158
159 sub inject_userpic {
160 my ($self, $msg) = @_;
161
162 $userpic{$msg->{name}} = $msg->{data};
163 $_->($userpic{$msg->{name}}) for @{delete $userpic_cb{$msg->{name}} || []};
164 }
165
166 sub event_disconnect { }
167
168 1;
169