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 |
|
18 |
use Glib::Object::Subclass |
19 |
Gtk2::Window, |
20 |
signals => { |
21 |
update_stack_view => { return_type => undef, param_types => [Glib::Int, Glib::Int, Glib::Scalar] }, |
22 |
}; |
23 |
|
24 |
use strict; |
25 |
|
26 |
sub delete_arch { |
27 |
my ($self, $x, $y) = @_; |
28 |
|
29 |
return 0 unless |
30 |
defined $self->{map}; |
31 |
|
32 |
my $s = map_pop_tile_stack ($self->{map}, $x, $y); |
33 |
$self->{map}->update_map ($x, $y, 1, 1); |
34 |
} |
35 |
|
36 |
sub get_top_arch { |
37 |
my ($self, $x, $y) = @_; |
38 |
|
39 |
return 0 unless |
40 |
defined $self->{map}; |
41 |
|
42 |
map_get_tile_stack ($self->{map}, $self->{map}->coord ($x, $y))->[-1] |
43 |
} |
44 |
|
45 |
sub place_pick { |
46 |
my ($self, $x, $y) = @_; |
47 |
|
48 |
return 0 unless |
49 |
defined $self->{map} |
50 |
and defined $self->{pick_arch}; |
51 |
|
52 |
my $s = map_get_tile_stack ($self->{map}, $x, $y); |
53 |
my $top = $s->[-1]; |
54 |
my $arch = { _name => $self->{pick_arch}->{_name} }; |
55 |
|
56 |
if ($top->{_name} ne $arch->{_name}) { |
57 |
map_push_tile_stack ($self->{map}, $x, $y, $arch); |
58 |
} |
59 |
|
60 |
$self->{map}->update_map ($x, $y, 1, 1); |
61 |
} |
62 |
|
63 |
sub INIT_INSTANCE { |
64 |
my ($self) = @_; |
65 |
|
66 |
$self->signal_connect ('delete-event' => sub { |
67 |
Gtk2->main_quit; |
68 |
}); |
69 |
$self->set_title ("gce - main window"); |
70 |
|
71 |
my $menu_tree = [ |
72 |
_File => { |
73 |
item_type => '<Branch>', |
74 |
children => [ |
75 |
_New => { |
76 |
callback => sub { $self->new_cb }, |
77 |
accelerator => '<ctrl>N' |
78 |
}, |
79 |
_Open => { |
80 |
callback => sub { $self->open_cb }, |
81 |
accelerator => '<ctrl>O' |
82 |
}, |
83 |
_Quit => { |
84 |
callback => sub { Gtk2->main_quit }, |
85 |
accelerator => '<ctrl>Q' |
86 |
} |
87 |
] |
88 |
}, |
89 |
_Edit => { |
90 |
item_type => '<Branch>', |
91 |
children => [ |
92 |
_Fill => { |
93 |
callback => sub { die "NO IMPL" }, accelerator => "<ctrl>F" |
94 |
}, |
95 |
"Clear _Top" => { |
96 |
callback => sub { die "NO IMPL" }, accelerator => "<ctrl>T" |
97 |
}, |
98 |
"_Clear All" => { |
99 |
callback => sub { die "NO IMPL" }, accelerator => "<ctrl>C" |
100 |
}, |
101 |
"_Attributes" => { |
102 |
callback => sub { |
103 |
return if defined $self->{attr_edit}; |
104 |
my $w = Gtk2::Window->new; |
105 |
$w->set_title ("gce - edit attrs"); |
106 |
$w->add ($self->{attr_edit} = GCE::AttrEdit->new); |
107 |
$w->signal_connect ('delete-event' => sub { delete $self->{attr_edit} }); |
108 |
$w->show_all; |
109 |
}, |
110 |
accelerator => "<ctrl>A" |
111 |
}, |
112 |
"Open _Picker" => { |
113 |
callback => sub { |
114 |
my $p = GCE::PickWindow->new ( |
115 |
set_sel_cb => sub { $self->update_pick ($_[0]) }, |
116 |
arch_edit_cb => sub { $self->{attr_edit} and $self->{attr_edit}->set_arch ($_[0]) } |
117 |
); |
118 |
$p->init; |
119 |
}, accelerator => "<ctrl>P" |
120 |
}, |
121 |
] |
122 |
} |
123 |
]; |
124 |
my $men = Gtk2::SimpleMenu->new ( |
125 |
menu_tree => $menu_tree, |
126 |
default_callback => \&default_cb, |
127 |
); |
128 |
|
129 |
$self->add (my $vb = Gtk2::VBox->new); |
130 |
$vb->pack_start ($men->{widget}, 0, 1, 0); |
131 |
$vb->pack_start (my $lbl = Gtk2::Label->new ("no selection"), 0, 1, 0); |
132 |
$self->{pick_view} = $lbl; |
133 |
|
134 |
$self->add_accel_group ($men->{accel_group}); |
135 |
|
136 |
my $map = new Crossfire::MapWidget; |
137 |
# XXX:load $ARGV _cleanly_? |
138 |
my $path = $ARGV[0] || "$Crossfire::LIB/maps/dragonisland/advguild3"; |
139 |
$map->set_map (arch2map read_arch $path); |
140 |
$self->{map} = $map; |
141 |
|
142 |
$map->signal_connect (button_press_event => sub { |
143 |
my ($map, $event) = @_; |
144 |
|
145 |
my ($x, $y) = $map->coord ($event->x, $event->y); |
146 |
|
147 |
if ($event->button == 1) { |
148 |
$map->disable_tooltip unless $self->{draw_mode}; |
149 |
$self->{draw_mode} = [1, $x, $y]; |
150 |
$self->place_pick ($x, $y); |
151 |
return 1; |
152 |
|
153 |
} elsif ($event->button == 3) { |
154 |
$map->disable_tooltip unless $self->{draw_mode}; |
155 |
$self->{draw_mode} = [2, $x, $y]; |
156 |
$self->delete_arch ($x, $y); |
157 |
return 1; |
158 |
} |
159 |
|
160 |
0 |
161 |
}); |
162 |
|
163 |
$map->signal_connect_after (motion_notify_event => sub { |
164 |
my ($map, $event) = @_; |
165 |
|
166 |
return unless $self->{draw_mode}; |
167 |
|
168 |
my ($x, $y) = $map->coord ($map->get_pointer); |
169 |
|
170 |
return if $x == $self->{draw_mode}[1] |
171 |
&& $y == $self->{draw_mode}[2]; |
172 |
|
173 |
@{$self->{draw_mode}}[1,2] = ($x, $y); |
174 |
|
175 |
if ($self->{draw_mode}[0] == 1) { |
176 |
$self->place_pick ($x, $y); |
177 |
return 1; |
178 |
|
179 |
} elsif ($self->{draw_mode}[0] == 2) { |
180 |
$self->delete_arch ($x, $y); |
181 |
return 1; |
182 |
|
183 |
} |
184 |
|
185 |
0 |
186 |
}); |
187 |
|
188 |
$map->signal_connect (button_release_event => sub { |
189 |
my ($map, $event) = @_; |
190 |
|
191 |
$map->enable_tooltip if delete $self->{draw_mode}; |
192 |
|
193 |
if ($event->button == 1 && $event->state * "shift-mask") { |
194 |
return 0 unless defined $self->{attr_edit}; |
195 |
$self->{attr_edit}->set_arch ($self->get_top_arch ($event->x, $event->y)); |
196 |
return 1; |
197 |
} |
198 |
|
199 |
0 |
200 |
}); |
201 |
|
202 |
$vb->pack_start ($map, 1, 1, 0); |
203 |
} |
204 |
|
205 |
sub new_cb { |
206 |
my ($self) = @_; |
207 |
die "NOT IMPLEMENTED YET"; |
208 |
} |
209 |
|
210 |
sub open_cb { |
211 |
my ($self) = @_; |
212 |
|
213 |
my $fc = Gtk2::FileChooserDialog->new ( |
214 |
'Open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok' |
215 |
); |
216 |
$fc->add_shortcut_folder ("$Crossfire::LIB/maps"); |
217 |
$fc->set_current_folder ($self->{fc_last_folder} || "$Crossfire::LIB/maps"); |
218 |
|
219 |
if ('ok' eq $fc->run) { |
220 |
my $map = arch2map read_arch $fc->get_filename; |
221 |
$self->{fc_last_folder} = $fc->get_current_folder; |
222 |
$self->{map}->set_map ($map); |
223 |
$self->{map}->hide; |
224 |
$self->{map}->show_all; |
225 |
} |
226 |
|
227 |
$fc->destroy; |
228 |
} |
229 |
|
230 |
sub update_pick { |
231 |
my ($self, $arch) = @_; |
232 |
|
233 |
$self->{pick_arch} = $arch; |
234 |
$self->{pick_view}->set_text ($arch->{_name}); |
235 |
} |
236 |
|
237 |
=head1 AUTHOR |
238 |
|
239 |
Marc Lehmann <schmorp@schmorp.de> |
240 |
http://home.schmorp.de/ |
241 |
|
242 |
Robin Redeker <elmex@ta-sa.org> |
243 |
http://www.ta-sa.org/ |
244 |
|
245 |
=cut |
246 |
1; |
247 |
|