[gnome-maps/wip/routing: 35/35] WIP Add sidebar support



commit 66dc3925e3acf82edc5f881c709d0903a214e49a
Author: Mattias Bengtsson <mattias jc bengtsson gmail com>
Date:   Sat Sep 7 11:40:11 2013 +0200

    WIP Add sidebar support

 data/gnome-maps.css                      |   32 +++
 data/icons/Makefile.am                   |    6 +
 data/icons/direction-continue.png        |  Bin 0 -> 488 bytes
 data/icons/direction-left.png            |  Bin 0 -> 587 bytes
 data/icons/direction-right.png           |  Bin 0 -> 564 bytes
 data/icons/direction-roundabout.png      |  Bin 0 -> 1137 bytes
 data/icons/direction-sharpleft.png       |  Bin 0 -> 678 bytes
 data/icons/direction-sharpright.png      |  Bin 0 -> 659 bytes
 data/icons/direction-slightleft.png      |  Bin 0 -> 616 bytes
 data/icons/direction-slightright.png     |  Bin 0 -> 611 bytes
 data/icons/direction-uturn.png           |  Bin 0 -> 804 bytes
 data/icons/directions.svg                |  329 ++++++++++++++++++++++++++++++
 data/icons/route-car-symbolic.svg        |   67 ++++++
 data/icons/route-pedestrian-symbolic.svg |   78 +++++++
 data/icons/route-transit-symbolic.svg    |   68 ++++++
 src/gnome-maps.data.gresource.xml        |   18 ++
 src/gnome-maps.js.gresource.xml          |    1 +
 src/instruction-row.ui                   |   43 ++++
 src/mapLocation.js                       |    2 +-
 src/mapView.js                           |   37 +++-
 src/placeStore.js                        |   17 ++
 src/routeService.js                      |    9 +-
 src/sidebar.js                           |  303 +++++++++++++++++++++++-----
 src/sidebar.ui                           |  297 +++++++++++++++++++++++++++
 src/turnLocation.js                      |   42 ++++
 25 files changed, 1285 insertions(+), 64 deletions(-)
---
diff --git a/data/gnome-maps.css b/data/gnome-maps.css
index c093548..64aedda 100644
--- a/data/gnome-maps.css
+++ b/data/gnome-maps.css
@@ -12,6 +12,38 @@
        border-radius: 0px;
 }
 
+#sidebar-form {
+    padding-bottom: 15px;
+}
+
+#sidebar-form > GtkLabel {
+    padding-right: 5px;
+}
+
+#sidebar-form .transportation-mode-button > GtkImage {
+    padding-left:   7px;
+    padding-right:  7px;
+    padding-top:    4px;
+    padding-bottom: 4px;
+}
+
+#sidebar-instruction-list > GtkBox {
+    margin-left: 10px;
+    margin-right: 10px;
+    padding-right: 10px;
+    padding-left: 10px;
+}
+#sidebar-instruction-list GtkImage {
+    margin-right: 5px;
+}
+
+.search-popover GtkTreeView {
+       border-style: solid;
+       border-width: 1px;
+       border-color: darker(@theme_bg_color);
+       background-color: white;
+}
+
 .zoom-control {
     background-color: transparent;
 }
diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
index 55493aa..bc28ae7 100644
--- a/data/icons/Makefile.am
+++ b/data/icons/Makefile.am
@@ -1,3 +1,6 @@
+# -*- indent-tabs-mode: nil; tab-width: 4 -*-
+# vim: set et ts=4 sw=4: */
+
 NULL =
 
 public_icons_themes =                          \
@@ -17,6 +20,9 @@ imagesdir = $(datadir)/gnome-maps/pixmaps
 images_DATA =                                   \
        bubble.svg                              \
        pin.svg                                 \
+    route-car-symbolic.svg         \
+    route-transit-symbolic.svg     \
+    route-pedestrian-symbolic.svg  \
         $(NULL)
 
 noinst_DATA =                                  \
