[gnome-maps/wip/mlundblad/transit-routing: 4/20] Add label widget for route labels



commit f0b8ceb0ad3cd479f9301b24d14c4eace914acb3
Author: Marcus Lundblad <ml update uu se>
Date:   Tue May 31 23:26:26 2016 +0200

    Add label widget for route labels
    
    This adds a label widget for representing parts of transit
    journeys.
    The label can use "long" or "compact" mode, where the latter
    is suited for presenting in an overview and the former
    for a detailed view of an itinerary.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755808

 data/gnome-maps.css                    |   10 +++
 data/org.gnome.Maps.data.gresource.xml |    2 +
 data/ui/transit-route-label.ui         |   20 +++++
 src/org.gnome.Maps.src.gresource.xml   |    1 +
 src/transitRouteLabel.js               |  137 ++++++++++++++++++++++++++++++++
 5 files changed, 170 insertions(+), 0 deletions(-)
---
diff --git a/data/gnome-maps.css b/data/gnome-maps.css
index 7639f47..5ff11b5 100644
--- a/data/gnome-maps.css
+++ b/data/gnome-maps.css
@@ -85,3 +85,13 @@
 .printing-text {
     color: rgb(0, 0, 0);
 }
+
+.route-label {
+    padding-left: 2px;
+    padding-right: 2px;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    min-width: 16px;
+    min-height: 16px;
+    font-size: smaller;
+}
diff --git a/data/org.gnome.Maps.data.gresource.xml b/data/org.gnome.Maps.data.gresource.xml
index 2c9c82d..33cbea1 100644
--- a/data/org.gnome.Maps.data.gresource.xml
+++ b/data/org.gnome.Maps.data.gresource.xml
@@ -31,6 +31,8 @@
     <file preprocess="xml-stripblanks">ui/sidebar.ui</file>
     <file preprocess="xml-stripblanks">ui/social-place-more-results-row.ui</file>
     <file preprocess="xml-stripblanks">ui/social-place-row.ui</file>
+    <file preprocess="xml-stripblanks">ui/transit-itinerary-row.ui</file>
+    <file preprocess="xml-stripblanks">ui/transit-route-label.ui</file>
     <file preprocess="xml-stripblanks">ui/user-location-bubble.ui</file>
     <file preprocess="xml-stripblanks">ui/zoom-control.ui</file>
     <file preprocess="xml-stripblanks">ui/zoom-in-notification.ui</file>
diff --git a/data/ui/transit-route-label.ui b/data/ui/transit-route-label.ui
new file mode 100644
index 0000000..423f782
--- /dev/null
+++ b/data/ui/transit-route-label.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<interface>
+  <requires lib="gtk+" version="3.14"/>
+  <template class="Gjs_TransitRouteLabel" parent="GtkLabel">
+    <property name="visible">True</property>
+    <property name="use-markup">True</property>
+    <property name="max-width-chars">12</property>
+    <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
+    <!-- we need to add spacing at the end of the label, rather that in the
+         itinerary row's grid, as to not mess up alignment for the case when
+         there is no route label, i.e. for walking legs
+    -->
+    <property name="margin-end">3</property>
+    <property name="hexpand">False</property>
+    <property name="halign">GTK_ALIGN_START</property>
+    <style>
+      <class name="route-label"/>
+    </style>
+  </template>
+</interface>
diff --git a/src/org.gnome.Maps.src.gresource.xml b/src/org.gnome.Maps.src.gresource.xml
index 768df76..645f1a4 100644
--- a/src/org.gnome.Maps.src.gresource.xml
+++ b/src/org.gnome.Maps.src.gresource.xml
@@ -79,6 +79,7 @@
     <file>togeojson/togeojson.js</file>
     <file>transitOptions.js</file>
     <file>transitPlan.js</file>
+    <file>transitRouteLabel.js</file>
     <file>translations.js</file>
     <file>turnPointMarker.js</file>
     <file>userLocationBubble.js</file>
