[libshumate] Add ShumateSimpleMap



commit 58399cd869d4af092c200b57dc4bf0f580bacf0d
Author: James Westman <james jwestman net>
Date:   Tue Dec 21 23:35:19 2021 -0600

    Add ShumateSimpleMap
    
    This widget is designed for simple use cases of libshumate, mainly in
    apps where maps aren't the main focus. It takes care of license text,
    source switching, base vs. overlay layers, etc. but offers somewhat less
    control. The individual child widgets that make up the widget are still
    accessible.
    
    Also removes the custom styling on the compass widget, because it
    doesn't look right where I put it in the ShumateSimpleMap.
    
    Fixes #20.

 data/compass.css              |   8 -
 data/libshumate.gresource.xml |   2 +-
 data/shumate-simple-map.ui    |  69 ++++++
 demos/shumate-demo-window.c   |  58 +----
 demos/shumate-demo-window.ui  |  32 +--
 shumate/meson.build           |   2 +
 shumate/shumate-compass.c     |   9 +-
 shumate/shumate-simple-map.c  | 518 ++++++++++++++++++++++++++++++++++++++++++
 shumate/shumate-simple-map.h  |  59 +++++
 shumate/shumate.h             |   1 +
 10 files changed, 658 insertions(+), 100 deletions(-)
---
diff --git a/data/libshumate.gresource.xml b/data/libshumate.gresource.xml
index 6c26462..ed06938 100644
--- a/data/libshumate.gresource.xml
+++ b/data/libshumate.gresource.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/shumate/">
-    <file compressed="true">compass.css</file>
     <file compressed="true">scale.css</file>
     <file compressed="true">license.css</file>
     <file compressed="true">point.css</file>
     <file preprocess="xml-stripblanks">icons/32x32/status/map-compass.svg</file>
+    <file preprocess="xml-stripblanks">shumate-simple-map.ui</file>
   </gresource>
 </gresources>
diff --git a/data/shumate-simple-map.ui b/data/shumate-simple-map.ui
new file mode 100644
index 0000000..d11764e
--- /dev/null
+++ b/data/shumate-simple-map.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <template class="ShumateSimpleMap" parent="GtkWidget">
+    <child>
+      <object class="ShumateMap" id="map"></object>
+    </child>
+    <child>
+      <object class="ShumateLicense" id="license">
+        <property name="halign">end</property>
+        <property name="valign">end</property>
+      </object>
+    </child>
+    <child>
+      <object class="ShumateScale" id="scale">
+        <property name="halign">start</property>
+        <property name="valign">end</property>
+        <property name="viewport" bind-source="map" bind-property="viewport" bind-flags="sync-create"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="halign">end</property>
+        <property name="valign">start</property>
+        <property name="orientation">vertical</property>
+        <property name="margin-top">6</property>
+        <property name="margin-bottom">6</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkBox" id="zoom_buttons">
+            <style>
+              <class name="linked"/>
+            </style>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkButton">
+                <property name="tooltip-text">Zoom In</property>
+                <signal name="clicked" handler="on_zoom_in_clicked" swapped="true"/>
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">zoom-in-symbolic</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="tooltip-text">Zoom Out</property>
+                <signal name="clicked" handler="on_zoom_out_clicked" swapped="true"/>
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">zoom-out-symbolic</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="ShumateCompass" id="compass">
+            <property name="viewport" bind-source="map" bind-property="viewport" bind-flags="sync-create"/>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/demos/shumate-demo-window.c b/demos/shumate-demo-window.c
index 77638bd..e259386 100644
--- a/demos/shumate-demo-window.c
+++ b/demos/shumate-demo-window.c
@@ -24,19 +24,13 @@ struct _ShumateDemoWindow
 {
   GtkApplicationWindow parent_instance;
 
-  ShumateMap *map;
-  GtkOverlay *overlay;
-  ShumateScale *scale;
-  ShumateLicense *license;
-  ShumateCompass *compass;
+  ShumateSimpleMap *map;
   GtkDropDown *layers_dropdown;
   ShumateMapSourceRegistry *registry;
 
   ShumateMapLayer *tile_layer;
   ShumateMarkerLayer *marker_layer;
   ShumatePathLayer *path_layer;
-
-  ShumateMapSource *current_source;
 };
 
 G_DEFINE_TYPE (ShumateDemoWindow, shumate_demo_window, GTK_TYPE_APPLICATION_WINDOW)
