[gnome-maps/wip/mlundblad/transit-routing: 3/13] sidebar: Add functionallity for transit routing



commit 0b79a2835cdf3c6896ff8335d9d99a0c7e89e94f
Author: Marcus Lundblad <ml update uu se>
Date:   Thu Mar 17 21:34:11 2016 +0100

    sidebar: Add functionallity for transit routing
    
    Adds a new mode button (enabled when the service file
    indicates an OpenTripPlanner instance, or if explicitly
    pointed out via an env variable).
    Adds showing transit itineraries in addition to regular
    turn-by-turn-based routes, and options for transit route
    search.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755808

 data/gnome-maps.css |    5 +
 data/ui/sidebar.ui  |  298 ++++++++++++++++++++++++++++++++++++++++++++++-----
 src/sidebar.js      |  252 ++++++++++++++++++++++++++++++++++++-------
 3 files changed, 489 insertions(+), 66 deletions(-)
---
diff --git a/data/gnome-maps.css b/data/gnome-maps.css
index 5f500fe..bde40bf 100644
--- a/data/gnome-maps.css
+++ b/data/gnome-maps.css
@@ -86,6 +86,11 @@
     color: rgb(0, 0, 0);
 }
 
+.shaded {
+    background-color: alpha(black, 0.1);
+    border-bottom: 1px solid alpha(black, 0.2);
+}
+
 .route-label {
     padding-left: 2px;
     padding-right: 2px;
diff --git a/data/ui/sidebar.ui b/data/ui/sidebar.ui
index 77347ed..41da44d 100644
--- a/data/ui/sidebar.ui
+++ b/data/ui/sidebar.ui
@@ -94,6 +94,29 @@
                 </style>
               </object>
             </child>
+            <child>
+              <object class="GtkRadioButton" id="modeTransitToggle">
+                <property name="name">mode-transit-toggle</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="draw_indicator">False</property>
+                <property name="group">modeCarToggle</property>
+                <property name="height-request">32</property>
+                <property name="width-request">42</property>
+                <child>
+                  <object class="GtkImage" id="mode-transit-image">
+                    <property name="visible">False</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon-name">route-transit-symbolic</property>
+                  </object>
+                </child>
+                <style>
+                  <class name="transportation-mode-button"/>
+                </style>
+              </object>
+            </child>
             <style>
               <class name="linked"/>
             </style>
@@ -140,55 +163,276 @@
           </object>
         </child>
         <child>
-          <object class="GtkStack" id="instructionStack">
+          <object class="GtkGrid">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="valign">fill</property>
+            <property name="vexpand">True</property>
+            <property name="hexpand_set">True</property>
+            <style>
+              <class name="frame"/>
+            </style>
+            <child>
+              <object class="GtkRevealer" id="transitRevealer">
+                <child>
+                  <object class="GtkStack" id="transitHeader">
+                    <property name="visible">True</property>
+                    <property name="transition-type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
             <child>
-              <object class="GtkScrolledWindow" id="instructionWindow">
-                <property name="name">instruction-window</property>
+              <object class="GtkStack" id="instructionStack">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="valign">fill</property>
-                <property name="vexpand">True</property>
-                <property name="margin">1</property>
-                <property name="hscrollbar_policy">never</property>
                 <child>
-                  <object class="GtkListBox" id="instructionList">
-                    <property name="name">instruction-list</property>
+                  <object class="GtkScrolledWindow" id="instructionWindow">
+                    <property name="name">instruction-window</property>
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="valign">fill</property>
-                    <style>
-                      <class name="frame"/>
-                    </style>
+                    <property name="vexpand">True</property>
+                    <property name="margin">1</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <child>
+                      <object class="GtkListBox" id="instructionList">
+                        <property name="name">instruction-list</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="valign">fill</property>
+                        <property name="hexpand">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="transitWindow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">fill</property>
+                    <property name="vexpand">True</property>
+                    <property name="margin">1</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <child>
+                      <object class="GtkStack" id="transitListStack">
+                        <property name="visible">True</property>
+                        <property 
name="transition-type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property>
+                        <child>
+                          <object class="GtkListBox" id="transitOverviewListBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="name">overview</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkListBox" id="transitItineraryListBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="selection-mode">GTK_SELECTION_NONE</property>
+                          </object>
+                          <packing>
+                            <property name="name">itinerary</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkSpinner" id="instructionSpinner">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="active">True</property>
                   </object>
                 </child>
               </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+              </packing>
             </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="linkButtonStack">
             <child>
-              <object class="GtkSpinner" id="instructionSpinner">
+              <object class="GtkLinkButton" id="graphHopperLinkButton">
+                <property name="label" translatable="yes">Route search by GraphHopper</property>
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="active">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="relief">none</property>
+                <property name="uri">https://graphhopper.com</property>
+                <style>
+                  <class name="small-label"/>
+                </style>
               </object>
+              <packing>
+                <property name="name">graphHopper</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="halign">GTK_ALIGN_END</property>
+                <child>
+                  <object class="GtkLinkButton" id="openTripPlannerLinkButton">
+                    <property name="label" translatable="yes">Route search by OpenTripPlanner</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="relief">none</property>
+                    <!-- opentripplanner.org uses an SSL cert only valid for github
+                         domains... -->
+                    <property name="uri">http://www.opentripplanner.org</property>
+                    <style>
+                      <class name="small-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton">
+                    <property name="visible">True</property>
+                    <property name="popover">openTripPlannerDisclaimerPopover</property>
+                    <property name="halign">GTK_ALIGN_END</property>
+                    <property name="margin-top">5</property>
+                    <property name="margin-bottom">5</property>
+                    <property name="margin-end">5</property>
+                    <property name="margin-start">5</property>
+                    <style>
+                      <class name="flat"/>
+                    </style>
+                    <child>
+                      <object class="GtkGrid">
+                        <property name="visible">True</property>
+                        <property name="valign">GTK_ALIGN_CENTER</property>
+                        <child>
+                          <object class="GtkImage">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">GTK_ALIGN_CENTER</property>
+                            <property name="hexpand">False</property>
+                            <property name="icon-name">dialog-information-symbolic</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="name">openTripPlanner</property>
+              </packing>
             </child>
           </object>
         </child>
+      </object>
+    </child>
+  </template>
+  <object class="GtkPopover" id="openTripPlannerDisclaimerPopover">
+    <property name="visible">False</property>
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
         <child>
-          <object class="GtkLinkButton" id="linkbutton1">
-            <property name="label" translatable="yes">Route search by GraphHopper</property>
+          <object class="GtkLabel">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="use_action_appearance">False</property>
-            <property name="relief">none</property>
-            <property name="uri">https://graphhopper.com</property>
-            <style>
-              <class name="small-label"/>
-            </style>
+            <property name="margin-top">5</property>
+            <property name="margin-bottom">5</property>
+            <property name="margin-start">5</property>
+            <property name="margin-end">5</property>
+            <property name="label" translatable="yes">Routing itineraries for public transit is provided by 
GNOME
+using timetable data obtained from transit companies or agencies.
+The companies and agencies can not be held responsible for the results shown.
+GNOME can not guarantee correctness of the itineraries and schedules shown.
+Names and brands shown are to be considered as registred trademarks when applicable.</property>
           </object>
         </child>
       </object>
     </child>
-  </template>
+  </object>
+  <object class="GtkGrid" id="transitItineraryHeader">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <style>
+      <class name="shaded"/>
+    </style>
+    <child>
+      <object class="GtkButton" id="transitItineraryBackButton">
+        <property name="visible">True</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="margin-top">4</property>
+        <property name="margin-bottom">4</property>
+        <property name="halign">GTK_ALIGN_START</property>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="valign">GTK_ALIGN_CENTER</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">False</property>
+                <property name="icon-name">go-previous-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left-attach">0</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="transitItineraryTimeLabel">
+        <property name="visible">True</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="margin-top">4</property>
+        <property name="margin-bottom">4</property>
+        <property name="hexpand">False</property>
+        <property name="halign">GTK_ALIGN_START</property>
+      </object>
+      <packing>
+        <property name="left-attach">1</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="transitItineraryDurationLabel">
+        <property name="visible">True</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="margin-top">4</property>
+        <property name="margin-bottom">4</property>
+        <property name="hexpand">True</property>
+        <property name="halign">GTK_ALIGN_START</property>
+        <style>
+          <class name="dim-label"/>
+        </style>
+      </object>
+      <packing>
+        <property name="left-attach">2</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+  </object>
 </interface>
diff --git a/src/sidebar.js b/src/sidebar.js
index 64ec5e6..9ad76f5 100644
--- a/src/sidebar.js
+++ b/src/sidebar.js
@@ -33,6 +33,11 @@ const PlaceStore  = imports.placeStore;
 const RouteEntry = imports.routeEntry;
 const RouteQuery = imports.routeQuery;
 const StoredRoute = imports.storedRoute;
+const TransitArrivalRow = imports.transitArrivalRow;
+const TransitItineraryRow = imports.transitItineraryRow;
+const TransitLegRow = imports.transitLegRow;
+const TransitMoreRow = imports.transitMoreRow;
+const TransitOptionsPanel = imports.transitOptionsPanel;
 const Utils = imports.utils;
 
 const Sidebar = new Lang.Class({
@@ -48,40 +53,72 @@ const Sidebar = new Lang.Class({
                         'modeBikeToggle',
                         'modeCarToggle',
                         'modePedestrianToggle',
-                        'timeInfo' ],
+                        'modeTransitToggle',
+                        'timeInfo',
+                        'linkButtonStack',
+                        'transitWindow',
+                        'transitRevealer',
+                        //'transitOptionsPanel',
+                        'transitHeader',
+                        'transitListStack',
+                        'transitOverviewListBox',
+                        'transitItineraryHeader',
+                        'transitItineraryListBox',
+                        'transitItineraryBackButton',
+                        'transitItineraryTimeLabel',
+                        'transitItineraryDurationLabel'],
 
     _init: function(mapView) {
         this.parent({ transition_type: Gtk.RevealerTransitionType.SLIDE_LEFT });
 
         this._mapView = mapView;
 
+        this._query = Application.routeQuery;
         this._initInstructionList();
-
         this._initTransportationToggles(this._modePedestrianToggle,
                                         this._modeBikeToggle,
-                                        this._modeCarToggle);
-        this._initQuerySignals();
+                                        this._modeCarToggle,
+                                        this._modeTransitToggle);
 
-        let query = Application.routeService.query;
-
-        query.addPoint(0);
-        query.addPoint(1);
+        this._initQuerySignals();
+        this._query.addPoint(0);
+        this._query.addPoint(1);
+        this._switchRoutingMode(RouteQuery.Transportation.CAR);
+        /* enable/disable transit mode switch based on the presence of
+         * OpenTripPlanner
+         */
+        if (Application.routingDelegator.openTripPlanner.enabled)
+            this._modeTransitToggle.sensitive = true;
+        /* I could not get the custom GTK+ template widget to init properly
+         * from the UI file, we also need to manually insert the transit
+         * itinerary header widget into the GtkStack to get the correct
+         * animation direction.
+         */
+        this._transitOptionsPanel =
+            new TransitOptionsPanel.TransitOptionsPanel({ visible: true });
+        this._transitHeader.add_named(this._transitOptionsPanel, 'options');
+        this._transitHeader.add_named(this._transitItineraryHeader,
+                                      'itinerary-header');
     },
 
-    _initTransportationToggles: function(pedestrian, bike, car) {
-        let query = Application.routeService.query;
+    _initTransportationToggles: function(pedestrian, bike, car, transit) {
         let transport = RouteQuery.Transportation;
 
         let onToggle = function(mode, button) {
-            if (button.active && query.transportation !== mode)
-                query.transportation = mode;
+            let previousMode = this._query.transportation;
+
+            if (button.active && previousMode !== mode) {
+                this._switchRoutingMode(mode);
+                this._query.transportation = mode;
+            }
         };
         pedestrian.connect('toggled', onToggle.bind(this, transport.PEDESTRIAN));
         car.connect('toggled', onToggle.bind(this, transport.CAR));
         bike.connect('toggled', onToggle.bind(this, transport.BIKE));
+        transit.connect('toggled', onToggle.bind(this, transport.TRANSIT))
 
         let setToggles = function() {
-            switch(query.transportation) {
+            switch(Application.routeQuery.transportation) {
             case transport.PEDESTRIAN:
                 pedestrian.active = true;
                 break;
@@ -91,21 +128,39 @@ const Sidebar = new Lang.Class({
             case transport.BIKE:
                 bike.active = true;
                 break;
+            case transport.TRANSIT:
+                transit.active = true;
+                break;
             }
+
+            this._switchRoutingMode(Application.routeQuery.transportation);
         };
 
-        setToggles();
-        query.connect('notify::transportation', setToggles);
+        setToggles.bind(this)();
+        this._query.connect('notify::transportation', setToggles.bind(this));
     },
 
-    _initQuerySignals: function() {
-        let query = Application.routeService.query;
+    _switchRoutingMode: function(mode) {
+        if (mode === RouteQuery.Transportation.TRANSIT) {
+            Application.routingDelegator.useTransit = true;
+            this._linkButtonStack.visible_child_name = 'openTripPlanner';
+            this._transitOptionsPanel.reset();
+            this._transitRevealer.reveal_child = true;
+            this._clearInstructions();
+        } else {
+            Application.routingDelegator.useTransit = false;
+            this._linkButtonStack.visible_child_name = 'graphHopper';
+            this._transitRevealer.reveal_child = false;
+            Application.routingDelegator.openTripPlanner.plan.deselectItinerary();
+        }
+    },
 
-        query.connect('point-added', (function(obj, point, index) {
+    _initQuerySignals: function() {
+        this._query.connect('point-added', (function(obj, point, index) {
             this._createRouteEntry(index, point);
         }).bind(this));
 
-        query.connect('point-removed', (function(obj, point, index) {
+        this._query.connect('point-removed', (function(obj, point, index) {
             let row = this._entryList.get_row_at_index(index);
             row.destroy();
         }).bind(this));
@@ -133,40 +188,55 @@ const Sidebar = new Lang.Class({
         if (type === RouteEntry.Type.FROM) {
             routeEntry.button.connect('clicked', (function() {
                 let lastIndex = this._entryList.get_children().length;
-                Application.routeService.query.addPoint(lastIndex - 1);
+                this._query.addPoint(lastIndex - 1);
             }).bind(this));
 
             this.bind_property('child-revealed',
                                routeEntry.entry, 'has_focus',
                                GObject.BindingFlags.DEFAULT);
         } else if (type === RouteEntry.Type.VIA) {
-            routeEntry.button.connect('clicked', function() {
+            routeEntry.button.connect('clicked', (function() {
                 let row = routeEntry.get_parent();
-                Application.routeService.query.removePoint(row.get_index());
-            });
+                this._query.removePoint(row.get_index());
+            }).bind(this));
         }
 
         this._initRouteDragAndDrop(routeEntry);
     },
 
     _initInstructionList: function() {
-        let route = Application.routeService.route;
-        let query = Application.routeService.query;
+        let route = Application.routingDelegator.graphHopper.route;
+        let transitPlan = Application.routingDelegator.openTripPlanner.plan;
 
         route.connect('reset', (function() {
             this._clearInstructions();
 
             let length = this._entryList.get_children().length;
             for (let index = 1; index < (length - 1); index++) {
-                query.removePoint(index);
+                this._query.removePoint(index);
             }
         }).bind(this));
 
-        query.connect('notify', (function() {
-            if (query.isValid())
+        transitPlan.connect('reset', (function() {
+            this._clearTransitOverview();
+            this._showTransitOverview();
+            this._instructionStack.visible_child = this._transitWindow;
+            /* don't remove query points as with the turn-based routing,
+             * since we might get "no route" because of the time selected
+             * and so on */
+        }).bind(this));
+
+        this._query.connect('notify', (function() {
+            if (this._query.isValid()) {
                 this._instructionStack.visible_child = this._instructionSpinner;
-            else
-                this._clearInstructions();
+            } else {
+                if (this._query.transportation === RouteQuery.Transportation.TRANSIT) {
+                    this._clearTransitOverview();
+                    this._showTransitOverview();
+                } else {
+                    this._clearInstructions();
+                }
+            }
 
             if (this._storeRouteTimeoutId)
                 this._cancelStore();
@@ -181,11 +251,11 @@ const Sidebar = new Lang.Class({
 
             this._storeRouteTimeoutId = Mainloop.timeout_add(5000, (function() {
                 let placeStore = Application.placeStore;
-                let places = query.filledPoints.map(function(point) {
+                let places = this._query.filledPoints.map(function(point) {
                     return point.place;
                 });
                 let storedRoute = new StoredRoute.StoredRoute({
-                    transportation: query.transportation,
+                    transportation: this._query.transportation,
                     route: route,
                     places: places,
                     geoclue: Application.geoclue
@@ -213,8 +283,114 @@ const Sidebar = new Lang.Class({
             if (row)
                 this._mapView.showTurnPoint(row.turnPoint);
         }).bind(this));
+
+        transitPlan.connect('update', (function() {
+            this._clearTransitOverview();
+            this._showTransitOverview();
+            this._populateTransitItineraryOverview();
+        }).bind(this));
+
+        /* use list separators for the transit itinerary overview list */
+        this._transitOverviewListBox.set_header_func(function(row, prev) {
+            if (prev)
+                row.set_header(new Gtk.Separator());
+        });
+
+        this._transitOverviewListBox.connect('row-activated',
+                                             this._onItineraryOverviewRowActivated.bind(this));
+        this._transitItineraryBackButton.connect('clicked',
+                                                 this._showTransitOverview.bind(this));
+
     },
 
+    _clearTransitOverview: function() {
+        let listBox = this._transitOverviewListBox;
+        listBox.forall(listBox.remove.bind(listBox));
+
+        this._instructionStack.visible_child = this._transitWindow;
+        this._timeInfo.label = '';
+        this._distanceInfo.label = '';
+    },
+
+    _clearTransitItinerary: function() {
+        let listBox = this._transitItineraryListBox;
+        listBox.forall(listBox.remove.bind(listBox));
+    },
+
+    _showTransitOverview: function() {
+        let plan = Application.routingDelegator.openTripPlanner.plan;
+
+        this._transitListStack.visible_child_name = 'overview';
+        this._transitHeader.visible_child_name = 'options';
+        plan.deselectItinerary();
+    },
+
+    _showTransitItineraryView: function() {
+        this._transitListStack.visible_child_name = 'itinerary';
+        this._transitHeader.visible_child_name = 'itinerary-header';
+    },
+
+    _populateTransitItineraryOverview: function() {
+        let plan = Application.routingDelegator.openTripPlanner.plan;
+
+        plan.itineraries.forEach((function(itinerary) {
+            let row =
+                new TransitItineraryRow.TransitItineraryRow({ visible: true,
+                                                              itinerary: itinerary });
+            this._transitOverviewListBox.add(row);
+        }).bind(this));
+        /* add the "load more" row */
+        this._transitOverviewListBox.add(
+            new TransitMoreRow.TransitMoreRow({ visible: true }));
+
+        /* add an empty list row to get a final separator */
+        this._transitOverviewListBox.add(new Gtk.ListBoxRow({ visible: true }));
+    },
+
+    _onItineraryActivated: function(itinerary) {
+        let plan = Application.routingDelegator.openTripPlanner.plan;
+
+        this._populateTransitItinerary(itinerary);
+        this._showTransitItineraryView();
+        plan.selectItinerary(itinerary);
+    },
+
+    _onMoreActivated: function(row) {
+        row.startLoading();
+        Application.routingDelegator.openTripPlanner.fetchMoreResults();
+    },
+
+    _onItineraryOverviewRowActivated: function(listBox, row) {
+        this._transitOverviewListBox.unselect_all();
+
+        if (row.itinerary)
+            this._onItineraryActivated(row.itinerary);
+        else
+            this._onMoreActivated(row);
+    },
+
+    _populateTransitItinerary: function(itinerary) {
+        this._transitItineraryTimeLabel.label =
+            itinerary.prettyPrintTimeInterval();
+        this._transitItineraryDurationLabel.label =
+            itinerary.prettyPrintDuration();
+
+        this._clearTransitItinerary();
+        for (let i = 0; i < itinerary.legs.length; i++) {
+            let leg = itinerary.legs[i];
+            let row = new TransitLegRow.TransitLegRow({ leg: leg,
+                                                        start: i === 0,
+                                                        mapView: this._mapView });
+            this._transitItineraryListBox.add(row);
+        }
+
+        /* insert the additional arrival row, showing the arrival place and time */
+        this._transitItineraryListBox.add(
+            new TransitArrivalRow.TransitArrivalRow({ itinerary: itinerary,
+                                                      mapView: this._mapView }));
+    },
+
+
     _clearInstructions: function() {
         let listBox = this._instructionList;
         listBox.forall(listBox.remove.bind(listBox));
@@ -226,8 +402,7 @@ const Sidebar = new Lang.Class({
 
     // Iterate over points and establish the new order of places
     _reorderRoutePoints: function(srcIndex, destIndex) {
-        let query = Application.routeService.query;
-        let points = query.points;
+        let points = this._query.points;
         let srcPlace = this._draggedPoint.place;
 
         // Determine if we are swapping from "above" or "below"
@@ -235,19 +410,18 @@ const Sidebar = new Lang.Class({
 
         // Hold off on notifying the changes to query.points until
         // we have re-arranged the places.
-        query.freeze_notify();
+        this._query.freeze_notify();
 
         for (let i = destIndex; i !== (srcIndex + step); i += step) {
             // swap
             [points[i].place, srcPlace] = [srcPlace, points[i].place];
         }
 
-        query.thaw_notify();
+        this._query.thaw_notify();
     },
 
     _onDragDrop: function(row, context, x, y, time) {
-        let query = Application.routeService.query;
-        let srcIndex = query.points.indexOf(this._draggedPoint);
+        let srcIndex = this._query.points.indexOf(this._draggedPoint);
         let destIndex = row.get_index();
 
         this._reorderRoutePoints(srcIndex, destIndex);
@@ -352,4 +526,4 @@ const Sidebar = new Lang.Class({
 
         this._initDragWidget();
     }
-});
+})


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