[gnome-maps] Reuse UserLocationMarker when location updates



commit 5b32a2965b3a8fb5d6c129e0662c41bb36636b4f
Author: James Westman <flyingpimonster gmail com>
Date:   Wed Jan 1 21:56:03 2020 -0600

    Reuse UserLocationMarker when location updates
    
    Fixes #202. Also fixes the UserLocationBubble flickering whenever the
    location changes.

 data/ui/user-location-bubble.ui |  1 -
 po/POTFILES.in                  |  1 +
 src/mapMarker.js                | 33 +++++++++++++++++++-----
 src/mapView.js                  | 21 +++++++--------
 src/userLocationBubble.js       | 26 ++++++++++++-------
 src/userLocationMarker.js       | 57 +++++++++++++++++++++++++++++------------
 6 files changed, 94 insertions(+), 45 deletions(-)
---
diff --git a/data/ui/user-location-bubble.ui b/data/ui/user-location-bubble.ui
index 085cca2a..9bf448b6 100644
--- a/data/ui/user-location-bubble.ui
+++ b/data/ui/user-location-bubble.ui
@@ -25,7 +25,6 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="halign">start</property>
-            <property name="label" translatable="yes" comments="To translators: %s can be 
&quot;Unknown&quot;, &quot;Exact&quot; or &quot;%f km²&quot;">Accuracy: %s</property>
             <style>
               <class name="bubble-subtitle"/>
             </style>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 529f5163..ca98b288 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -57,5 +57,6 @@ src/transitMoreRow.js
 src/transitOptionsPanel.js
 src/transitPlan.js
 src/translations.js
+src/userLocationBubble.js
 src/utils.js
 src/transitplugins/openTripPlanner.js