diff --git a/data/icons/direction-continue.png b/data/icons/direction-continue.png
new file mode 100644
index 0000000..141690d
Binary files /dev/null and b/data/icons/direction-continue.png differ
diff --git a/data/icons/direction-left.png b/data/icons/direction-left.png
new file mode 100644
index 0000000..022401e
Binary files /dev/null and b/data/icons/direction-left.png differ
diff --git a/data/icons/direction-right.png b/data/icons/direction-right.png
new file mode 100644
index 0000000..1e718de
Binary files /dev/null and b/data/icons/direction-right.png differ
diff --git a/data/icons/direction-roundabout.png b/data/icons/direction-roundabout.png
new file mode 100644
index 0000000..705b81a
Binary files /dev/null and b/data/icons/direction-roundabout.png differ
diff --git a/data/icons/direction-sharpleft.png b/data/icons/direction-sharpleft.png
new file mode 100644
index 0000000..086c990
Binary files /dev/null and b/data/icons/direction-sharpleft.png differ
diff --git a/data/icons/direction-sharpright.png b/data/icons/direction-sharpright.png
new file mode 100644
index 0000000..3012fdd
Binary files /dev/null and b/data/icons/direction-sharpright.png differ
diff --git a/data/icons/direction-slightleft.png b/data/icons/direction-slightleft.png
new file mode 100644
index 0000000..b584db1
Binary files /dev/null and b/data/icons/direction-slightleft.png differ
diff --git a/data/icons/direction-slightright.png b/data/icons/direction-slightright.png
new file mode 100644
index 0000000..ba3ecd8
Binary files /dev/null and b/data/icons/direction-slightright.png differ
diff --git a/data/icons/direction-uturn.png b/data/icons/direction-uturn.png
new file mode 100644
index 0000000..9758c77
Binary files /dev/null and b/data/icons/direction-uturn.png differ
diff --git a/data/icons/directions.svg b/data/icons/directions.svg
new file mode 100644
index 0000000..d89796d
--- /dev/null
+++ b/data/icons/directions.svg
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="32px"
+   height="32px"
+   id="svg13790"
+   version="1.1"
+   inkscape:version="0.48+devel r12417"
+   sodipodi:docname="directions.svg"
+   inkscape:export-filename="/home/andreasn/SparkleShare/gnome-icons/maps-symbolic/direction-roundabout.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs13792" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2"
+     inkscape:cx="66.547746"
+     inkscape:cy="19.043947"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:snap-global="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-bbox="true"
+     inkscape:bbox-paths="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     showborder="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1021"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid13798" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata13795">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-44"
+       width="32.10268"
+       height="31.942713"
+       x="160.00635"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-7-84"
+       width="3.9737358"
+       height="11.347995"
+       x="9.9818344"
+       y="-180.36581"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-0"
+       width="4.0049858"
+       height="17.051868"
+       x="-170.02029"
+       y="-27.035873"
+       transform="scale(-1,-1)" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-8-3"
+       width="32.10268"
+       height="31.942713"
+       x="200.00635"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-7-6-3"
+       width="3.9737358"
+       height="10.972995"
+       x="-144.88109"
+       y="157.918"
+       transform="matrix(-0.70710678,0.70710678,0.70710678,0.70710678,0,0)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-2-2"
+       width="4.1924858"
+       height="10.054085"
+       x="217.91138"
+       y="-27.059189"
+       transform="scale(1,-1)" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-4-7"
+       width="32.10268"
+       height="31.942713"
+       x="120.00635"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 124.6453,12.01558 8.42654,5.950595 L 133.07184,6.064983 Z"
+       id="rect13802-1-3-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-7-8-9"
+       width="3.9737358"
+       height="11.347995"
+       x="9.9818344"
+       y="131.67984"
+       transform="matrix(0,1,1,0,0,0)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-8-3"
+       width="4.0049858"
+       height="17.051868"
+       x="142.02536"
+       y="-27.035873"
+       transform="scale(1,-1)" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-8-4-2-7"
+       width="32.10268"
+       height="31.942713"
+       x="-352.10901"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306"
+       transform="scale(-1,1)" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 328.01905,10.939736 11.2672,8.045185 2.30944,-3.233739 L 328.01579,6.054647 Z"
+       id="rect13805-7-6-7-7-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-2-5-0-6"
+       width="3.9936121"
+       height="17.505117"
+       x="-332.01636"
+       y="-27.000946"
+       transform="scale(-1,-1)" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-4-9-5"
+       width="32.10268"
+       height="31.942713"
+       x="80.006348"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 96.00234,6.033529 90.34282,14.039892 101.66187,14.039892 Z"
+       id="rect13802-1-3-1-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-8-8-8"
+       width="4.0049858"
+       height="18.024139"
+       x="94.047668"
+       y="-27.039391"
+       transform="scale(1,-1)" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-4-9-4-97"
+       width="32.10268"
+       height="31.942713"
+       x="40.006348"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-8-8-7-9"
+       width="4.0049858"
+       height="8.3306971"
+       x="-63.996399"
+       y="11.774483"
+       transform="scale(-1,1)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-8-8-7-5-1"
+       width="4.0049858"
+       height="13.009145"
+       x="-50.022888"
+       y="11.908539"
+       transform="scale(-1,1)" />
+    <path
+       
style="fill:none;stroke:#555753;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 48.04469,13.008885 c 0,0 0.11927,-7.046316 7.04632,-7.046316 6.92704,0 6.94646,6.985563 
6.94646,6.985563"
+       id="path14648-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="czc" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 188.39767,12.01558 179.97112,17.966175 179.97112,6.064983 Z"
+       id="rect13802-1-3-2-0"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 61.98801,24.993885 67.64754,16.987522 56.32848,16.987522 Z"
+       id="rect13802-1-3-1-2-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 208.16883,5.957036 218.335,7.707799 209.91959,16.123212 Z"
+       id="rect13802-1-3-2-0-0"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-8-3-8"
+       width="32.10268"
+       height="31.942713"
+       x="-272.10901"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306"
+       transform="scale(-1,1)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-7-6-3-5"
+       width="3.9737358"
+       height="10.972995"
+       x="188.9549"
+       y="-175.91797"
+       transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-2-2-1"
+       width="4.1924858"
+       height="10.054085"
+       x="-254.20398"
+       y="-27.059189"
+       transform="scale(-1,-1)" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 263.94653,5.957036 253.78036,7.707799 262.19577,16.123212 Z"
+       id="rect13802-1-3-2-0-0-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 347.01125,21.98242 343.52037,12.275209 336.69551,22.02506 Z"
+       id="rect13802-1-3-2-0-0-5-0"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-8-4-2-7-1"
+       width="32.10268"
+       height="31.942713"
+       x="280.00635"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 304.09632,10.939736 -11.2672,8.045185 -2.30944,-3.233739 L 304.09958,6.054647 Z"
+       id="rect13805-7-6-7-7-9-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <rect
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13805-3-4-2-5-0-6-9"
+       width="3.9936121"
+       height="17.505117"
+       x="300.099"
+       y="-27.000946"
+       transform="scale(1,-1)" />
+    <path
+       
style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 285.10412,21.98242 288.595,12.275209 295.41986,22.02506 Z"
+       id="rect13802-1-3-2-0-0-5-0-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <rect
+       
style="color:#000000;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect13852-7-4-9-4-9-3-04-4"
+       width="32.10268"
+       height="31.942713"
+       x="0.0063476562"
+       y="0.0831604"
+       rx="2.9755306"
+       ry="2.9755306" />
+    <path
+       
style="font-size:xx-small;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#555753;fill-opacity:1;stroke:none;stroke-width:2.8946228;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;clip-rule:nonzero;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;font-family:sans-serif;-inkscape-font-specification:sans-serif"
+       d="m 13.97683,4.317626 c -5.62461,0.953573 -9.94198,5.849698 -9.94198,11.721069 0,1.600593 
0.32477,3.12763 0.90503,4.524568 l 3.44473,-2.204142 c -0.2228,-0.733042 -0.34428,-1.511518 
-0.34428,-2.320426 0,-3.702207 2.51084,-6.773804 5.9365,-7.64886 L 16.62848,6.100499 z m 4,0.0024 0,4.073763 
c 3.4178,0.880328 5.92114,3.948279 5.92114,7.644953 0,0.803474 -0.1205,1.576647 -0.34043,2.305381 l 
0.0596,3.32594 3.38654,-1.120919 C 27.5803,19.155966 27.90349,17.634026 27.90349,16.038742 27.90345,10.172644 
23.59396,5.279848 17.97683,4.319979 z m 3.48373,17.431085 c -1.42166,1.35889 -3.35077,2.19475 
-5.49141,2.19475 -2.13509,0 -4.05947,-0.831849 -5.48008,-2.184491 l -3.0995,-0.926067 -0.30913,3.10712 c 
2.1892,2.444729 5.36093,3.997962 8.88873,3.997962 C 19.50231,27.940338 22.67845,26.382505 24.86795,23.931318 
Z"
+       id="path15446"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csccscccccscccscccccccccc" />
+  </g>
+</svg>
diff --git a/data/icons/route-car-symbolic.svg b/data/icons/route-car-symbolic.svg
new file mode 100644
index 0000000..c511fe1
--- /dev/null
+++ b/data/icons/route-car-symbolic.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16px"
+   height="16px"
+   id="svg6558"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="route-walking-symbolic.svg">
+  <defs
+     id="defs6560" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.197802"
+     inkscape:cx="9.2245257"
+     inkscape:cy="9.6312031"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:snap-nodes="false"
+     inkscape:snap-bbox="true"
+     inkscape:window-width="1600"
+     inkscape:window-height="841"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7232" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata6563">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       inkscape:connector-curvature="0"
+       
style="color:#000000;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 4,4 C 3.480625,4 3.19205,4.4345415 3.0625,4.9375 L 2.28125,8 1.9375,8 C 1.418125,8 1,8.418125 
1,8.9375 l 0,4.125 C 1,13.581875 1.480625,14 2,14 l 0,0.90625 C 2,15.512187 2.446,16 3,16 3.554,16 
4,15.512187 4,14.90625 L 4,14 l 8,0 0,0.90625 C 12,15.512187 12.446,16 13,16 c 0.554,0 1,-0.487813 1,-1.09375 
L 14,14 c 0.546725,0 1,-0.418125 1,-0.9375 l 0,-4.125 C 15,8.418125 14.581875,8 14.0625,8 L 13.71875,8 
12.9375,4.9375 C 12.80795,4.4345415 12.519375,4 12,4 L 4,4 z m 1.0625,1 5.875,0 C 11.543438,5 
11.816859,5.5161519 12,6.09375 L 12.625,8 c 0.183141,0.577598 -0.112812,1 -0.71875,1 L 4.09375,9 C 3.487812,9 
3.153528,8.606555 3.34375,8.03125 L 4,6.09375 C 4.190222,5.5184449 4.456562,5 5.0625,5 z M 4,10 c 0.552285,0 
1,0.447715 1,1 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 0.447715,-1 1,-1 z m 
8,0 c 0.552285,0 1,0.447715 1,1 0,0.552285 -0.447715,1 -1,1 -0.552285,0 -1,-0.447715 -1,-1 0,-0.552285 
0.447715,-1 1,-1 z"
+       id="rect6086" />
+  </g>
+</svg>
diff --git a/data/icons/route-pedestrian-symbolic.svg b/data/icons/route-pedestrian-symbolic.svg
new file mode 100644
index 0000000..7317b86
--- /dev/null
+++ b/data/icons/route-pedestrian-symbolic.svg
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16px"
+   height="16px"
+   id="svg6558"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="New document 18">
+  <defs
+     id="defs6560" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.197802"
+     inkscape:cx="9.2245257"
+     inkscape:cy="9.6312031"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:snap-nodes="false"
+     inkscape:snap-bbox="true"
+     inkscape:window-width="1600"
+     inkscape:window-height="841"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7232" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata6563">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       
style="color:#000000;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 5.7191343,5.0308108 3.96875,7.03125 3.0625,9.6875 c -0.2635754,0.511148 0.016909,1.224387 
0.5625,1.40625 0.545591,0.181864 1.2166716,-0.214187 1.3125,-0.78125 L 5.71875,8.0625 6,7.75 6,13.25 4.375,15 
5.875,16.375 8,14.03125 8,11.90625 10.09375,16 11.875,15.09375 9,9.40625 9,7.65625 11.34375,9.75 c 
0.383224,0.3968 1.108768,0.37896 1.472028,-0.03619 C 13.179038,9.298651 13.100409,8.5771604 12.65625,8.25 L 
9,5 z"
+       id="rect7046"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccscccccccccccccsccc" />
+    <path
+       sodipodi:type="arc"
+       
style="color:#000000;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path6214"
+       sodipodi:cx="9.1592426"
+       sodipodi:cy="5.4265437"
+       sodipodi:rx="2.4638252"
+       sodipodi:ry="2.4638252"
+       d="m 11.623068,5.4265437 a 2.4638252,2.4638252 0 1 1 -4.9276506,0 2.4638252,2.4638252 0 1 1 
4.9276506,0 z"
+       transform="matrix(0.81174588,0,0,0.8117459,0.5650225,-2.4049746)" />
+  </g>
+</svg>
diff --git a/data/icons/route-transit-symbolic.svg b/data/icons/route-transit-symbolic.svg
new file mode 100644
index 0000000..05a49d5
--- /dev/null
+++ b/data/icons/route-transit-symbolic.svg
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16px"
+   height="16px"
+   id="svg6558"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="route-driving-symbolic.svg">
+  <defs
+     id="defs6560" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.696216"
+     inkscape:cx="5.7511062"
+     inkscape:cy="13.453719"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:snap-nodes="false"
+     inkscape:snap-bbox="true"
+     inkscape:window-width="1600"
+     inkscape:window-height="841"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7232" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata6563">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       
style="color:#000000;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="M 1.9375,1 C 1.418125,1 1,1.418125 1,1.9375 L 1,14.90625 C 1,15.512187 1.487812,16 2.09375,16 l 
0.8125,0 C 3.512188,16 4,15.512187 4,14.90625 L 4,14 l 8,0 0,0.90625 C 12,15.512187 12.487812,16 13.09375,16 
l 0.8125,0 C 14.512188,16 15,15.512187 15,14.90625 L 15,1.9375 C 15,1.418125 14.581875,1 14.0625,1 z m 
1.15625,1 9.8125,0 C 13.512188,2 14,2.4878125 14,3.09375 l 0,4.8125 C 14,8.5121875 13.512188,9 12.90625,9 L 
3.09375,9 C 2.487812,9 2,8.5121875 2,7.90625 L 2,3.09375 C 2,2.4878125 2.487812,2 3.09375,2 z M 3.5,10 C 
4.328427,10 5,10.671573 5,11.5 5,12.328427 4.328427,13 3.5,13 2.671573,13 2,12.328427 2,11.5 2,10.671573 
2.671573,10 3.5,10 z m 9,0 C 13.328427,10 14,10.671573 14,11.5 14,12.328427 13.328427,13 12.5,13 11.671573,13 
11,12.328427 11,11.5 11,10.671573 11.671573,10 12.5,10 z"
+       id="rect6086-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="sccsssccsssccsssssssssssssssssssss" />
+  </g>
+</svg>
diff --git a/src/gnome-maps.data.gresource.xml b/src/gnome-maps.data.gresource.xml
index d30b5eb..7636e6c 100644
--- a/src/gnome-maps.data.gresource.xml
+++ b/src/gnome-maps.data.gresource.xml
@@ -7,10 +7,28 @@
     <file preprocess="xml-stripblanks">search-popup.ui</file>
     <file preprocess="xml-stripblanks">context-menu.ui</file>
     <file preprocess="xml-stripblanks">map-location.ui</file>
