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