Index: src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(Revision 19199)
+++ src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(Arbeitskopie)
@@ -242,10 +242,10 @@
         /* Colors (without custom alpha channel, if given) for HDOP painting. */
         hdopScale = ColorScale.createHSBScale(256).makeReversed().addTitle(tr("HDOP"));
         qualityScale = ColorScale.createFixedScale(rtkLibQualityColors).addTitle(tr("Quality")).addColorBarTitles(rtkLibQualityNames);
-        fixScale = ColorScale.createFixedScale(gpsFixQualityColors).addTitle(tr("GPS fix")).addColorBarTitles(gpsFixQualityNames);
-        refScale = ColorScale.createCyclicScale(1).addTitle(tr("GPS ref"));
-        dateScale = ColorScale.createHSBScale(256).addTitle(tr("Time"));
-        directionScale = ColorScale.createCyclicScale(256).setIntervalCount(4).addTitle(tr("Direction"));
+        fixScale = ColorScale.createFixedScale(gpsFixQualityColors).addTitle(tr("GPS fix value")).addColorBarTitles(gpsFixQualityNames);
+        refScale = ColorScale.createCyclicScale(1).addTitle(tr("GPS Ref-ID"));
+        dateScale = ColorScale.createHSBScale(256).addTitle(tr("Track date"));
+        directionScale = ColorScale.createCyclicScale(256).setIntervalCount(4).addTitle(tr("Direction [°]"));
 
         systemOfMeasurementChanged(null, null);
     }
@@ -253,7 +253,7 @@
     @Override
     public void systemOfMeasurementChanged(String oldSoM, String newSoM) {
         SystemOfMeasurement som = SystemOfMeasurement.getSystemOfMeasurement();
-        velocityScale.addTitle(tr("Velocity, {0}", som.speedName));
+        velocityScale.addTitle(tr("Velocity [{0}]", som.speedName));
         layer.invalidate();
     }
 
@@ -554,6 +554,37 @@
     }
 
     /**
+     *  @param minTime saves the start time of the track as epoch seconds
+     *  @param maxTime saves the end time of the  track as epoch seconds
+     */
+    private double minTime;
+    private double maxTime;
+
+    /**
+     *  gets the minimum (start) time of the track
+     */
+    private double getMinTime() {
+        return minTime;
+    }
+
+    /**
+     *  gets the maximum (end) time of the track
+     */
+    private double getMaxTime() {
+        return maxTime;
+    }
+
+    /**
+     *  sets the minimum (start) and maximum (end) time of the track
+     *  @param minTime start time of the track
+     *  @param maxTime end time of the track
+     */
+    private void setMinMaxTime(double minTime, double maxTime) {
+        this.minTime = minTime;
+        this.maxTime = maxTime;
+    }
+
+    /**
      *  Calculate colors of way segments based on latest configuration settings
      */
     public void calculateColors() {
@@ -622,6 +653,9 @@
             Interval interval = data.getMinMaxTimeForAllTracks().orElse(new Interval(Instant.EPOCH, Instant.now()));
             minval = interval.getStart().getEpochSecond();
             maxval = interval.getEnd().getEpochSecond();
+
+            setMinMaxTime(minval, maxval);
+
             dateScale.setRange(minval, maxval);
         }
 
@@ -641,7 +675,7 @@
             if (!refs.isEmpty()) {
                 Collections.sort(refs);
                 String[] a = {};
-                refScale = ColorScale.createCyclicScale(refs.size()).addTitle(tr("GPS ref")).addColorBarTitles(refs.toArray(a));
+                refScale = ColorScale.createCyclicScale(refs.size()).addTitle(tr("GPS ref ID")).addColorBarTitles(refs.toArray(a));
                 refScale.setRange(0, refs.size());
             }
         }
