Commit fe6cbad5 authored by Corentin Noël's avatar Corentin Noël Committed by Corentin Noël
Browse files

viewport: Rewrite the ShumateViewport and all the Layers to synchronize around...

viewport: Rewrite the ShumateViewport and all the Layers to synchronize around a common ShumateViewport widget

This allows to use a ShumateTile or ShumateLayer without a ShumateView.
parent 7769d8ff
......@@ -27,12 +27,14 @@ callback (GtkWidget *parent)
{
if (!view)
{
ShumateViewport *viewport;
/* Create the map view */
view = GTK_WIDGET (shumate_view_new ());
gtk_widget_insert_after (view, parent, NULL);
shumate_view_set_zoom_level (SHUMATE_VIEW (view), 12);
shumate_view_center_on (SHUMATE_VIEW (view), 45.466, -73.75);
viewport = shumate_view_get_viewport (SHUMATE_VIEW (view));
shumate_viewport_set_zoom_level (viewport, 12);
shumate_location_set_location (SHUMATE_LOCATION (viewport), 45.466, -73.75);
}
else
g_clear_pointer (&view, gtk_widget_unparent);
......
......@@ -32,11 +32,13 @@ map_view_button_release_cb (GtkGestureClick *gesture,
ShumateView *view)
{
gdouble lat, lon;
ShumateViewport *viewport;
lon = shumate_view_x_to_longitude (view, x);
lat = shumate_view_y_to_latitude (view, y);
viewport = shumate_view_get_viewport (view);
lon = shumate_viewport_widget_x_to_longitude (viewport, GTK_WIDGET (view), x);
lat = shumate_viewport_widget_y_to_latitude (viewport, GTK_WIDGET (view), y);
g_print ("Map clicked at %f, %f \n", lat, lon);
g_print ("Map clicked at %f, %f\n", lon, lat);
}
static void
......@@ -49,14 +51,18 @@ activate (GtkApplication* app,
ShumateView *view;
ShumateMarkerLayer *layer;
ShumatePathLayer *path;
ShumateViewport *viewport;
/* Create the map view */
overlay = gtk_overlay_new ();
view = shumate_view_new ();
view = shumate_view_new_simple ();
viewport = shumate_view_get_viewport (view);
gtk_overlay_set_child (GTK_OVERLAY (overlay), GTK_WIDGET (view));
/* Create the markers and marker layer */
layer = create_marker_layer (view, &path);
shumate_view_add_layer (view, SHUMATE_LAYER (path));
shumate_view_add_layer (view, SHUMATE_LAYER (layer));
click_gesture = gtk_gesture_click_new ();
......@@ -65,9 +71,9 @@ activate (GtkApplication* app,
/* Finish initialising the map view */
g_object_set (view,
"zoom-level", 12,
"kinetic-mode", TRUE,
NULL);
shumate_viewport_set_zoom_level (viewport, 12);
shumate_view_center_on (view, 45.466, -73.75);
window = GTK_WINDOW (gtk_application_window_new (app));
......
......@@ -22,14 +22,17 @@
ShumateMarkerLayer *
create_marker_layer (G_GNUC_UNUSED ShumateView *view, ShumatePathLayer **path)
create_marker_layer (ShumateView *view, ShumatePathLayer **path)
{
ShumateMarker *marker;
ShumateMarkerLayer *layer;
GtkWidget *label;
ShumateViewport *viewport;
*path = shumate_path_layer_new ();
layer = shumate_marker_layer_new_full (GTK_SELECTION_SINGLE);
viewport = shumate_view_get_viewport (view);
*path = shumate_path_layer_new (viewport);
layer = shumate_marker_layer_new_full (viewport, GTK_SELECTION_SINGLE);
marker = shumate_marker_new ();
label = gtk_label_new ("Montréal\n<span size=\"xx-small\">Québec</span>");
......
......@@ -27,20 +27,32 @@ activate (GtkApplication* app,
GtkWindow *window;
GtkWidget *overlay;
ShumateView *view;
ShumateViewport *viewport;
ShumateScale *scale;
ShumateLicense *license;
ShumatePathLayer *path_layer;
ShumateMapSourceFactory *factory;
ShumateMapSource *source;
ShumateMapLayer *layer;
/* Create the map view */
overlay = gtk_overlay_new ();
view = shumate_view_new ();
viewport = shumate_view_get_viewport (view);
factory = shumate_map_source_factory_dup_default ();
source = shumate_map_source_factory_create_cached_source (factory, SHUMATE_MAP_SOURCE_OSM_MAPNIK);
shumate_viewport_set_reference_map_source (viewport, source);
layer = shumate_map_layer_new (source, viewport);
shumate_view_add_layer (view, SHUMATE_LAYER (layer));
gtk_overlay_set_child (GTK_OVERLAY (overlay), GTK_WIDGET (view));
scale = shumate_scale_new ();
scale = shumate_scale_new (shumate_view_get_viewport (view));
g_object_set (G_OBJECT (scale),
"valign", GTK_ALIGN_END,
"halign", GTK_ALIGN_START,
NULL);
shumate_scale_connect_view (scale, view);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), GTK_WIDGET (scale));
license = shumate_license_new ();
......@@ -48,10 +60,10 @@ activate (GtkApplication* app,
"valign", GTK_ALIGN_END,
"halign", GTK_ALIGN_END,
NULL);
shumate_license_connect_view (license, view);
shumate_license_append_map_source (license, source);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), GTK_WIDGET (license));
path_layer = shumate_path_layer_new ();
path_layer = shumate_path_layer_new (viewport);
shumate_view_add_layer (view, SHUMATE_LAYER (path_layer));
window = GTK_WINDOW (gtk_application_window_new (app));
......
......@@ -116,14 +116,16 @@ activate (GtkApplication *app,
ShumateView *view;
ShumateMarkerLayer *layer;
SoupSession *session;
ShumateViewport *viewport;
/* Create the map view */
overlay = gtk_overlay_new ();
view = shumate_view_new ();
viewport = shumate_view_get_viewport (view);
gtk_overlay_set_child (GTK_OVERLAY (overlay), GTK_WIDGET (view));
/* Create the markers and marker layer */
layer = shumate_marker_layer_new_full (GTK_SELECTION_SINGLE);
layer = shumate_marker_layer_new_full (viewport, GTK_SELECTION_SINGLE);
shumate_view_add_layer (view, SHUMATE_LAYER (layer));
session = soup_session_new ();
create_marker_from_url (layer, session, 48.218611, 17.146397,
......
......@@ -27,54 +27,95 @@
#include "shumate-layer.h"
G_DEFINE_ABSTRACT_TYPE (ShumateLayer, shumate_layer, GTK_TYPE_WIDGET)
enum
{
PROP_VIEWPORT = 1,
N_PROPERTIES
};
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
typedef struct {
ShumateViewport *viewport;
} ShumateLayerPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ShumateLayer, shumate_layer, GTK_TYPE_WIDGET)
static void
shumate_layer_class_init (ShumateLayerClass *klass)
shumate_layer_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
klass->set_view = NULL;
klass->get_bounding_box = NULL;
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), g_intern_static_string ("map-layer"));
}
ShumateLayer *self = SHUMATE_LAYER (object);
ShumateLayerPrivate *priv = shumate_layer_get_instance_private (self);
switch (property_id)
{
case PROP_VIEWPORT:
priv->viewport = g_value_dup_object (value);
break;
/**
* shumate_layer_set_view:
* @layer: a #ShumateLayer
* @view: a #ShumateView
*
* #ShumateView calls this method to pass a reference to itself to the layer
* when the layer is added to the view. When the layer is removed from the
* view, it passes NULL to the layer. Custom layers can implement this method
* and perform the necessary initialization. This method should not be called
* by user code.
*/
void
shumate_layer_set_view (ShumateLayer *layer,
ShumateView *view)
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
shumate_layer_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
g_return_if_fail (SHUMATE_IS_LAYER (layer));
ShumateLayer *self = SHUMATE_LAYER (object);
ShumateLayerPrivate *priv = shumate_layer_get_instance_private (self);
SHUMATE_LAYER_GET_CLASS (layer)->set_view (layer, view);
}
switch (property_id)
{
case PROP_VIEWPORT:
g_value_set_object (value, priv->viewport);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/**
* shumate_layer_get_bounding_box:
* @layer: a #ShumateLayer
*
* Gets the bounding box occupied by the elements inside the layer.
*
* Returns: The bounding box.
*/
ShumateBoundingBox *
shumate_layer_get_bounding_box (ShumateLayer *layer)
static void
shumate_layer_dispose (GObject *object)
{
g_return_val_if_fail (SHUMATE_IS_LAYER (layer), NULL);
ShumateLayerPrivate *priv = shumate_layer_get_instance_private (SHUMATE_LAYER (object));
return SHUMATE_LAYER_GET_CLASS (layer)->get_bounding_box (layer);
g_clear_object (&priv->viewport);
G_OBJECT_CLASS (shumate_layer_parent_class)->dispose (object);
}
static void
shumate_layer_class_init (ShumateLayerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->set_property = shumate_layer_set_property;
object_class->get_property = shumate_layer_get_property;
object_class->dispose = shumate_layer_dispose;
obj_properties[PROP_VIEWPORT] =
g_param_spec_object ("viewport",
"Viewport",
"The viewport used to display the layer",
SHUMATE_TYPE_VIEWPORT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class,
N_PROPERTIES,
obj_properties);
gtk_widget_class_set_css_name (widget_class, g_intern_static_string ("map-layer"));
}
static void
shumate_layer_init (ShumateLayer *self)
......@@ -84,3 +125,21 @@ shumate_layer_init (ShumateLayer *self)
"vexpand", TRUE,
NULL);
}
/**
* shumate_layer_get_viewport:
* @self: a #ShumateLayer
*
* Gets the #ShumateViewport used by this layer.
*
* Returns: (transfer none): The #ShumateViewport.
*/
ShumateViewport *
shumate_layer_get_viewport (ShumateLayer *self)
{
ShumateLayerPrivate *priv = shumate_layer_get_instance_private (self);
g_return_val_if_fail (SHUMATE_IS_LAYER (self), NULL);
return priv->viewport;
}
......@@ -24,8 +24,7 @@
#ifndef __SHUMATE_LAYER_H__
#define __SHUMATE_LAYER_H__
#include <shumate/shumate-defines.h>
#include <shumate/shumate-bounding-box.h>
#include <shumate/shumate-viewport.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
......@@ -43,16 +42,9 @@ G_DECLARE_DERIVABLE_TYPE (ShumateLayer, shumate_layer, SHUMATE, LAYER, GtkWidget
struct _ShumateLayerClass
{
GtkWidgetClass parent_class;
void (*set_view)(ShumateLayer *layer,
ShumateView *view);
ShumateBoundingBox * (*get_bounding_box)(ShumateLayer * layer);
};
void shumate_layer_set_view (ShumateLayer *layer,
ShumateView *view);
ShumateBoundingBox *shumate_layer_get_bounding_box (ShumateLayer *layer);
ShumateViewport *shumate_layer_get_viewport (ShumateLayer *self);
G_END_DECLS
......
......@@ -44,8 +44,7 @@ struct _ShumateLicense
GtkWidget *extra_text_label;
GtkWidget *license_label;
ShumateView *view;
GPtrArray *map_sources;
};
G_DEFINE_TYPE (ShumateLicense, shumate_license, GTK_TYPE_WIDGET);
......@@ -98,22 +97,24 @@ shumate_license_set_property (GObject *object,
}
static void
shumate_license_assign_source (ShumateLicense *self)
shumate_license_sources_changed (ShumateLicense *self)
{
ShumateMapSource *map_source;
g_autoptr(GString) license_str = NULL;
guint i;
g_assert (SHUMATE_IS_LICENSE (self));
map_source = shumate_view_get_map_source (self->view);
gtk_label_set_label (GTK_LABEL (self->license_label), shumate_map_source_get_license (map_source));
}
license_str = g_string_new (NULL);
for (i = 0; i < self->map_sources->len; i++)
{
ShumateMapSource *map_source = g_ptr_array_index (self->map_sources, i);
if (i == 0)
g_string_append (license_str, shumate_map_source_get_license (map_source));
else
g_string_append_printf (license_str, "\n%s", shumate_map_source_get_license (map_source));
}
static void
on_map_source_changed (ShumateLicense *self,
GParamSpec *pspec,
ShumateView *view)
{
shumate_license_assign_source (self);
gtk_label_set_label (GTK_LABEL (self->license_label), license_str->str);
}
static void
......@@ -121,9 +122,7 @@ shumate_license_dispose (GObject *object)
{
ShumateLicense *self = SHUMATE_LICENSE (object);
if (self->view)
shumate_license_disconnect_view (self);
g_clear_pointer (&self->map_sources, g_ptr_array_unref);
g_clear_pointer (&self->extra_text_label, gtk_widget_unparent);
g_clear_pointer (&self->license_label, gtk_widget_unparent);
......@@ -187,7 +186,7 @@ shumate_license_class_init (ShumateLicenseClass *klass)
static void
shumate_license_init (ShumateLicense *self)
{
self->view = NULL;
self->map_sources = g_ptr_array_new_with_free_func (g_object_unref);
self->license_label = gtk_label_new (NULL);
self->extra_text_label = gtk_label_new (NULL);
......@@ -220,51 +219,6 @@ shumate_license_new (void)
return SHUMATE_LICENSE (g_object_new (SHUMATE_TYPE_LICENSE, NULL));
}
/**
* shumate_license_connect_view:
* @license: The license
* @view: a #ShumateView
*
* This method connects to the necessary signals of #ShumateView to make the
* license change automatically when the map source changes.
*/
void
shumate_license_connect_view (ShumateLicense *license,
ShumateView *view)
{
g_return_if_fail (SHUMATE_IS_LICENSE (license));
if (license->view == view)
return;
if (license->view)
shumate_license_disconnect_view (license);
license->view = g_object_ref (view);
g_signal_connect_swapped (view, "notify::map-source", G_CALLBACK (on_map_source_changed), license);
shumate_license_assign_source (license);
}
/**
* shumate_license_disconnect_view:
* @license: The license
*
* This method disconnects from the signals previously connected by shumate_license_connect_view().
*/
void
shumate_license_disconnect_view (ShumateLicense *license)
{
g_return_if_fail (SHUMATE_IS_LICENSE (license));
g_signal_handlers_disconnect_by_data (license->view, license);
g_clear_object (&license->view);
}
/**
* shumate_license_set_extra_text:
* @license: a #ShumateLicense
......@@ -338,3 +292,33 @@ shumate_license_get_xalign (ShumateLicense *license)
return gtk_label_get_xalign (GTK_LABEL (license->license_label));
}
void
shumate_license_append_map_source (ShumateLicense *license,
ShumateMapSource *map_source)
{
g_return_if_fail (SHUMATE_IS_LICENSE (license));
g_ptr_array_add (license->map_sources, g_object_ref (map_source));
shumate_license_sources_changed (license);
}
void
shumate_license_prepend_map_source (ShumateLicense *license,
ShumateMapSource *map_source)
{
g_return_if_fail (SHUMATE_IS_LICENSE (license));
g_ptr_array_insert (license->map_sources, 0, g_object_ref (map_source));
shumate_license_sources_changed (license);
}
void
shumate_license_remove_map_source (ShumateLicense *license,
ShumateMapSource *map_source)
{
g_return_if_fail (SHUMATE_IS_LICENSE (license));
g_ptr_array_remove (license->map_sources, map_source);
shumate_license_sources_changed (license);
}
......@@ -24,7 +24,7 @@
#ifndef SHUMATE_LICENSE_H
#define SHUMATE_LICENSE_H
#include <shumate/shumate-defines.h>
#include <shumate/shumate-map-source.h>
#include <glib-object.h>
#include <gtk/gtk.h>
......@@ -51,9 +51,12 @@ void shumate_license_set_xalign (ShumateLicense *license,
gfloat xalign);
gfloat shumate_license_get_xalign (ShumateLicense *license);
void shumate_license_connect_view (ShumateLicense *license,
ShumateView *view);
void shumate_license_disconnect_view (ShumateLicense *license);
void shumate_license_append_map_source (ShumateLicense *license,
ShumateMapSource *map_source);
void shumate_license_prepend_map_source (ShumateLicense *license,
ShumateMapSource *map_source);
void shumate_license_remove_map_source (ShumateLicense *license,
ShumateMapSource *map_source);
G_END_DECLS
......
......@@ -25,7 +25,6 @@ struct _ShumateMapLayer
ShumateLayer parent_instance;
ShumateMapSource *map_source;
ShumateView *view;
GPtrArray *tiles_positions;
guint required_tiles_x;
......@@ -100,33 +99,41 @@ shumate_map_layer_compute_grid (ShumateMapLayer *self)
guint center_x, center_y;
gint x_offset, y_offset;
guint tile_x, tile_y;
guint tile_initial_x, tile_initial_y;
guint source_rows, source_columns;
gint width, height;
GtkAllocation child_allocation;
ShumateViewport *viewport;
g_assert (SHUMATE_IS_MAP_LAYER (self));
viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
tile_size = shumate_map_source_get_tile_size (self->map_source);
zoom_level = shumate_view_get_zoom_level (self->view);
center_latitude = shumate_view_get_center_latitude (self->view);
center_longitude = shumate_view_get_center_longitude (self->view);
zoom_level = shumate_viewport_get_zoom_level (viewport);
center_latitude = shumate_location_get_latitude (SHUMATE_LOCATION (viewport));
center_longitude = shumate_location_get_longitude (SHUMATE_LOCATION (viewport));
center_x = (guint) shumate_map_source_get_x (self->map_source, zoom_level, center_longitude);
center_y = (guint) shumate_map_source_get_y (self->map_source, zoom_level, center_latitude);
source_rows = shumate_map_source_get_row_count (self->map_source, zoom_level);
source_columns = shumate_map_source_get_column_count (self->map_source, zoom_level);
width = gtk_widget_get_width (GTK_WIDGET (self));
height = gtk_widget_get_height (GTK_WIDGET (self));
x_offset = -(gint)(((self->required_tiles_x) * tile_size - width)/2) - center_x % tile_size;
y_offset = -(gint)(((self->required_tiles_y) * tile_size - height)/2) - center_y % tile_size;
child_allocation.x = x_offset;
// This is the (x,y) of the top left ShumateTile
tile_initial_x = (center_x - width/2)/tile_size;
tile_initial_y = (center_y - height/2)/tile_size;
x_offset = (center_x - tile_initial_x * tile_size) - width/2;
y_offset = (center_y - tile_initial_y * tile_size) - height/2;
child_allocation.x = -x_offset;
child_allocation.width = tile_size;
child_allocation.height = tile_size;
tile_x = center_x/tile_size - self->required_tiles_x/2;
tile_x = tile_initial_x;
for (gint x = 0; x < self->required_tiles_x; x++)
{
child_allocation.y = y_offset;
tile_y = center_y/tile_size - self->required_tiles_y/2;
child_allocation.y = -y_offset;
tile_y = tile_initial_y;
for (gint y = 0; y < self->required_tiles_y; y++)
{
TileGridPosition *tile_child;
......@@ -174,7 +181,7 @@ shumate_map_layer_compute_grid (ShumateMapLayer *self)
static void
on_view_longitude_changed (ShumateMapLayer *self,
GParamSpec *pspec,
ShumateView *view)
ShumateViewport *view)
{
g_assert (SHUMATE_IS_MAP_LAYER (self));
......@@ -185,7 +192,7 @@ on_view_longitude_changed (ShumateMapLayer *self,
static void
on_view_latitude_changed (ShumateMapLayer *self,
GParamSpec *pspec,
ShumateView *view)
ShumateViewport *view)
{
g_assert (SHUMATE_IS_MAP_LAYER (self));
......@@ -196,7 +203,7 @@ on_view_latitude_changed (ShumateMapLayer *self,
static void
on_view_zoom_level_changed (ShumateMapLayer *self,
GParamSpec *pspec,
ShumateView *view)
ShumateViewport *view)
{
g_assert (SHUMATE_IS_MAP_LAYER (self));
......@@ -248,8 +255,10 @@ static void
shumate_map_layer_dispose (GObject *object)
{
ShumateMapLayer *self = SHUMATE_MAP_LAYER (object);
ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
GtkWidget *child;
g_signal_handlers_disconnect_by_data (viewport, self);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
gtk_widget_unparent (child);
......@@ -260,21 +269,15 @@ shumate_map_layer_dispose (GObject *object)
G_OBJECT_CLASS (shumate_map_layer_parent_class)->dispose (object);
}
static void
shumate_map_layer_finalize (GObject *object)
{
ShumateMapLayer *self = SHUMATE_MAP_LAYER (object);
g_signal_handlers_disconnect_by_data (self->view, self);
self->view = NULL;
G_OBJECT_CLASS (shumate_map_layer_parent_class)->finalize (object);
}
static void