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

# User Rev Content
1 root 1.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 root 1.10 # w_s id @attr # widget member set
9     # w_g id rid @attr # widget member get
10 root 1.1 #
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 root 1.4 Scalar::Util::weaken (my $weakns = $ns);
20    
21 root 1.1 $ns->{id} = "a";
22 root 1.4 $ns->{json_coder}->filter_json_single_key_object (__widget_ref__ => sub {
23     # cannot deserialise ATM
24     undef
25     });
26 root 1.1 },
27     );
28    
29 root 1.2 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 root 1.3 has_close_button => 1,
49     on_delete => sub {
50     $ws->destroy;
51     },
52 root 1.2 );
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 root 1.3 [0, "Str"],
62     [1, "Dex"],
63     [2, "Con"],
64     [3, "Int"],
65     [4, "Wis"],
66     [5, "Pow"],
67     [6, "Cha"],
68 root 1.2 ) {
69 root 1.3 my ($x, $label) = @$_;
70 root 1.2
71 root 1.9 $statstable->add_at ($x, 0, $ws->new (Label =>
72 root 1.2 can_hover => 1, can_events => 1,
73     align => +1, text => $label, tooltip => "#stat_$label",
74     ));
75 root 1.9 $statstable->add_at ($x, 1, $ws->{stat}{$label} = $ws->new (Label =>
76 root 1.2 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 root 1.1 cf::player->attach (
87     on_login => sub {
88     my ($pl) = @_;
89    
90 root 1.8 return unless $cf::CFG{devel};
91 root 1.1
92     my $ns = $pl->ns;
93    
94 root 1.2 return unless $ns->{can_widget};
95 root 1.5 #csc_start $ns;
96 root 1.1 },
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 root 1.4 $ns->send_packet ("ext " . $ns->{json_coder}->encode (\%msg));
161 root 1.1 }
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 root 1.10 $self->msg (w_s => attr => [ [$member, $value] ]);
251 root 1.1 }
252    
253     sub get {
254     my ($self, $member, $cb) = @_;
255    
256 root 1.10 $self->msg_cb ($cb, w_g => attr => [$member]);
257 root 1.1 }
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