@@ -1618,18 +1652,20 @@
         g.setComposite(AlphaComposite.SrcOver.derive(1.00f));
 
         if (colored == ColorMode.HDOP) {
-            hdopScale.drawColorBar(g, w-30, 50, 20, 100, 1.0);
+            hdopScale.drawColorBar(g, w-10, 50, 20, 100, 1.0);
         } else if (colored == ColorMode.QUALITY) {
-            qualityScale.drawColorBar(g, w-30, 50, 20, 100, 1.0);
+            qualityScale.drawColorBar(g, w-10, 50, 20, 100, 1.0);
         } else if (colored == ColorMode.FIX) {
-            fixScale.drawColorBar(g, w-30, 50, 20, 175, 1.0);
+            fixScale.drawColorBar(g, w-10, 50, 20, 175, 1.0);
         } else if (colored == ColorMode.REF) {
-            refScale.drawColorBar(g, w-30, 50, 20, 175, 1.0);
+            refScale.drawColorBar(g, w-10, 50, 20, 175, 1.0);
         } else if (colored == ColorMode.VELOCITY) {
             SystemOfMeasurement som = SystemOfMeasurement.getSystemOfMeasurement();
-            velocityScale.drawColorBar(g, w-30, 50, 20, 100, som.speedValue);
+            velocityScale.drawColorBar(g, w-10, 50, 20, 100, som.speedValue);
         } else if (colored == ColorMode.DIRECTION) {
-            directionScale.drawColorBar(g, w-30, 50, 20, 100, 180.0/Math.PI);
+            directionScale.drawColorBar(g, w-10, 50, 20, 100, 180.0/Math.PI);
+        } else if (colored == ColorMode.TIME) {
+            dateScale.drawColorBarTime(g, w-10, 50, 20, 100, 1.0, getMinTime(), getMaxTime());
         }
     }
 
Index: src/org/openstreetmap/josm/tools/ColorScale.java
===================================================================
--- src/org/openstreetmap/josm/tools/ColorScale.java	(Revision 19199)
+++ src/org/openstreetmap/josm/tools/ColorScale.java	(Arbeitskopie)
@@ -1,11 +1,23 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.tools;
 
+import static org.openstreetmap.josm.tools.I18n.marktr;
+
 import java.awt.Color;
 import java.awt.FontMetrics;
 import java.awt.Graphics2D;
+import java.awt.Font;
 import java.util.Arrays;
