ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/widget.ext
Revision: 1.11
Committed: Sat Jul 21 18:01:26 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.10: +0 -30 lines
Log Message:
implement simplistic/slow/safe object merging for objects with perl data, start of a worldmap item

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 => $self->{w}{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 if (my $ws = $self->{ws}) {
202 delete $ws->{w}{$self->{id}};
203 $self->msg (w_c => name => "destroy");
204 }
205 }
206
207 sub msg {
208 my ($self, $type, %msg) = @_;
209
210 if (my $ws = $self->{ws}) {
211 $ws->msg ($type,
212 %msg,
213 id => $self->{id},
214 );
215 }
216 }
217
218 sub msg_cb {
219 my ($self, $cb, $type, %msg) = @_;
220
221 if (my $ws = $self->{ws}) {
222
223 my $rid = ++$ws->{ns}{id};
224
225 $self->msg ($type, %msg, rid => $rid);
226
227 if ($cb) {
228 $ws->{ns}{widget_return}{$rid} = $cb;
229 } else {
230 # synchronous case
231 my $wait = new Coro::Signal;
232 my @res;
233
234 $ws->{ns}{widget_return}{$rid} = sub {
235 @res = @_;
236 $wait->send;
237 };
238 $wait->wait;
239
240 return @res;
241 }
242 }
243
244 ()
245 }
246
247 sub set {
248 my ($self, $member, $value) = @_;
249
250 $self->msg (w_s => attr => [ [$member, $value] ]);
251 }
252
253 sub get {
254 my ($self, $member, $cb) = @_;
255
256 $self->msg_cb ($cb, w_g => attr => [$member]);
257 }
258
259 sub TO_JSON {
260 { __widget_ref__ => $_[0]{id} }
261 }
262
263 our $AUTOLOAD;
264
265 sub AUTOLOAD {
266 $AUTOLOAD =~ s/^.*://
267 or return;
268
269 my $self = shift;
270
271 $self->msg (w_c => name => $AUTOLOAD, args => \@_);
272
273 ()
274 }
275