ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/AttrEdit.pm
Revision: 1.18
Committed: Thu Mar 16 02:19:00 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.17: +29 -35 lines
Log Message:
fixed a bug in the inventory editor

File Contents

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