Embedded Maps with ShumateSimpleMap

29 January 2022

The first alpha release of libshumate is out, and one of the notable new features is ShumateSimpleMap. If you just want to embed a map in your app without thinking too much about layers, copyright licenses, and viewports, ShumateSimpleMap is what you’re looking for.

Displaying a map

ShumateSimpleMap is designed to work out of the box with very little code.

Shumate.SimpleMap map { }
<object class="ShumateSimpleMap" id="map"></object>
map_source = Shumate.MapSourceRegistry.new_with_defaults().get_by_id(Shumate.MAP_SOURCE_OSM_MAPNIK)
map.set_map_source(map_source)

This code will get you a map widget with the default OpenStreetMap style. (Keep in mind that this style is only available for testing, or with permission from the OSM Foundation to use their tile servers). It also contains all the widgets you’d expect in an embedded map: zoom buttons, license/copyright information, and a scale.

Adding a Marker

You can create a marker layer, then add a marker to it:

Shumate.Marker marker {
  latitude: -48.8767;
  longitude: -123.3933;
  Image {
    icon-name: "view-pin-symbolic";
  }
}
<object class="ShumateMarker" id="marker">
  <property name="latitude">-48.8767</property>
  <property name="longitude">-123.3933</property>
  <child>
    <object class="GtkImage">
      <property name="icon-name">view-pin-symbolic</property>
    </object>
  </child>
</object>
viewport = map.get_viewport()
marker_layer = Shumate.MarkerLayer.new(viewport)
marker_layer.add_marker(marker)
map.add_overlay_layer(marker_layer)

Markers aren’t restricted to just icons. They can contain any widget you want, even containers with multiple children or interactive widgets like buttons.

Setting the Viewport

The “viewport” refers to the displayed location of the map, its zoom level, rotation, etc. You can use the Shumate.Viewport methods to change the map’s viewport.

viewport.set_location(-48.8767, -123.3933)
viewport.set_zoom_level(3)

Accessing Internal Children

ShumateSimpleMap exposes internal children “compass”, “license”, “scale”, and “map”. You can use this, for example, to add extra license text:

Shumate.SimpleMap map {
  [internal-child license]
  Shumate.License {
    extra-text: _("Additional data from Wikipedia");
  }
}
<object class="ShumateSimpleMap" id="map">
  <child internal-child="license">
    <object class="ShumateLicense">
      <property name="extra-text">Additional data from Wikipedia</property>
    </object>
  </child>
</object>

You can also overlay your own widgets over the map. Just add them as children of the ShumateSimpleMap, and use the halign and valign properties to position them (just like a Gtk.Overlay):

Shumate.SimpleMap map {
  Gtk.Button {
    label: _("Open in Maps");
    halign: start;
    valign: start;
    margin-start: 6;
    margin-top: 6;
  }
}
<object class="ShumateSimpleMap" id="map">
  <child>
    <object class="GtkButton">
      <property name="label">Open in Maps</property>
      <property name="halign">start</property>
      <property name="valign">start</property>
      <property name="margin-start">6</property>
      <property name="margin-top">6</property>
    </object>
  </child>
</object>

Next

Next Steps for Blueprint

Blueprint is my markup language for creating GTK user interfaces. Since the last blog post, I and several contributors have fixed a number of bugs that have come up and added several bits of missing syntax. Thanks to everyone who’s contributed by reporting issues or submitting merge requests!

Previous

Introducing Blueprint: A New Way to Craft User Interfaces

In a recent blog post, I presented my latest project, a markup language for creating GTK user interfaces. I’m excited to announce it’s now ready to use!