Ticket #23926: josm_legend_2.patch
File josm_legend_2.patch, 17.0 KB (added by , 13 months ago) |
---|
-
src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
242 242 /* Colors (without custom alpha channel, if given) for HDOP painting. */ 243 243 hdopScale = ColorScale.createHSBScale(256).makeReversed().addTitle(tr("HDOP")); 244 244 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("T ime"));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 [°]")); 249 249 250 250 systemOfMeasurementChanged(null, null); 251 251 } … … 253 253 @Override 254 254 public void systemOfMeasurementChanged(String oldSoM, String newSoM) { 255 255 SystemOfMeasurement som = SystemOfMeasurement.getSystemOfMeasurement(); 256 velocityScale.addTitle(tr("Velocity , {0}", som.speedName));256 velocityScale.addTitle(tr("Velocity [{0}]", som.speedName)); 257 257 layer.invalidate(); 258 258 } 259 259 … … 554 554 } 555 555 556 556 /** 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 /** 557 588 * Calculate colors of way segments based on latest configuration settings 558 589 */ 559 590 public void calculateColors() { … … 622 653 Interval interval = data.getMinMaxTimeForAllTracks().orElse(new Interval(Instant.EPOCH, Instant.now())); 623 654 minval = interval.getStart().getEpochSecond(); 624 655 maxval = interval.getEnd().getEpochSecond(); 656 657 setMinMaxTime(minval, maxval); 658 625 659 dateScale.setRange(minval, maxval); 626 660 } 627 661 … … 641 675 if (!refs.isEmpty()) { 642 676 Collections.sort(refs); 643 677 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)); 645 679 refScale.setRange(0, refs.size()); 646 680 } 647 681 } … … 1618 1652 g.setComposite(AlphaComposite.SrcOver.derive(1.00f)); 1619 1653 1620 1654 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); 1622 1656 } 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); 1624 1658 } 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); 1626 1660 } 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); 1628 1662 } else if (colored == ColorMode.VELOCITY) { 1629 1663 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); 1631 1665 } 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); 1667 } else if (colored == ColorMode.TIME) { 1668 dateScale.drawColorBarTime(g, w-10, 50, 20, 100, 1.0, getMinTime(), getMaxTime()); 1633 1669 } 1634 1670 } 1635 1671 -
src/org/openstreetmap/josm/tools/ColorScale.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.tools; 3 3 4 import static org.openstreetmap.josm.tools.I18n.marktr; 5 4 6 import java.awt.Color; 5 7 import java.awt.FontMetrics; 6 8 import java.awt.Graphics2D; 9 import java.awt.Font; 7 10 import java.util.Arrays; 11 import java.util.Date; 12 import java.time.ZoneId; 13 import java.time.Instant; 14 import java.time.ZonedDateTime; 15 import java.time.format.DateTimeFormatter; 8 16 17 import org.openstreetmap.josm.data.preferences.NamedColorProperty; 18 19 import javax.swing.UIManager; 20 9 21 /** 10 22 * Utility class that helps to work with color scale for coloring GPX tracks etc. 11 23 * @since 7319 … … 21 33 private String title = ""; 22 34 private int intervalCount = 5; 23 35 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 24 41 private ColorScale() { 25 42 26 43 } … … 225 242 } 226 243 227 244 /** 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 /** 228 268 * Draws a color bar representing this scale on the given graphics 229 269 * @param g The graphics to draw on 230 270 * @param x Rect x 231 271 * @param y Rect y 232 * @param w Rectwidth233 * @param h Rectheight272 * @param w Color bar width 273 * @param h Color bar height 234 274 * @param valueScale The scale factor of the values 235 275 */ 236 276 public void drawColorBar(Graphics2D g, int x, int y, int w, int h, double valueScale) { 237 277 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);242 } else {243 g.fillRect(x+i*w/n, y, w/n+1, h);244 }245 }246 278 279 // color bar texts width & height 247 280 int fw, fh; 281 282 Font newFont = UIManager.getFont("PopupMenu.font"); 283 g.setFont(newFont); 248 284 FontMetrics fm = g.getFontMetrics(); 249 285 fh = fm.getHeight()/2; 286 int titleWidth = fm.stringWidth(title); 287 288 String txt; 289 Color color; 290 291 int arcWidth = 20; 292 int arcHeight = 20; 293 294 g.setColor(LEGEND_BACKGROUND); 295 int xText = x; 296 int xRect; 297 int rectWidth; 298 299 // padding from text to edge of rectangle 300 int padding = 19; 301 302 // calculates the width of the color bar texts 250 303 if (colorBarTitles != null && colorBarTitles.length > 0) { 251 304 fw = Arrays.stream(colorBarTitles).mapToInt(fm::stringWidth).max().orElse(50); 252 305 } else { 253 306 fw = fm.stringWidth( 254 307 String.valueOf(Math.max((int) Math.abs(max * valueScale), (int) Math.abs(min * valueScale)))) 255 308 + fm.stringWidth("0.123"); 256 309 } 257 g.setColor(noDataColor); 310 311 // background rectangle 312 if (fw + w > titleWidth) { 313 rectWidth = w + fw + padding * 2; 314 xRect = x - rectWidth; 315 xText = xRect + (int) (padding / 1.2); 316 g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight); 317 } else { 318 if (titleWidth >= 120) { 319 titleWidth = 120; 320 } 321 rectWidth = w + titleWidth + padding + padding / 2; 322 xRect = x - rectWidth; 323 xText = xRect + padding / 2 + rectWidth / 2 - fw; 324 325 g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight); 326 } 327 328 // colorbar 329 for (int i = 0; i < n; i++) { 330 g.setColor(colors[i]); 331 if (w < h) { 332 double factor = 1.07 + (0.045 * Math.log(n)); 333 if (n == 6) { 334 factor = 1.2; 335 g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * (int) (h / n * factor), w, (int) (h / n * factor)); 336 } else if (n < 200) { 337 g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * (int) (h / n * factor), w, (int) (h / n * factor)); 338 } else { 339 g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * h / (int) (n * 0.875), w, (h / n + 1)); 340 } 341 } else { 342 g.fillRect(xText + fw + 7 + i * w / n, y, w / n, h + 1); 343 } 344 } 345 346 // legend title 258 347 if (title != null) { 259 g.drawString(title, x-fw-3, y-fh*3/2); 348 g.setColor(LEGEND_TITLE); 349 g.drawString(title, xRect + rectWidth / 2 - titleWidth / 2, y - fh * 3 / 2 - 10); 260 350 } 351 352 // legend texts 261 353 for (int i = 0; i <= intervalCount; i++) { 262 g.setColor(colors[(int) (1.0*i*n/intervalCount-1e-10)]); 263 String txt; 354 color = colors[(int) (1.0 * i * n / intervalCount - 1e-10)]; 355 g.setColor(color); 356 264 357 if (colorBarTitles != null && i < colorBarTitles.length) { 265 358 txt = colorBarTitles[i]; 266 359 } else { … … 268 361 txt = String.format("%.3f", val*valueScale); 269 362 } 270 363 if (intervalCount == 0) { 271 g.drawString(txt, x-fw-3, y+h/2+fh/2); 364 drawOutline(g, txt, xText, y + h / 2 + fh / 2, color); 365 g.drawString(txt, xText, y + h / 2 + fh / 2); 272 366 } else if (w < h) { 273 g.drawString(txt, x-fw-3, y+i*h/intervalCount+fh/2); 367 drawOutline(g, txt, xText, y + i * h / intervalCount + fh / 2, color); 368 g.drawString(txt, xText, y + i * h / intervalCount + fh / 2); 274 369 } else { 275 g.drawString(txt, x+i*w/intervalCount-fw/2, y+fh-3); 370 drawOutline(g, txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5, color); 371 g.drawString(txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5); 276 372 } 277 373 } 374 375 g.setColor(noDataColor); 278 376 } 377 378 /** 379 * Draws a color bar representing the time scale on the given graphics 380 * @param g The graphics to draw on 381 * @param x Rect x 382 * @param y Rect y 383 * @param w Color bar width 384 * @param h Color bar height 385 * @param valueScale The scale factor of the values 386 * @param minVal start time of the track 387 * @param maxVal end time of the track 388 */ 389 public void drawColorBarTime(Graphics2D g, int x, int y, int w, int h, double valueScale, double minVal, double maxVal) { 390 int n = colors.length; 391 392 // color bar texts width & height 393 int fw, fh; 394 395 Font newFont = UIManager.getFont("PopupMenu.font"); 396 g.setFont(newFont); 397 FontMetrics fm = g.getFontMetrics(); 398 fh = fm.getHeight()/2; 399 int titleWidth = fm.stringWidth(title); 400 401 String txt; 402 Color color; 403 404 int arcWidth = 20; 405 int arcHeight = 20; 406 407 g.setColor(LEGEND_BACKGROUND); 408 int xText = x; 409 int xRect; 410 int rectWidth; 411 412 // padding from text to edge of rectangle 413 int padding = 19; 414 415 String formatDay = "yyyy-MM-dd HH:mm"; 416 String formatTime = "HH:mm:ss"; 417 418 // calculates the width of the colorbar texts 419 if (maxVal-minVal > 86400) { 420 fw = fm.stringWidth(formatDay); 421 } else { 422 fw = fm.stringWidth(formatTime); 423 } 424 425 g.setColor(LEGEND_BACKGROUND); 426 427 // background rectangle 428 if (fw + w > titleWidth) { 429 rectWidth = w + fw + padding * 2; 430 xRect = x - rectWidth; 431 xText = xRect + (int) (padding / 1.2); 432 g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight); 433 } else { 434 if (titleWidth >= 120) { 435 titleWidth = 120; 436 } 437 rectWidth = w + titleWidth + padding + padding / 2; 438 xRect = x - rectWidth; 439 xText = xRect + padding / 2 + rectWidth / 2 - fw; 440 g.fillRoundRect(xRect, (fh * 3 / 2), rectWidth, h + y - (fh * 3 / 2) + (int) (padding / 1.5), arcWidth, arcHeight); 441 } 442 443 // colorbar 444 for (int i = 0; i < n; i++) { 445 g.setColor(colors[i]); 446 if (w < h) { 447 g.fillRect(xText + fw + padding / 3, y - padding / 2 + i * h / (int) (n * 0.875), w, (h / n + 1)); 448 } else { 449 g.fillRect(xText + fw + padding / 3 + i * w / n, y, w / n + 1, h); 450 } 451 } 452 453 // legend title 454 if (title != null) { 455 g.setColor(LEGEND_TITLE); 456 g.drawString(title, xRect + rectWidth / 2 - titleWidth / 2, y - fh * 3 / 2 - padding / 2);; 457 } 458 459 // legend texts 460 for (int i = 0; i <= intervalCount; i++) { 461 color = colors[(int) (1.0 * i * n / intervalCount - 1e-10)]; 462 g.setColor(color); 463 464 if (colorBarTitles != null && i < colorBarTitles.length) { 465 txt = colorBarTitles[i]; 466 } else { 467 final double val = minVal + i * (maxVal - minVal) / intervalCount; 468 long longval = (long) val; 469 470 Date date = new Date(longval * 1000L); 471 Instant dateInst = date.toInstant(); 472 473 ZoneId gmt = ZoneId.of("GMT"); 474 ZonedDateTime zonedDateTime = dateInst.atZone(gmt); 475 476 String formatted; 477 478 if (maxVal-minVal > 86400) { 479 DateTimeFormatter day = DateTimeFormatter.ofPattern(formatDay); 480 formatted = zonedDateTime.format(day); 481 } else { 482 DateTimeFormatter time = DateTimeFormatter.ofPattern(formatTime); 483 formatted = zonedDateTime.format(time); 484 } 485 486 txt = formatted; 487 } 488 if (intervalCount == 0) { 489 drawOutline(g, txt, xText, y + h / 2 + fh / 2, color); 490 g.drawString(txt, xText, y + h / 2 + fh / 2); 491 } else if (w < h) { 492 drawOutline(g, txt, xText, y + i * h / intervalCount + fh / 2, color); 493 g.drawString(txt, xText, y + i * h / intervalCount + fh / 2); 494 } else { 495 drawOutline(g, txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5, color); 496 g.drawString(txt, xText + i * w / intervalCount - fw / 2 - (int) (padding / 1.3), y + fh - 5); 497 } 498 } 499 500 g.setColor(noDataColor); 501 } 279 502 }