ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/Map.pm
Revision: 1.4
Committed: Sun Feb 5 05:32:57 2006 UTC (18 years, 4 months ago) by root
Branch: MAIN
Changes since 1.3: +3 -17 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Gtk2::CV::Schnauzer - a widget for displaying image collections
4    
5     =head1 SYNOPSIS
6    
7     use Gtk2::CV::Schnauzer;
8    
9     =head1 DESCRIPTION
10    
11     =head2 METHODS
12    
13     =over 4
14    
15     =cut
16    
17     package GCE::Map;
18    
19     use strict;
20    
21     use Gtk2;
22    
23     use Crossfire;
24     use Crossfire::Gtk2;
25    
26     use Glib::Object::Subclass
27 root 1.4 'Gtk2::DrawingArea';
28 root 1.1
29     use List::Util qw(min max);
30    
31     sub INIT_INSTANCE {
32     my ($self) = @_;
33    
34     $self->signal_connect (destroy => sub { %{$_[0]} = () });
35     $self->signal_connect (realize => sub {
36     my ($self) = @_;
37    
38     $self->{window} = $self->window;
39    
40     1
41     });
42    
43     #$self->set_redraw_on_allocate (0); # nope
44 root 1.2 $self->double_buffered (0);
45 root 1.1
46     $self->signal_connect (size_request => sub {
47     $_[1]->width (20 * TILESIZE);
48     $_[1]->height (20 * TILESIZE);
49    
50     1
51     });
52    
53     $self->signal_connect (expose_event => sub {
54     $self->expose ($_[1]);
55     });
56    
57     $self->signal_connect (button_press_event => sub {
58     my ($self, $event) = @_;
59    
60     my ($x, $y) = ($event->x, $event->y);
61    
62     if ($_[1]->button == 2) {
63     $_[0]->grab_focus;
64     $self->{in_drag} = [$self->{x}, $self->{y}, $x, $y];
65 root 1.2 return 0;
66 root 1.1 }
67    
68     1
69     });
70    
71     $self->signal_connect (motion_notify_event => sub {
72     my ($self) = @_;
73    
74     my ($x, $y) = $self->get_pointer;
75    
76     if (my $di = $self->{in_drag}) {
77     my $dx = $x - $di->[2];
78     my $dy = $y - $di->[3];
79    
80     my $nx = max 0, $di->[0] - $dx;
81     my $ny = max 0, $di->[1] - $dy;
82    
83     $self->window->scroll ($self->{x} - $nx, $self->{y} - $ny);
84    
85     ($self->{x}, $self->{y}) = ($nx, $ny);
86 root 1.2 return 0;
87 root 1.1 }
88    
89     1;
90     });
91    
92     $self->signal_connect (button_release_event => sub {
93     my ($self) = @_;
94    
95     delete $self->{in_drag};
96    
97     1
98     });
99    
100     # unnecessary redraws...
101     $self->signal_connect (focus_in_event => sub { 1 });
102     $self->signal_connect (focus_out_event => sub { 1 });
103    
104     # gtk+ supports no motion compression, a major lacking feature. we have to pay for the
105     # workaround with incorrect behaviour and extra server-turnarounds.
106     $self->add_events ([qw(key_press_mask key_release_mask button_press_mask button_release_mask button-motion-mask scroll_mask pointer-motion-hint-mask)]);
107     $self->can_focus (1);
108    
109     # $self->signal_connect (key_press_event => sub { $self->handle_key ($_[1]->keyval, $_[1]->state) });
110     }
111    
112     sub do_size_allocate_rounded {
113     use integer;
114    
115     $_[1]->width ($_[1]->width / TILESIZE * TILESIZE);
116     $_[1]->height ($_[1]->height / TILESIZE * TILESIZE);
117    
118     $_[0]->signal_chain_from_overridden ($_[1]);
119     }
120    
121     sub coord {
122     my ($self, $x, $y) = @_;
123    
124     (
125     int $self->{x} + $x / TILESIZE,
126     int $self->{y} + $y / TILESIZE,
127     )
128     }
129    
130     #sub handle_key {
131     # my ($self, $key, $state) = @_;
132     #
133     # $self->prefetch_cancel;
134     #
135     # if ($state * "control-mask") {
136     # if ($key == $Gtk2::Gdk::Keysyms{g}) {
137     # my @sel = keys %{$self->{sel}};
138     # $self->generate_thumbnails (@sel ? @sel : 0 .. $#{$self->{entry}});
139     # } elsif ($key == $Gtk2::Gdk::Keysyms{a}) {
140     # $self->select_all;
141     # } elsif ($key == $Gtk2::Gdk::Keysyms{A}) {
142     # $self->select_range ($self->{offs}, $self->{offs} + $self->{cols} * $self->{page} - 1);
143     # } elsif ($key == $Gtk2::Gdk::Keysyms{s}) {
144     # $self->rescan;
145     # } elsif ($key == $Gtk2::Gdk::Keysyms{d}) {
146     # $self->unlink (keys %{$self->{sel}});
147     # } elsif ($key == $Gtk2::Gdk::Keysyms{u}) {
148     # my @sel = keys %{$self->{sel}};
149     # $self->update_thumbnails (@sel ? @sel : 0 .. $#{$self->{entry}});
150     #
151     # } elsif ($key == $Gtk2::Gdk::Keysyms{Return}) {
152     # $self->cursor_move (0) unless $self->cursor_valid;
153     # $self->emit_activate ($self->{cursor});
154     # } elsif ($key == $Gtk2::Gdk::Keysyms{space}) {
155     # $self->cursor_move (1) or return 1
156     # if $self->{cursor_current} || !$self->cursor_valid;
157     # $self->emit_activate ($self->{cursor}) if $self->cursor_valid;
158     # $self->prefetch (1);
159     # } elsif ($key == $Gtk2::Gdk::Keysyms{BackSpace}) {
160     # $self->cursor_move (-1) or return 1;
161     # $self->emit_activate ($self->{cursor}) if $self->cursor_valid;
162     # $self->prefetch (-1);
163     #
164     # } else {
165     # return 0;
166     # }
167     # } else {
168     # if ($key == $Gtk2::Gdk::Keysyms{Page_Up}) {
169     # my $value = $self->{adj}->value;
170     # $self->{adj}->set_value ($value >= $self->{page} ? $value - $self->{page} : 0);
171     # $self->clear_cursor;
172     # } elsif ($key == $Gtk2::Gdk::Keysyms{Page_Down}) {
173     # my $value = $self->{adj}->value + $self->{page};
174     # $self->{adj}->set_value ($value <= $self->{maxrow} ? $value : $self->{maxrow});
175     # $self->clear_cursor;
176     #
177     # } elsif ($key == $Gtk2::Gdk::Keysyms{Home}) {
178     # $self->{adj}->set_value (0);
179     # $self->clear_cursor;
180     # } elsif ($key == $Gtk2::Gdk::Keysyms{End}) {
181     # $self->{adj}->set_value ($self->{maxrow});
182     # $self->clear_cursor;
183     #
184     # } elsif ($key == $Gtk2::Gdk::Keysyms{Up}) {
185     # $self->cursor_move (-$self->{cols});
186     # } elsif ($key == $Gtk2::Gdk::Keysyms{Down}) {
187     # $self->cursor_move (+$self->{cols});
188     # } elsif ($key == $Gtk2::Gdk::Keysyms{Left}) {
189     # $self->cursor_move (-1);
190     # } elsif ($key == $Gtk2::Gdk::Keysyms{Right}) {
191     # $self->cursor_move (+1);
192     #
193     # } elsif ($key == $Gtk2::Gdk::Keysyms{Return}) {
194     # $self->cursor_move (0) unless $self->cursor_valid;
195     # $self->emit_activate ($self->{cursor});
196     # } elsif ($key == $Gtk2::Gdk::Keysyms{space}) {
197     # $self->cursor_move (1) or return 1
198     # if $self->{cursor_current} || !$self->cursor_valid;
199     # $self->emit_activate ($self->{cursor}) if $self->cursor_valid;
200     # $self->prefetch (1);
201     # } elsif ($key == $Gtk2::Gdk::Keysyms{BackSpace}) {
202     # $self->cursor_move (-1) or return 1;
203     # $self->emit_activate ($self->{cursor}) if $self->cursor_valid;
204     # $self->prefetch (-1);
205     #
206     # } elsif ($key == ord '^') {
207     # $self->updir if exists $self->{dir};
208     #
209     # } elsif (($key >= (ord '0') && $key <= (ord '9'))
210     # || ($key >= (ord 'a') && $key <= (ord 'z'))) {
211     #
212     # $key = chr $key;
213     #
214     # my ($idx, $cursor) = (0, 0);
215     #
216     # $self->clear_selection;
217     #
218     # for my $entry (@{$self->{entry}}) {
219     # $idx++;
220     # $cursor = $idx if $key gt lcfirst $entry->[1];
221     # }
222     #
223     # if ($cursor < @{$self->{entry}}) {
224     # delete $self->{cursor_current};
225     # $self->{sel}{$cursor} = $self->{entry}[$cursor];
226     # $self->{cursor} = $cursor;
227     #
228     # $self->{adj}->set_value (min $self->{maxrow}, $cursor / $self->{cols});
229     # $self->emit_sel_changed;
230     # $self->invalidate_all;
231     # }
232     # } else {
233     # return 0;
234     # }
235     # }
236     #
237     # 1
238     #}
239    
240     #sub invalidate {
241     # my ($self, $x1, $y1, $x2, $y2) = @_;
242     #
243     # return unless $self->{window};
244     #
245     # $self->{draw}->queue_draw_area (
246     # $x1 * (IW + IX), $y1 * (IH + IY),
247     # ($x2 - $x1 + 1) * (IW + IX), ($y2 - $y1 + 1) * (IH + IY),
248     # );
249     #}
250    
251     sub invalidate_all {
252     my ($self) = @_;
253    
254     # $self->invalidate (0, 0, $self->{cols} - 1, $self->{page} - 1);
255     }
256    
257     sub expose {
258     my ($self, $event) = @_;
259    
260     no integer;
261    
262     my $ox = $self->{x}; my $ix = int $ox / TILESIZE;
263     my $oy = $self->{y}; my $iy = int $oy / TILESIZE;
264    
265 root 1.4 # get_rectangles is buggy in older versions
266     for my $area ($Gtk2::VERSION >= 1.115 ? $event->region->get_rectangles : $event->area) {
267 root 1.1 my ($x, $y, $w, $h) = $area->values; # x y w h
268    
269     my @x = ((int ($ox + $x) / TILESIZE) .. int +($ox + $x + $w + TILESIZE - 1) / TILESIZE);
270     my @y = ((int ($oy + $y) / TILESIZE) .. int +($oy + $y + $h + TILESIZE - 1) / TILESIZE);
271    
272     my $PB = $Crossfire::Gtk2::TILECACHE;
273     my $TC = \%Crossfire::Gtk2::TILECACHE;
274    
275     my $window = $self->{window};
276    
277     my $pb = new Gtk2::Gdk::Pixbuf 'rgb', 0, 8, TILESIZE * (@x + 1), TILESIZE * (@y + 1);
278     $pb->fill (0x00000000);
279    
280     for my $x (@x) {
281 root 1.2 my $as = $self->{map}{map}[$x];
282 root 1.1 for my $y (@y) {
283 root 1.2 for my $a (@{ $as->[$y] || [] }) {
284 root 1.1 my $o = $ARCH->{$a->{_name}}
285     or (warn "arch '$a->{_name}' not found at ($x|$y)\n"), next;
286    
287     my $face = $a->{face} || $o->{face};
288     my $tile = $TC->{$face}
289     or (warn "no gfx found for arch '$a->{_name}' at ($x|$y)\n"), next;
290    
291     my $idx = $tile->{idx}; # + $a->{x} * $tile->{w} + $a->{y};
292    
293     my $dx = ($x - $x[0]) * TILESIZE;
294     my $dy = ($y - $y[0]) * TILESIZE;
295    
296     $PB->composite ($pb,
297     $dx, $dy,
298     TILESIZE, TILESIZE,
299     $dx - ($idx % 64) * TILESIZE, $dy - TILESIZE * int $idx / 64,
300     1, 1, 'nearest', 255
301     );
302     }
303     }
304     }
305    
306     $pb->render_to_drawable ($window, $self->style->black_gc,
307     0, 0,
308     $x[0] * TILESIZE - $ox, $y[0] * TILESIZE - $oy,
309     TILESIZE * @x, TILESIZE * @y,
310     'max', 0, 0);
311     }
312    
313     1
314     }
315    
316 root 1.3 #my $win = new Gtk2::Window 'toplevel';
317     #my $map = new GCE::Map;
318     #$win->add ($map);
319     #$win->show_all;
320     #$map->{map} = arch2map read_arch "$Crossfire::LIB/maps/mlab/university1";
321     #main Gtk2;
322 root 1.1
323     =back
324    
325     =head1 AUTHOR
326    
327     Marc Lehmann <schmorp@schmorp.de>
328    
329     =cut
330    
331     1
332