ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/deliantra/gde/GCE/MainWindow.pm
Revision: 1.28
Committed: Fri Mar 10 20:32:47 2006 UTC (20 years, 6 months ago) by elmex
Branch: MAIN
Changes since 1.27: +62 -11 lines
Log Message:
implemented edit tools widgets and improved the placement tool

File Contents

# User Rev Content
1 elmex 1.1 package GCE::MainWindow;
2    
3     =head1 NAME
4    
5     GCE::MainWindow - the main window class for gce
6    
7     =cut
8    
9     use Gtk2;
10     use Gtk2::Gdk::Keysyms;
11 elmex 1.2 use Gtk2::SimpleMenu;
12 root 1.7
13     use Crossfire;
14     use Crossfire::MapWidget;
15    
16 elmex 1.2 use GCE::AttrEdit;
17 elmex 1.13 use GCE::MapEditor;
18 elmex 1.15 use GCE::StackView;
19 elmex 1.17 use GCE::EditAction;
20     use GCE::PickWindow;
21 elmex 1.2
22 elmex 1.14 use GCE::AttrTypemap;
23    
24 elmex 1.2 use Glib::Object::Subclass
25 elmex 1.13 Gtk2::Window;
26 elmex 1.2
27 elmex 1.28 use GCE::Util;
28    
29 elmex 1.2 use strict;
30    
31 elmex 1.18 # XXX: make a recursive call from save_layout to all (interesting) sub-widgets
32 elmex 1.17 sub save_layout {
33     my ($self) = @_;
34    
35     $main::CFG->{attr_edit_on} = exists $self->{attr_edit} ? 1 : 0;
36     $main::CFG->{stack_view_on} = exists $self->{sv} ? 1 : 0;
37     $main::CFG->{picker_on} = exists $self->{last_pick_window} ? 1 : 0;
38     $main::CFG->{main_window} = main::get_pos_and_size ($self);
39     $main::CFG->{map_window} = main::get_pos_and_size ($self->{last_map_window}) if $self->{last_map_window};
40     $main::CFG->{stack_view} = main::get_pos_and_size ($self->{sv_win}) if $self->{sv_win};
41     $main::CFG->{attr_view} = main::get_pos_and_size ($self->{attr_edit_win}) if $self->{attr_edit_win};
42    
43     $main::CFG->{open_pickers} = [];
44    
45     for (@{$self->{open_pick_windows}}) {
46    
47     next unless defined $_;
48    
49     push @{$main::CFG->{open_pickers}}, {
50     p_and_s => main::get_pos_and_size ($_),
51     selection => $_->{last_selection}
52     };
53     }
54    
55 root 1.26 main::write_cfg ("$Crossfire::VARDIR/gceconfig");
56 elmex 1.17 }
57    
58     sub load_layout {
59     my ($self) = @_;
60    
61     $main::CFG->{attr_edit_on}
62     and $self->show_attr_editor;
63    
64     $main::CFG->{stack_view_on}
65     and $self->show_stack_view;
66    
67     for (@{$main::CFG->{open_pickers}}) {
68     $self->open_pick_window ($_);
69     }
70     }
71    
72     sub open_map_editor {
73     my ($self, $mapfile) = @_;
74    
75     # XXX: last_map_window is a dirty trick to get the position and size
76     # for save layout
77    
78     my $w = $self->{last_map_window} = GCE::MapEditor->new;
79 root 1.25
80 elmex 1.17 $w->open_map ($mapfile);
81    
82 root 1.25 ::set_pos_and_size ($w, $main::CFG->{map_window});
83 elmex 1.17
84     $w->show_all;
85     # my $w = $self->{last_map_window} = Gtk2::Window->new ('toplevel');
86     # $w->set_title ('gce - map editor');
87     # $w->add (my $mapedit = $self->{mapedit} = new GCE::MapEditor);
88     # $mapedit->open_map ($mapfile);
89     #
90     #
91     # $w->show_all;
92     }
93    
94     sub show_stack_view {
95 elmex 1.15 my ($self) = @_;
96    
97     return if defined $self->{sv};
98    
99 elmex 1.17 my $w = $self->{sv_win} = Gtk2::Window->new ('toplevel');
100 elmex 1.15 $w->set_title ('gce - stack view');
101 root 1.23 $w->signal_connect (delete_event => sub { delete $self->{sv}; 0 });
102 elmex 1.15 $w->add ($self->{sv} = GCE::StackView->new);
103 elmex 1.17
104     main::set_pos_and_size ($w, $main::CFG->{stack_view});
105    
106 elmex 1.15 $w->show_all;
107     }
108    
109     sub show_attr_editor {
110     my ($self) = @_;
111    
112 elmex 1.17 return if $self->{attr_edit};
113    
114 elmex 1.15 my $w = $self->{attr_edit_win} = Gtk2::Window->new;
115     $w->set_title ("gce - edit attrs");
116     $w->add ($self->{attr_edit} = GCE::AttrEdit->new);
117 root 1.23 $w->signal_connect (delete_event => sub { delete $self->{attr_edit}; 0 });
118 elmex 1.17
119     main::set_pos_and_size ($w, $main::CFG->{attr_view});
120    
121 elmex 1.15 $w->show_all;
122     }
123    
124     sub update_attr_editor {
125 elmex 1.17 my ($self, $arch, $cb) = @_;
126 elmex 1.15
127     return unless $self->{attr_edit};
128    
129 elmex 1.17 $self->{attr_edit}->set_arch ($arch, $cb);
130 elmex 1.15 $self->{attr_edit_win}->set_title ("gce - edit $arch->{_name}");
131     }
132    
133     sub update_stack_view {
134 elmex 1.17 my ($self, $mapedit, $x, $y) = @_;
135 elmex 1.15
136     return unless $self->{sv};
137    
138 elmex 1.17 $self->{sv}->set_stack ($mapedit, $x, $y);
139 elmex 1.15 }
140    
141 elmex 1.17 sub open_pick_window {
142     my ($self, $layout) = @_;
143    
144     # XXX: Yes, also fix this, save _every_ pick window and their posistions and their
145     # selection
146     my $p = GCE::PickWindow->new ();
147 elmex 1.15
148 elmex 1.17 push @{$self->{open_pick_windows}}, $p;
149    
150     my $idx = (@{$self->{open_pick_windows}}) - 1;
151 elmex 1.15
152 elmex 1.17 $p->signal_connect ('delete-event' => sub {
153     $self->{open_pick_windows}->[$idx] = undef;
154     });
155 elmex 1.10
156 elmex 1.17 if ($layout) {
157     main::set_pos_and_size ($p, $layout->{p_and_s});
158     }
159 elmex 1.10
160 elmex 1.17 $p->show_all;
161 elmex 1.10
162 elmex 1.17 $p->set_selection ($layout->{selection});
163 elmex 1.10 }
164    
165 elmex 1.13 sub build_menu {
166 elmex 1.1 my ($self) = @_;
167    
168 elmex 1.2 my $menu_tree = [
169     _File => {
170     item_type => '<Branch>',
171     children => [
172     _New => {
173     callback => sub { $self->new_cb },
174     accelerator => '<ctrl>N'
175     },
176     _Open => {
177     callback => sub { $self->open_cb },
178     accelerator => '<ctrl>O'
179     },
180 elmex 1.17 "_Save Layout" => {
181     callback => sub { $self->save_layout },
182     accelerator => '<ctrl>L'
183     },
184 elmex 1.2 _Quit => {
185     callback => sub { Gtk2->main_quit },
186     accelerator => '<ctrl>Q'
187     }
188     ]
189     },
190 root 1.24 _Dialogs => {
191 elmex 1.2 item_type => '<Branch>',
192     children => [
193 elmex 1.17 "_Attr Editor" => {
194     callback => sub { $self->show_attr_editor },
195     accelerator => "<ctrl>A"
196 elmex 1.2 },
197 elmex 1.17 "_Picker" => {
198     callback => sub { $self->open_pick_window },
199     accelerator => "<ctrl>P"
200     },
201     "_Stack View" => {
202     callback => sub { $self->show_stack_view },
203     accelerator => "<ctrl>V"
204     },
205 elmex 1.15 "Open _Attr Editor" => {
206     callback => sub { $self->show_attr_editor },
207     accelerator => "<ctrl>A"
208     },
209 elmex 1.9 "Open _Picker" => {
210 elmex 1.13 callback => sub { $self->open_pick_window },
211     accelerator => "<ctrl>P"
212 elmex 1.9 },
213 elmex 1.15 "Open _Stack View" => {
214 elmex 1.17 callback => sub { $self->show_stack_view },
215 elmex 1.15 accelerator => "<ctrl>V"
216     },
217    
218 elmex 1.2 ]
219 elmex 1.9 }
220 elmex 1.17
221 elmex 1.2 ];
222    
223 elmex 1.13 my $men =
224     Gtk2::SimpleMenu->new (
225     menu_tree => $menu_tree,
226     default_callback => \&default_cb,
227     );
228 elmex 1.10
229 elmex 1.2 $self->add_accel_group ($men->{accel_group});
230    
231 elmex 1.13 return $men->{widget};
232     }
233 elmex 1.10
234 elmex 1.17 sub add_button {
235     my ($self, $table, $plcinfo, $lbl, $cb) = @_;
236    
237     my ($lx, $ly) = @{$plcinfo->{next}};
238    
239     unless ($lx < $plcinfo->{width}) {
240    
241     $ly++;
242     $lx = 0;
243     }
244    
245     $ly < $plcinfo->{height}
246     or die "too many buttons, make table bigger!";
247    
248     $table->attach_defaults (my $btn = Gtk2::Button->new_with_label ($lbl), $lx, $lx + 1, $ly, $ly + 1);
249     $btn->signal_connect (clicked => $cb);
250    
251     $plcinfo->{next} = [$lx + 1, $ly];
252     }
253    
254     sub build_buttons {
255     my ($self) = @_;
256    
257     my $tbl = Gtk2::Table->new (2, 2);
258     my $plcinfo = { width => 1, height => 3, next => [0, 0] };
259    
260 elmex 1.28 $self->{edit_collection}{pick} = GCE::EditAction::Pick->new;
261 elmex 1.17 $self->{edit_collection}{place} = GCE::EditAction::Place->new;
262     $self->{edit_collection}{erase} = GCE::EditAction::Erase->new;
263    
264 elmex 1.28 $self->update_edit_tool ($self->{edit_collection}{pick}, "Pick");
265    
266 elmex 1.17 $self->add_button ($tbl, $plcinfo, "Pick", sub {
267 elmex 1.28 $self->update_edit_tool ($self->{edit_collection}{pick}, "Pick");;
268 elmex 1.17 });
269     $self->add_button ($tbl, $plcinfo, "Place", sub {
270 elmex 1.28 $self->update_edit_tool ($self->{edit_collection}{place}, "Place");;
271 elmex 1.17 });
272     $self->add_button ($tbl, $plcinfo, "Erase", sub {
273 elmex 1.28 $self->update_edit_tool ($self->{edit_collection}{erase}, "Erase");;
274 elmex 1.17 });
275    
276     return $tbl;
277     }
278 elmex 1.10
279 elmex 1.28 sub update_edit_tool {
280     my ($self, $tool, $name) = @_;
281    
282     $self->{edit_tool}->set_text ($name);
283     $self->{sel_editaction} = $tool;
284    
285     my $widget = $tool->tool_widget;
286    
287     for ($self->{edit_tool_cont}->get_children) {
288     $_->hide;
289     $self->{edit_tool_cont}->remove ($_);
290     }
291    
292     defined $widget or return;
293    
294     $self->{edit_tool_cont}->add ($widget);
295     $widget->show_all;
296     }
297    
298     sub update_pick_view {
299     my ($self, $arch) = @_;
300    
301     defined $arch->{_face}
302     or $arch = $Crossfire::ARCH{$arch->{_name}};
303    
304     $arch->{_face}
305     or warn "Arch $arch->{_name} has no face!";
306     $arch->{_face}
307     or return;
308    
309     fill_pb_from_arch ($self->{pick_view_pb}, $arch);
310     $self->{pick_view_img}->set_from_pixbuf ($self->{pick_view_pb});
311    
312     $self->{pick_view_lbl}->set_text ($arch->{_name});
313     }
314    
315 root 1.11
316 elmex 1.13 sub INIT_INSTANCE {
317     my ($self) = @_;
318 elmex 1.10
319 root 1.24 $::MAINWIN = $self;
320 elmex 1.15
321 elmex 1.13 $self->set_title ("gce - main window");
322 elmex 1.10
323 elmex 1.28 $self->{edit_tool} = Gtk2::Label->new;
324     $self->{edit_tool_cont} = Gtk2::VBox->new;
325    
326 elmex 1.13 $self->add (my $vb = Gtk2::VBox->new);
327     $vb->pack_start ($self->build_menu, 0, 1, 0);
328 elmex 1.28
329     $vb->pack_start (my $hb = $self->{pick_view_hb} = Gtk2::HBox->new, 0, 1, 0);
330     $hb->pack_start ($self->{pick_view_img} = Gtk2::Image->new, 0, 1, 0);
331     $hb->pack_start ($self->{pick_view_lbl} = Gtk2::Label->new, 0, 1, 0);
332     $self->{pick_view_pb} = new_arch_pb ();
333    
334     $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
335     $vb->pack_start (my $tbl = $self->build_buttons, 0, 1, 0);
336    
337     $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
338     $vb->pack_start ($self->{edit_tool}, 0, 1, 0);
339    
340     $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
341     $vb->pack_start ($self->{edit_tool_cont}, 0, 1, 0);
342 elmex 1.10
343 elmex 1.13 # XXX:load $ARGV _cleanly_?
344 root 1.27 $self->open_map_editor ($_)
345     for @ARGV;
346 root 1.11
347 elmex 1.13 $self->signal_connect ('delete-event' => sub {
348     Gtk2->main_quit;
349 elmex 1.10 });
350 elmex 1.17
351 root 1.24 ::set_pos_and_size ($self, $main::CFG->{main_window});
352 elmex 1.2 }
353    
354     sub new_cb {
355     my ($self) = @_;
356 root 1.25 warn "new map not yet implemented\n";
357 elmex 1.2 }
358    
359 root 1.25 sub new_filechooser {
360 elmex 1.2 my ($self) = @_;
361    
362 root 1.25 my $fc = new Gtk2::FileChooserDialog (
363 elmex 1.13 'gce - open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok'
364     );
365    
366 root 1.27 $fc->add_shortcut_folder ("$Crossfire::LIB/maps") if -d "$Crossfire::LIB/maps";
367 elmex 1.13 $fc->add_shortcut_folder ($_) for keys %{$self->{fc_last_folders}};
368 elmex 1.10 $fc->set_current_folder ($self->{fc_last_folder} || "$Crossfire::LIB/maps");
369 elmex 1.2
370 root 1.25 $fc
371     }
372    
373     sub open_cb {
374     my ($self) = @_;
375    
376     my $fc = $self->new_filechooser;
377    
378 elmex 1.2 if ('ok' eq $fc->run) {
379 elmex 1.13
380 elmex 1.10 $self->{fc_last_folder} = $fc->get_current_folder;
381 elmex 1.13 $self->{fc_last_folders}->{$self->{fc_last_folder}}++;
382 elmex 1.17
383     $self->open_map_editor ($fc->get_filename);
384 elmex 1.2 }
385    
386     $fc->destroy;
387     }
388    
389 elmex 1.17 sub set_pick {
390     my ($self, $arch) = @_;
391    
392     $self->{pick_arch} = $arch;
393 elmex 1.28 $self->update_pick_view ($arch);
394 elmex 1.17 }
395    
396     sub get_pick {
397     my ($self) = @_;
398    
399     # XXX: This is just to make sure that this function always returns something
400     return $self->{pick_arch} || { _name => 'platinacoin' };
401     }
402    
403 elmex 1.1 =head1 AUTHOR
404    
405     Marc Lehmann <schmorp@schmorp.de>
406     http://home.schmorp.de/
407    
408     Robin Redeker <elmex@ta-sa.org>
409     http://www.ta-sa.org/
410    
411     =cut
412     1;
413