ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/widget.ext
Revision: 1.12
Committed: Sun Jul 22 20:08:38 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.11: +7 -6 lines
Log Message:
preliminary worldmap hack + widget toolkit fixes

File Contents

# Content
1 #! perl # mandatory depends=login
2
3 # sends the following ext message types
4 # ws_n id # widgetset new
5 # ws_d id # widgetset destroy
6 # ws_c ws id class args # widgetset create
7 # w_c id [rid] name args # widget method call
8 # w_s id @attr # widget member set
9 # w_g id rid @attr # widget member get
10 #
11 # and expects the following exti message types
12 # w_r rid res # widget call return
13 # w_e id name args # widget_event
14
15 cf::client->attach (
16 on_connect => sub {
17 my ($ns) = @_;
18
19 Scalar::Util::weaken (my $weakns = $ns);
20
21 $ns->{id} = "a";
22 $ns->{json_coder}->filter_json_single_key_object (__widget_ref__ => sub {
23 # cannot deserialise ATM
24 undef
25 });
26 },
27 );
28
29 sub csc_update_stats {
30 my ($ns) = @_;
31
32 while (my ($k, $v) = each %{ $ns->{csc}{stat} }) {
33 $v->set_text ($ns->pl->ob->stats->$k);
34 }
35 }
36
37 sub csc_start {
38 my ($ns) = @_;
39
40 my $ws = $ns->{csc} = $ns->new_widgetset;
41
42 my $w = $ws->new (Toplevel =>
43 min_w => 600,
44 min_h => 400,
45 x => "center",
46 y => "center",
47 title => "Character Creation",
48 has_close_button => 1,
49 on_delete => sub {
50 $ws->destroy;
51 },
52 );
53
54 $w->add (my $ntb = $ws->new (Notebook => expand => 1));
55
56 $ntb->add (Statistics => (my $stats = $ws->new (Table => expand => 1)), "Basic statistics of your new character");
57
58 $stats->add (0, 0, (my $statstable = $ws->new ("Table")));
59
60 for (
61 [0, "Str"],
62 [1, "Dex"],
63 [2, "Con"],
64 [3, "Int"],
65 [4, "Wis"],
66 [5, "Pow"],
67 [6, "Cha"],
68 ) {
69 my ($x, $label) = @$_;
70
71 $statstable->add_at ($x, 0, $ws->new (Label =>
72 can_hover => 1, can_events => 1,
73 align => +1, text => $label, tooltip => "#stat_$label",
74 ));
75 $statstable->add_at ($x, 1, $ws->{stat}{$label} = $ws->new (Label =>
76 can_hover => 1, can_events => 1,
77 align => +1, template => "88", tooltip => "#stat_$label",
78 ));
79 }
80
81 csc_update_stats $ns;
82
83 $w->show;
84 }
85
86 cf::player->attach (
87 on_login => sub {
88 my ($pl) = @_;
89
90 return unless $cf::CFG{devel};
91
92 my $ns = $pl->ns;
93
94 return unless $ns->{can_widget};
95 #csc_start $ns;
96 },
97 );
98
99 cf::register_exticmd w_e => sub {
100 my ($ns, $pkt) = @_;
101
102 if (my $w = $ns->{widget}{$pkt->{id}}) {
103 if (my $cb = $w->{ev}{$pkt->{name}}) {
104 $_->($w, @{ $pkt->{args} || [] })
105 for @$cb;
106 }
107 }
108
109 ()
110 };
111
112 cf::register_exticmd w_r => sub {
113 my ($ns, $pkt) = @_;
114
115 if (my $cb = delete $ns->{widget_return}{$pkt->{rid}}) {
116 $cb->(@{$pkt->{res} || [] });
117 }
118
119 ()
120 };
121
122 sub cf::client::new_widgetset {
123 my ($self) = @_;
124
125 my $id = ++$self->{id};
126
127 my $ws = bless {
128 id => $id,
129 ns => $self,
130 _w => {},
131 }, "ext::widget::set";
132
133 $ws->msg (ws_n => id => $id);
134
135 $ws
136 }
137
138 #############################################################################
139
140 package ext::widget::set;
141
142 sub DESTROY {
143 $_[0]->destroy;
144 }
145
146 sub destroy {
147 my ($self) = @_;
148
149 $self->msg (ws_d => id => $self->{id});
150 delete $self->{ns};
151 $_->destroy
152 for values %{ $self->{w} };
153 }
154
155 sub msg {
156 my ($self, $type, %msg) = @_;
157
158 if (my $ns = shift->{ns}) {
159 $msg{msgtype} = $type;
160 $ns->send_packet ("ext " . $ns->{json_coder}->encode (\%msg));
161 }
162 }
163
164 sub new {
165 my ($self, $class, %args) = @_;
166
167 my $id = ++$self->{ns}{id};
168
169 my $proxy = $self->{_w}{$id} = bless {
170 id => $id,
171 }, "ext::widget::proxy";
172
173 Scalar::Util::weaken ($proxy->{ws} = $self);
174 Scalar::Util::weaken ($proxy->{ns} = $self->{ns});
175 Scalar::Util::weaken ($self->{ns}{widget}{$id} = $proxy);
176
177 for my $ev (grep /^on_/, keys %args) {
178 push @{$proxy->{ev}{$ev}}, $args{$ev};
179 $args{$ev} = 0;
180 }
181
182 $self->msg (ws_c =>
183 ws => $proxy->{id},
184 id => $id,
185 class => $class,
186 args => \%args,
187 );
188
189 $proxy
190 }
191
192 #############################################################################
193
194 package ext::widget::proxy;
195
196 sub DESTROY {
197 my ($self) = @_;
198
199 delete $self->{ns}{widget}{$self->{id}};
200
201 #warn "DES<$self> $self->{ws}\n";#d#
202 if (my $ws = $self->{ws}) {
203 $self->msg (w_c => name => "destroy");
204 delete $ws->{_w}{$self->{id}};
205 }
206 }
207
208 sub msg {
209 my ($self, $type, %msg) = @_;
210
211 if (my $ws = $self->{ws}) {
212 $ws->msg ($type,
213 %msg,
214 id => $self->{id},
215 );
216 }
217 }
218
219 sub msg_cb {
220 my ($self, $cb, $type, %msg) = @_;
221
222 if (my $ws = $self->{ws}) {
223
224 my $rid = ++$ws->{ns}{id};
225
226 $self->msg ($type, %msg, rid => $rid);
227
228 if ($cb) {
229 $ws->{ns}{widget_return}{$rid} = $cb;
230 } else {
231 # synchronous case
232 my $wait = new Coro::Signal;
233 my @res;
234
235 $ws->{ns}{widget_return}{$rid} = sub {
236 @res = @_;
237 $wait->send;
238 };
239 $wait->wait;
240
241 return @res;
242 }
243 }
244
245 ()
246 }
247
248 sub set {
249 my ($self, @kv) = @_;
250
251 $self->msg (w_s => attr => \@kv);
252 }
253
254 sub get {
255 my ($self, $member, $cb) = @_;
256
257 $self->msg_cb ($cb, w_g => attr => [$member]);
258 }
259
260 sub TO_JSON {
261 { __widget_ref__ => $_[0]{id} }
262 }
263
264 our $AUTOLOAD;
265
266 sub AUTOLOAD {
267 $AUTOLOAD =~ s/^.*://
268 or return;
269
270 my $self = shift;
271
272 $self->msg (w_c => name => $AUTOLOAD, args => \@_);
273
274 ()
275 }
276