ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/MainWindow.pm
Revision: 1.31
Committed: Sun Mar 12 13:40:34 2006 UTC (18 years, 3 months ago) by elmex
Branch: MAIN
Changes since 1.30: +0 -13 lines
Log Message:
Simple attribute editing now works. Still missing: bitmasks and there
are some refreshbugs in the StackView and AttrEdit. Should be refreshed
when the map detects changes...

File Contents

# Content
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 use Gtk2::SimpleMenu;
12
13 use Crossfire;
14 use Crossfire::MapWidget;
15
16 use GCE::AttrEdit;
17 use GCE::MapEditor;
18 use GCE::StackView;
19 use GCE::EditAction;
20 use GCE::PickWindow;
21
22 use GCE::AttrTypemap;
23
24 use Glib::Object::Subclass
25 Gtk2::Window;
26
27 use GCE::Util;
28
29 use strict;
30
31 # XXX: make a recursive call from save_layout to all (interesting) sub-widgets
32 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 main::write_cfg ("$Crossfire::VARDIR/gceconfig");
56 }
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
80 $w->open_map ($mapfile);
81
82 ::set_pos_and_size ($w, $main::CFG->{map_window}, 500, 500, 200, 0);
83
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 my ($self) = @_;
96
97 return if defined $self->{sv};
98
99 my $w = $self->{sv_win} = Gtk2::Window->new ('toplevel');
100 $w->set_title ('gce - stack view');
101 $w->signal_connect (delete_event => sub { delete $self->{sv}; 0 });
102 $w->add ($self->{sv} = GCE::StackView->new);
103
104 main::set_pos_and_size ($w, $main::CFG->{stack_view}, 150, 250);
105
106 $w->show_all;
107 }
108
109 sub show_attr_editor {
110 my ($self) = @_;
111
112 return if $self->{attr_edit};
113
114 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 $w->signal_connect (delete_event => sub { delete $self->{attr_edit}; 0 });
118
119 main::set_pos_and_size ($w, $main::CFG->{attr_view}, 200, 200);
120
121 $w->show_all;
122 }
123
124 sub update_attr_editor {
125 my ($self, $arch, $cb) = @_;
126
127 return unless $self->{attr_edit};
128
129 $self->{attr_edit}->set_arch ($arch, $cb);
130 $self->{attr_edit_win}->set_title ("gce - edit $arch->{_name}");
131 }
132
133 sub update_stack_view {
134 my ($self, $mapedit, $x, $y) = @_;
135
136 return unless $self->{sv};
137
138 $self->{sv}->set_stack ($mapedit, $x, $y);
139 }
140
141 sub open_pick_window {
142 my ($self, $layout) = @_;
143
144 # XXX: Yes, also fix this, save _every_ pick window and their positions and their
145 # selection
146 my $p = GCE::PickWindow->new ();
147
148 push @{$self->{open_pick_windows}}, $p;
149
150 my $idx = (@{$self->{open_pick_windows}}) - 1;
151
152 $p->signal_connect ('delete-event' => sub {
153 $self->{open_pick_windows}->[$idx] = undef;
154 });
155
156 if ($layout) {
157 main::set_pos_and_size ($p, $layout->{p_and_s}, 200, 200);
158 }
159
160 $p->show_all;
161
162 $p->set_selection ($layout->{selection});
163 }
164
165 sub build_menu {
166 my ($self) = @_;
167
168 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 "_Save Layout" => {
181 callback => sub { $self->save_layout },
182 accelerator => '<ctrl>L'
183 },
184 _Quit => {
185 callback => sub { Gtk2->main_quit },
186 accelerator => '<ctrl>Q'
187 }
188 ]
189 },
190 _Dialogs => {
191 item_type => '<Branch>',
192 children => [
193 "_Attr Editor" => {
194 callback => sub { $self->show_attr_editor },
195 accelerator => "<ctrl>A"
196 },
197 "_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 ]
206 }
207
208 ];
209
210 my $men =
211 Gtk2::SimpleMenu->new (
212 menu_tree => $menu_tree,
213 default_callback => \&default_cb,
214 );
215
216 $self->add_accel_group ($men->{accel_group});
217
218 return $men->{widget};
219 }
220
221 sub add_button {
222 my ($self, $table, $plcinfo, $lbl, $cb) = @_;
223
224 my ($lx, $ly) = @{$plcinfo->{next}};
225
226 unless ($lx < $plcinfo->{width}) {
227
228 $ly++;
229 $lx = 0;
230 }
231
232 $ly < $plcinfo->{height}
233 or die "too many buttons, make table bigger!";
234
235 $table->attach_defaults (my $btn = Gtk2::Button->new_with_label ($lbl), $lx, $lx + 1, $ly, $ly + 1);
236 $btn->signal_connect (clicked => $cb);
237
238 $plcinfo->{next} = [$lx + 1, $ly];
239 }
240
241 sub build_buttons {
242 my ($self) = @_;
243
244 my $tbl = Gtk2::Table->new (2, 2);
245 my $plcinfo = { width => 1, height => 3, next => [0, 0] };
246
247 $self->{edit_collection}{pick} = GCE::EditAction::Pick->new;
248 $self->{edit_collection}{place} = GCE::EditAction::Place->new;
249 $self->{edit_collection}{erase} = GCE::EditAction::Erase->new;
250
251 $self->update_edit_tool ($self->{edit_collection}{pick}, "Pick");
252
253 $self->add_button ($tbl, $plcinfo, "Pick", sub {
254 $self->update_edit_tool ($self->{edit_collection}{pick}, "Pick");;
255 });
256 $self->add_button ($tbl, $plcinfo, "Place", sub {
257 $self->update_edit_tool ($self->{edit_collection}{place}, "Place");;
258 });
259 $self->add_button ($tbl, $plcinfo, "Erase", sub {
260 $self->update_edit_tool ($self->{edit_collection}{erase}, "Erase");;
261 });
262
263 return $tbl;
264 }
265
266 sub update_edit_tool {
267 my ($self, $tool, $name) = @_;
268
269 $self->{edit_tool}->set_text ($name);
270 $self->{sel_editaction} = $tool;
271
272 my $widget = $tool->tool_widget;
273
274 for ($self->{edit_tool_cont}->get_children) {
275 $_->hide;
276 $self->{edit_tool_cont}->remove ($_);
277 }
278
279 defined $widget or return;
280
281 $self->{edit_tool_cont}->add ($widget);
282 $widget->show_all;
283 }
284
285 sub update_pick_view {
286 my ($self, $arch) = @_;
287
288 defined $arch->{_face}
289 or $arch = $Crossfire::ARCH{$arch->{_name}};
290
291 $arch->{_face}
292 or warn "Arch $arch->{_name} has no face!";
293 $arch->{_face}
294 or return;
295
296 fill_pb_from_arch ($self->{pick_view_pb}, $arch);
297 $self->{pick_view_img}->set_from_pixbuf ($self->{pick_view_pb});
298
299 $self->{pick_view_lbl}->set_text ($arch->{_name});
300 }
301
302 sub INIT_INSTANCE {
303 my ($self) = @_;
304
305 $::MAINWIN = $self;
306
307 $self->set_title ("gce - main window");
308
309 $self->{edit_tool} = Gtk2::Label->new;
310 $self->{edit_tool_cont} = Gtk2::VBox->new;
311
312 $self->add (my $vb = Gtk2::VBox->new);
313 $vb->pack_start ($self->build_menu, 0, 1, 0);
314
315 $vb->pack_start (my $hb = $self->{pick_view_hb} = Gtk2::HBox->new, 0, 1, 0);
316 $hb->pack_start ($self->{pick_view_img} = Gtk2::Image->new, 0, 1, 0);
317 $hb->pack_start ($self->{pick_view_lbl} = Gtk2::Label->new, 0, 1, 0);
318 $self->{pick_view_pb} = new_arch_pb ();
319
320 $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
321 $vb->pack_start (my $tbl = $self->build_buttons, 0, 1, 0);
322
323 $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
324 $vb->pack_start ($self->{edit_tool}, 0, 1, 0);
325
326 $vb->pack_start (Gtk2::HSeparator->new, 0, 1, 0);
327 $vb->pack_start ($self->{edit_tool_cont}, 0, 1, 0);
328
329 # XXX:load $ARGV _cleanly_?
330 $self->open_map_editor ($_)
331 for @ARGV;
332
333 $self->signal_connect ('delete-event' => sub {
334 Gtk2->main_quit;
335 });
336
337 ::set_pos_and_size ($self, $main::CFG->{main_window}, 150, 200, 0, 0);
338 }
339
340 sub new_cb {
341 my ($self) = @_;
342 warn "new map not yet implemented\n";
343 }
344
345 sub new_filechooser {
346 my ($self) = @_;
347
348 my $fc = new Gtk2::FileChooserDialog (
349 'gce - open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok'
350 );
351
352 $fc->add_shortcut_folder ("$Crossfire::LIB/maps") if -d "$Crossfire::LIB/maps";
353 $fc->add_shortcut_folder ($_) for keys %{$self->{fc_last_folders}};
354 $fc->set_current_folder ($self->{fc_last_folder} || "$Crossfire::LIB/maps");
355
356 $fc
357 }
358
359 sub open_cb {
360 my ($self) = @_;
361
362 my $fc = $self->new_filechooser;
363
364 if ('ok' eq $fc->run) {
365
366 $self->{fc_last_folder} = $fc->get_current_folder;
367 $self->{fc_last_folders}->{$self->{fc_last_folder}}++;
368
369 $self->open_map_editor ($fc->get_filename);
370 }
371
372 $fc->destroy;
373 }
374
375 sub set_pick {
376 my ($self, $arch) = @_;
377
378 $self->{pick_arch} = $arch;
379 $self->update_pick_view ($arch);
380 }
381
382 sub get_pick {
383 my ($self) = @_;
384
385 # XXX: This is just to make sure that this function always returns something
386 return $self->{pick_arch} || { _name => 'platinacoin' };
387 }
388
389 =head1 AUTHOR
390
391 Marc Lehmann <schmorp@schmorp.de>
392 http://home.schmorp.de/
393
394 Robin Redeker <elmex@ta-sa.org>
395 http://www.ta-sa.org/
396
397 =cut
398 1;
399