6
use Clutter::TestHelper tests => 82;
8
use Champlain ':coords';
16
test_ensure_visible();
17
test_ensure_markers_visible();
27
# Test some default functionality.
30
my $view = Champlain::View->new();
31
isa_ok($view, 'Champlain::View');
33
# center_on() can be tested by checking the properties latitude and longitude.
34
# And even then, the values set are not the ones returned
35
my $latitude = $view->get('latitude');
36
my $longitude = $view->get('longitude');
37
$view->center_on(48.144722, 17.112778);
38
ok($view->get('latitude') != $latitude, "center_on() changed latitude");
39
ok($view->get('longitude') != $longitude, "center_on() changed longitude");
41
# NOTE: In recent versions of libchamplain the view requests the first tile
42
# (0, 0 at zoom level 0). If the tile is already in the cache then it
43
# will be loaded and the view's initial size will be of the tile's size.
44
# If the tile is not in the cache then it will be downloaded
45
# asynchronously and the view will have a size of (0, 0).
47
# For the moment there's no mechanism for disabling the cache nor for
48
# finding out if the view has a tile loaded. This is why the test for
52
my $source_original = $view->get('map-source');
53
ok($view->get('width') == 0 || $view->get('width') == $source_original->get_tile_size, "original width");
54
ok($view->get('height') == 0 || $view->get('height') == $source_original->get_tile_size, "original height");
56
# set_size() can be tested by checking the properties width and height
57
$view->set_size(600, 400);
58
is($view->get('width'), 600, "set_size() changed width");
59
is($view->get('height'), 400, "set_size() changed height");
62
# Can't be tested but at least we check that it doesn't crash when invoked
63
my $layer = Champlain::Layer->new();
64
$view->add_layer($layer);
67
# Change the map source (get a different map source)
68
my $factory = Champlain::MapSourceFactory->dup_default();
69
my $source_new = $factory->create(Champlain::MapSourceFactory->OSM_MAPNIK);
70
if ($source_original->get_id eq $source_new->get_id) {
71
# Same kind of map source, take another one
72
$source_new = $factory->create(Champlain::MapSourceFactory->OAM);
74
$view->set_map_source($source_new);
75
is($view->get('map-source'), $source_new, "set_map_source()");
76
is($view->get_map_source, $source_new, "get_map_source()");
79
# Change the decel rate
80
$view->set_decel_rate(0.5);
81
is($view->get('decel-rate'), 0.5, "set_decel_rate()");
82
$view->set_decel_rate(1.5);
83
is($view->get('decel-rate'), 1.5, "set_decel_rate()");
84
is($view->get_decel_rate, 1.5, "get_decel_rate()");
87
# Change the scroll mode
88
$view->set_scroll_mode('push');
89
is($view->get('scroll-mode'), 'push', "set_scroll_mode('push')");
90
$view->set_scroll_mode('kinetic');
91
is($view->get('scroll-mode'), 'kinetic', "set_scroll_mode('kinetic')");
92
is($view->get_scroll_mode, 'kinetic', "get_scroll_mode()");
95
# Change the show license property
96
$view->set_show_license(TRUE);
97
ok($view->get('show-license'), "set_show_license(TRUE)");
98
$view->set_show_license(FALSE);
99
ok(!$view->get('show-license'), "set_show_license(FALSE)");
100
ok(!$view->get_show_license, "get_show_license");
103
# Change the set zoom on double click property
104
$view->set_zoom_on_double_click(TRUE);
105
ok($view->get('zoom-on-double-click'), "set_zoom_on_double_click(TRUE)");
106
$view->set_zoom_on_double_click(FALSE);
107
ok(!$view->get('zoom-on-double-click'), "set_zoom_on_double_click(FALSE)");
108
ok(!$view->get_zoom_on_double_click, "get_zoom_on_double_click()");
111
# Change the keep center on resize property
112
$view->set_keep_center_on_resize(TRUE);
113
ok($view->get('keep-center-on-resize'), "set_keep_center_on_resize(TRUE)");
114
$view->set_keep_center_on_resize(FALSE);
115
ok(!$view->get('keep-center-on-resize'), "set_keep_center_on_resize(FALSE)");
116
ok(!$view->get_keep_center_on_resize, "get_keep_center_on_resize()");
119
# Call ensure_visible(), it's to test, but at least we test that it doesn't crash
120
$view->ensure_visible(10, 10, 30, 30, TRUE);
125
# Test the zoom functionality.
128
my $view = Champlain::View->new();
129
isa_ok($view, 'Champlain::View');
133
is($view->get('zoom-level'), 0, "original zoom-level");
135
is($view->get('zoom-level'), 1, "zoom-in once");
137
is($view->get('zoom-level'), 2, "zoom-in twice");
141
is($view->get('zoom-level'), 1, "zoom-out once");
143
is($view->get('zoom-level'), 0, "zoom-out twice");
145
my $map_source = $view->get('map-source');
147
# Zoom out past the min zoom level
148
my $min = $map_source->get_min_zoom_level;
149
$view->set_zoom_level($min);
150
is($view->get('zoom-level'), $min, "zoom-out to the minimal level");
151
is($view->get_zoom_level, $min, "get_zoom_level()");
153
$view->set("zoom-level", $min);
154
is($view->get('zoom-level'), $min, "set('zoom-level') to the minimal level");
157
is($view->get('zoom-level'), $min, "zoom-out past minimal level has no effect");
160
# Zoom in after the max zoom level
161
my $max = $map_source->get_max_zoom_level;
162
$view->set_zoom_level($max);
163
is($view->get('zoom-level'), $max, "zoom-in to the maximal level");
165
$view->set("zoom-level", $max);
166
is($view->get('zoom-level'), $max, "set('zoom-level') to the maximal level");
169
is($view->get('zoom-level'), $max, "zoom-in past maximal level has no effect");
171
# Go to the middle zoom level
172
my $middle = int( ($max - $min) / 2 );
173
$view->set_zoom_level($middle);
174
is($view->get('zoom-level'), $middle, "set zoom to the middle level");
176
$view->set("zoom-level", $middle);
177
is($view->get('zoom-level'), $middle, "set('zoom-level', (max-min)/2) to the middle level");
180
# Try to set directly the zoom level to a value inferior to min level
181
$view->set_zoom_level($min - 1);
182
is($view->get('zoom-level'), $middle, "set zoom (min - 1) has no effect");
184
# NOTE: This gives a warning because -1 out of range for property `zoom-level'
185
#$view->set("zoom-level", $min - 1);
186
#is($view->get('zoom-level'), $middle, "set('zoom-level', min - 1) has no effect");
188
# Try to set directly the zoom level to a valu superior to max level
189
$view->set_zoom_level($max + 1);
190
is($view->get('zoom-level'), $middle, "set zoom (max + 1) has no effect");
192
$view->set("zoom-level", $max + 1);
193
is($view->get('zoom-level'), $middle, "set('zoom-level', max + 1) has no effect");
196
# Limit the application's zoom levels
197
$view->set_zoom_level(1);
198
is($view->get('zoom-level'), 1, "set('zoom-level', 1)");
199
is($view->get('min-zoom-level'), $min, "defaullt min-zoom-level");
200
is($view->get_min_zoom_level, $min, "get_min_zoom_level()");
201
$view->set_min_zoom_level(3);
202
is($view->get('min-zoom-level'), 3, "set_min_zoom_level(3)");
203
is($view->get('zoom-level'), 3, "zoom-level level is 3 after setting min-zoom-level to 3");
205
$view->set_zoom_level(6);
206
is($view->get('zoom-level'), 6, "set('zoom-level', 6)");
207
is($view->get('max-zoom-level'), $max, "defaullt max-zoom-level");
208
is($view->get_max_zoom_level, $max, "get_max_zoom_level()");
209
$view->set_max_zoom_level(4);
210
is($view->get('max-zoom-level'), 4, "set_mx_zoom_level(4)");
211
is($view->get('zoom-level'), 4, "zoom-level level is 4 after setting min-zoom-level to 4");
216
# Test getting the coordinates from an event.
218
# This tests simulates that the user clicked at the coordinate (0, 0) (where
219
# Greenwich meets the Equator). In order to simulate this, the test sets the
220
# view to be as big as the first tile and will simulate a click in the middle of
221
# the tile. Because the computations are made with a projection a slight error
222
# threshold will be accepted.
225
my $view = Champlain::View->new();
226
isa_ok($view, 'Champlain::View');
228
my $map_source = $view->get('map-source');
229
my $size = $map_source->get_tile_size;
230
ok($size > 0, "Tile has a decent size");
232
# NOTE: At the moment this works only if the view is in a stage and if
233
# show_all() was called
234
my $stage = Clutter::Stage->get_default();
235
$view->set_size($size, $size);
236
$view->center_on(0, 0);
239
# Create a fake event in the middle of the tile
240
my $event = Clutter::Event->new('button_press');
241
my $middle = int($size/2);
244
is($event->x, $middle, "Fake event is in the middle (x)");
245
is($event->y, $middle, "Fake event is in the middle (y)");
247
my ($latitude, $longitude) = $view->get_coords_from_event($event);
248
ok($latitude >= -2.0 && $latitude <= 2.0, "get_coords_from_event() latitude");
249
ok($longitude >= -2.0 && $longitude <= 2.0, "get_coords_from_event() longitude");
251
($latitude, $longitude) = $view->get_coords_at($event->x, $event->y);
252
ok($latitude >= -2.0 && $latitude <= 2.0, "get_coords_at() latitude");
253
ok($longitude >= -2.0 && $longitude <= 2.0, "get_coords_at() longitude");
258
# Test going to a different location with go_to().
261
my $view = Champlain::View->new();
262
isa_ok($view, 'Champlain::View');
264
# Place the view in the center
265
$view->center_on(0, 0);
266
is($view->get('latitude'), 0, "center_on() reset latitude");
267
is($view->get('longitude'), 0, "center_on() reset longitude");
270
# Go to a different place
271
my ($latitude, $longitude) = (48.218611, 17.146397);
272
$view->go_to($latitude, $longitude);
274
run_animation_loop($view);
276
# Check if we got somewhere close to desired location
277
is_view_near($view, $latitude, $longitude);
280
# Replace the view in the center
281
$view->center_on(0, 0);
282
is($view->get('latitude'), 0, "center_on() reset latitude");
283
is($view->get('longitude'), 0, "center_on() reset longitude");
285
# Go to a different place. This is too fast and can't be tested properly.
286
$view->go_to($latitude, $longitude);
287
Glib::Idle->add(sub {$view->stop_go_to()});
288
run_animation_loop($view);
290
is($view->get('latitude'), 0, "stop_go_to() at latitude 0");
291
is($view->get('longitude'), 0, "stop_go_to() at longitude 0");
299
my $view = Champlain::View->new();
300
isa_ok($view, 'Champlain::View');
302
my $line = Champlain::Polygon->new();
303
my $triangle = Champlain::Polygon->new();
304
my $square = Champlain::Polygon->new();
306
# Note these can't be tested as the API provides no way for querying the polygons
307
$view->add_polygon($line);
308
$view->add_polygon($triangle);
309
$view->add_polygon($square);
311
$view->remove_polygon($line);
312
$view->remove_polygon($square);
317
# Test ensure_visible().
319
sub test_ensure_visible {
320
my $view = Champlain::View->new();
321
isa_ok($view, 'Champlain::View');
323
# Place the view in the center and zoomed
324
$view->center_on(0, 0);
325
$view->set_zoom_level(6);
326
is($view->get('latitude'), 0);
327
is($view->get('longitude'), 0);
328
is($view->get('zoom-level'), 6);
330
# Must add the view to a stage for this test
331
my $stage = Clutter::Stage->get_default();
332
$view->set_size(400, 400);
335
# Ensure that 2 points are visible
336
my (@marker1) = (48.218611, 17.146397);
337
my (@marker2) = (48.21066, 16.31476);
338
$view->ensure_visible(@marker1, @marker2, TRUE);
340
run_animation_loop($view);
342
# Check if we got somewhere close to the middle of the markers
343
my $middle_latitude = ($marker1[0] + $marker2[0]) / 2;
344
my $middle_longitude = ($marker1[1] + $marker2[1]) / 2;
345
is_view_near($view, $middle_latitude, $middle_longitude);
350
# Test ensure_markers_visible().
352
sub test_ensure_markers_visible {
353
my $view = Champlain::View->new();
354
isa_ok($view, 'Champlain::View');
356
# Place the view in the center and zoomed
357
$view->center_on(0, 0);
358
$view->set_zoom_level(6);
359
is($view->get('latitude'), 0);
360
is($view->get('longitude'), 0);
361
is($view->get('zoom-level'), 6);
363
# Ensure that some markers are visible
365
create_marker('A', 48.218611, 17.146397),
366
create_marker('B', 48.14838, 17.10791),
367
create_marker('C', 48.21066, 16.31476),
370
my $layer = Champlain::Layer->new();
371
foreach my $marker (@markers) {
372
$layer->add($marker);
374
$view->add_layer($layer);
376
# Must add the view to a stage and give a size for this test
377
my $stage = Clutter::Stage->get_default();
379
$view->set_size(400, 400);
381
$view->ensure_markers_visible(\@markers, TRUE);
383
run_animation_loop($view);
385
# Check if we got somewhere close to the middle of the markers
386
is_view_near($view, 48.0, 16.5, 5.0);
391
# Test if the view is near the given (latitude, longitude). This function checks
392
# if the cordinate is close to the given point by accepting an error margin. If
393
# no margin is given then one degree is assumed.
396
my ($view, $latitude, $longitude, $delta) = @_;
397
$delta = 1.0 unless defined $delta;
399
# Check if the view is close to the given position
400
my ($current_latitude, $current_longitude) = $view->get('latitude', 'longitude');
401
my $delta_latitude = $current_latitude - $latitude;
402
my $delta_longitude = $current_longitude - $longitude;
403
my $tester = Test::Builder->new();
404
$tester->ok($delta_latitude >= -$delta && $delta_latitude <= $delta, "ensure_visible() changed latitude close enough (delta: $delta_latitude)");
405
$tester->ok($delta_longitude >= -$delta && $delta_longitude <= $delta, "ensure_visible() changed longitude close enough (delta: $delta_longitude)");
410
my ($label, $latitude, $longitude) = @_;
411
my $marker = Champlain::Marker->new_with_text($label);
412
$marker->set_position($latitude, $longitude);
418
# Runs a main loop for the purpose of executing one animation. The main loop is
419
# timed in case where the test doesn't work.
421
sub run_animation_loop {
424
# if (my $stage = $view->get_stage) {
425
# $stage->show_all();
429
# Give us a bit of time to get there since this is an animation and it
430
# requires an event loop. We add an idle timeout in order to make sure that we
431
# don't wait forever.
432
$view->signal_connect('animation-completed' => sub {
433
Clutter->main_quit();
435
Glib::Timeout->add(10_000, sub {
436
diag("Event loop timeout, perhaps the animation needs more time?");
437
Clutter->main_quit();