ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/AttrEdit.pm
Revision: 1.16
Committed: Wed Mar 15 21:45:54 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.15: +1 -1 lines
Log Message:
fixed cursors

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