Ticket #23926: josm_legend.patch

File josm_legend.patch, 16.3 KB (added by Pauline, 4 months ago)
  • src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java

     
    242242        /* Colors (without custom alpha channel, if given) for HDOP painting. */
    243243        hdopScale = ColorScale.createHSBScale(256).makeReversed().addTitle(tr("HDOP"));
    244244        qualityScale = ColorScale.createFixedScale(rtkLibQualityColors).addTitle(tr("Quality")).addColorBarTitles(rtkLibQualityNames);
    245         fixScale = ColorScale.createFixedScale(gpsFixQualityColors).addTitle(tr("GPS fix")).addColorBarTitles(gpsFixQualityNames);
    246         refScale = ColorScale.createCyclicScale(1).addTitle(tr("GPS ref"));
    247         dateScale = ColorScale.createHSBScale(256).addTitle(tr("Time"));
    248         directionScale = ColorScale.createCyclicScale(256).setIntervalCount(4).addTitle(tr("Direction"));
     245        fixScale = ColorScale.createFixedScale(gpsFixQualityColors).addTitle(tr("GPS fix value")).addColorBarTitles(gpsFixQualityNames);
     246        refScale = ColorScale.createCyclicScale(1).addTitle(tr("GPS Ref-ID"));
     247        dateScale = ColorScale.createHSBScale(256).addTitle(tr("Track date"));
     248        directionScale = ColorScale.createCyclicScale(256).setIntervalCount(4).addTitle(tr("Direction [°]"));
    249249
    250250        systemOfMeasurementChanged(null, null);
    251251    }
     
    253253    @Override
    254254    public void systemOfMeasurementChanged(String oldSoM, String newSoM) {
    255255        SystemOfMeasurement som = SystemOfMeasurement.getSystemOfMeasurement();
    256         velocityScale.addTitle(tr("Velocity, {0}", som.speedName));
     256        velocityScale.addTitle(tr("Velocity [{0}]", som.speedName));
    257257        layer.invalidate();
    258258    }
    259259
     
    554554    }
    555555
    556556    /**
     557     *  @param minTime saves the start time of the track as epoch seconds
     558     *  @param maxTime saves the end time of the  track as epoch seconds
     559     */
     560    private double minTime;
     561    private double maxTime;
     562
     563    /**
     564     *  gets the minimum (start) time of the track
     565     */
     566    private double getMinTime() {
     567        return minTime;
     568    }
     569
     570    /**
     571     *  gets the maximum (end) time of the track
     572     */
     573    private double getMaxTime() {
     574        return maxTime;
     575    }
     576
     577    /**
     578     *  sets the minimum (start) and maximum (end) time of the track
     579     *  @param minTime start time of the track
     580     *  @param maxTime end time of the track
     581     */
     582    private void setMinMaxTime(double minTime, double maxTime) {
     583        this.minTime = minTime;
     584        this.maxTime = maxTime;
     585    }
     586
     587    /**
    557588     *  Calculate colors of way segments based on latest configuration settings
    558589     */
    559590    public void calculateColors() {
     
    622653            Interval interval = data.getMinMaxTimeForAllTracks().orElse(new Interval(Instant.EPOCH, Instant.now()));
    623654            minval = interval.getStart().getEpochSecond();
    624655            maxval = interval.getEnd().getEpochSecond();
     656
     657            setMinMaxTime(minval, maxval);
     658
    625659            dateScale.setRange(minval, maxval);
    626660        }
    627661
     
    641675            if (!refs.isEmpty()) {
    642676                Collections.sort(refs);
    643677                String[] a = {};
    644                 refScale = ColorScale.createCyclicScale(refs.size()).addTitle(tr("GPS ref")).addColorBarTitles(refs.toArray(a));
     678                refScale = ColorScale.createCyclicScale(refs.size()).addTitle(tr("GPS ref ID")).addColorBarTitles(refs.toArray(a));
    645679                refScale.setRange(0, refs.size());
    646680            }
    647681        }
     
    16181652        g.setComposite(AlphaComposite.SrcOver.derive(1.00f));
    16191653
    16201654        if (colored == ColorMode.HDOP) {
    1621             hdopScale.drawColorBar(g, w-30, 50, 20, 100, 1.0);
     1655            hdopScale.drawColorBar(g, w-10, 50, 20, 100, 1.0, 0.0, 0.0);
    16221656        } else if (colored == ColorMode.QUALITY) {
    1623             qualityScale.drawColorBar(g, w-30, 50, 20, 100, 1.0);
     1657            qualityScale.drawColorBar(g, w-10, 50, 20, 100, 1.0, 0.0, 0.0);
    16241658        } else if (colored == ColorMode.FIX) {
    1625             fixScale.drawColorBar(g, w-30, 50, 20, 175, 1.0);
     1659            fixScale.drawColorBar(g, w-10, 50, 20, 175, 1.0, 0.0, 0.0);
    16261660        } else if (colored == ColorMode.REF) {
    1627             refScale.drawColorBar(g, w-30, 50, 20, 175, 1.0);
     1661            refScale.drawColorBar(g, w-10, 50, 20, 175, 1.0, 0.0, 0.0);
    16281662        } else if (colored == ColorMode.VELOCITY) {
    16291663            SystemOfMeasurement som = SystemOfMeasurement.getSystemOfMeasurement();
    1630             velocityScale.drawColorBar(g, w-30, 50, 20, 100, som.speedValue);
     1664            velocityScale.drawColorBar(g, w-10, 50, 20, 100, som.speedValue, 0.0, 0.0);
    16311665        } else if (colored == ColorMode.DIRECTION) {
    1632             directionScale.drawColorBar(g, w-30, 50, 20, 100, 180.0/Math.PI);
     1666            directionScale.drawColorBar(g, w-10, 50, 20, 100, 180.0/Math.PI, 0.0, 0.0);
     1667        } else if (colored == ColorMode.TIME) {
     1668            dateScale.drawColorBar(g, w-10, 50, 20, 100, 1.0, getMinTime(), getMaxTime());
    16331669        }
    16341670    }
    16351671
  • src/org/openstreetmap/josm/tools/ColorScale.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.tools;
    33
     4import static org.openstreetmap.josm.tools.I18n.marktr;
     5
    46import java.awt.Color;
    57import java.awt.FontMetrics;
    68import java.awt.Graphics2D;
     9import java.awt.Font;
    710import java.util.Arrays;
     11import java.util.Date;
     12import java.time.ZoneId;
     13import java.time.Instant;
     14import java.time.ZonedDateTime;
     15import java.time.format.DateTimeFormatter;
    816
     17import org.openstreetmap.josm.data.preferences.NamedColorProperty;
     18
     19import javax.swing.UIManager;
     20
    921/**
    1022 * Utility class that helps to work with color scale for coloring GPX tracks etc.
    1123 * @since 7319
     
    2133    private String title = "";
    2234    private int intervalCount = 5;
    2335
     36    private static final Color LEGEND_BACKGROUND = new NamedColorProperty(marktr("gpx legend background"), new Color(180, 180, 180, 160)).get();
     37    private static final Color LEGEND_TEXT_OUTLINE_DARK = new NamedColorProperty(marktr("gpx legend text outline dark"), new Color(102, 102, 102)).get();
     38    private static final Color LEGEND_TEXT_OUTLINE_BRIGHT = new NamedColorProperty(marktr("gpx legend text outline bright"), new Color(204, 204, 204)).get();
     39    private static final Color LEGEND_TITLE = new NamedColorProperty(marktr("gpx legend title color"), new Color(0, 0, 0)).get();
     40
    2441    private ColorScale() {
    2542
    2643    }
     
    225242    }
    226243
    227244    /**
     245     * draws an outline for the legend texts
     246     * @param g The graphics to draw on
     247     * @param txt The text to draw the outline
     248     * @param x Text x
     249     * @param y Text y
     250     * @param color The color of the text
     251     */
     252    public void drawOutline(Graphics2D g, String txt, int x, int y, Color color) {
     253        int greenValue = color.getGreen();
     254        if (greenValue >= 170) {
     255            g.setColor(LEGEND_TEXT_OUTLINE_DARK);
     256        } else {
     257            g.setColor(LEGEND_TEXT_OUTLINE_BRIGHT);
     258        }
     259
     260        g.drawString(txt, x -1, y -1);
     261        g.drawString(txt, x +1, y -1);
     262        g.drawString(txt, x -1, y +1);
     263        g.drawString(txt, x +1, y +1);
     264        g.setColor(color);
     265    }
     266
     267    /**
    228268     * Draws a color bar representing this scale on the given graphics
    229269     * @param g The graphics to draw on
    230270     * @param x Rect x
     
    233273     * @param h Rect height
    234274     * @param valueScale The scale factor of the values
    235275     */
    236     public void drawColorBar(Graphics2D g, int x, int y, int w, int h, double valueScale) {
     276    public void drawColorBar(Graphics2D g, int x, int y, int w, int h, double valueScale, double minVal, double maxVal) {
    237277        int n = colors.length;
    238         for (int i = 0; i < n; i++) {
    239             g.setColor(colors[i]);
    240             if (w < h) {
    241                 g.fillRect(x, y+i*h/n, w, h/n+1);
     278        int fw, fh;
     279        Font newFont = UIManager.getFont("PopupMenu.font");
     280        g.setFont(newFont);
     281        FontMetrics fm = g.getFontMetrics();
     282        fh = fm.getHeight()/2;
     283        int titleWidth = fm.stringWidth(title);
     284
     285        String txt;
     286        Color color;
     287
     288        int arcWidth = 20;
     289        int arcHeight = 20;
     290
     291        g.setColor(LEGEND_BACKGROUND);
     292        int xText = x;
     293        int xRect;
     294        int rectWidth;
     295
     296        if (minVal == 0.0 && maxVal == 0.0) {
     297
     298            // calculates the width of the colorbar texts
     299            if (colorBarTitles != null && colorBarTitles.length > 0) {
     300                fw = Arrays.stream(colorBarTitles).mapToInt(fm::stringWidth).max().orElse(50);
    242301            } else {
    243                 g.fillRect(x+i*w/n, y, w/n+1, h);
     302                fw = fm.stringWidth(
     303                        String.valueOf(Math.max((int) Math.abs(max * valueScale), (int) Math.abs(min * valueScale))))
     304                        + fm.stringWidth("0.123");
    244305            }
    245         }
    246306
    247         int fw, fh;
    248         FontMetrics fm = g.getFontMetrics();
    249         fh = fm.getHeight()/2;
    250         if (colorBarTitles != null && colorBarTitles.length > 0) {
    251              fw = Arrays.stream(colorBarTitles).mapToInt(fm::stringWidth).max().orElse(50);
     307            // background rectangle
     308            if (fw + w > titleWidth) {
     309                rectWidth = w+fw+37;
     310                xRect = x-rectWidth-10;
     311                xText = xRect + 13;
     312                g.fillRoundRect(xRect, (fh*3/2), rectWidth, h+y-(fh*3/2)+10, arcWidth, arcHeight+7);
     313            } else {
     314                if (titleWidth >= 120) {
     315                    titleWidth = 120;
     316                }
     317                rectWidth = w+titleWidth+27;
     318                xRect = x-rectWidth-10;
     319                xText = xRect+10+rectWidth/2-fw;
     320
     321                g.fillRoundRect(xRect, (fh*3/2), rectWidth, h+y-(fh*3/2)+10, arcWidth, arcHeight+7);
     322            }
     323
     324            // colorbar
     325            for (int i = 0; i < n; i++) {
     326                g.setColor(colors[i]);
     327                if (w < h) {
     328                    double factor = 1.07 + (0.045 * Math.log(n));
     329                    if (n == 6) {
     330                        factor = 1.2;
     331                        g.fillRect(xText+fw+7, y-9+i*(int) (h/n*factor), w, (int) (h/n*factor));
     332                    } else if (n < 200) {
     333                        g.fillRect(xText+fw+7, y-9+i*(int) (h/n*factor), w, (int) (h/n*factor));
     334                    } else {
     335                        g.fillRect(xText+fw+7, y-9+i*h/(int) (n*0.875), w, (h/n+1));
     336                    }
     337                } else {
     338                    g.fillRect(xText+fw+7+i*w/n, y, w/n, h+1);
     339                }
     340            }
     341
     342
     343            if (title != null) {
     344                g.setColor(LEGEND_TITLE);
     345                g.drawString(title, xRect+rectWidth/2-titleWidth/2, y-fh*3/2-10);
     346            }
     347            for (int i = 0; i <= intervalCount; i++) {
     348                color = colors[(int) (1.0*i*n/intervalCount-1e-10)];
     349                g.setColor(color);
     350
     351                if (colorBarTitles != null && i < colorBarTitles.length) {
     352                    txt = colorBarTitles[i];
     353                } else {
     354                    final double val = min+i*(max-min)/intervalCount;
     355                    txt = String.format("%.3f", val*valueScale);
     356                }
     357                if (intervalCount == 0) {
     358                    drawOutline(g, txt, xText, y+h/2+fh/2, color);
     359                    g.drawString(txt, xText, y+h/2+fh/2);
     360                } else if (w < h) {
     361                    drawOutline(g, txt, xText, y+i*h/intervalCount+fh/2, color);
     362                    g.drawString(txt, xText, y+i*h/intervalCount+fh/2);
     363                } else {
     364                    drawOutline(g, txt, xText+i*w/intervalCount-fw/2-15, y+fh-5, color);
     365                    g.drawString(txt, xText+i*w/intervalCount-fw/2-15, y+fh-5);
     366                }
     367            }
    252368        } else {
    253             fw = fm.stringWidth(
    254                     String.valueOf(Math.max((int) Math.abs(max * valueScale), (int) Math.abs(min * valueScale))))
    255                     + fm.stringWidth("0.123");
    256         }
    257         g.setColor(noDataColor);
    258         if (title != null) {
    259             g.drawString(title, x-fw-3, y-fh*3/2);
    260         }
    261         for (int i = 0; i <= intervalCount; i++) {
    262             g.setColor(colors[(int) (1.0*i*n/intervalCount-1e-10)]);
    263             String txt;
    264             if (colorBarTitles != null && i < colorBarTitles.length) {
    265                 txt = colorBarTitles[i];
     369            String formatDay = "yyyy-MM-dd      HH:mm";
     370            String formatTime = "HH:mm:ss";
     371
     372            // calculates the width of the colorbar texts
     373            if (maxVal-minVal > 86400) {
     374                fw = fm.stringWidth(formatDay);
    266375            } else {
    267                 final double val = min+i*(max-min)/intervalCount;
    268                 txt = String.format("%.3f", val*valueScale);
     376                fw = fm.stringWidth(formatTime);
    269377            }
    270             if (intervalCount == 0) {
    271                 g.drawString(txt, x-fw-3, y+h/2+fh/2);
    272             } else if (w < h) {
    273                 g.drawString(txt, x-fw-3, y+i*h/intervalCount+fh/2);
     378
     379            g.setColor(LEGEND_BACKGROUND);
     380
     381            // background rectangle
     382            if (fw + w > titleWidth) {
     383                rectWidth = w+fw+37;
     384                xRect = x-rectWidth-10;
     385                xText = xRect + 13;
     386                g.fillRoundRect(xRect, (fh*3/2), rectWidth, h+y-(fh*3/2)+10, arcWidth, arcHeight+7);
    274387            } else {
    275                 g.drawString(txt, x+i*w/intervalCount-fw/2, y+fh-3);
     388                if (titleWidth >= 120) {
     389                    titleWidth = 120;
     390                }
     391                rectWidth = w+titleWidth+27;
     392                xRect = x-rectWidth-10;
     393                xText = xRect+10+rectWidth/2-fw;
     394                g.fillRoundRect(xRect, (fh*3/2), rectWidth, h+y-(fh*3/2)+10, arcWidth, arcHeight+7);
    276395            }
     396
     397            // colorbar
     398            for (int i = 0; i < n; i++) {
     399                g.setColor(colors[i]);
     400                if (w < h) {
     401                    g.fillRect(xText+fw+7, y-9+i*h/(int) (n*0.875), w, (h/n+1));
     402                } else {
     403                    g.fillRect(xText+fw+7+i*w/n, y, w/n+1, h);
     404                }
     405            }
     406
     407            if (title != null) {
     408                g.setColor(LEGEND_TITLE);
     409                g.drawString(title, xRect+rectWidth/2-titleWidth/2, y-fh*3/2-10);;
     410            }
     411
     412            for (int i = 0; i <= intervalCount; i++) {
     413                color = colors[(int) (1.0*i*n/intervalCount-1e-10)];
     414                g.setColor(color);
     415
     416                if (colorBarTitles != null && i < colorBarTitles.length) {
     417                    txt = colorBarTitles[i];
     418                } else {
     419                    final double val = minVal+i*(maxVal-minVal)/intervalCount;
     420                    long longval = (long) val;
     421
     422                    Date date = new Date(longval * 1000L);
     423                    Instant dateInst = date.toInstant();
     424
     425                    ZoneId gmt = ZoneId.of("GMT");
     426                    ZonedDateTime zonedDateTime = dateInst.atZone(gmt);
     427
     428                    String formatted;
     429
     430                    if (maxVal-minVal > 86400) {
     431                        DateTimeFormatter day = DateTimeFormatter.ofPattern(formatDay);
     432                        formatted = zonedDateTime.format(day);
     433                    } else {
     434                        DateTimeFormatter time = DateTimeFormatter.ofPattern(formatTime);
     435                        formatted = zonedDateTime.format(time);
     436                    }
     437
     438                    txt = formatted;
     439                }
     440                if (intervalCount == 0) {
     441                    drawOutline(g, txt, xText, y+h/2+fh/2, color);
     442                    g.drawString(txt, xText, y+h/2+fh/2);
     443                } else if (w < h) {
     444                    drawOutline(g, txt, xText, y+i*h/intervalCount+fh/2, color);
     445                    g.drawString(txt, xText, y+i*h/intervalCount+fh/2);
     446                } else {
     447                    drawOutline(g, txt, xText+i*w/intervalCount-fw/2-15, y+fh-5, color);
     448                    g.drawString(txt, xText+i*w/intervalCount-fw/2-15, y+fh-5);
     449                }
     450            }
    277451        }
     452        g.setColor(noDataColor);
    278453    }
    279454}