Ticket #17072: 17072.1.patch

File 17072.1.patch, 7.1 KB (added by taylor.smock, 4 years ago)

Add option to have background of error text show up (disabled by default -- can be hard on the eyes), properly show loading/error text

  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    import java.awt.geom.Rectangle2D;  
    2424import java.awt.image.BufferedImage;
    2525import java.awt.image.ImageObserver;
    2626import java.io.File;
     27import java.util.Objects;
    2728
    2829import javax.swing.JComponent;
    2930import javax.swing.SwingUtilities;
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    4849    /** The file that is currently displayed */
    4950    private ImageEntry entry;
    5051
     52    /** The previous file that is currently displayed. Cleared on paint. Only used to help improve UI error information. */
     53    private ImageEntry oldEntry;
     54
    5155    /** The image currently displayed */
    5256    private transient Image image;
    5357
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    9498    private static double bilinUpper;
    9599    private static double bilinLower;
    96100
     101    /** Show a background for the error text (may be hard on eyes) */
     102    private static final BooleanProperty ERROR_MESSAGE_BACKGROUND = new BooleanProperty("geoimage.message.error.background", false);
     103
    97104    @Override
    98105    public void preferenceChanged(PreferenceChangeEvent e) {
    99106        if (e == null ||
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    345352                    }
    346353
    347354                    ImageDisplay.this.image = img;
     355                    // This will clear the loading info box
     356                    ImageDisplay.this.oldEntry = ImageDisplay.this.entry;
    348357                    visibleRect = new VisRect(0, 0, width, height);
    349358
    350359                    Logging.debug("Loaded {0} with dimensions {1}x{2} memoryTaken={3}m exifOrientationSwitchedDimension={4}",
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    690699     */
    691700    public void setImage(ImageEntry entry) {
    692701        synchronized (this) {
     702            this.oldEntry = this.entry;
    693703            this.entry = entry;
    694             image = null;
     704            if (entry == null) {
     705                image = null;
     706                this.oldEntry = null;
     707            }
    695708            errorLoading = false;
    696709        }
    697710        repaint();
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    724737    @Override
    725738    public void paintComponent(Graphics g) {
    726739        ImageEntry entry;
     740        ImageEntry oldEntry;
    727741        Image image;
    728742        VisRect visibleRect;
    729743        boolean errorLoading;
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    731745        synchronized (this) {
    732746            image = this.image;
    733747            entry = this.entry;
     748            oldEntry = this.oldEntry;
    734749            visibleRect = this.visibleRect;
    735750            errorLoading = this.errorLoading;
    736751        }
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    740755        }
    741756
    742757        Dimension size = getSize();
    743         if (entry == null) {
    744             g.setColor(Color.black);
    745             if (emptyText == null) {
    746                 emptyText = tr("No image");
    747             }
    748             String noImageStr = emptyText;
    749             Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(noImageStr, g);
    750             g.drawString(noImageStr,
    751                     (int) ((size.width - noImageSize.getWidth()) / 2),
    752                     (int) ((size.height - noImageSize.getHeight()) / 2));
    753         } else if (image == null) {
    754             g.setColor(Color.black);
    755             String loadingStr;
    756             if (!errorLoading) {
    757                 loadingStr = tr("Loading {0}", entry.getFile().getName());
    758             } else {
    759                 loadingStr = tr("Error on file {0}", entry.getFile().getName());
    760             }
    761             Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(loadingStr, g);
    762             g.drawString(loadingStr,
    763                     (int) ((size.width - noImageSize.getWidth()) / 2),
    764                     (int) ((size.height - noImageSize.getHeight()) / 2));
    765         } else {
     758        // Draw the image first, then draw error information
     759        if (image != null && (entry != null || oldEntry != null)) {
    766760            Rectangle r = new Rectangle(visibleRect);
    767761            Rectangle target = calculateDrawImageRectangle(visibleRect, size);
    768762            double scale = target.width / (double) r.width; // pixel ratio is 1:1
    769763
    770764            if (selectedRect == null && !visibleRect.isDragUpdate &&
    771                 bilinLower < scale && scale < bilinUpper) {
     765                    bilinLower < scale && scale < bilinUpper) {
    772766                try {
    773767                    BufferedImage bi = ImageProvider.toBufferedImage(image, r);
    774768                    if (bi != null) {
    public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    851845                g.drawString(line, x, y + ascent);
    852846            }
    853847        }
     848        final String errorMessage;
     849        // If the new entry is null, then there is no image.
     850        if (entry == null) {
     851            if (emptyText == null) {
     852                emptyText = tr("No image");
     853            }
     854            errorMessage = emptyText;
     855        } else if (image == null || !Objects.equals(entry, oldEntry)) {
     856            // The image is not necessarily null when loading anymore. If the oldEntry is not the same as the new entry,
     857            // we are probably still loading the image. (oldEntry gets set to entry when the image finishes loading).
     858            if (!errorLoading) {
     859                errorMessage = tr("Loading {0}", entry.getFile().getName());
     860            } else {
     861                errorMessage = tr("Error on file {0}", entry.getFile().getName());
     862            }
     863        } else {
     864            errorMessage = null;
     865        }
     866        if (errorMessage != null && !errorMessage.trim().isEmpty()) {
     867            Rectangle2D errorStringSize = g.getFontMetrics(g.getFont()).getStringBounds(errorMessage, g);
     868            if (Boolean.TRUE.equals(ERROR_MESSAGE_BACKGROUND.get())) {
     869                int height = g.getFontMetrics().getHeight();
     870                int descender = g.getFontMetrics().getDescent();
     871                g.setColor(getBackground());
     872                int width = (int) (errorStringSize.getWidth() * 1);
     873                // top-left of text
     874                int tlx = (int) ((size.getWidth() - errorStringSize.getWidth()) / 2);
     875                int tly = (int) ((size.getHeight() - 3 * errorStringSize.getHeight()) / 2 + descender);
     876                g.fillRect(tlx, tly, width, height);
     877            }
     878
     879            // lower-left of text
     880            int llx = (int) ((size.width - errorStringSize.getWidth()) / 2);
     881            int lly = (int) ((size.height - errorStringSize.getHeight()) / 2);
     882            g.setColor(getForeground());
     883            g.drawString(errorMessage, llx, lly);
     884        }
    854885    }
    855886
    856887    static Point img2compCoord(VisRect visibleRect, int xImg, int yImg, Dimension compSize) {