+import java.util.Date;
+import java.time.ZoneId;
+import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 
+import org.openstreetmap.josm.data.preferences.NamedColorProperty;
+
+import javax.swing.UIManager;
+
 /**
  * Utility class that helps to work with color scale for coloring GPX tracks etc.
  * @since 7319
@@ -21,6 +33,11 @@
     private String title = "";
     private int intervalCount = 5;
 
+    private static final Color LEGEND_BACKGROUND = new NamedColorProperty(marktr("gpx legend background"), new Color(180, 180, 180, 160)).get();
+    private static final Color LEGEND_TEXT_OUTLINE_DARK = new NamedColorProperty(marktr("gpx legend text outline dark"), new Color(102, 102, 102)).get();
+    private static final Color LEGEND_TEXT_OUTLINE_BRIGHT = new NamedColorProperty(marktr("gpx legend text outline bright"), new Color(204, 204, 204)).get();
+    private static final Color LEGEND_TITLE = new NamedColorProperty(marktr("gpx legend title color"), new Color(0, 0, 0)).get();
+
     private ColorScale() {
 
     }
@@ -225,42 +242,118 @@
     }
 
     /**
+     * draws an outline for the legend texts
+     * @param g The graphics to draw on
+     * @param txt The text to draw the outline
+     * @param x Text x
+     * @param y Text y
+     * @param color The color of the text
+     */
+    public void drawOutline(Graphics2D g, String txt, int x, int y, Color color) {
+        int greenValue = color.getGreen();
+        if (greenValue >= 170) {
+            g.setColor(LEGEND_TEXT_OUTLINE_DARK);
+        } else {
+            g.setColor(LEGEND_TEXT_OUTLINE_BRIGHT);
+        }
+
+        g.drawString(txt, x -1, y -1);
+        g.drawString(txt, x +1, y -1);
+        g.drawString(txt, x -1, y +1);
+        g.drawString(txt, x +1, y +1);
+        g.setColor(color);
+    }
+
+    /**
      * Draws a color bar representing this scale on the given graphics
      * @param g The graphics to draw on
      * @param x Rect x
      * @param y Rect y
-     * @param w Rect width
-     * @param h Rect height
+     * @param w Color bar width
+     * @param h Color bar height
      * @param valueScale The scale factor of the values
      */
     public void drawColorBar(Graphics2D g, int x, int y, int w, int h, double valueScale) {
         int n = colors.length;
-        for (int i = 0; i < n; i++) {
-            g.setColor(colors[i]);
-            if (w < h) {
-                g.fillRect(x, y+i*h/n, w, h/n+1);
-            } else {
-                g.fillRect(x+i*w/n, y, w/n+1, h);
-            }
-        }
 
+        // color bar texts width & height
         int fw, fh;
+
+        Font newFont = UIManager.getFont("PopupMenu.font");
+        g.setFont(newFont);
         FontMetrics fm = g.getFontMetrics();
         fh = fm.getHeight()/2;
+        int titleWidth = fm.stringWidth(title);
+
+        String txt;
+        Color color;
+
+        int arcWidth = 20;
+        int arcHeight = 20;
+
+        g.setColor(LEGEND_BACKGROUND);
+        int xText = x;
+        int xRect;
+        int rectWidth;
+
+        // padding from text to edge of rectangle
+        int padding = 19;
+
+        // calculates the width of the color bar texts
         if (colorBarTitles != null && colorBarTitles.length > 0) {
-             fw = Arrays.stream(colorBarTitles).mapToInt(fm::stringWidth).max().orElse(50);
+            fw = Arrays.stream(colorBarTitles).mapToInt(fm::stringWidth).max().orElse(50);
         } else {
             fw = fm.stringWidth(
                     String.valueOf(Math.max((int) Math.abs(max * valueScale), (int) Math.abs(min * valueScale))))
                     + fm.stringWidth("0.123");
         }
-        g.setColor(noDataColor);
+
+        // background rectangle
+        if (fw + w > titleWidth) {
+            rectWidth = w + fw + padding * 2;
+            xRect = x - rectWidth;
+            xText = xRect + (int) (padding / 1.2);
+            g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight);
+        } else {
+            if (titleWidth >= 120) {
+                titleWidth = 120;
+            }
+            rectWidth = w + titleWidth + padding + padding / 2;
+            xRect = x - rectWidth;
+            xText = xRect + padding / 2 + rectWidth / 2 - fw;
+
+            g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight);
+        }
+
+        // colorbar
+        for (int i = 0; i < n; i++) {
+            g.setColor(colors[i]);
+            if (w < h) {
+                double factor = 1.07 + (0.045 * Math.log(n));
+                if (n == 6) {
+                    factor = 1.2;
+                    g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * (int) (h / n * factor), w, (int) (h / n * factor));
+                } else if (n < 200) {
+                    g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * (int) (h / n * factor), w, (int) (h / n * factor));
+                } else {
+                    g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * h / (int) (n * 0.875), w, (h / n + 1));
+                }
+            } else {
+                g.fillRect(xText + fw + 7 + i * w / n, y, w / n, h + 1);
+            }
+        }
+
+        // legend title
         if (title != null) {
-            g.drawString(title, x-fw-3, y-fh*3/2);
+            g.setColor(LEGEND_TITLE);
+            g.drawString(title, xRect + rectWidth / 2 - titleWidth / 2, y - fh * 3 / 2 - 10);
         }
+
+        // legend texts
         for (int i = 0; i <= intervalCount; i++) {
-            g.setColor(colors[(int) (1.0*i*n/intervalCount-1e-10)]);
-            String txt;
+            color = colors[(int) (1.0 * i * n / intervalCount - 1e-10)];
+            g.setColor(color);
+
             if (colorBarTitles != null && i < colorBarTitles.length) {
                 txt = colorBarTitles[i];
             } else {
@@ -268,12 +361,142 @@
                 txt = String.format("%.3f", val*valueScale);
             }
             if (intervalCount == 0) {
-                g.drawString(txt, x-fw-3, y+h/2+fh/2);
+                drawOutline(g, txt, xText, y + h / 2 + fh / 2, color);
+                g.drawString(txt, xText, y + h / 2 + fh / 2);
             } else if (w < h) {
-                g.drawString(txt, x-fw-3, y+i*h/intervalCount+fh/2);
+                drawOutline(g, txt, xText, y + i * h / intervalCount + fh / 2, color);
+                g.drawString(txt, xText, y + i * h / intervalCount + fh / 2);
             } else {
-                g.drawString(txt, x+i*w/intervalCount-fw/2, y+fh-3);
+                drawOutline(g, txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5, color);
+                g.drawString(txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5);
             }
         }
+
+        g.setColor(noDataColor);
     }