@@ -65,44 +59,11 @@ create_marker (ShumateDemoWindow *self, double lat, double lng)
 }
 
 
-static void
-set_map_source (ShumateDemoWindow *self, ShumateMapSource *new_source)
-{
-  ShumateViewport *viewport = shumate_map_get_viewport (self->map);
-  ShumateMapLayer *tile_layer;
-
-  if (self->current_source) {
-    shumate_license_remove_map_source (self->license, self->current_source);
-  }
-
-  g_set_object (&self->current_source, new_source);
-
-  shumate_viewport_set_reference_map_source (viewport, new_source);
-  shumate_map_set_map_source (self->map, new_source);
-
-  tile_layer = shumate_map_layer_new (new_source, viewport);
-  shumate_map_insert_layer_behind (self->map, SHUMATE_LAYER (tile_layer), SHUMATE_LAYER (self->tile_layer));
-  if (self->tile_layer) {
-    shumate_map_remove_layer (self->map, SHUMATE_LAYER (self->tile_layer));
-  }
-  self->tile_layer = tile_layer;
-
-  shumate_license_append_map_source (self->license, new_source);
-}
-
-static void
-on_layers_dropdown_notify_selected (ShumateDemoWindow *self, GParamSpec *pspec, GtkDropDown *dropdown)
-{
-  set_map_source (self, gtk_drop_down_get_selected_item (dropdown));
-}
-
-
 static void
 shumate_demo_window_dispose (GObject *object)
 {
   ShumateDemoWindow *self = SHUMATE_DEMO_WINDOW (object);
 
-  g_clear_object (&self->current_source);
   g_clear_object (&self->registry);
 
   G_OBJECT_CLASS (shumate_demo_window_parent_class)->dispose (object);
@@ -119,12 +80,7 @@ shumate_demo_window_class_init (ShumateDemoWindowClass *klass)
 
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Shumate/Demo/ui/shumate-demo-window.ui");
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, map);
-  gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, overlay);
-  gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, scale);
-  gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, license);
-  gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, compass);
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, layers_dropdown);
-  gtk_widget_class_bind_template_callback (widget_class, on_layers_dropdown_notify_selected);
 }
 
 static gchar *
@@ -175,19 +131,13 @@ shumate_demo_window_init (ShumateDemoWindow *self)
         shumate_map_source_registry_add (self->registry, SHUMATE_MAP_SOURCE (renderer));
     }
 
-  viewport = shumate_map_get_viewport (self->map);
-
-  /* Set the map source */
-  on_layers_dropdown_notify_selected (self, NULL, self->layers_dropdown);
-
-  shumate_scale_set_viewport (self->scale, viewport);
-  shumate_compass_set_viewport (self->compass, viewport);
+  viewport = shumate_simple_map_get_viewport (self->map);
 
   /* Add the marker layers */
   self->marker_layer = shumate_marker_layer_new (viewport);
-  shumate_map_add_layer (self->map, SHUMATE_LAYER (self->marker_layer));
+  shumate_simple_map_add_overlay_layer (self->map, SHUMATE_LAYER (self->marker_layer));
   self->path_layer = shumate_path_layer_new (viewport);
-  shumate_map_add_layer (self->map, SHUMATE_LAYER (self->path_layer));
+  shumate_simple_map_add_overlay_layer (self->map, SHUMATE_LAYER (self->path_layer));
 
   create_marker (self, 35.426667, -116.89);
   create_marker (self, 40.431389, -4.248056);
diff --git a/demos/shumate-demo-window.ui b/demos/shumate-demo-window.ui
index d2ee6d0..f07ddad 100644
--- a/demos/shumate-demo-window.ui
+++ b/demos/shumate-demo-window.ui
@@ -10,41 +10,13 @@
       <object class="GtkHeaderBar">
         <child>
           <object class="GtkDropDown" id="layers_dropdown">
