ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/widget.ext
Revision: 1.3
Committed: Tue Jun 26 04:50:05 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.2: +12 -8 lines
Log Message:
shstr is utf-8

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