+
+    /**
+     * Draws a color bar representing the time scale on the given graphics
+     * @param g The graphics to draw on
+     * @param x Rect x
+     * @param y Rect y
+     * @param w Color bar width
+     * @param h Color bar height
+     * @param valueScale The scale factor of the values
+     * @param minVal start time of the track
+     * @param maxVal end time of the track
+     */
+    public void drawColorBarTime(Graphics2D g, int x, int y, int w, int h, double valueScale, double minVal, double maxVal) {
+        int n = colors.length;
+
+        // color bar texts width & height
+        int fw, fh;
+
+        Font newFont = UIManager.getFont("PopupMenu.font");
+        g.setFont(newFont);
+        FontMetrics fm = g.getFontMetrics();
+        fh = fm.getHeight()/2;
+        int titleWidth = fm.stringWidth(title);
+
+        String txt;
+        Color color;
+
+        int arcWidth = 20;
+        int arcHeight = 20;
+
+        g.setColor(LEGEND_BACKGROUND);
+        int xText = x;
+        int xRect;
+        int rectWidth;
+
+        // padding from text to edge of rectangle
+        int padding = 19;
+
+        String formatDay = "yyyy-MM-dd      HH:mm";
+        String formatTime = "HH:mm:ss";
+
+        // calculates the width of the colorbar texts
+        if (maxVal-minVal > 86400) {
+            fw = fm.stringWidth(formatDay);
+        } else {
+            fw = fm.stringWidth(formatTime);
+        }
+
+        g.setColor(LEGEND_BACKGROUND);
+
+        // background rectangle
+        if (fw + w > titleWidth) {
+            rectWidth = w + fw + padding * 2;
+            xRect = x - rectWidth;
+            xText = xRect + (int) (padding / 1.2);
+            g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight);
+        } else {
+            if (titleWidth >= 120) {
+                titleWidth = 120;
+            }
+            rectWidth = w + titleWidth + padding + padding / 2;
+            xRect = x - rectWidth;
+            xText = xRect + padding / 2 + rectWidth / 2 - fw;
+            g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight);
+        }
+
+        // colorbar
+        for (int i = 0; i < n; i++) {
+            g.setColor(colors[i]);
+            if (w < h) {
+                g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * h / (int) (n * 0.875), w, (h / n + 1));
+            } else {
+                g.fillRect(xText + fw + padding / 3 + i * w / n, y, w / n + 1, h);
+            }
+        }
+
+        // legend title
+        if (title != null) {
+            g.setColor(LEGEND_TITLE);
+            g.drawString(title, xRect + rectWidth / 2 - titleWidth / 2, y - fh * 3 / 2 - padding / 2);;
+        }
+
+        // legend texts
+        for (int i = 0; i <= intervalCount; i++) {
+            color = colors[(int) (1.0 * i * n / intervalCount - 1e-10)];
+            g.setColor(color);
+
+            if (colorBarTitles != null && i < colorBarTitles.length) {
+                txt = colorBarTitles[i];
+            } else {
+                final double val = minVal + i * (maxVal - minVal) / intervalCount;
+                long longval = (long) val;
+
+                Date date = new Date(longval * 1000L);
+                Instant dateInst = date.toInstant();
+
+                ZoneId gmt = ZoneId.of("GMT");
+                ZonedDateTime zonedDateTime = dateInst.atZone(gmt);
+
+                String formatted;
+
+                if (maxVal-minVal > 86400) {
+                    DateTimeFormatter day = DateTimeFormatter.ofPattern(formatDay);
+                    formatted = zonedDateTime.format(day);
+                } else {
+                    DateTimeFormatter time = DateTimeFormatter.ofPattern(formatTime);
+                    formatted = zonedDateTime.format(time);
+                }
+
+                txt = formatted;
+            }
+            if (intervalCount == 0) {
+                drawOutline(g, txt, xText, y + h / 2 + fh / 2, color);
+                g.drawString(txt, xText, y + h / 2 + fh / 2);
+            } else if (w < h) {
+                drawOutline(g, txt, xText, y + i * h / intervalCount + fh / 2, color);
+                g.drawString(txt, xText, y + i * h / intervalCount + fh / 2);
+            } else {
+                drawOutline(g, txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5, color);
+                g.drawString(txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5);
+            }
+        }
+
+        g.setColor(noDataColor);
+    }
 }