-            <signal name="notify::selected" handler="on_layers_dropdown_notify_selected" swapped="true" />
           </object>
         </child>
       </object>
     </child>
     <child>
-      <object class="GtkOverlay" id="overlay">
-        <property name="vexpand">True</property>
-        <child>
-          <object class="ShumateMap" id="map">
-          </object>
-        </child>
-        <child type="overlay">
-          <object class="ShumateScale" id="scale">
-            <property name="halign">start</property>
-            <property name="valign">end</property>
-          </object>
-        </child>
-        <child type="overlay">
-          <object class="GtkBox">
-            <property name="orientation">vertical</property>
-            <property name="halign">end</property>
-            <property name="valign">end</property>
-            <child>
-              <object class="ShumateCompass" id="compass">
-                <property name="halign">end</property>
-              </object>
-            </child>
-            <child>
-              <object class="ShumateLicense" id="license">
-                <property name="halign">end</property>
-              </object>
-            </child>
-          </object>
-        </child>
+      <object class="ShumateSimpleMap" id="map">
+        <property name="map-source" bind-source="layers_dropdown" bind-property="selected-item" 
bind-flags="sync-create"/>
       </object>
     </child>
   </template>
diff --git a/shumate/meson.build b/shumate/meson.build
index 871ecef..89c7ef4 100644
--- a/shumate/meson.build
+++ b/shumate/meson.build
@@ -16,6 +16,7 @@ libshumate_public_h = [
   'shumate-path-layer.h',
   'shumate-point.h',
   'shumate-scale.h',
+  'shumate-simple-map.h',
   'shumate-raster-renderer.h',
   'shumate-tile.h',
   'shumate-tile-downloader.h',
@@ -61,6 +62,7 @@ libshumate_sources = [
   'shumate-path-layer.c',
   'shumate-point.c',
   'shumate-scale.c',
+  'shumate-simple-map.c',
   'shumate-raster-renderer.c',
   'shumate-tile.c',
   'shumate-tile-downloader.c',
diff --git a/shumate/shumate-compass.c b/shumate/shumate-compass.c
index 32fede2..32f7793 100644
--- a/shumate/shumate-compass.c
+++ b/shumate/shumate-compass.c
@@ -179,13 +179,7 @@ shumate_compass_class_init (ShumateCompassClass *klass)
   display = gdk_display_get_default ();
   if (display)
     {
-      GtkIconTheme *icon_theme;
-      g_autoptr(GtkCssProvider) provider = gtk_css_provider_new ();
-      gtk_css_provider_load_from_resource (provider, "/org/gnome/shumate/compass.css");
-      gtk_style_context_add_provider_for_display (display,
-                                                  GTK_STYLE_PROVIDER (provider),
-                                                  GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
-      icon_theme = gtk_icon_theme_get_for_display (display);
+      GtkIconTheme *icon_theme = gtk_icon_theme_get_for_display (display);
       gtk_icon_theme_add_resource_path (icon_theme, "/org/gnome/shumate/icons");
     }
 }
@@ -197,6 +191,7 @@ shumate_compass_init (ShumateCompass *self)
   gtk_revealer_set_transition_type (GTK_REVEALER (self->revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
   gtk_widget_insert_after (self->revealer, GTK_WIDGET (self), NULL);
   self->image = gtk_image_new_from_icon_name ("map-compass");
+  gtk_image_set_icon_size (GTK_IMAGE (self->image), GTK_ICON_SIZE_LARGE);
   gtk_revealer_set_child (GTK_REVEALER (self->revealer), self->image);
 }
 
diff --git a/shumate/shumate-simple-map.c b/shumate/shumate-simple-map.c
new file mode 100644
index 0000000..568c126
--- /dev/null
+++ b/shumate/shumate-simple-map.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "shumate-simple-map.h"
+#include "shumate-map.h"
+#include "shumate-map-layer.h"
+
+struct _ShumateSimpleMap
+{
+  GtkWidget parent_instance;
+
+  ShumateMapSource *map_source;
+  GList *overlay_layers;
+
+  ShumateMap *map;
+  ShumateMapLayer *map_layer;
+
+  ShumateLicense *license;
+  ShumateScale *scale;
+  ShumateCompass *compass;
+
+  GtkBox *buttons;
+  GtkBox *zoom_buttons;
+};
+
+static void buildable_interface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ShumateSimpleMap, shumate_simple_map, GTK_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_interface_init))
+
+enum {
+  PROP_0,
+  PROP_MAP_SOURCE,
+  PROP_VIEWPORT,
+  PROP_COMPASS,
+  PROP_LICENSE,
+  PROP_SCALE,
+  PROP_SHOW_ZOOM_BUTTONS,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+ShumateSimpleMap *
+shumate_simple_map_new (void)
+{
+  return g_object_new (SHUMATE_TYPE_SIMPLE_MAP, NULL);
+}
+
+
+static void
+shumate_simple_map_finalize (GObject *object)
+{
+  ShumateSimpleMap *self = (ShumateSimpleMap *)object;
+
+  g_clear_object (&self->map_source);
+  g_clear_list (&self->overlay_layers, NULL);
+
+  G_OBJECT_CLASS (shumate_simple_map_parent_class)->finalize (object);
+}
+
+
+static void
+shumate_simple_map_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  ShumateSimpleMap *self = SHUMATE_SIMPLE_MAP (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAP_SOURCE:
+      g_value_set_object (value, shumate_simple_map_get_map_source (self));
+      break;
+
+    case PROP_VIEWPORT:
+      g_value_set_object (value, shumate_simple_map_get_viewport (self));
+      break;
+
+    case PROP_COMPASS:
+      g_value_set_object (value, shumate_simple_map_get_compass (self));
+      break;
+
+    case PROP_SCALE:
+      g_value_set_object (value, shumate_simple_map_get_scale (self));
+      break;
+
+    case PROP_LICENSE:
+      g_value_set_object (value, shumate_simple_map_get_license (self));
+      break;
+
+    case PROP_SHOW_ZOOM_BUTTONS:
+      g_value_set_boolean (value, shumate_simple_map_get_show_zoom_buttons (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+shumate_simple_map_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  ShumateSimpleMap *self = SHUMATE_SIMPLE_MAP (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAP_SOURCE:
+      shumate_simple_map_set_map_source (self, g_value_get_object (value));
+      break;
+
+    case PROP_SHOW_ZOOM_BUTTONS:
+      shumate_simple_map_set_show_zoom_buttons (self, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+shumate_simple_map_dispose (GObject *object)
+{
+  GtkWidget *child;
+
+  while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
+    gtk_widget_unparent (child);
+
+  G_OBJECT_CLASS (shumate_simple_map_parent_class)->dispose (object);
+}
+
+
+static void
+on_zoom_in_clicked (ShumateSimpleMap *self,
+                    GtkButton        *button)
+{
+  shumate_viewport_zoom_in (shumate_map_get_viewport (self->map));
+}
+
+
+static void
+on_zoom_out_clicked (ShumateSimpleMap *self,
+                     GtkButton        *button)
+{
+  shumate_viewport_zoom_out (shumate_map_get_viewport (self->map));
+}
+
+
+static GObject *
+shumate_simple_map_get_internal_child (GtkBuildable *buildable,
+                                       GtkBuilder *builder,
+                                       const char *childname)
+{
+  ShumateSimpleMap *self = SHUMATE_SIMPLE_MAP (buildable);
+
+  if (!g_strcmp0 (childname, "compass"))
+    return G_OBJECT (self->compass);
+  else if (!g_strcmp0 (childname, "license"))
+    return G_OBJECT (self->license);
+  else if (!g_strcmp0 (childname, "scale"))
+    return G_OBJECT (self->scale);
+  else if (!g_strcmp0 (childname, "map"))
+    return G_OBJECT (self->map);
+  else
+    return NULL;
+}
+
+
+static void
+shumate_simple_map_class_init (ShumateSimpleMapClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = shumate_simple_map_dispose;
+  object_class->finalize = shumate_simple_map_finalize;
+  object_class->get_property = shumate_simple_map_get_property;
+  object_class->set_property = shumate_simple_map_set_property;
+
+  properties[PROP_VIEWPORT] =
+    g_param_spec_object ("viewport",
+                         "Viewport",
+                         "Viewport",
+                         SHUMATE_TYPE_VIEWPORT,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MAP_SOURCE] =
+    g_param_spec_object ("map-source",
+                         "Map source",
+                         "Map source",
+                         SHUMATE_TYPE_MAP_SOURCE,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  properties[PROP_COMPASS] =
+    g_param_spec_object ("compass",
+                         "Compass",
+                         "Compass",
+                         SHUMATE_TYPE_COMPASS,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_LICENSE] =
+    g_param_spec_object ("license",
+                         "License",
+                         "License",
+                         SHUMATE_TYPE_LICENSE,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_SCALE] =
+    g_param_spec_object ("scale",
+                         "Scale",
+                         "Scale",
+                         SHUMATE_TYPE_SCALE,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_SHOW_ZOOM_BUTTONS] =
+    g_param_spec_boolean ("show-zoom-buttons",
+                          "Show zoom buttons",
+                          "Show zoom buttons",
+                          TRUE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/shumate/shumate-simple-map.ui");
+  gtk_widget_class_bind_template_child (widget_class, ShumateSimpleMap, map);
+  gtk_widget_class_bind_template_child (widget_class, ShumateSimpleMap, license);
+  gtk_widget_class_bind_template_child (widget_class, ShumateSimpleMap, scale);
+  gtk_widget_class_bind_template_child (widget_class, ShumateSimpleMap, compass);
+  gtk_widget_class_bind_template_child (widget_class, ShumateSimpleMap, zoom_buttons);
+  gtk_widget_class_bind_template_callback (widget_class, on_zoom_in_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_zoom_out_clicked);
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static void
+buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->get_internal_child = shumate_simple_map_get_internal_child;
+}
+
+static void
+shumate_simple_map_init (ShumateSimpleMap *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+
+/**
+ * shumate_simple_map_get_viewport:
+ * @self: a [class@Map]
+ *
+ * Gets the map's viewport, needed for constructing map layers that will be added
+ * to it.
+ *
+ * Returns: (transfer none): a [class@Viewport]
+ */
+ShumateViewport *
+shumate_simple_map_get_viewport (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), NULL);
+  return shumate_map_get_viewport (self->map);
+}
+
+
+/**
+ * shumate_simple_map_get_map_source:
+ * @self: a [class@SimpleMap]
+ *
+ * Gets the map source for the current base layer.
+ *
+ * Returns: (transfer none): a [class@MapSource]
+ */
+ShumateMapSource *
+shumate_simple_map_get_map_source (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), NULL);
+  return self->map_source;
+}
+
+
+/**
+ * shumate_simple_map_set_map_source:
+ * @self: a [class@SimpleMap]
+ * @map_source: (nullable): a [class@MapSource]
+ *
+ * Sets the source for the base map.
+ */
+void
+shumate_simple_map_set_map_source (ShumateSimpleMap *self,
+                                   ShumateMapSource *map_source)
+{
+  ShumateViewport *viewport;
+  ShumateMapLayer *map_layer;
+
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  g_return_if_fail (map_source == NULL || SHUMATE_IS_MAP_SOURCE (map_source));
+
+  viewport = shumate_map_get_viewport (self->map);
+
+  if (self->map_source == map_source)
+    return;
+
+  if (self->map_source) {
+    shumate_license_remove_map_source (self->license, self->map_source);
+  }
+
+  g_set_object (&self->map_source, map_source);
+
+  shumate_viewport_set_reference_map_source (viewport, map_source);
+  shumate_map_set_map_source (self->map, map_source);
+
+  map_layer = shumate_map_layer_new (map_source, viewport);
+  shumate_map_insert_layer_behind (self->map, SHUMATE_LAYER (map_layer), SHUMATE_LAYER (self->map_layer));
+  if (self->map_layer) {
+    shumate_map_remove_layer (self->map, SHUMATE_LAYER (self->map_layer));
+  }
+  self->map_layer = map_layer;
+
+  shumate_license_append_map_source (self->license, map_source);
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MAP_SOURCE]);
+}
+
+
+/**
+ * shumate_simple_map_add_overlay_layer:
+ * @self: a [class@SimpleMap]
+ * @layer: a [class@Layer] to add
+ *
+ * Adds a map layer as an overlay on top of the base map.
+ */
+void
+shumate_simple_map_add_overlay_layer (ShumateSimpleMap *self,
+                                      ShumateLayer     *layer)
+{
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  g_return_if_fail (SHUMATE_IS_LAYER (layer));
+
+  self->overlay_layers = g_list_append (self->overlay_layers, layer);
+  shumate_map_add_layer (self->map, layer);
+}
+
+
+/**
+ * shumate_simple_map_insert_overlay_layer_above:
+ * @self: a [class@SimpleMap]
+ * @layer: a [class@Layer] to insert
+ *
+ * Inserts a map layer as an overlay on top of the base map. The layer will
+ * appear above @sibling, or at the bottom (but still above the base map)
+ * if @sibling is %NULL.
+ */
+void
+shumate_simple_map_insert_overlay_layer_above (ShumateSimpleMap *self,
+                                               ShumateLayer     *layer,
+                                               ShumateLayer     *sibling)
+{
+  gint idx;
+
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  g_return_if_fail (SHUMATE_IS_LAYER (layer));
+  g_return_if_fail (sibling == NULL || SHUMATE_IS_LAYER (sibling));
+
+  if (sibling == NULL)
+    idx = 0;
+  else
+    idx = g_list_index (self->overlay_layers, sibling) + 1;
+
+  self->overlay_layers = g_list_insert (self->overlay_layers, layer, idx);
+  shumate_map_insert_layer_above (self->map, layer, sibling);
+}
+
+
+/**
+ * shumate_simple_map_insert_overlay_layer_behind:
+ * @self: a [class@SimpleMap]
+ * @layer: a [class@Layer] to insert
+ *
+ * Inserts a map layer as an overlay on top of the base map. The layer will
+ * appear just below @sibling, or above everything else if @sibling is %NULL.
+ */
+void
+shumate_simple_map_insert_overlay_layer_behind (ShumateSimpleMap *self,
+                                                ShumateLayer     *layer,
+                                                ShumateLayer     *sibling)
+{
+  GList *sibling_link;
+
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  g_return_if_fail (SHUMATE_IS_LAYER (layer));
+  g_return_if_fail (sibling == NULL || SHUMATE_IS_LAYER (sibling));
+
+  sibling_link = g_list_find (self->overlay_layers, sibling);
+  self->overlay_layers = g_list_insert_before (self->overlay_layers, sibling_link, layer);
+  shumate_map_insert_layer_behind (self->map, layer, sibling);
+}
+
+
+/**
+ * shumate_simple_map_remove_overlay_layer:
+ * @self: a [class@SimpleMap]
+ * @layer: a [class@Layer] that was added to the map previously
+ *
+ * Removes a layer from the map.
+ */
+void
+shumate_simple_map_remove_overlay_layer (ShumateSimpleMap *self,
+                                         ShumateLayer     *layer)
+{
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  g_return_if_fail (SHUMATE_IS_LAYER (layer));
+
+  self->overlay_layers = g_list_remove (self->overlay_layers, layer);
+  shumate_map_remove_layer (self->map, layer);
+}
+
+
+/**
+ * shumate_simple_map_get_compass:
+ * @self: a [class@SimpleMap]
+ *
+ * Gets the compass widget for the map.
+ *
+ * Returns: (transfer none): a [class@Compass]
+ */
+ShumateCompass *
+shumate_simple_map_get_compass (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), NULL);
+
+  return self->compass;
+}
+
+
+/**
+ * shumate_simple_map_get_license:
+ * @self: a [class@SimpleMap]
+ *
+ * Gets the license widget for the map.
+ *
+ * Returns: (transfer none): a [class@License]
+ */
+ShumateLicense *
+shumate_simple_map_get_license (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), NULL);
+
+  return self->license;
+}
+
+
+/**
+ * shumate_simple_map_get_scale:
+ * @self: a [class@SimpleMap]
+ *
+ * Gets the scale widget for the map.
+ *
+ * Returns: (transfer none): a [class@Scale]
+ */
+ShumateScale *
+shumate_simple_map_get_scale (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), NULL);
+  return self->scale;
+}
+
+
+/**
+ * shumate_simple_map_get_show_zoom_buttons:
+ * @self: a [class@SimpleMap]
+ *
+ * Gets whether or not the zoom buttons are shown.
+ *
+ * Returns: %TRUE if the zoom buttons are visible, otherwise %FALSE
+ */
+gboolean
+shumate_simple_map_get_show_zoom_buttons (ShumateSimpleMap *self)
+{
+  g_return_val_if_fail (SHUMATE_IS_SIMPLE_MAP (self), FALSE);
+  return gtk_widget_is_visible (GTK_WIDGET (self->zoom_buttons));
+}
+
+
+/**
+ * shumate_simple_map_set_show_zoom_buttons:
+ * @self: a [class@SimpleMap]
+ * @show_zoom_buttons: %TRUE to show the zoom buttons, %FALSE to hide them
+ *
+ * Sets whether or not the zoom buttons are shown.
+ */
+void
+shumate_simple_map_set_show_zoom_buttons (ShumateSimpleMap *self,
+                                          gboolean          show_zoom_buttons)
+{
+  g_return_if_fail (SHUMATE_IS_SIMPLE_MAP (self));
+  gtk_widget_set_visible (GTK_WIDGET (self->zoom_buttons), show_zoom_buttons);
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_ZOOM_BUTTONS]);
+}
diff --git a/shumate/shumate-simple-map.h b/shumate/shumate-simple-map.h
new file mode 100644
index 0000000..95f0430
--- /dev/null
+++ b/shumate/shumate-simple-map.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <shumate/shumate-map-source.h>
+#include <shumate/shumate-layer.h>
+#include <shumate/shumate-compass.h>
+#include <shumate/shumate-license.h>
+#include <shumate/shumate-scale.h>
+
+G_BEGIN_DECLS
+
+#define SHUMATE_TYPE_SIMPLE_MAP (shumate_simple_map_get_type())
+
+G_DECLARE_FINAL_TYPE (ShumateSimpleMap, shumate_simple_map, SHUMATE, SIMPLE_MAP, GtkWidget)
+
+ShumateSimpleMap *shumate_simple_map_new (void);
+
+ShumateViewport  *shumate_simple_map_get_viewport (ShumateSimpleMap *self);
+
+ShumateMapSource *shumate_simple_map_get_map_source (ShumateSimpleMap *self);
+void              shumate_simple_map_set_map_source (ShumateSimpleMap *self,
+                                                     ShumateMapSource *map_source);
+
+void              shumate_simple_map_add_overlay_layer (ShumateSimpleMap *self,
+                                                        ShumateLayer     *layer);
+void              shumate_simple_map_insert_overlay_layer (ShumateSimpleMap *self,
+                                                           ShumateLayer     *layer,
+                                                           guint             idx);
+void              shumate_simple_map_remove_overlay_layer (ShumateSimpleMap *self,
+                                                           ShumateLayer     *layer);
+
+ShumateCompass   *shumate_simple_map_get_compass (ShumateSimpleMap *self);
+
+ShumateLicense   *shumate_simple_map_get_license (ShumateSimpleMap *self);
+
+ShumateScale     *shumate_simple_map_get_scale (ShumateSimpleMap *self);
+
+gboolean          shumate_simple_map_get_show_zoom_buttons (ShumateSimpleMap *self);
+void              shumate_simple_map_set_show_zoom_buttons (ShumateSimpleMap *self,
+                                                            gboolean          show_zoom_buttons);
+
+G_END_DECLS
diff --git a/shumate/shumate.h b/shumate/shumate.h
index d521dcc..56118b5 100644
--- a/shumate/shumate.h
+++ b/shumate/shumate.h
@@ -43,6 +43,7 @@
 #include "shumate/shumate-raster-renderer.h"
 #include "shumate/shumate-viewport.h"
 #include "shumate/shumate-scale.h"
+#include "shumate/shumate-simple-map.h"
 #include "shumate/shumate-map-source.h"
 #include "shumate/shumate-map-source-registry.h"
 #include "shumate/shumate-tile-downloader.h"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]