ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/MapEditor.pm
Revision: 1.43
Committed: Sat Oct 14 15:18:46 2006 UTC (17 years, 8 months ago) by elmex
Branch: MAIN
Changes since 1.42: +30 -3 lines
Log Message:
added meta data loading, adjusted environment variable handling

File Contents

# User Rev Content
1 elmex 1.1 package GCE::MapEditor;
2    
3     =head1 NAME
4    
5     GCE::MapEditor - the map editing widget
6    
7     =cut
8    
9     use Gtk2;
10     use Gtk2::Gdk::Keysyms;
11     use Gtk2::SimpleMenu;
12    
13     use Crossfire;
14 root 1.3 use Crossfire::Map;
15 elmex 1.1 use Crossfire::MapWidget;
16    
17     use GCE::AttrEdit;
18 elmex 1.22 use GCE::Util;
19 elmex 1.1
20 elmex 1.4 use Glib::Object::Subclass
21 elmex 1.6 Gtk2::Window;
22 elmex 1.1
23     use strict;
24    
25 elmex 1.35 sub do_context_menu {
26     my ($self, $map, $event) = @_;
27    
28     my ($x, $y) = $map->coord ($event->x, $event->y);
29    
30     my $menu = Gtk2::Menu->new;
31     foreach my $cm (
32     [
33     Follow => sub {
34 elmex 1.36 $::MAINWIN->{edit_collection}{followexit}->edit ($map, $x, $y, $self)
35 elmex 1.38 },
36 elmex 1.35 ]
37     ) {
38     my $item = Gtk2::MenuItem->new ($cm->[0]);
39     $menu->append ($item);
40     $item->show;
41     $item->signal_connect (activate => $cm->[1]);
42     }
43 elmex 1.38
44     my $inv_item = Gtk2::MenuItem->new ("Add inventory");
45     $inv_item->set_submenu (my $smenu = new Gtk2::Menu);
46     $menu->append ($inv_item);
47    
48     for my $sr (reverse $self->get_stack_refs ($map, $x, $y)) {
49     my $item = Gtk2::MenuItem->new ($sr->longname);
50     $smenu->append ($item);
51     $item->show;
52     $item->signal_connect (activate => sub {
53     $sr->add_inv ($::MAINWIN->get_pick);
54     });
55     }
56    
57     $inv_item->show;
58 elmex 1.35 $menu->popup (undef, undef, undef, undef, $event->button, $event->time);
59     }
60    
61 root 1.9 sub build_menu {
62     my ($self) = @_;
63    
64     my $menu_tree = [
65     _File => {
66     item_type => '<Branch>',
67     children => [
68     "_Save" => {
69 root 1.10 callback => sub { $self->save_map },
70 root 1.9 accelerator => '<ctrl>S'
71     },
72 root 1.10 "Save As" => {
73     callback => sub { $self->save_map_as },
74     },
75 elmex 1.42 "Map _Properties" => {
76 elmex 1.32 callback => sub { $self->open_map_prop },
77     accelerator => "<ctrl>P"
78     },
79 elmex 1.42 "Map _Attachments" => {
80     callback => sub { $self->open_attach_edit },
81     accelerator => "<ctrl>A"
82     },
83 elmex 1.32 "_Map Resize" => {
84     callback => sub { $self->open_resize_map },
85     },
86 root 1.13 "Close" => {
87 elmex 1.31 callback => sub { $self->destroy },
88 root 1.13 },
89 root 1.10 ]
90 root 1.9 },
91     _Edit => {
92     item_type => '<Branch>',
93     children => [
94     "_Undo" => {
95     callback => sub { $self->undo },
96 elmex 1.17 accelerator => "<ctrl>Z"
97 root 1.9 },
98     "_Redo" => {
99     callback => sub { $self->redo },
100 elmex 1.17 accelerator => "<ctrl>Y"
101     },
102 root 1.9 ]
103     },
104 elmex 1.27 _Go => {
105     item_type => '<Branch>',
106     children => [
107     "_Up" => {
108     callback => sub { $self->follow ('u') },
109 elmex 1.33 accelerator => "<ctrl>Up"
110 elmex 1.27 },
111     "_Down" => {
112     callback => sub { $self->follow ('d') },
113 elmex 1.33 accelerator => "<ctrl>Down"
114 elmex 1.27 },
115     "_Right" => {
116     callback => sub { $self->follow ('r') },
117 elmex 1.33 accelerator => "<ctrl>Right"
118 elmex 1.27 },
119     "_Left" => {
120     callback => sub { $self->follow ('l') },
121 elmex 1.33 accelerator => "<ctrl>Left"
122 elmex 1.27 },
123     ]
124     },
125 elmex 1.29 _Help => {
126     item_type => '<Branch>',
127     children => [
128 elmex 1.30 _Manual => {
129 elmex 1.29 callback => sub { $::MAINWIN->show_help_window },
130     accelerator => "<ctrl>H"
131     },
132     ]
133     },
134 root 1.9 ];
135    
136     my $men =
137     Gtk2::SimpleMenu->new (
138     menu_tree => $menu_tree,
139     default_callback => \&default_cb,
140     );
141    
142 elmex 1.23 for (
143     [i => 'pick'],
144     [p => 'place'],
145 elmex 1.24 [e => 'erase'],
146     [s => 'select'],
147     [l => 'eval'],
148 elmex 1.37 [t => 'connect'],
149 elmex 1.24 [f => 'followexit']
150 elmex 1.23 )
151     {
152 elmex 1.24 my $tool = $_->[1];
153 elmex 1.23 $men->{accel_group}->connect ($Gtk2::Gdk::Keysyms{$_->[0]}, [], 'visible',
154 elmex 1.24 sub { $::MAINWIN->set_edit_tool ($tool) });
155 elmex 1.23 }
156    
157 elmex 1.39 $men->{accel_group}->connect ($Gtk2::Gdk::Keysyms{'r'}, ['control-mask'], 'visible',
158     sub { $self->redo });
159    
160 root 1.9 $self->add_accel_group ($men->{accel_group});
161    
162     return $men->{widget};
163     }
164    
165 elmex 1.31 sub set_edit_tool {
166     my ($self, $tool) = @_;
167    
168     $self->{etool} = $tool;
169    
170     if ($self->ea->special_arrow) {
171     $self->{map}{window}->set_cursor (Gtk2::Gdk::Cursor->new ($self->ea->special_arrow));
172 elmex 1.34 } else {
173     # FIXME: Get the original cursor and insert it here
174     $self->{map}{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
175 elmex 1.31 }
176     }
177    
178 elmex 1.19 sub ea {
179     my ($self) = @_;
180 elmex 1.31 $self->{ea_alt} || $self->{etool};
181 elmex 1.19 }
182    
183 elmex 1.1 sub INIT_INSTANCE {
184     my ($self) = @_;
185    
186 elmex 1.6 $self->set_title ('gce - map editor');
187     $self->add (my $vb = Gtk2::VBox->new);
188 elmex 1.1
189 root 1.9 $vb->pack_start (my $menu = $self->build_menu, 0, 1, 0);
190    
191     $vb->pack_start (my $map = $self->{map} = Crossfire::MapWidget->new, 1, 1, 0);
192    
193 elmex 1.31 $map->signal_connect_after (key_press_event => sub {
194 elmex 1.19 my ($map, $event) = @_;
195 root 1.9
196 elmex 1.19 my $kv = $event->keyval;
197 root 1.9
198 elmex 1.31 my $ret = 0;
199    
200 elmex 1.23 my ($x, $y) = $map->coord ($map->get_pointer);
201     for ([Control_L => sub { $self->{ea_alt} = $::MAINWIN->{edit_collection}{erase} }],
202     [Alt_L => sub { $self->{ea_alt} = $::MAINWIN->{edit_collection}{pick} }],
203     [c => sub { $::MAINWIN->{edit_collection}{select}->copy }],
204 elmex 1.28 [v => sub { $::MAINWIN->{edit_collection}{select}->paste ($map, $x, $y) }],
205 elmex 1.24 [n => sub { $::MAINWIN->{edit_collection}{select}->invoke }],
206 elmex 1.23 )
207     {
208 elmex 1.34 my $ed = $_;
209    
210     if ($kv == $Gtk2::Gdk::Keysyms{$ed->[0]}) {
211     my $was_in_draw = defined $self->{draw_mode};
212    
213     $self->stop_drawmode ($map)
214     if $was_in_draw && grep { $ed->[0] eq $_ } qw/Control_L Alt_L/;
215    
216     $ed->[1]->();
217 elmex 1.31 $ret = 1;
218 elmex 1.34
219     $self->start_drawmode ($map)
220     if $was_in_draw && grep { $ed->[0] eq $_ } qw/Control_L Alt_L/;
221 elmex 1.23 }
222 elmex 1.19 }
223 root 1.9
224 elmex 1.19 if ($self->ea->special_arrow) {
225     $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($self->ea->special_arrow));
226 elmex 1.34 } else {
227     # FIXME: Get the original cursor and insert it here
228     $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
229 elmex 1.19 }
230 elmex 1.31
231     $ret
232 elmex 1.19 });
233 elmex 1.31
234     $map->signal_connect_after (key_release_event => sub {
235 elmex 1.19 my ($map, $event) = @_;
236    
237 elmex 1.31 my $ret = 0;
238    
239 elmex 1.19 if ($event->keyval == $Gtk2::Gdk::Keysyms{Control_L}
240     or $event->keyval == $Gtk2::Gdk::Keysyms{Alt_L})
241     {
242 elmex 1.34 my $was_in_draw = defined $self->{draw_mode};
243    
244     $self->stop_drawmode ($map)
245     if $was_in_draw;
246    
247 elmex 1.19 delete $self->{ea_alt};
248 elmex 1.31 $ret = 1;
249 elmex 1.34
250     $self->start_drawmode ($map)
251     if $was_in_draw;
252 elmex 1.19 }
253    
254     if ($self->ea->special_arrow) {
255     $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($self->ea->special_arrow));
256     } else {
257 elmex 1.31 # FIXME: Get the original cursor and insert it here
258 elmex 1.19 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
259     }
260 elmex 1.31
261     $ret
262 elmex 1.19 });
263 elmex 1.31 $map->signal_connect_after (button_press_event => sub {
264 elmex 1.19 my ($map, $event) = @_;
265 elmex 1.1
266 elmex 1.31 if ((not $self->{draw_mode}) and $event->button == 1) {
267 elmex 1.19 my $ea = $self->ea;
268 elmex 1.4
269 elmex 1.34 $self->start_drawmode ($map);
270 root 1.9
271 elmex 1.19 $ea->want_cursor
272     or $map->disable_tooltip;
273 root 1.9
274 elmex 1.19 return 1;
275 elmex 1.35 } elsif ($event->button == 3) {
276     $self->do_context_menu ($map, $event);
277     return 1;
278 elmex 1.19 }
279 elmex 1.31
280 elmex 1.19 0
281 root 1.9 });
282    
283     $map->signal_connect_after (motion_notify_event => sub {
284     my ($map, $event) = @_;
285    
286     $self->{draw_mode}
287     or return;
288    
289 elmex 1.19 my $ea = $self->ea;
290    
291     my ($X, $Y) = @{$self->{draw_mode}}[0,1];
292 root 1.9 my ($x, $y) = $map->coord ($map->get_pointer);
293 elmex 1.4
294 root 1.9 while ($x != $X || $y != $Y) {
295 elmex 1.4
296 root 1.9 $X++ if $X < $x;
297     $X-- if $X > $x;
298     $Y++ if $Y < $y;
299     $Y-- if $Y > $y;
300 elmex 1.4
301 elmex 1.39 unless ($ea->only_on_click) {
302     $ea->edit ($map, $X, $Y, $self)
303     if $X >= 0 and $Y >= 0 and $X < $map->{map}{width} and $Y < $map->{map}{height};
304     }
305 root 1.9 }
306 elmex 1.4
307 elmex 1.19 @{$self->{draw_mode}}[0,1] = ($X, $Y);
308 elmex 1.1
309 root 1.9 1
310     });
311 elmex 1.1
312 elmex 1.31 $map->signal_connect_after (button_release_event => sub {
313 root 1.9 my ($map, $event) = @_;
314 elmex 1.1
315 elmex 1.31 if ($self->{draw_mode} and $event->button == 1) {
316 elmex 1.19 my $ea = $self->ea;
317 elmex 1.1
318 elmex 1.34 $self->stop_drawmode ($map);
319 elmex 1.4
320 root 1.9 $ea->want_cursor
321     or $map->enable_tooltip;
322 elmex 1.1
323 root 1.9 return 1;
324     }
325 elmex 1.1
326 root 1.9 0
327     });
328     }
329 elmex 1.8
330 elmex 1.34 sub start_drawmode {
331     my ($self, $map) = @_;
332    
333     $self->{draw_mode} and return;
334    
335     # XXX: is this okay? my ($x, $y) = $map->coord ($event->x, $event->y);
336     my ($x, $y) = $map->coord ($map->get_pointer);
337    
338     my $ea = $self->ea;
339    
340 elmex 1.36 $ea->begin ($map, $x, $y, $self);
341    
342     $ea->edit ($map, $x, $y, $self)
343 elmex 1.34 if $x >= 0 and $y >= 0 and $x < $map->{map}{width} and $y < $map->{map}{height};
344    
345     $self->{draw_mode} = [$x, $y];
346     }
347    
348     sub stop_drawmode {
349     my ($self, $map) = @_;
350    
351     $self->{draw_mode} or return;
352    
353     my ($x, $y) = $map->coord ($map->get_pointer);
354    
355     my $ea = $self->ea;
356     $ea->end ($map, $x, $y, $self);
357    
358     delete $self->{draw_mode};
359     }
360    
361 elmex 1.16 # FIXME: Fix the automatic update of the attribute editor! and also the stack view!
362 root 1.9 sub undo {
363     my ($self) = @_;
364 elmex 1.8
365 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
366 elmex 1.1
367 root 1.9 $map->{undo_stack_pos}
368     or return;
369 elmex 1.1
370 root 1.9 $map->change_swap ($map->{undo_stack}[--$map->{undo_stack_pos}]);
371     }
372 elmex 1.1
373 elmex 1.38 sub get_stack_refs {
374     my ($self, $map, $x, $y) = @_;
375    
376     my $cstack = $map->get ($x, $y);
377    
378     return [] unless @$cstack;
379    
380     my @refs;
381    
382     for my $arch (@$cstack) {
383     my ($ox, $oy) = ($x, $y);
384     if ($arch->{_virtual}) {
385     $ox = $arch->{virtual_x};
386     $oy = $arch->{virtual_y};
387     $arch = $arch->{_virtual};
388     $cstack = $map->get ($ox, $oy);
389     # XXX: This heavily blows up if $arch isn't on $cstack now.. and it actually really does :(
390     }
391    
392     push @refs,
393     GCE::ArchRef->new (
394     arch => $arch,
395     cb => sub {
396     $map->change_begin ('attredit');
397     $map->change_stack ($ox, $oy, $cstack);
398    
399     if (my $changeset = $map->change_end) {
400     splice @{ $map->{undo_stack} ||= [] },
401     $map->{undo_stack_pos}++, 1e6,
402     $changeset;
403     }
404     }
405     );
406     }
407    
408     return @refs;
409     }
410    
411 root 1.9 sub redo {
412     my ($self) = @_;
413 elmex 1.7
414 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
415 elmex 1.7
416 elmex 1.14 $map->{undo_stack}
417     and $map->{undo_stack_pos} < @{$map->{undo_stack}}
418     or return;
419 elmex 1.1
420 root 1.9 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]);
421 root 1.3 }
422    
423 elmex 1.43 sub load_meta_info {
424     my ($mapfile) = @_;
425     warn"MAPGFE $mapfile.meta <<!?!?\n";
426     if (-e "$mapfile.meta") {
427     warn "META LAODED!\n";
428     open my $metafh, "<", "$mapfile.meta"
429     or warn "Couldn't open meta file $mapfile.meta: $!";
430     my $metadata = do { local $/; <$metafh> };
431     warn "FEOG $metadata\n";
432     return Crossfire::from_json ($metadata);
433     }
434     }
435    
436     sub save_meta_info {
437     my ($mapfile, $metainfo) = @_;
438     open my $metafh, ">", "$mapfile.meta"
439     or warn "Couldn't write meta file $mapfile.meta: $!";
440     warn "META SAVE!\n";
441     print $metafh Crossfire::to_json ($metainfo);
442     }
443    
444 root 1.3 sub open_map {
445 elmex 1.26 my ($self, $path, $key) = @_;
446    
447     $self->{mapkey} = $key;
448 root 1.3
449 elmex 1.43
450 elmex 1.18 if (ref $path) {
451     $self->{map}->set_map ($path);
452 elmex 1.43 delete $self->{meta_info};
453 elmex 1.39 $self->set_title ('<ram>');
454 elmex 1.18
455     } else {
456     $self->{path} = $path;
457     $self->{map}->set_map (my $m = new_from_file Crossfire::Map $path);
458 elmex 1.43 $self->{meta_info} = load_meta_info ($path);
459 elmex 1.39 $self->set_title ("gce - map editor - $self->{path}");
460 elmex 1.18 }
461 root 1.3 }
462    
463 root 1.13 sub save_map {
464     my ($self) = @_;
465    
466 elmex 1.19 if ($self->{path}) {
467     $self->{map}{map}->write_file ($self->{path});
468 elmex 1.43 if ($self->{meta_info}) {
469     save_meta_info ($self->{path}, $self->{meta_info});
470     }
471 elmex 1.22 quick_msg ($self, "saved to $self->{path}");
472 elmex 1.39 $self->set_title ("gce - map editor - $self->{path}");
473 elmex 1.22 } else {
474     $self->save_map_as;
475 elmex 1.19 }
476 root 1.13 }
477    
478     sub save_map_as {
479     my ($self) = @_;
480 elmex 1.19
481 elmex 1.22 my $fc = $::MAINWIN->new_filechooser ('gce - save map', 1, $self->{path});
482 elmex 1.19
483     if ('ok' eq $fc->run) {
484    
485     $::MAINWIN->{fc_last_folder} = $fc->get_current_folder;
486     $::MAINWIN->{fc_last_folders}->{$self->{fc_last_folder}}++;
487    
488     $self->{map}{map}->write_file ($self->{path} = $fc->get_filename);
489 elmex 1.43 if ($self->{meta_info}) {
490     save_meta_info ($self->{path}, $self->{meta_info});
491     }
492 elmex 1.22 quick_msg ($self, "saved to $self->{path}");
493 elmex 1.39 $self->set_title ("gce - map editor - $self->{path}");
494 elmex 1.19 }
495    
496     $fc->destroy;
497 root 1.13 }
498    
499 elmex 1.17 sub _add_prop_entry {
500     my ($self, $table, $idx, $key, $desc, $type, $changecb) = @_;
501    
502     my $edwid;
503    
504     if ($type eq 'string') {
505     $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
506     $edwid = Gtk2::Entry->new;
507     $edwid->set_text ($self->{map}{map}{info}{$key});
508     $edwid->signal_connect (changed => sub {
509     $self->{map}{map}{info}{$key} = $_[0]->get_text;
510     if ($changecb) {
511     $changecb->($_[0]->get_text);
512     }
513     });
514     $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
515    
516     } elsif ($type eq 'button') {
517     $table->attach_defaults (my $b = Gtk2::Button->new_with_label ($desc), 0, 2, $idx, $idx + 1);
518     $b->signal_connect (clicked => ($changecb || sub {}));
519    
520     } elsif ($type eq 'label') {
521     $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
522     $edwid = Gtk2::Label->new ($self->{map}{map}{info}{$key});
523     $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
524    
525 elmex 1.27 } elsif ($type eq 'check') {
526     $table->attach_defaults (my $lbl1 = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
527     $table->attach_defaults (my $lbl = Gtk2::CheckButton->new, 1, 2, $idx, $idx + 1);
528     $lbl->set_active ($self->{map}{map}{info}{$key});
529     $lbl->signal_connect (toggled => sub {
530     my ($lbl) = @_;
531     $self->{map}{map}{info}{$key} = $lbl->get_active * 1;
532     ($changecb || sub {})->($lbl->get_active);
533     });
534    
535     } elsif ($type eq 'sep') {
536     $table->attach_defaults (my $lbl1 = Gtk2::HSeparator->new, 0, 2, $idx, $idx + 1);
537 elmex 1.17 } else {
538     $edwid = Gtk2::Label->new ("FOO");
539     }
540     }
541    
542     sub open_resize_map {
543     my ($self) = @_;
544    
545     my $w = Gtk2::Window->new ('toplevel');
546     $w->set_default_size (250, 150);
547     $w->add (my $sw = Gtk2::ScrolledWindow->new);
548     $sw->add_with_viewport (my $v = Gtk2::VBox->new);
549     $sw->set_policy ('automatic', 'automatic');
550     $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0);
551    
552     my $i = 0;
553     for (
554     [qw/width Width string/],
555     [qw/height Height string/],
556     [qw/save Save button/,
557     sub {
558     $self->{map}{map}->resize ($self->{map}{map}{info}{width}, $self->{map}{map}{info}{height});
559 elmex 1.19 $self->{map}->invalidate_all;
560     $w->destroy;
561 elmex 1.17 }
562     ],
563     )
564     {
565     $self->_add_prop_entry ($t, $i++, @$_);
566     }
567    
568     $w->show_all;
569     }
570    
571 elmex 1.27 sub follow {
572     my ($self, $dir) = @_;
573    
574     my %dir_to_path = (
575     u => 'tile_path_1',
576     d => 'tile_path_3',
577     r => 'tile_path_2',
578     l => 'tile_path_4',
579     );
580    
581     defined $dir_to_path{$dir}
582     or return;
583     my $map = $self->{map}{map}{info}{$dir_to_path{$dir}}
584     or return;
585    
586     $map = map2abs ($map, $self);
587     $::MAINWIN->open_map_editor ($map);
588     }
589    
590 elmex 1.42 sub open_attach_edit {
591     my ($self) = @_;
592    
593     my $w = GCE::AttachEditor->new;
594     $w->set_attachment (
595     $self->{map}{map}{info}{attach},
596     sub {
597     if (@{$_[0]}) {
598     $self->{map}{map}{info}{attach} = $_[0]
599     } else {
600     delete $self->{map}{map}{info}{attach};
601     }
602     }
603     );
604     $self->{attach_editor} = $w;
605     $w->signal_connect (destroy => sub { delete $self->{attach_editor} });
606     $w->show_all;
607     }
608    
609     sub close_windows {
610     my ($self) = @_;
611    
612     $self->{attach_editor}->destroy
613     if $self->{attach_editor};
614     $self->{map_properties}->destroy
615     if $self->{map_properties};
616     }
617    
618 elmex 1.17 sub open_map_prop {
619     my ($self) = @_;
620    
621 elmex 1.42 return if $self->{map_properties};
622    
623     my $w = $self->{map_properties} = Gtk2::Window->new ('toplevel');
624     $w->signal_connect (destroy => sub { delete $self->{map_properties} });
625 elmex 1.17
626     $w->set_default_size (500, 500);
627     $w->add (my $sw = Gtk2::ScrolledWindow->new);
628     $sw->add_with_viewport (my $v = Gtk2::VBox->new);
629     $sw->set_policy ('automatic', 'automatic');
630     $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0);
631    
632     my $i = 0;
633     for (
634 elmex 1.27 [qw/name Name string/],
635     [qw/region Region string/],
636     [qw/enter_x Enter-x string/],
637     [qw/enter_y Enter-y string/],
638     [qw/reset_timeout Reset-timeout string/],
639     [qw/swap_time Swap-timeout string/],
640     [qw/x x sep/],
641     [qw/difficulty Difficulty string/],
642     [qw/windspeed Windspeed string/],
643     [qw/pressure Pressure string/],
644     [qw/humid Humid string/],
645     [qw/temp Temp string/],
646     [qw/darkness Darkness string/],
647     [qw/sky Sky string/],
648     [qw/winddir Winddir string/],
649     [qw/x x sep/],
650     [qw/width Width label/], # sub { $self->{map}{map}->resize ($_[0], $self->{map}{map}{height}) }],
651     [qw/height Height label/], # sub { $self->{map}{map}->resize ($self->{map}{map}{width}, $_[0]) }],
652     [qw/x x sep/],
653     [qw/msg Text text/],
654     [qw/maplore Maplore text/],
655     [qw/outdoor Outdoor check/],
656     [qw/unique Unique check/],
657     [qw/fixed_resettime Fixed-resettime check/],
658     [qw/x x sep/],
659     [qw/tile_path_1 Northpath string/],
660     [qw/tile_path_2 Eastpath string/],
661     [qw/tile_path_3 Southpath string/],
662     [qw/tile_path_4 Westpath string/],
663     [qw/tile_path_5 Toppath string/],
664     [qw/tile_path_6 Bottompath string/],
665 elmex 1.39 [qw/x x sep/],
666     ['x', 'For shop description look in the manual', 'button', sub { $::MAINWIN->show_help_window }],
667     [qw/shopmin Shopmin string/],
668     [qw/shopmax Shopmax string/],
669     [qw/shoprace Shoprace string/],
670     [qw/shopgreed Shopgreed string/],
671     [qw/shopitems Shopitems string/],
672 elmex 1.17 )
673     {
674     $self->_add_prop_entry ($t, $i++, @$_);
675     }
676    
677     $w->show_all;
678     }
679    
680 elmex 1.1 =head1 AUTHOR
681    
682     Marc Lehmann <schmorp@schmorp.de>
683     http://home.schmorp.de/
684    
685     Robin Redeker <elmex@ta-sa.org>
686     http://www.ta-sa.org/
687    
688     =cut
689     1;
690