+    <file preprocess="xml-stripblanks">sidebar.ui</file>
+    <file preprocess="xml-stripblanks">instruction-row.ui</file>
+    <file preprocess="xml-stripblanks"
+          alias="route-pedestrian-symbolic">../data/icons/route-pedestrian-symbolic.svg</file>
+    <file preprocess="xml-stripblanks"
+          alias="route-bike-symbolic">../data/icons/route-transit-symbolic.svg</file>
+    <file preprocess="xml-stripblanks"
+          alias="route-car-symbolic">../data/icons/route-car-symbolic.svg</file>
+
     <file alias="application.css">../data/gnome-maps.css</file>
     <file alias="zoom-in.png">../data/media/zoom-in.png</file>
     <file alias="zoom-out.png">../data/media/zoom-out.png</file>
     <file alias="zoom-in-insensitive.png">../data/media/zoom-in-insensitive.png</file>
     <file alias="zoom-out-insensitive.png">../data/media/zoom-out-insensitive.png</file>
+    <file alias="direction-left">../data/icons/direction-left.png</file>
+    <file alias="direction-right">../data/icons/direction-right.png</file>
+    <file alias="direction-roundabout">../data/icons/direction-roundabout.png</file>
+    <file alias="direction-sharpleft">../data/icons/direction-sharpleft.png</file>
+    <file alias="direction-sharpright">../data/icons/direction-sharpright.png</file>
+    <file alias="direction-slightleft">../data/icons/direction-slightleft.png</file>
+    <file alias="direction-slightright">../data/icons/direction-slightright.png</file>
+    <file alias="direction-continue">../data/icons/direction-continue.png</file>
+    <file alias="direction-uturn">../data/icons/direction-uturn.png</file>
   </gresource>
 </gresources>