diff --git a/src/mapMarker.js b/src/mapMarker.js
index 3e614737..49cf491c 100644
--- a/src/mapMarker.js
+++ b/src/mapMarker.js
@@ -76,13 +76,17 @@ var MapMarker = GObject.registerClass({
 
             // Some markers are draggable, we want to sync the marker location and
             // the location saved in the GeocodePlace
-            this.bind_property('latitude',
-                               this.place.location, 'latitude',
-                               GObject.BindingFlags.DEFAULT);
+            // These are not bindings because the place may have a different
+            // location later
+            this.connect('notify::latitude', () => {
+                this.place.location.latitude = this.latitude;
+            });
+            this.connect('notify::longitude', () => {
+                this.place.location.longitude = this.longitude;
+            });
+
+            this.place.connect('notify::location', this._onLocationChanged.bind(this));
 
-            this.bind_property('longitude',
-                               this.place.location, 'longitude',
-                               GObject.BindingFlags.DEFAULT);
             this._view.bind_property('latitude', this, 'view-latitude',
                                      GObject.BindingFlags.DEFAULT);
             this._view.bind_property('longitude', this, 'view-longitude',
@@ -170,6 +174,17 @@ var MapMarker = GObject.registerClass({
         this.set_translation(-this.anchor.x, -this.anchor.y, 0);
     }
 
+    _onLocationChanged() {
+        this.set_location(this.place.location.latitude, this.place.location.longitude);
+
+        if (this._bubble) {
+            if (this._isInsideView())
+                this._positionBubble(this._bubble);
+            else
+                this.hideBubble();
+        }
+    }
+
     /**
      * Returns: The anchor point for the marker icon, relative to the
      * top left corner.
@@ -295,6 +310,12 @@ var MapMarker = GObject.registerClass({
         let dragMotionSignalId = this.connect('drag-motion', () => {
             this.set_selected(false);
         });
+        let markerHiddenSignalId = this.connect('notify::visible', () => {
+            if (!this.visible) {
+                this.set_selected(false);
+            }
+        });
+
         Utils.once(this.bubble, 'closed', () => {
             this._mapView.disconnect(markerSelectedSignalId);
             this._mapView.disconnect(goingToSignalId);
diff --git a/src/mapView.js b/src/mapView.js
index 6197f0ed..feedf2c2 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -469,22 +469,19 @@ var MapView = GObject.registerClass({
 
         if (Application.geoclue.state !== Geoclue.State.ON) {
             if (this._userLocation)
-                this._userLocation.destroy();
-            this._userLocation = null;
+                this._userLocation.visible = false;
             return;
         }
 
-        let place = Application.geoclue.place;
-        let previousSelected = this._userLocation && this._userLocation.selected;
-
-        if (this._userLocation)
-            this._userLocation.destroy();
-        this._userLocation = new UserLocationMarker.UserLocationMarker({ place: place,
-                                                                         mapView: this });
-        this._userLocationLayer.remove_all();
-        this._userLocation.addToLayer(this._userLocationLayer);
+        if (!this._userLocation) {
+            let place = Application.geoclue.place;
+            this._userLocation = new UserLocationMarker.UserLocationMarker({ place: place,
+                                                                             mapView: this });
+            this._userLocationLayer.remove_all();
+            this._userLocation.addToLayer(this._userLocationLayer);
+        }
 
-        this._userLocation.selected = previousSelected;
+        this._userLocation.visible = true;
 
         this.emit('user-location-changed');
     }
diff --git a/src/userLocationBubble.js b/src/userLocationBubble.js
index 75e2c5d0..77320e53 100644
--- a/src/userLocationBubble.js
+++ b/src/userLocationBubble.js
@@ -19,6 +19,8 @@
  * Author: Damián Nohales <damiannohales gmail com>
  */
 
+const _ = imports.gettext.gettext;
+
 const GObject = imports.gi.GObject;
 
 const MapBubble = imports.mapBubble;
@@ -28,9 +30,9 @@ var UserLocationBubble = GObject.registerClass(
 class UserLocationBubble extends MapBubble.MapBubble {
 
     _init(params) {
-        let ui = Utils.getUIObject('user-location-bubble', [ 'grid-content',
-                                                             'label-accuracy',
-                                                             'label-coordinates' ]);
+        this._ui = Utils.getUIObject('user-location-bubble', [ 'grid-content',
+                                                               'label-accuracy',
+                                                               'label-coordinates' ]);
         params.buttons = MapBubble.Button.ROUTE |
                          MapBubble.Button.SEND_TO |
                          MapBubble.Button.CHECK_IN;
@@ -42,12 +44,18 @@ class UserLocationBubble extends MapBubble.MapBubble {
         this.image.icon_name = 'find-location-symbolic';
         this.image.pixel_size = 48;
 
-        let accuracyDescription = Utils.getAccuracyDescription(this.place.location.accuracy);
-        ui.labelAccuracy.label = ui.labelAccuracy.label.format(accuracyDescription);
-        ui.labelCoordinates.label = this.place.location.latitude.toFixed(5)
-                                  + ', '
-                                  + this.place.location.longitude.toFixed(5);
+        this.updateLocation();
+        this.content.add(this._ui.gridContent);
+    }
 
-        this.content.add(ui.gridContent);
+    updateLocation() {
+        /* Called by the UserLocationMarker when its location changes */
+
+        let accuracyDescription = Utils.getAccuracyDescription(this.place.location.accuracy);
+        /* Translators: %s can be "Unknown", "Exact" or "%f km" (or ft/mi/m) */
+        this._ui.labelAccuracy.label = _("Accuracy: %s").format(accuracyDescription);
+        this._ui.labelCoordinates.label = this.place.location.latitude.toFixed(5)
+                                          + ', '
+                                          + this.place.location.longitude.toFixed(5);
     }
 });
diff --git a/src/userLocationMarker.js b/src/userLocationMarker.js
index fc121b55..cb4b4189 100644
--- a/src/userLocationMarker.js
+++ b/src/userLocationMarker.js
@@ -45,6 +45,9 @@ class AccuracyCirleMarker extends Champlain.Point {
     }
 
     refreshGeometry(view) {
+        this.latitude = this.place.location.latitude;
+        this.longitude = this.place.location.longitude;
+
         let zoom = view.zoom_level;
         let source = view.map_source;
         let metersPerPixel = source.get_meters_per_pixel(zoom,
@@ -67,21 +70,15 @@ class UserLocationMarker extends MapMarker.MapMarker {
     _init(params) {
         super._init(params);
 
-        if (this.place.location.heading > -1) {
-            let actor = this._actorFromIconName('user-location-compass', 0);
-            actor.set_pivot_point(0.5, 0.5);
-            actor.set_rotation_angle(Clutter.RotateAxis.Z_AXIS, this.place.location.heading);
-            this.add_actor(actor);
-        } else {
-            this.add_actor(this._actorFromIconName('user-location', 0));
-        }
+        this._accuracyMarker = new AccuracyCircleMarker({ place: this.place });
+        this.connect('notify::view-zoom-level',
+                     () => this._accuracyMarker.refreshGeometry(this._view));
+         this._accuracyMarker.refreshGeometry(this._view);
 
-        if (this.place.location.accuracy > 0) {
-            this._accuracyMarker = new AccuracyCircleMarker({ place: this.place });
-            this._accuracyMarker.refreshGeometry(this._view);
-            this.connect('notify::view-zoom-level',
-                         () => this._accuracyMarker.refreshGeometry(this._view));
-        }
+        this.place.connect('notify::location', this._updateLocation.bind(this));
+        this._updateLocation();
+
+        this.connect('notify::visible', this._updateAccuracyCircle.bind(this));
     }
 
     get anchor() {
@@ -95,9 +92,35 @@ class UserLocationMarker extends MapMarker.MapMarker {
     }
 
     addToLayer(layer) {
-        if (this._accuracyMarker)
-            layer.add_marker(this._accuracyMarker);
-
+        layer.add_marker(this._accuracyMarker);
         layer.add_marker(this);
     }
+
+    _updateLocation() {
+        if (this._actor) {
+            this._actor.destroy();
+            delete this._actor;
+        }
+
+        if (this.place.location.heading > -1) {
+            this._actor = this._actorFromIconName('user-location-compass', 0);
+            this._actor.set_pivot_point(0.5, 0.5);
+            this._actor.set_rotation_angle(Clutter.RotateAxis.Z_AXIS, this.place.location.heading);
+        } else {
+            this._actor = this._actorFromIconName('user-location', 0);
+        }
+        this.add_actor(this._actor);
+
+        this._updateAccuracyCircle();
+        if (this._bubble)
+            this._bubble.updateLocation();
+    }
+
+    _updateAccuracyCircle() {
+        if (this.visible && this.place.location.accuracy > 0) {
+            this._accuracyMarker.refreshGeometry(this._view);
+        } else {
+            this._accuracyMarker.visible = false;
+        }
+    }
 });


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