ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/MainWindow.pm
Revision: 1.21
Committed: Mon Feb 20 23:53:37 2006 UTC (18 years, 3 months ago) by elmex
Branch: MAIN
Changes since 1.20: +2 -4 lines
Log Message:
fixed undo/redo $map access

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 strict;
28
29 our $MAINWIN;
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 ($main::VARDIR . '/config');
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 $w->open_map ($mapfile);
80
81 main::set_pos_and_size ($w, $main::CFG->{map_window});
82
83 $w->show_all;
84 # my $w = $self->{last_map_window} = Gtk2::Window->new ('toplevel');
85 # $w->set_title ('gce - map editor');
86 # $w->add (my $mapedit = $self->{mapedit} = new GCE::MapEditor);
87 # $mapedit->open_map ($mapfile);
88 #
89 #
90 # $w->show_all;
91 }
92
93 sub show_stack_view {
94 my ($self) = @_;
95
96 return if defined $self->{sv};
97
98 my $w = $self->{sv_win} = Gtk2::Window->new ('toplevel');
99 $w->set_title ('gce - stack view');
100 $w->signal_connect ('delete-event' => sub { delete $self->{sv}; 0 });
101 $w->add ($self->{sv} = GCE::StackView->new);
102
103 main::set_pos_and_size ($w, $main::CFG->{stack_view});
104
105 $w->show_all;
106 }
107
108 sub show_attr_editor {
109 my ($self) = @_;
110
111 return if $self->{attr_edit};
112
113 my $w = $self->{attr_edit_win} = Gtk2::Window->new;
114 $w->set_title ("gce - edit attrs");
115 $w->add ($self->{attr_edit} = GCE::AttrEdit->new);
116 $w->signal_connect ('delete-event' => sub { delete $self->{attr_edit}; 0 });
117
118 main::set_pos_and_size ($w, $main::CFG->{attr_view});
119
120 $w->show_all;
121 }
122
123 sub update_attr_editor {
124 my ($self, $arch, $cb) = @_;
125
126 return unless $self->{attr_edit};
127
128 $self->{attr_edit}->set_arch ($arch, $cb);
129 $self->{attr_edit_win}->set_title ("gce - edit $arch->{_name}");
130 }
131
132 sub update_stack_view {
133 my ($self, $mapedit, $x, $y) = @_;
134
135 return unless $self->{sv};
136
137 $self->{sv}->set_stack ($mapedit, $x, $y);
138 }
139
140 sub open_pick_window {
141 my ($self, $layout) = @_;
142
143 # XXX: Yes, also fix this, save _every_ pick window and their posistions and their
144 # selection
145 my $p = GCE::PickWindow->new ();
146
147 push @{$self->{open_pick_windows}}, $p;
148
149 my $idx = (@{$self->{open_pick_windows}}) - 1;
150
151 $p->signal_connect ('delete-event' => sub {
152 $self->{open_pick_windows}->[$idx] = undef;
153 });
154
155 if ($layout) {
156 main::set_pos_and_size ($p, $layout->{p_and_s});
157 }
158
159 $p->show_all;
160
161 $p->set_selection ($layout->{selection});
162 }
163
164 sub undo {
165 my ($self) = @_;
166
167 # XXX: Move to GCE::MapEdior in a popup-menu or real menu
168 my $map = $self->{last_map_window}{map}; # the Crossfire::MapWidget
169
170 warn "USI: $map->{undo_stack_pos} @{$map->{undo_stack} || []}\n";#d#
171 $map->{undo_stack_pos}
172 or return;
173
174 $map->change_swap ($map->{undo_stack}[--$map->{undo_stack_pos}]);
175 }
176
177 sub redo {
178 my ($self) = @_;
179
180 # XXX: Move to GCE::MapEdior in a popup-menu or real menu
181 my $map = $self->{last_map_window}{map}; # the Crossfire::MapWidget
182
183 warn "RSI: $map->{undo_stack_pos} @{$map->{undo_stack}}\n";#d#
184
185 $map->{undo_stack_pos} < @{$map->{undo_stack}}
186 or return;
187
188 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]);
189 }
190
191 sub build_menu {
192 my ($self) = @_;
193
194 my $menu_tree = [
195 _File => {
196 item_type => '<Branch>',
197 children => [
198 _New => {
199 callback => sub { $self->new_cb },
200 accelerator => '<ctrl>N'
201 },
202 _Open => {
203 callback => sub { $self->open_cb },
204 accelerator => '<ctrl>O'
205 },
206 "_Save Layout" => {
207 callback => sub { $self->save_layout },
208 accelerator => '<ctrl>L'
209 },
210 _Quit => {
211 callback => sub { Gtk2->main_quit },
212 accelerator => '<ctrl>Q'
213 }
214 ]
215 },
216 _Edit => {
217 item_type => '<Branch>',
218 children => [
219 "_Undo" => {
220 callback => sub { $self->undo },
221 accelerator => "<ctrl>Z"
222 },
223 "_Redo" => {
224 callback => sub { $self->redo },
225 accelerator => "<ctrl>Y"
226 },
227 "_Attr Editor" => {
228 callback => sub { $self->show_attr_editor },
229 accelerator => "<ctrl>A"
230 },
231 "_Picker" => {
232 callback => sub { $self->open_pick_window },
233 accelerator => "<ctrl>P"
234 },
235 "_Stack View" => {
236 callback => sub { $self->show_stack_view },
237 accelerator => "<ctrl>V"
238 },
239
240 ]
241 },
242 _View => {
243 item_type => '<Branch>',
244 children => [
245 "Open _Attr Editor" => {
246 callback => sub { $self->show_attr_editor },
247 accelerator => "<ctrl>A"
248 },
249 "Open _Picker" => {
250 callback => sub { $self->open_pick_window },
251 accelerator => "<ctrl>P"
252 },
253 "Open _Stack View" => {
254 callback => sub { $self->show_stack_view },
255 accelerator => "<ctrl>V"
256 },
257
258 ]
259 }
260
261 ];
262
263 my $men =
264 Gtk2::SimpleMenu->new (
265 menu_tree => $menu_tree,
266 default_callback => \&default_cb,
267 );
268
269 $self->add_accel_group ($men->{accel_group});
270
271 return $men->{widget};
272 }
273
274 sub add_button {
275 my ($self, $table, $plcinfo, $lbl, $cb) = @_;
276
277 my ($lx, $ly) = @{$plcinfo->{next}};
278
279 unless ($lx < $plcinfo->{width}) {
280
281 $ly++;
282 $lx = 0;
283 }
284
285 $ly < $plcinfo->{height}
286 or die "too many buttons, make table bigger!";
287
288 $table->attach_defaults (my $btn = Gtk2::Button->new_with_label ($lbl), $lx, $lx + 1, $ly, $ly + 1);
289 $btn->signal_connect (clicked => $cb);
290
291 $plcinfo->{next} = [$lx + 1, $ly];
292 }
293
294 sub build_buttons {
295 my ($self) = @_;
296
297 my $tbl = Gtk2::Table->new (2, 2);
298 my $plcinfo = { width => 1, height => 3, next => [0, 0] };
299
300 $self->{edit_collection}{pick} = GCE::EditAction::Pick->new;
301 $self->{edit_collection}{place} = GCE::EditAction::Place->new;
302 $self->{edit_collection}{erase} = GCE::EditAction::Erase->new;
303
304 $self->add_button ($tbl, $plcinfo, "Pick", sub {
305 $self->{sel_editaction} = $self->{edit_collection}{pick};
306 $self->{edit_tool}->set_text ("Pick");
307 });
308 $self->add_button ($tbl, $plcinfo, "Place", sub {
309 $self->{sel_editaction} = $self->{edit_collection}{place};
310 $self->{edit_tool}->set_text ("Place");
311 });
312 $self->add_button ($tbl, $plcinfo, "Erase", sub {
313 $self->{sel_editaction} = $self->{edit_collection}{erase};
314 $self->{edit_tool}->set_text ("Erase");
315 });
316
317 return $tbl;
318 }
319
320
321 sub INIT_INSTANCE {
322 my ($self) = @_;
323
324 $MAINWIN = $self;
325
326 $self->set_title ("gce - main window");
327
328 $self->add (my $vb = Gtk2::VBox->new);
329 $vb->pack_start ($self->build_menu, 0, 1, 0);
330 $vb->pack_start (my $tbl = $self->build_buttons, 1, 1, 0);
331 $vb->pack_start ($self->{edit_tool} = Gtk2::Label->new, 0, 1, 0);
332 $vb->pack_start ($self->{pick_view} = Gtk2::Label->new, 0, 1, 0);
333
334 # XXX:load $ARGV _cleanly_?
335 $self->open_map_editor ($ARGV[0] || "$Crossfire::LIB/maps/dragonisland/advguild3");
336
337 $self->signal_connect ('delete-event' => sub {
338 Gtk2->main_quit;
339 });
340
341 main::set_pos_and_size ($self, $main::CFG->{main_window});
342 }
343
344 sub new_cb {
345 my ($self) = @_;
346 die "NOT IMPLEMENTED YET";
347 }
348
349 sub open_cb {
350 my ($self) = @_;
351
352 my $fc =
353 Gtk2::FileChooserDialog->new (
354 'gce - open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok'
355 );
356
357 $fc->add_shortcut_folder ("$Crossfire::LIB/maps");
358 $fc->add_shortcut_folder ($_) for keys %{$self->{fc_last_folders}};
359 $fc->set_current_folder ($self->{fc_last_folder} || "$Crossfire::LIB/maps");
360
361 if ('ok' eq $fc->run) {
362
363 $self->{fc_last_folder} = $fc->get_current_folder;
364 $self->{fc_last_folders}->{$self->{fc_last_folder}}++;
365
366 $self->open_map_editor ($fc->get_filename);
367 }
368
369 $fc->destroy;
370 }
371
372 sub set_pick {
373 my ($self, $arch) = @_;
374
375 $self->{pick_arch} = $arch;
376 $self->{pick_view}->set_text ($arch->{_name});
377 }
378
379 sub get_pick {
380 my ($self) = @_;
381
382 # XXX: This is just to make sure that this function always returns something
383 return $self->{pick_arch} || { _name => 'platinacoin' };
384 }
385
386 =head1 AUTHOR
387
388 Marc Lehmann <schmorp@schmorp.de>
389 http://home.schmorp.de/
390
391 Robin Redeker <elmex@ta-sa.org>
392 http://www.ta-sa.org/
393
394 =cut
395 1;
396