Changeset 11156 in josm


Ignore:
Timestamp:
2016-10-24T12:42:06+02:00 (3 years ago)
Author:
bastiK
Message:

rework/simplify inheritance structure of PlatformHook

PlatformHookUnixoid is no longer base class of PlatformHookWindows
and PlatformHookOsx; move common methods to PlatformHook

Location:
trunk/src/org/openstreetmap/josm
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java

    r11113 r11156  
    110110            .append((int) maxScreenSize.getHeight()).append('\n');
    111111
    112         if (Main.platform.getClass() == PlatformHookUnixoid.class) {
     112        if (Main.platform instanceof PlatformHookUnixoid) {
    113113            // Add Java package details
    114114            String packageDetails = ((PlatformHookUnixoid) Main.platform).getJavaPackageDetails();
  • trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java

    r10627 r11156  
    4848                    // Desktop API works fine under Windows, so we don't try any fallback in case of I/O exceptions because it's not API's fault
    4949                    Desktop.getDesktop().browse(uri);
    50                 } else if (Main.platform instanceof PlatformHookUnixoid) {
     50                } else if (Main.platform instanceof PlatformHookUnixoid || Main.platform instanceof PlatformHookOsx) {
    5151                    // see #5629 #5108 #9568
    5252                    Main.platform.openUrl(uri.toString());
  • trunk/src/org/openstreetmap/josm/tools/PlatformHook.java

    r8512 r11156  
    22package org.openstreetmap.josm.tools;
    33
     4import java.awt.GraphicsEnvironment;
    45import java.io.File;
    56import java.io.IOException;
     
    2324      * that we want to be integrated with the OS before we setup our GUI.
    2425      */
    25     void preStartupHook();
     26    default void preStartupHook() {
     27        // Do nothing
     28    }
    2629
    2730    /**
     
    3134      * It is guaranteed to be called before the GUI setup has started.
    3235      */
    33     void afterPrefStartupHook();
     36    default void afterPrefStartupHook() {
     37        // Do nothing
     38    }
    3439
    3540    /**
     
    4045      * OS, so we'll receive events from the system menu.
    4146      */
    42     void startupHook();
     47    default void startupHook() {
     48        // Do nothing
     49    }
    4350
    4451    /**
     
    7986      * JVM is too dumb to provide correct names for all the keys.
    8087      *
    81       * Another reason not to use the implementation in the *nix
    82       * hook are LAFs that don't understand HTML, such as the OSX LAFs.
     88      * Some LAFs don't understand HTML, such as the OSX LAFs.
    8389      *
    8490     * @param name Tooltip text to display
     
    8692     * @return Full tooltip text (name + accelerator)
    8793      */
    88     String makeTooltip(String name, Shortcut sc);
     94    default String makeTooltip(String name, Shortcut sc) {
     95        StringBuilder result = new StringBuilder();
     96        result.append("<html>").append(name);
     97        if (sc != null && !sc.getKeyText().isEmpty()) {
     98            result.append(" <font size='-2'>(")
     99                  .append(sc.getKeyText())
     100                  .append(")</font>");
     101        }
     102        return result.append("&nbsp;</html>").toString();
     103    }
    89104
    90105    /**
     
    98113     * @return {@code true} if full screen is allowed, {@code false} otherwise
    99114     */
    100     boolean canFullscreen();
     115    default boolean canFullscreen() {
     116        return !GraphicsEnvironment.isHeadless() &&
     117                GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isFullScreenSupported();
     118    }
    101119
    102120    /**
     
    106124     * @return {@code true} if the file has been renamed, {@code false} otherwise
    107125     */
    108     boolean rename(File from, File to);
     126    default boolean rename(File from, File to) {
     127        return from.renameTo(to);
     128    }
    109129
    110130    /**
     
    126146     * @since 7343
    127147     */
    128     boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
    129             throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException;
     148    default boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
     149            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
     150        // TODO setup HTTPS certificate on Unix and OS X systems
     151        return false;
     152    }
    130153
    131154    /**
  • trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java

    r11093 r11156  
    2828 * @since 1023
    2929 */
    30 public class PlatformHookOsx extends PlatformHookUnixoid implements InvocationHandler {
    31 
    32     private static PlatformHookOsx ivhandler = new PlatformHookOsx();
     30public class PlatformHookOsx implements PlatformHook, InvocationHandler {
     31
     32    private static final PlatformHookOsx ivhandler = new PlatformHookOsx();
    3333
    3434    @Override
  • trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java

    r11096 r11156  
    66import java.awt.Desktop;
    77import java.awt.Dimension;
    8 import java.awt.GraphicsEnvironment;
    98import java.awt.event.KeyEvent;
    109import java.io.BufferedReader;
    11 import java.io.BufferedWriter;
    1210import java.io.File;
    13 import java.io.FileInputStream;
    1411import java.io.IOException;
    1512import java.io.InputStreamReader;
    16 import java.io.OutputStream;
    17 import java.io.OutputStreamWriter;
    18 import java.io.Writer;
    1913import java.net.URI;
    2014import java.net.URISyntaxException;
    2115import java.nio.charset.StandardCharsets;
    22 import java.nio.file.FileSystems;
    2316import java.nio.file.Files;
    2417import java.nio.file.Path;
    2518import java.nio.file.Paths;
    26 import java.security.KeyStore;
    27 import java.security.KeyStoreException;
    28 import java.security.NoSuchAlgorithmException;
    29 import java.security.cert.CertificateException;
    30 import java.util.ArrayList;
    3119import java.util.Arrays;
    32 import java.util.Collection;
    33 import java.util.List;
    34 import java.util.Locale;
    35 import java.util.Properties;
    3620
    3721import javax.swing.JOptionPane;
    3822
    3923import org.openstreetmap.josm.Main;
    40 import org.openstreetmap.josm.data.Preferences.pref;
    41 import org.openstreetmap.josm.data.Preferences.writeExplicitly;
    4224import org.openstreetmap.josm.gui.ExtendedDialog;
    4325import org.openstreetmap.josm.gui.util.GuiHelper;
     
    5133public class PlatformHookUnixoid implements PlatformHook {
    5234
    53     /**
    54      * Simple data class to hold information about a font.
    55      *
    56      * Used for fontconfig.properties files.
    57      */
    58     public static class FontEntry {
    59         /**
    60          * The character subset. Basically a free identifier, but should be unique.
    61          */
    62         @pref
    63         public String charset;
    64 
    65         /**
    66          * Platform font name.
    67          */
    68         @pref
    69         @writeExplicitly
    70         public String name = "";
    71 
    72         /**
    73          * File name.
    74          */
    75         @pref
    76         @writeExplicitly
    77         public String file = "";
    78 
    79         /**
    80          * Constructs a new {@code FontEntry}.
    81          */
    82         public FontEntry() {
    83         }
    84 
    85         /**
    86          * Constructs a new {@code FontEntry}.
    87          * @param charset The character subset. Basically a free identifier, but should be unique
    88          * @param name Platform font name
    89          * @param file File name
    90          */
    91         public FontEntry(String charset, String name, String file) {
    92             this.charset = charset;
    93             this.name = name;
    94             this.file = file;
    95         }
    96     }
    97 
    9835    private String osDescription;
    9936
     
    10441            System.clearProperty("assistive_technologies");
    10542        }
    106     }
    107 
    108     @Override
    109     public void afterPrefStartupHook() {
    110         // Do nothing
    111     }
    112 
    113     @Override
    114     public void startupHook() {
    115         // Do nothing
    11643    }
    11744
     
    15178    }
    15279
    153     /**
    154      * This should work for all platforms. Yeah, should.
    155      * See PlatformHook.java for a list of reasons why this is implemented here...
    156      */
    157     @Override
    158     public String makeTooltip(String name, Shortcut sc) {
    159         StringBuilder result = new StringBuilder();
    160         result.append("<html>").append(name);
    161         if (sc != null && !sc.getKeyText().isEmpty()) {
    162             result.append(" <font size='-2'>(")
    163                   .append(sc.getKeyText())
    164                   .append(")</font>");
    165         }
    166         return result.append("&nbsp;</html>").toString();
    167     }
    168 
    16980    @Override
    17081    public String getDefaultStyle() {
    17182        return "javax.swing.plaf.metal.MetalLookAndFeel";
    172     }
    173 
    174     @Override
    175     public boolean canFullscreen() {
    176         return !GraphicsEnvironment.isHeadless() &&
    177                 GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isFullScreenSupported();
    178     }
    179 
    180     @Override
    181     public boolean rename(File from, File to) {
    182         return from.renameTo(to);
    18383    }
    18484
     
    469369
    470370    @Override
    471     public boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
    472             throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
    473         // TODO setup HTTPS certificate on Unix systems
    474         return false;
    475     }
    476 
    477     @Override
    478371    public File getDefaultCacheDirectory() {
    479372        return new File(Main.pref.getUserDataDirectory(), "cache");
     
    491384    }
    492385
    493     /**
    494      * <p>Add more fallback fonts to the Java runtime, in order to get
    495      * support for more scripts.</p>
    496      *
    497      * <p>The font configuration in Java doesn't include some Indic scripts,
    498      * even though MS Windows ships with fonts that cover these unicode ranges.</p>
    499      *
    500      * <p>To fix this, the fontconfig.properties template is copied to the JOSM
    501      * cache folder. Then, the additional entries are added to the font
    502      * configuration. Finally the system property "sun.awt.fontconfig" is set
    503      * to the customized fontconfig.properties file.</p>
    504      *
    505      * <p>This is a crude hack, but better than no font display at all for these languages.
    506      * There is no guarantee, that the template file
    507      * ($JAVA_HOME/lib/fontconfig.properties.src) matches the default
    508      * configuration (which is in a binary format).
    509      * Furthermore, the system property "sun.awt.fontconfig" is undocumented and
    510      * may no longer work in future versions of Java.</p>
    511      *
    512      * <p>Related Java bug: <a href="https://bugs.openjdk.java.net/browse/JDK-8008572">JDK-8008572</a></p>
    513      *
    514      * @param templateFileName file name of the fontconfig.properties template file
    515      */
    516     protected void extendFontconfig(String templateFileName) {
    517         String customFontconfigFile = Main.pref.get("fontconfig.properties", null);
    518         if (customFontconfigFile != null) {
    519             Utils.updateSystemProperty("sun.awt.fontconfig", customFontconfigFile);
    520             return;
    521         }
    522         if (!Main.pref.getBoolean("font.extended-unicode", true))
    523             return;
    524 
    525         String javaLibPath = System.getProperty("java.home") + File.separator + "lib";
    526         Path templateFile = FileSystems.getDefault().getPath(javaLibPath, templateFileName);
    527         if (!Files.isReadable(templateFile)) {
    528             Main.warn("extended font config - unable to find font config template file "+templateFile.toString());
    529             return;
    530         }
    531         try (FileInputStream fis = new FileInputStream(templateFile.toFile())) {
    532             Properties props = new Properties();
    533             props.load(fis);
    534             byte[] content = Files.readAllBytes(templateFile);
    535             File cachePath = Main.pref.getCacheDirectory();
    536             Path fontconfigFile = cachePath.toPath().resolve("fontconfig.properties");
    537             OutputStream os = Files.newOutputStream(fontconfigFile);
    538             os.write(content);
    539             try (Writer w = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8))) {
    540                 Collection<FontEntry> extrasPref = Main.pref.getListOfStructs(
    541                         "font.extended-unicode.extra-items", getAdditionalFonts(), FontEntry.class);
    542                 Collection<FontEntry> extras = new ArrayList<>();
    543                 w.append("\n\n# Added by JOSM to extend unicode coverage of Java font support:\n\n");
    544                 List<String> allCharSubsets = new ArrayList<>();
    545                 for (FontEntry entry: extrasPref) {
    546                     Collection<String> fontsAvail = getInstalledFonts();
    547                     if (fontsAvail != null && fontsAvail.contains(entry.file.toUpperCase(Locale.ENGLISH))) {
    548                         if (!allCharSubsets.contains(entry.charset)) {
    549                             allCharSubsets.add(entry.charset);
    550                             extras.add(entry);
    551                         } else {
    552                             Main.trace("extended font config - already registered font for charset ''{0}'' - skipping ''{1}''",
    553                                     entry.charset, entry.name);
    554                         }
    555                     } else {
    556                         Main.trace("extended font config - Font ''{0}'' not found on system - skipping", entry.name);
    557                     }
    558                 }
    559                 for (FontEntry entry: extras) {
    560                     allCharSubsets.add(entry.charset);
    561                     if ("".equals(entry.name)) {
    562                         continue;
    563                     }
    564                     String key = "allfonts." + entry.charset;
    565                     String value = entry.name;
    566                     String prevValue = props.getProperty(key);
    567                     if (prevValue != null && !prevValue.equals(value)) {
    568                         Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
    569                     }
    570                     w.append(key + '=' + value + '\n');
    571                 }
    572                 w.append('\n');
    573                 for (FontEntry entry: extras) {
    574                     if ("".equals(entry.name) || "".equals(entry.file)) {
    575                         continue;
    576                     }
    577                     String key = "filename." + entry.name.replace(' ', '_');
    578                     String value = entry.file;
    579                     String prevValue = props.getProperty(key);
    580                     if (prevValue != null && !prevValue.equals(value)) {
    581                         Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
    582                     }
    583                     w.append(key + '=' + value + '\n');
    584                 }
    585                 w.append('\n');
    586                 String fallback = props.getProperty("sequence.fallback");
    587                 if (fallback != null) {
    588                     w.append("sequence.fallback=" + fallback + ',' + Utils.join(",", allCharSubsets) + '\n');
    589                 } else {
    590                     w.append("sequence.fallback=" + Utils.join(",", allCharSubsets) + '\n');
    591                 }
    592             }
    593             Utils.updateSystemProperty("sun.awt.fontconfig", fontconfigFile.toString());
    594         } catch (IOException ex) {
    595             Main.error(ex);
    596         }
    597     }
    598 
    599     /**
    600      * Get a list of fonts that are installed on the system.
    601      *
    602      * Must be done without triggering the Java Font initialization.
    603      * (See {@link #extendFontconfig(java.lang.String)}, have to set system
    604      * property first, which is then read by sun.awt.FontConfiguration upon initialization.)
    605      *
    606      * @return list of file names
    607      */
    608     public Collection<String> getInstalledFonts() {
    609         throw new UnsupportedOperationException();
    610     }
    611 
    612     /**
    613      * Get default list of additional fonts to add to the configuration.
    614      *
    615      * Java will choose thee first font in the list that can render a certain character.
    616      *
    617      * @return list of FontEntry objects
    618      */
    619     public Collection<FontEntry> getAdditionalFonts() {
    620         throw new UnsupportedOperationException();
    621     }
    622386}
  • trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java

    r10627 r11156  
    2929
    3030import java.awt.GraphicsEnvironment;
     31import java.io.BufferedWriter;
    3132import java.io.File;
     33import java.io.FileInputStream;
    3234import java.io.IOException;
     35import java.io.OutputStream;
     36import java.io.OutputStreamWriter;
     37import java.io.Writer;
     38import java.nio.charset.StandardCharsets;
    3339import java.nio.file.DirectoryStream;
    3440import java.nio.file.FileSystems;
     
    5157import java.util.List;
    5258import java.util.Locale;
     59import java.util.Properties;
    5360
    5461import javax.swing.JOptionPane;
    5562
    5663import org.openstreetmap.josm.Main;
     64import org.openstreetmap.josm.data.Preferences;
    5765
    5866/**
     
    6068  * @since 1023
    6169  */
    62 public class PlatformHookWindows extends PlatformHookUnixoid {
    63 
    64     @Override
    65     public void startupHook() {
    66         // Do nothing
     70public class PlatformHookWindows implements PlatformHook {
     71
     72    /**
     73     * Simple data class to hold information about a font.
     74     *
     75     * Used for fontconfig.properties files.
     76     */
     77    public static class FontEntry {
     78        /**
     79         * The character subset. Basically a free identifier, but should be unique.
     80         */
     81        @Preferences.pref
     82        public String charset;
     83
     84        /**
     85         * Platform font name.
     86         */
     87        @Preferences.pref
     88        @Preferences.writeExplicitly
     89        public String name = "";
     90
     91        /**
     92         * File name.
     93         */
     94        @Preferences.pref
     95        @Preferences.writeExplicitly
     96        public String file = "";
     97
     98        /**
     99         * Constructs a new {@code FontEntry}.
     100         */
     101        public FontEntry() {
     102        }
     103
     104        /**
     105         * Constructs a new {@code FontEntry}.
     106         * @param charset The character subset. Basically a free identifier, but should be unique
     107         * @param name Platform font name
     108         * @param file File name
     109         */
     110        public FontEntry(String charset, String name, String file) {
     111            this.charset = charset;
     112            this.name = name;
     113            this.file = file;
     114        }
    67115    }
    68116
     
    319367
    320368    @Override
    321     public Collection<String> getInstalledFonts() {
     369    public File getDefaultUserDataDirectory() {
     370        // Use preferences directory by default
     371        return Main.pref.getPreferencesDirectory();
     372    }
     373
     374    /**
     375     * <p>Add more fallback fonts to the Java runtime, in order to get
     376     * support for more scripts.</p>
     377     *
     378     * <p>The font configuration in Java doesn't include some Indic scripts,
     379     * even though MS Windows ships with fonts that cover these unicode ranges.</p>
     380     *
     381     * <p>To fix this, the fontconfig.properties template is copied to the JOSM
     382     * cache folder. Then, the additional entries are added to the font
     383     * configuration. Finally the system property "sun.awt.fontconfig" is set
     384     * to the customized fontconfig.properties file.</p>
     385     *
     386     * <p>This is a crude hack, but better than no font display at all for these languages.
     387     * There is no guarantee, that the template file
     388     * ($JAVA_HOME/lib/fontconfig.properties.src) matches the default
     389     * configuration (which is in a binary format).
     390     * Furthermore, the system property "sun.awt.fontconfig" is undocumented and
     391     * may no longer work in future versions of Java.</p>
     392     *
     393     * <p>Related Java bug: <a href="https://bugs.openjdk.java.net/browse/JDK-8008572">JDK-8008572</a></p>
     394     *
     395     * @param templateFileName file name of the fontconfig.properties template file
     396     */
     397    protected void extendFontconfig(String templateFileName) {
     398        String customFontconfigFile = Main.pref.get("fontconfig.properties", null);
     399        if (customFontconfigFile != null) {
     400            Utils.updateSystemProperty("sun.awt.fontconfig", customFontconfigFile);
     401            return;
     402        }
     403        if (!Main.pref.getBoolean("font.extended-unicode", true))
     404            return;
     405
     406        String javaLibPath = System.getProperty("java.home") + File.separator + "lib";
     407        Path templateFile = FileSystems.getDefault().getPath(javaLibPath, templateFileName);
     408        if (!Files.isReadable(templateFile)) {
     409            Main.warn("extended font config - unable to find font config template file "+templateFile.toString());
     410            return;
     411        }
     412        try (FileInputStream fis = new FileInputStream(templateFile.toFile())) {
     413            Properties props = new Properties();
     414            props.load(fis);
     415            byte[] content = Files.readAllBytes(templateFile);
     416            File cachePath = Main.pref.getCacheDirectory();
     417            Path fontconfigFile = cachePath.toPath().resolve("fontconfig.properties");
     418            OutputStream os = Files.newOutputStream(fontconfigFile);
     419            os.write(content);
     420            try (Writer w = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8))) {
     421                Collection<FontEntry> extrasPref = Main.pref.getListOfStructs(
     422                        "font.extended-unicode.extra-items", getAdditionalFonts(), FontEntry.class);
     423                Collection<FontEntry> extras = new ArrayList<>();
     424                w.append("\n\n# Added by JOSM to extend unicode coverage of Java font support:\n\n");
     425                List<String> allCharSubsets = new ArrayList<>();
     426                for (FontEntry entry: extrasPref) {
     427                    Collection<String> fontsAvail = getInstalledFonts();
     428                    if (fontsAvail != null && fontsAvail.contains(entry.file.toUpperCase(Locale.ENGLISH))) {
     429                        if (!allCharSubsets.contains(entry.charset)) {
     430                            allCharSubsets.add(entry.charset);
     431                            extras.add(entry);
     432                        } else {
     433                            Main.trace("extended font config - already registered font for charset ''{0}'' - skipping ''{1}''",
     434                                    entry.charset, entry.name);
     435                        }
     436                    } else {
     437                        Main.trace("extended font config - Font ''{0}'' not found on system - skipping", entry.name);
     438                    }
     439                }
     440                for (FontEntry entry: extras) {
     441                    allCharSubsets.add(entry.charset);
     442                    if ("".equals(entry.name)) {
     443                        continue;
     444                    }
     445                    String key = "allfonts." + entry.charset;
     446                    String value = entry.name;
     447                    String prevValue = props.getProperty(key);
     448                    if (prevValue != null && !prevValue.equals(value)) {
     449                        Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
     450                    }
     451                    w.append(key + '=' + value + '\n');
     452                }
     453                w.append('\n');
     454                for (FontEntry entry: extras) {
     455                    if ("".equals(entry.name) || "".equals(entry.file)) {
     456                        continue;
     457                    }
     458                    String key = "filename." + entry.name.replace(' ', '_');
     459                    String value = entry.file;
     460                    String prevValue = props.getProperty(key);
     461                    if (prevValue != null && !prevValue.equals(value)) {
     462                        Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
     463                    }
     464                    w.append(key + '=' + value + '\n');
     465                }
     466                w.append('\n');
     467                String fallback = props.getProperty("sequence.fallback");
     468                if (fallback != null) {
     469                    w.append("sequence.fallback=" + fallback + ',' + Utils.join(",", allCharSubsets) + '\n');
     470                } else {
     471                    w.append("sequence.fallback=" + Utils.join(",", allCharSubsets) + '\n');
     472                }
     473            }
     474            Utils.updateSystemProperty("sun.awt.fontconfig", fontconfigFile.toString());
     475        } catch (IOException ex) {
     476            Main.error(ex);
     477        }
     478    }
     479
     480    /**
     481     * Get a list of fonts that are installed on the system.
     482     *
     483     * Must be done without triggering the Java Font initialization.
     484     * (See {@link #extendFontconfig(java.lang.String)}, have to set system
     485     * property first, which is then read by sun.awt.FontConfiguration upon initialization.)
     486     *
     487     * @return list of file names
     488     */
     489    protected Collection<String> getInstalledFonts() {
    322490        // Cannot use GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()
    323491        // because we have to set the system property before Java initializes its fonts.
     
    341509    }
    342510
    343     @Override
    344     public Collection<FontEntry> getAdditionalFonts() {
     511    /**
     512     * Get default list of additional fonts to add to the configuration.
     513     *
     514     * Java will choose thee first font in the list that can render a certain character.
     515     *
     516     * @return list of FontEntry objects
     517     */
     518    protected Collection<FontEntry> getAdditionalFonts() {
    345519        Collection<FontEntry> def = new ArrayList<>(33);
    346520        def.add(new FontEntry("devanagari", "", "")); // just include in fallback list font already defined in template
Note: See TracChangeset for help on using the changeset viewer.