diff --git a/src/gnome-maps.js.gresource.xml b/src/gnome-maps.js.gresource.xml
index 4294679..4a86811 100644
--- a/src/gnome-maps.js.gresource.xml
+++ b/src/gnome-maps.js.gresource.xml
@@ -18,6 +18,7 @@
     <file>searchPopup.js</file>
     <file>settings.js</file>
     <file>sidebar.js</file>
+    <file>turnLocation.js</file>
     <file>userLocation.js</file>
     <file>utils.js</file>
     <file>zoomControl.js</file>
diff --git a/src/instruction-row.ui b/src/instruction-row.ui
new file mode 100644
index 0000000..6bfc91f
--- /dev/null
+++ b/src/instruction-row.ui
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.15.2 on Mon Sep  9 08:19:47 2013 -->
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkBox" id="instruction-box">
+    <property name="height_request">48</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="spacing">6</property>
+    <property name="baseline_position">top</property>
+    <child>
+      <object class="GtkImage" id="direction-image">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xpad">2</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="instruction-label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="xalign">0</property>
+        <property name="ypad">3</property>
+        <property name="use_underline">True</property>
+        <property name="wrap">True</property>
+        <property name="ellipsize">end</property>
+        <property name="max_width_chars">28</property>
+        <property name="lines">3</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/src/mapLocation.js b/src/mapLocation.js
index 0350e75..28082ec 100644
--- a/src/mapLocation.js
+++ b/src/mapLocation.js
@@ -161,7 +161,7 @@ const MapLocation = new Lang.Class({
                 }
             }
         } else {
-            switch (this.placeType) {
+            switch (this.type) {
             case Geocode.PlaceType.STREET:
                 zoom = 16;
                 break;
diff --git a/src/mapView.js b/src/mapView.js
index 771d8a1..aa2906a 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -39,6 +39,7 @@ const Utils = imports.utils;
 const Path = imports.path;
 const MapLocation = imports.mapLocation;
 const UserLocation = imports.userLocation;
+const TurnLocation = imports.turnLocation;
 const Geoclue = imports.geoclue;
 const RouteService = imports.routeService;
 const _ = imports.gettext.gettext;
@@ -70,14 +71,14 @@ const MapView = new Lang.Class({
         this.view.connect('notify::latitude', this._onViewMoved.bind(this));
         this.view.connect('notify::longitude', this._onViewMoved.bind(this));
 
-        this._sidebar = new Sidebar.Sidebar(this);
-        // Don't show sidebar until it has something in it
-        //this.view.add_child(this._sidebar.actor);
-
         this._routeLayer = new Champlain.PathLayer();
         this._routeLayer.set_stroke_width(2.0);
         this.view.add_layer(this._routeLayer);
 
+        this._turnPointLayer = new Champlain.MarkerLayer();
+        this._turnPointLayer.set_selection_mode(Champlain.SelectionMode.SINGLE);
+        this.view.add_layer(this._turnPointLayer);
+
         this._markerLayer = new Champlain.MarkerLayer();
         this._markerLayer.set_selection_mode(Champlain.SelectionMode.SINGLE);
         this.view.add_layer(this._markerLayer);
@@ -102,7 +103,7 @@ const MapView = new Lang.Class({
         this.geoclue.connect("location-changed",
                              this._updateUserLocation.bind(this));
 
-        this._routeService = new RouteService.GraphHopper();
+        this.routeService = new RouteService.GraphHopper();
     },
 
     setMapType: function(mapType) {
@@ -194,9 +195,29 @@ const MapView = new Lang.Class({
     _onRouteRequest: function(location) {
         let from = this._userLocation.getCoordinate(),
             to   = location.getCoordinate();
-        this._routeService.getRoute([from, to],
-                                    DefaultTransportation,
-                                    this.showRoute.bind(this));
+
+        this.routeService.getRoute([from, to], DefaultTransportation, (function (route) {
+            if (route)
+                this.emit('got-route', route);
+            else
+                this._infobar.showError('Could not create a route to ' + location.description);
+        }).bind(this));;
+    },
+
+    showTurnPoint: function({ latitude, longitude }) {
+        let geocodeLocation = new Geocode.Location({ longitude: longitude,
+                                                     latitude: latitude });
+        let place = Geocode.Place.new_with_location("",
+                                                    Geocode.PlaceType.STREET,
+                                                    geocodeLocation);
+        let location = new TurnLocation.TurnLocation(place,
+                                                     this);
+        location.showNGoTo(true, this._turnPointLayer);
+    },
+
+    clearRouteLayers: function() {
+        this._routeLayer.remove_all();
+        this._turnPointLayer.remove_all();
     },
 
     showRoute: function(route) {
diff --git a/src/placeStore.js b/src/placeStore.js
index cb0a98f..fd9935d 100644
--- a/src/placeStore.js
+++ b/src/placeStore.js
@@ -48,6 +48,23 @@ const Columns = {
     ADDED: 4
 };
 
+function completionMatchFunc(completion, key, iter) {
+    let model = completion.get_model();
+    let name = model.get_value(iter, Columns.NAME);
+
+    if (name === null)
+        return false;
+
+    name = GLib.utf8_normalize (name, -1, GLib.NormalizeMode.ALL);
+    if (name === null)
+        return false;
+
+    if (!GLib.ascii_strncasecmp(name, key, key.length))
+        return true;
+    else
+        return false;
+}
+
 const PlaceStore = new Lang.Class({
     Name: 'PlaceStore',
     Extends: Gtk.ListStore,
diff --git a/src/routeService.js b/src/routeService.js
index 10db3b1..4f3bc36 100644
--- a/src/routeService.js
+++ b/src/routeService.js
@@ -103,8 +103,13 @@ const GraphHopper = new Lang.Class({
     },
 
     _parseResult: function(result) {
-        let route = JSON.parse(result).route,
-            directions = this._createDirections(route.instructions.indications),
+        let route = JSON.parse(result).route;
+
+        if (!route) {
+            return null;
+        }
+
+        let directions = this._createDirections(route.instructions.indications),
             coordinates = route.instructions.latLngs.map(function([lat, lng]) {
                 return new Champlain.Coordinate({ latitude: lat,
                                                   longitude: lng });
diff --git a/src/sidebar.js b/src/sidebar.js
index b9d873e..8f37d62 100644
--- a/src/sidebar.js
+++ b/src/sidebar.js
@@ -22,6 +22,7 @@
 
 const Clutter = imports.gi.Clutter;
 const Gdk = imports.gi.Gdk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 const Champlain = imports.gi.Champlain;
@@ -30,71 +31,267 @@ const MapView = imports.mapView;
 
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
+const Signals = imports.signals;
 
+const PlaceStore = imports.placeStore;
+const Path = imports.path;
+const Route = imports.route;
+const RouteService = imports.routeService;
+const SearchPopup = imports.searchPopup;
 const Utils = imports.utils;
 const _ = imports.gettext.gettext;
 
+const isRTL = Gtk.Widget.get_default_direction() === Gtk.TextDirection.RTL;
+
+const Icon = {
+    prev: isRTL ? 'go-previous-rtl-symbolic' : 'go-previous-symbolic',
+    next: isRTL ? 'go-next-rtl-symbolic'     : 'go-next-symbolic'
+};
+
 const Sidebar = new Lang.Class({
     Name: 'Sidebar',
+    Extends: Gtk.Revealer,
+
+    _init: function(mapView, placeStore) {
+        this.parent({ can_focus: false,
+                      visible: false,
+                      transition_type: 2,
+                      halign: Gtk.Align.END });
 
-    _init: function(mapView) {
         this._mapView = mapView;
-        this.actor = new Clutter.Actor({ layout_manager: new Clutter.BoxLayout({ spacing: 12 }),
-                                         y_expand: true,
-                                         x_align: Clutter.ActorAlign.END });
-
-        let isRtl = (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL);
-        let prevIconName = isRtl ? 'go-previous-rtl-symbolic' : 'go-previous-symbolic';
-        let nextIconName = isRtl ? 'go-next-rtl-symbolic' : 'go-next-symbolic';
-
-        // create the button
-        let revealImage = new Gtk.Image ({ icon_name: prevIconName,
-                                           icon_size: Gtk.IconSize.MENU });
-        let revealButton = new Gtk.Button({ child: revealImage,
-                                            valign: Gtk.Align.CENTER });
-        revealButton.get_style_context().add_class('osd');
-        revealButton.show();
-
-        // then the sidebar itself, packed into the revealer
-        let grid = new Gtk.Grid({ vexpand: true,
-                                  hexpand: true,
-                                  margin_top: 32,
-                                  margin_left: 32,
-                                  margin_right: 32,
-                                  row_spacing: 15,
-                                  orientation: Gtk.Orientation.VERTICAL,
-                                  valign: Gtk.Align.FILL });
-
-        let container = new Gtk.Frame({ child: grid,
-                                        shadow_type: Gtk.ShadowType.IN,
-                                        width_request: 200 });
-        container.get_style_context().add_class('maps-sidebar');
-
-        let revealer = new Gtk.Revealer({ child: container,
-                                         reveal_child: false,
-                                         transition_type: Gtk.RevealerTransitionType.CROSSFADE });
-        revealer.show_all();
-
-        revealButton.connect('clicked', (function() {
-            if (revealer.reveal_child) {
-                revealer.reveal_child = false;
-                revealButton.symbolic_icon_name = prevIconName;
-            } else {
-                revealer.reveal_child = true;
-                revealButton.symbolic_icon_name = nextIconName;
+        this._placeStore = placeStore;
+
+        this._ui = Utils.getUIObject('sidebar', [ 'sidebar',
+                                                  'instruction-list',
+                                                  'reveal-button',
+                                                  'reveal-image',
+                                                  'to-entry',
+                                                  'from-entry',
+                                                  'to-completion',
+                                                  'from-completion',
+                                                  'mode-pedestrian-toggle',
+                                                  'mode-bike-toggle',
+                                                  'mode-car-toggle',
+                                                  'route-button']);
+        this.revealButton = this._ui.revealButton;
+        this.revealButton.connect('clicked', this.toggle.bind(this));
+        this._ui.instructionList.connect('row-activated', (function(list, row) {
+            this.emit('instruction-selected', row.instruction);
+        }).bind(this));
+
+        this._initSearchEntries();
+
+        this._transportation = this._mapView.DefaultTransportation;
+
+        this._ui.modePedestrianToggle.connect('toggled', (function(toggleButton) {
+            if (toggleButton.active)
+                this._transportation = RouteService.Transportation.FOOT;
+        }).bind(this));
+        this._ui.modeBikeToggle.connect('toggled', (function(toggleButton) {
+            if (toggleButton.active)
+                this._transportation = RouteService.Transportation.BIKE;
+        }).bind(this));
+        this._ui.modeCarToggle.connect('toggled', (function(toggleButton) {
+            if (toggleButton.active)
+                this._transportation = RouteService.Transportation.CAR;
+        }).bind(this));
+
+        this._ui.routeButton.connect('clicked', (function() {
+            if (this._fromPlace && this._toPlace) {
+                let transportation =
+                        this._mapView.routeService.getRoute([this._fromPlace.location,
+                                                             this._toPlace.location],
+                                                            this._transportation,
+                                                            this.emit.bind(this._mapView,
+                                                                           'got-route'));
+
             }
         }).bind(this));
 
-        // now create actors
-        let buttonActor = new GtkClutter.Actor({ contents: revealButton,
-                                                 x_align: Clutter.ActorAlign.END });
+        this.add(this._ui.sidebar);
+        this.conceal();
+    },
+
+    _createActor: function() {
+        let actor = new Clutter.Actor({
+            layout_manager: new Clutter.BoxLayout({ spacing: 12 }),
+            y_expand: true,
+            x_align: Clutter.ActorAlign.END
+        });
+
+        let buttonActor = new GtkClutter.Actor({
+            contents: this._ui.revealButton,
+            x_align: Clutter.ActorAlign.END
+        });
         Utils.clearGtkClutterActorBg(buttonActor);
-        this.actor.add_child(buttonActor);
 
-        let revealerActor = new GtkClutter.Actor({ contents: revealer,
-                                                   x_align: Clutter.ActorAlign.END,
-                                                   x_expand: true,
-                                                   y_expand: true });
-        this.actor.add_child(revealerActor);
+        let revealerActor = new GtkClutter.Actor({
+            contents: this,
+            x_align: Clutter.ActorAlign.END,
+            x_expand: true,
+            y_expand: true
+        });
+
+        actor.add_child(buttonActor);
+        actor.add_child(revealerActor);
+
+        return actor;
+    },
+
+    _initSearchEntries: function() {
+        this._ui.toCompletion.model = this._placeStore;
+        this._ui.fromCompletion.model = this._placeStore;
+        this._ui.toCompletion.set_match_func(PlaceStore.completionMatchFunc);
+        this._ui.fromCompletion.set_match_func(PlaceStore.completionMatchFunc);
+        this._ui.fromCompletion.connect('match-selected',
+                                        this._onCompletionMatchSelected.bind(this));
+        this._ui.toCompletion.connect('match-selected',
+                                        this._onCompletionMatchSelected.bind(this));
+
+        this._fromPopover = new SearchPopup.SearchPopup(this._ui.fromEntry, 5);
+        this._toPopover = new SearchPopup.SearchPopup(this._ui.toEntry, 5);
+
+        this._fromPopover.connect('selected',
+                                  this._onSearchPopupSelected.bind(this));
+        this._toPopover.connect('selected',
+                                  this._onSearchPopupSelected.bind(this));
+
+
+        this._ui.toEntry.connect('activate', this._onSearchActivate.bind(this));
+        this._ui.fromEntry.connect('activate', this._onSearchActivate.bind(this));
+    },
+
+    _onCompletionMatchSelected: function(completion, model, iter) {
+        let entry;
+        let place = model.get_value(iter, PlaceStore.Columns.PLACE);
+
+        if (completion === this._ui.fromCompletion) {
+            entry = this._ui.fromEntry;
+            this._fromPlace = place;
+        } else {
+            entry = this._ui.toEntry;
+            this._toPlace = place;
+        }
+        entry.text = place.name;
+
+        return true;
+    },
+
+    _onSearchPopupSelected: function(popover, place) {
+        let entry;
+
+        if (popover === this._fromPopover) {
+            entry = this._ui.fromEntry;
+            this._fromPlace = place;
+        } else {
+            entry = this._ui.toEntry;
+            this._toPlace = place;
+        }
+        entry.text = place.name;
+        popover.hide();
+    },
+
+    _onSearchActivate: function(entry) {
+        let searchString = entry.get_text();
+
+        if (searchString.length > 0) {
+            let popover = (entry === this._ui.toEntry)
+                    ? this._toPopover
+                    : this._fromPopover;
+
+            popover.showSpinner();
+            this._mapView.geocodeSearch(searchString, function(places) {
+                if (places === null)
+                    popover.hide();
+
+                popover.update(places, searchString);
+                popover.showResult();
+            });
+        }
+    },
+
+    addInstructions: function(instructions) {
+        this.clearInstructions();
+        instructions.forEach(this._addInstruction.bind(this));
+    },
+
+    _addInstruction: function(instruction) {
+        this._ui.instructionList.add(new InstructionRow(instruction));
+    },
+
+    clearInstructions: function() {
+        let listBox = this._ui.instructionList;
+        listBox.forall(listBox.remove.bind(listBox));
+    },
+
+    reset: function () {
+        this.clearInstructions();
+        this._toPlace = null;
+        this._fromPlace = null;
+        this._ui.toEntry.text = "";
+        this._ui.fromEntry.text = "";
+    },
+
+    reveal: function() {
+        this.reveal_child = true;
+        this._ui.revealImage.icon_name = Icon.next;
+    },
+
+    conceal: function() {
+        this.reveal_child = false;
+        this._ui.revealImage.icon_name = Icon.prev;
+    },
+
+    toggle: function() {
+        if(this.reveal_child)
+            this.conceal();
+        else
+            this.reveal();
+    },
+
+    close: function() {
+        this.conceal();
+        this.reset();
+        this.hide();
+    },
+
+    open: function() {
+        this.show();
+        this.reveal();
     }
 });
+Signals.addSignalMethods(Sidebar.prototype);
+
+const InstructionRow = new Lang.Class({
+    Name: "InstructionRow",
+    Extends: Gtk.ListBoxRow,
+
+    _init: function(instruction) {
+        this.parent();
+
+        this.instruction = instruction;
+        this.visible = true;
+        let ui = Utils.getUIObject('instruction-row', ['instruction-box',
+                                                       'direction-image',
+                                                       'instruction-label']);
+        ui.instructionLabel.label = instruction.description;
+        ui.directionImage.resource = directionToResource(instruction.direction);
+        this.add(ui.instructionBox);
+    }
+});
+
+function directionToResource(direction) {
+    let dir = Route.Direction;
+    switch(direction) {
+    case dir.LEFT:         return '/org/gnome/maps/direction-left';
+    case dir.SHARP_LEFT:   return '/org/gnome/maps/direction-sharpleft';
+    case dir.SLIGHT_LEFT:  return '/org/gnome/maps/direction-slightleft';
+    case dir.RIGHT:        return '/org/gnome/maps/direction-right';
+    case dir.SHARP_RIGHT:  return '/org/gnome/maps/direction-sharpright';
+    case dir.SLIGHT_RIGHT: return '/org/gnome/maps/direction-slightright';
+    case dir.CONTINUE:     return '/org/gnome/maps/direction-continue';
+    case dir.U_TURN:       return '/org/gnome/maps/direction-uturn';
+    case dir.ROUNDABOUT:   return '/org/gnome/maps/direction-roundabout';
+    default:               return "";
+    }
+}
diff --git a/src/sidebar.ui b/src/sidebar.ui
new file mode 100644
index 0000000..3e47eac
--- /dev/null
+++ b/src/sidebar.ui
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.15.2 on Tue Sep 10 05:14:15 2013 -->
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkEntryCompletion" id="from-completion">
+    <property name="minimum_key_length">2</property>
+    <child>
+      <object class="GtkCellRendererPixbuf" id="from-icon-cell-renderer">
+        <property name="xpad">2</property>
+      </object>
+      <attributes>
+        <attribute name="pixbuf">0</attribute>
+      </attributes>
+    </child>
+    <child>
+      <object class="GtkCellRendererText" id="from-text-cell-renderer">
+        <property name="ypad">4</property>
+      </object>
+      <attributes>
+        <attribute name="text">2</attribute>
+      </attributes>
+    </child>
+  </object>
+  <object class="GtkEntryCompletion" id="to-completion">
+    <property name="minimum_key_length">2</property>
+    <child>
+      <object class="GtkCellRendererPixbuf" id="to-icon-cell-renderer">
+        <property name="xpad">2</property>
+      </object>
+      <attributes>
+        <attribute name="pixbuf">0</attribute>
+      </attributes>
+    </child>
+    <child>
+      <object class="GtkCellRendererText" id="to-text-cell-renderer">
+        <property name="ypad">4</property>
+      </object>
+      <attributes>
+        <attribute name="text">2</attribute>
+      </attributes>
+    </child>
+  </object>
+
+  <object class="GtkImage" id="close-image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">window-close-symbolic</property>
+    <property name="icon_size">1</property>
+  </object>
+  <object class="GtkImage" id="reveal-image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_size">1</property>
+  </object>
+  <object class="GtkButton" id="reveal-button">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="receives_default">False</property>
+    <property name="valign">center</property>
+    <property name="image">reveal-image</property>
+    <style>
+      <class name="osd"/>
+    </style>
+  </object>
+  <object class="GtkFrame" id="sidebar">
+    <property name="width_request">300</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="label_xalign">1</property>
+    <property name="shadow_type">none</property>
+    <style>
+      <class name="maps-sidebar"/>
+    </style>
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">10</property>
+        <child>
+          <object class="GtkGrid" id="grid">
+            <property name="name">sidebar-form</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">7</property>
+            <property name="margin_right">7</property>
+            <property name="orientation">vertical</property>
+            <property name="row_spacing">10</property>
+            <child>
+              <object class="GtkBox" id="mode">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">center</property>
+                <property name="homogeneous">True</property>
+                <style>
+                  <class name="linked"/>
+                </style>
+                <child>
+                  <object class="GtkRadioButton" id="mode-pedestrian-toggle">
+                    <property name="name">mode-pedestrian-toggle</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="xalign">0.5</property>
+                    <property name="draw_indicator">False</property>
+                    <style>
+                      <class name="transportation-mode-button"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="mode-pedestrian-image">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="pixbuf">route-pedestrian-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="mode-bike-toggle">
+                    <property name="name">mode-bike-toggle</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="xalign">0.5</property>
+                    <property name="draw_indicator">False</property>
+                    <property name="group">mode-pedestrian-toggle</property>
+                    <style>
+                      <class name="transportation-mode-button"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="mode-bike-image">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="pixbuf">route-bike-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="mode-car-toggle">
+                    <property name="name">mode-car-toggle</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="xalign">0.5</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">False</property>
+                    <property name="group">mode-pedestrian-toggle</property>
+                    <style>
+                      <class name="transportation-mode-button"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="mode-car-image">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="pixbuf">route-car-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="route-button">
+                <property name="visible">True</property>
+                <property name="label">Get route</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+
+            <child>
+              <object class="GtkLabel" id="to-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">To</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="to-entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="completion">to-completion</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="from-entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="completion">from-completion</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="from-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">From</property>
+                <property name="ellipsize">end</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="instruction-list-scrolled">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkListBox" id="instruction-list">
+                <property name="name">sidebar-instruction-list</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="label">
+      <object class="GtkButton" id="close-button">
+        <property name="name">sidebar-close-button</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="action_name">win.route-mode-close</property>
+        <property name="image">close-image</property>
+        <property name="relief">none</property>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/turnLocation.js b/src/turnLocation.js
new file mode 100644
index 0000000..a110aa9
--- /dev/null
+++ b/src/turnLocation.js
@@ -0,0 +1,42 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2011, 2012, 2013 Red Hat, Inc.
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps 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 General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ */
+
+const Champlain = imports.gi.Champlain;
+const Clutter = imports.gi.Clutter;
+
+const Lang = imports.lang;
+
+const MapLocation = imports.mapLocation;
+
+const TurnLocation = new Lang.Class({
+    Name: 'TurnLocation',
+    Extends: MapLocation.MapLocation,
+
+    show: function(layer) {
+        layer.remove_all();
+        let point = new Champlain.Point({ longitude: this.longitude,
+                                          latitude: this.latitude,
+                                          size: 8.0 });
+        layer.add_marker(point);
+    }
+
+});


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