diff --git a/src/transitRouteLabel.js b/src/transitRouteLabel.js
new file mode 100644
index 0000000..0fca374
--- /dev/null
+++ b/src/transitRouteLabel.js
@@ -0,0 +1,137 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2017 Marcus Lundblad.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+const Lang = imports.lang;
+
+const Cairo = imports.cairo;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+
+const Contrast = imports.contrast;
+
+/* threashhold for route color luminance when we consider it more or less
+ * as white, and draw an outline around the label
+ */
+const OUTLINE_LUMINANCE_THREASHHOLD = 0.9;
+
+const TransitRouteLabel = new Lang.Class({
+    Name: 'TransitRouteLabel',
+    Extends: Gtk.Label,
+    Template: 'resource:///org/gnome/Maps/ui/transit-route-label.ui',
+
+    _init: function(params) {
+        let leg = params.leg;
+        let compact = params.compact;
+
+        delete params.leg;
+        delete params.compact;
+        this.parent(params);
+
+        this._setLabel(leg, compact);
+        this.connect('draw', this._onDraw.bind(this));
+    },
+
+    _setLabel: function(leg, compact) {
+        let color = leg.color;
+        let textColor = leg.textColor;
+        let label = leg.route;
+
+        textColor = Contrast.getContrastingForegroundColor(color, textColor);
+
+        this._bgRed = parseInt(color.substring(0, 2), 16) / 255;
+        this._bgGreen = parseInt(color.substring(2, 4), 16) / 255;
+        this._bgBlue = parseInt(color.substring(4, 6), 16) / 255;
+        this._fgRed = parseInt(textColor.substring(0, 2), 16) / 255;
+        this._fgGreen = parseInt(textColor.substring(2, 4), 16) / 255;
+        this._fgBlue = parseInt(textColor.substring(4, 6), 16) / 255;
+
+        if (Contrast.relativeLuminance(color) > OUTLINE_LUMINANCE_THREASHHOLD)
+            this._hasOutline = true;
+
+        /* for compact (overview) mode, try to shorten the label if the route
+         * name was more than 6 characters
+         */
+        if (compact && label.length > 6) {
+            if (leg.route.startsWith(leg.agencyName)) {
+                /* if the agency name is a prefix of the route name, display the
+                 * agency name in the overview, this way we get a nice "transition"
+                 * into the expanded route showing the full route name
+                 */
+                label = leg.agencyName;
+            } else if (leg.tripShortName &&
+                       (leg.agencyName.length < leg.tripShortName.length)) {
+                /* if the agency name is shorter than the trip short name,
+                 * which can sometimes be a more "internal" number, like a
+                 * "train number", which is less known by the general public,
+                 * prefer the agency name */
+                label = leg.agencyName;
+            } else if (leg.tripShortName && leg.tripShortName.length <= 6) {
+                /* if the above conditions are unmet, use the trip short name
+                 * as a fallback if it was shorter than the original route name */
+                label = leg.tripShortName;
+            }
+            /* if none of the above is true, use the original route name,
+             * and rely on label ellipsization */
+        }
+
+        if (compact) {
+            /* restrict number of characters shown in the label when compact mode
+             * is requested
+             */
+            this.max_width_chars = 6;
+        } else if (leg && !leg.headsign) {
+            // if there is no trip headsign to display, allow more space
+            this.max_width_chars = 25;
+        }
+
+        this.label = '<span foreground="#%s">%s</span>'.format(
+                                        textColor,
+                                        GLib.markup_escape_text(label, -1));
+    },
+
+    /* I didn't find any easy/obvious way to override widget background color
+     * and getting rounded corner just using CSS styles, so doing a custom
+     * Cairo drawing of a "roundrect"
+     */
+    _onDraw: function(widget, cr) {
+        let width = widget.get_allocated_width();
+        let height = widget.get_allocated_height();
+        let radius = this._hasOutline ? 5 : 3;
+
+        cr.newSubPath();
+        cr.arc(width - radius, radius, radius, -Math.PI / 2, 0);
+        cr.arc(width - radius, height - radius, radius, 0 , Math.PI / 2);
+        cr.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
+        cr.arc(radius, radius, radius, Math.PI, 3 * Math.PI / 2);
+        cr.closePath();
+
+        cr.setSourceRGB(this._bgRed, this._bgGreen, this._bgBlue);
+        cr.fillPreserve();
+
+        if (this._hasOutline) {
+            cr.setSourceRGB(this._fgRed, this._fgGreen, this._fgBlue);
+            cr.setLineWidth(1);
+            cr.stroke();
+        }
+
+        return false;
+    }
+});


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