ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/AttrEdit.pm
Revision: 1.21
Committed: Thu Mar 16 22:19:35 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.20: +3 -2 lines
Log Message:
implemented type display in attreditor

File Contents

# Content
1 package GCE::AttrEdit;
2
3 =head1 NAME
4
5 GCE::AttrEdit - an edit wiget for attributes
6
7 =cut
8
9 use Gtk2;
10 use Gtk2::Gdk::Keysyms;
11 use Gtk2::SimpleList;
12
13 use GCE::Util;
14 use GCE::InventoryEditor;
15
16 use Glib::Object::Subclass Gtk2::VBox;
17
18 use Crossfire;
19
20 sub INIT_INSTANCE {
21 my ($self) = @_;
22
23 $self->pack_start (my $lbl = $self->{arch_name_lbl} = Gtk2::Label->new, 0, 1, 0);
24 $self->pack_start (my $ntbook = $self->{ntbook} = Gtk2::Notebook->new, 1, 1, 0);
25 }
26
27 sub update_arch {
28 my ($self, $arch, $key, $value) = @_;
29
30 if ($value ne '') {
31
32 my $al_arch = $Crossfire::ARCH{$arch->{_name}};
33 if (ref $value) {
34 $arch->{$key} = $value;
35
36 } else {
37 if (not defined $al_arch->{$key}) {
38 if (not defined $value) {
39 # try to normalize
40 delete $arch->{$key};
41 } else {
42 # try to normalize
43 $arch->{$key} = $value;
44 }
45 } else {
46 if ($al_arch->{$key} ne $value) {
47 $arch->{$key} = $value;
48 } else {
49 # try to normalize
50 delete $arch->{$key};
51 }
52 }
53 }
54
55 } else {
56
57 delete $arch->{$key};
58 }
59
60 $self->{change_cb}->($arch)
61 if defined $self->{change_cb};
62 }
63
64 sub set_attr {
65 my ($self, $key, $value) = @_;
66
67 my $attr = $self->{arch}->{$key};
68
69 unless (ref $attr) {
70
71 $self->update_arch ($self->{arch}, $key, $value);
72 }
73 }
74
75 sub set_arch {
76 my ($self, $arch, $change_cb) = @_;
77
78 $self->{change_cb} = $change_cb;
79
80 $self->{arch} = $arch;
81
82 my $ar = Crossfire::arch_attr $arch;
83
84 $self->{arch_name_lbl}->set_text (
85 $arch->{_name} . ($arch->{name} ? " - $arch->{name}" : "") . " ($ar->{name})"
86 );
87
88 my $al_arch = $Crossfire::ARCH{$arch->{_name}};
89 $self->hide;
90 $self->{ntbook}->remove ($_)
91 for $self->{ntbook}->get_children;
92
93 # warn "FO1:" . Data::Dumper::Dumper ($al_arch) . ">\n";
94 # warn "FO2:" . Data::Dumper::Dumper ($ar) . ">\n";
95 # warn "REAL: " . Data::Dumper::Dumper ($arch) . "\n";
96
97 $self->{ttip} = Gtk2::Tooltips->new;
98
99 #$self->add_section_edit_widgets ($self->{ntbook}, 'general', $arch, $ar->{attr});
100
101 for my $sec (@{$ar->{section}}) {
102 my $secname = shift @$sec;
103 $self->add_section_edit_widgets ($self->{ntbook}, $secname, $arch, $sec);#$sects{$sec});
104 }
105
106 for my $key (qw/lore msg/) {
107 $self->{ntbook}->append_page (my $v = Gtk2::VBox->new, $key);
108 $v->pack_start (my $sw = Gtk2::ScrolledWindow->new, 1, 1, 0);
109 $sw->set_policy ('automatic', 'automatic');
110 $sw->add (my $tb = $self->{"${key}_txt"} = Gtk2::TextView->new);
111 my $buf = $tb->get_buffer;
112 $buf->set_text ($arch->{$key});
113 $buf->signal_connect (changed => sub {
114 my ($buf) = @_;
115 $self->update_arch ($arch, $key,
116 $buf->get_text ($buf->get_start_iter, $buf->get_end_iter, 0)
117 );
118 });
119 }
120
121 $self->{ntbook}->append_page (my $inv = GCE::InventoryEditor->new, 'inventory');
122 $inv->set_arch ($arch, $change_cb);
123
124 $self->{ttip}->enable;
125
126 $self->show_all;
127 }
128
129 sub add_section_edit_widgets {
130 my ($self, $ntbook, $name, $arch, $section) = @_;
131
132 $self->{ntbook}->append_page (my $sw = Gtk2::ScrolledWindow->new, $name);
133 $sw->set_policy ('always', 'always');
134 $sw->add_with_viewport (my $vb = Gtk2::VBox->new);
135 $vb->pack_start (my $table = new Gtk2::Table (2, $cnt), 0, 1, 0);
136
137 my $i = 0;
138 for my $sec (@$section) {
139 my $bwid = Gtk2::EventBox->new;
140 my $al = Gtk2::Alignment->new (0.0, 0.5, 0, 1);
141 my $key = $sec->[0];
142 $sec = $sec->[1];
143 $al->add (Gtk2::Label->new (def ($sec->{name}, $key)));
144 $bwid->add ($al);
145 if ($sec->{desc} !~ m/^\s*$/s) {
146 $self->{ttip}->set_tip ($bwid, $sec->{desc});
147 }
148 $table->attach ($bwid, 0, 1, $i, $i + 1, ['shrink','fill'], 'fill', 5, 0);
149
150 $al = Gtk2::Alignment->new (0.0, 0.5, 1, 0);
151 $al->add ($self->get_edit_widget ($key, $sec, $arch, $bwid));
152 $table->attach ($al, 1, 2, $i, $i + 1, ['expand', 'fill'], 'expand', 0, 0);
153 $i++;
154 }
155 }
156
157 sub label_set_color_default {
158 my ($self, $lbl, $arch, $key, $val) = @_;
159 my $al_arch = $Crossfire::ARCH{$arch->{_name}};
160
161 # my $fgcolor = $lbl->get_default_style-> Gtk2::Gdk::Color->parse ("lightblue");
162 # my $fgcolor2 = Gtk2::Gdk::Color->parse ("black");#grey");
163
164 if ( (defined $al_arch->{$key} and $al_arch->{$key} ne $val)
165 or (not (defined $al_arch->{$key}) and defined $val))
166 {
167 for (qw/normal active prelight selected insensitive/) {
168 $lbl->modify_bg ($_, $lbl->get_default_style->bg ('active'));
169 $lbl->modify_fg ($_, $lbl->get_default_style->fg ('active'));
170 }
171 } else {
172 for (qw/normal active prelight selected insensitive/) {
173 $lbl->modify_bg ($_, $lbl->get_default_style->bg ($_));
174 }
175 }
176 }
177
178 # XXX: Warning: Ugly code ahead:
179 sub get_edit_widget {
180 my ($self, $key, $edspec, $arch, $lbl) = @_;
181
182 my $type = $edspec->{type};
183 my $al_arch = $Crossfire::ARCH{$arch->{_name}};
184
185 if ($type eq 'bool') {
186 my $boolval = def ($edspec->{value}, [0, 1]);
187
188 my $chk = new Gtk2::CheckButton (def ($edspec->{name}, $key));
189
190 $self->{ttip}->set_tip ($chk, $al_arch->{$key} * 1);
191
192 $chk->set_active (def ($arch->{$key}, $al_arch->{$key}) == $boolval->[1]);
193 $self->label_set_color_default ($lbl, $arch, $key, def ($arch->{$key}, $al_arch->{$key}));
194 $chk->signal_connect (clicked => sub {
195 my ($chk) = @_;
196 $self->label_set_color_default ($lbl, $arch, $key, $boolval->[$chk->get_active * 1]);
197 $self->update_arch ($arch, $key, $boolval->[$chk->get_active * 1]);
198 });
199 return $chk
200
201 } elsif (grep { $type eq $_ } qw/string int treasurelist float/) {
202 my $entry = new Gtk2::Entry;
203 $self->{ttip}->set_tip ($entry, $al_arch->{$key});
204 $entry->set_text (def ($arch->{$key}, $al_arch->{$key}));
205 $self->label_set_color_default ($lbl, $arch, $key, def ($arch->{$key}, $al_arch->{$key}));
206 $entry->signal_connect (changed => sub {
207 my ($entry) = @_;
208 $self->label_set_color_default ($lbl, $arch, $key, $entry->get_text);
209 $self->update_arch ($arch, $key, $entry->get_text);
210 });
211 return $entry
212
213 } elsif ($type eq 'spell' or $type eq 'nz_spell') { # XXX: nz_spell bug in datafiles?
214 my $comb = Gtk2::ComboBox->new_text;
215 my $spells_idx = {};
216 my $spells_cmb_idx = {};
217 my $sp = \%Crossfire::Data::SPELL;
218
219 $comb->append_text ("<none>");
220
221 my $idx = 1; # XXX: replace this idx with a more save/correct method?
222 for (sort { $sp->{$a} cmp $sp->{$b} } keys %$sp) {
223 $spells_cmd_idx{$idx} = $_;
224 $spells_idx{$_} = $idx++;
225
226 $comb->append_text ($sp->{$_});
227 }
228 #XXX: FIXME: $self->{ttip}->set_tip ($comb, $sp->{$al_arch->{$key}});
229 $comb->set_active ($spells_idx{def ($arch->{$key}, $al_arch->{$key})});
230 $self->label_set_color_default ($lbl, $arch, $key, def ($arch->{$key}, $al_arch->{$key}));
231
232 $comb->signal_connect (changed => sub {
233 my ($comb) = @_;
234 $self->label_set_color_default ($lbl, $arch, $key, $spells_cmd_idx{$comb->get_active});
235 $self->update_arch ($arch, $key, $spells_cmd_idx{$comb->get_active});
236 });
237 return $comb
238
239 } elsif ($type eq 'bitmask') {
240 my $lblb = Gtk2::Label->new ("bitmask: " . (def ($arch->{$key}, $al_arch->{$key})) * 1);
241 my $btn = Gtk2::Button->new;
242 $self->{ttip}->set_tip ($btn, $al_arch->{$key});
243 $btn->add ($lblb);
244 my $chval = def ($arch->{$key}, $al_arch->{$key});
245 my $menu = $self->create_bitmask_menu ($edspec->{value}, $lbl, $lblb, $arch, $key, \$chval);
246
247 $self->label_set_color_default ($lbl, $arch, $key, def ($arch->{$key}, $al_arch->{$key}));
248
249 $btn->signal_connect (button_press_event => sub {
250 my ($btn, $ev) = @_;
251 $menu->popup (undef, undef, undef, undef, $ev->button, 0);
252 });
253 return $btn;
254
255 } elsif ($type eq 'list') {
256 my $lblb = Gtk2::Label->new ($edspec->{value}->{def($arch->{$key}, $al_arch->{$key}) * 1});
257 my $btn = Gtk2::Button->new;
258 $self->{ttip}->set_tip ($btn, $edspec->{value}->{$al_arch->{$key}});
259 $btn->add ($lblb);
260 my $menu = $self->create_list_menu ($edspec->{value}, $lbl, $lblb, $arch, $key);
261
262 $self->label_set_color_default ($lbl, $arch, $key, def ($arch->{$key}, $al_arch->{$key}));
263
264 $btn->signal_connect (button_press_event => sub {
265 my ($btn, $ev) = @_;
266 $menu->popup (undef, undef, undef, undef, $ev->button, 0);
267 });
268 return $btn;
269
270 } elsif ($type eq 'fixed') {
271 return Gtk2::Label->new ("$edspec->{name} = $edspec->{value}");
272
273 } elsif ($type eq 'text') {
274 return Gtk2::Label->new ("<see $key tab>");
275
276 } else {
277 return Gtk2::Label->new ("$key => $edspec->{name} ($type)");
278
279 }
280 }
281
282 sub bitmask_to_list {
283 my ($self, $bitlist, $bits) = @_;
284
285 my @l;
286 for (%$bitlist) {
287 if ($bits & (1 << $_)) {
288 push @l, $bitlist->{$_};
289 }
290 }
291 return @l;
292 }
293
294 sub create_list_menu {
295 my ($self, $list, $clbl, $lbl, $arch, $key) = @_;
296
297 my $menu = Gtk2::Menu->new;
298
299 for my $item (sort keys %$list) {
300 my $lbltxt = $list->{$item};
301 my $menuitem = Gtk2::MenuItem->new_with_label ($lbltxt);
302 $menuitem->signal_connect (activate => sub {
303 my ($menuitem) = @_;
304 $lbl->set_text ($list->{$item});
305 $self->label_set_color_default ($clbl, $arch, $key, $item);
306 $self->update_arch ($arch, $key, $item);
307 });
308 $menu->append ($menuitem);
309 $menuitem->show;
310 }
311
312 return $menu;
313 }
314
315 sub create_bitmask_menu {
316 my ($self, $bits, $clbl, $lbl, $arch, $key, $rval) = @_;
317
318 my $menu = Gtk2::Menu->new;
319
320 for my $bit (keys %$bits) {
321 my $lbltxt = $bits->{$bit};
322 my $menuitem = Gtk2::CheckMenuItem->new_with_label ($lbltxt);
323 if ($$rval & (1 << $bit)) {
324 $menuitem->set_active (1);#$arch->{$key} & (1 << $bit));
325 }
326 $menuitem->signal_connect (toggled => sub {
327 my ($menuitem) = @_;
328 my $newval = $arch->{$key};
329 $$rval &= ~(1 << $bit);
330 $$rval |= (1 << $bit) if $menuitem->get_active;
331 $lbl->set_text ("bitmask: " . ($$rval * 1));
332 $self->label_set_color_default ($clbl, $arch, $key, $$rval);
333 $self->update_arch ($arch, $key, $$rval);
334 });
335 $menu->append ($menuitem);
336 $menuitem->show;
337 }
338
339 return $menu;
340 }
341
342
343 =head1 AUTHOR
344
345 Marc Lehmann <schmorp@schmorp.de>
346 http://home.schmorp.de/
347
348 Robin Redeker <elmex@ta-sa.org>
349 http://www.ta-sa.org/
350
351 =cut
352 1;