ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/AttrEdit.pm
Revision: 1.17
Committed: Wed Mar 15 22:16:43 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.16: +3 -7 lines
Log Message:
fixed bool in attredit initialisation

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