001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences.display; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.GridBagLayout; 008import java.util.ArrayList; 009import java.util.Comparator; 010import java.util.List; 011import java.util.Locale; 012 013import javax.swing.Box; 014import javax.swing.DefaultListCellRenderer; 015import javax.swing.JLabel; 016import javax.swing.JList; 017import javax.swing.JPanel; 018import javax.swing.ListCellRenderer; 019 020import org.openstreetmap.josm.gui.help.HelpUtil; 021import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting; 022import org.openstreetmap.josm.gui.preferences.PreferenceSetting; 023import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory; 024import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane; 025import org.openstreetmap.josm.gui.widgets.JosmComboBox; 026import org.openstreetmap.josm.gui.widgets.JosmComboBoxModel; 027import org.openstreetmap.josm.spi.preferences.Config; 028import org.openstreetmap.josm.tools.GBC; 029import org.openstreetmap.josm.tools.I18n; 030import org.openstreetmap.josm.tools.LanguageInfo; 031 032/** 033 * Language preferences. 034 * @since 1065 035 */ 036public class LanguagePreference extends DefaultTabPreferenceSetting { 037 038 private static final String LANGUAGE = "language"; 039 040 /** 041 * Factory used to create a new {@code LanguagePreference}. 042 */ 043 public static class Factory implements PreferenceSettingFactory { 044 @Override 045 public PreferenceSetting createPreferenceSetting() { 046 return new LanguagePreference(); 047 } 048 } 049 050 LanguagePreference() { 051 super(/* ICON(preferences/) */ "language", tr("Language"), tr("Change the language of JOSM.")); 052 } 053 054 /** the combo box with the available locales */ 055 private JosmComboBox<Locale> langCombo; 056 057 @Override 058 public void addGui(final PreferenceTabbedPane gui) { 059 LanguageComboBoxModel model = new LanguageComboBoxModel(); 060 // Selecting the language BEFORE the JComboBox listens to model changes speed up initialization by ~35ms (see #7386) 061 // See https://stackoverflow.com/questions/3194958/fast-replacement-for-jcombobox-basiccomboboxui 062 model.selectLanguage(Config.getPref().get(LANGUAGE)); 063 langCombo = new JosmComboBox<>(model); 064 langCombo.setRenderer(new LanguageCellRenderer()); 065 066 final JPanel panel = new JPanel(new GridBagLayout()); 067 panel.add(new JLabel(tr("Language")), GBC.std().insets(20, 0, 0, 0)); 068 panel.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 069 panel.add(langCombo, GBC.eol().fill(GBC.HORIZONTAL)); 070 panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); 071 072 createPreferenceTabWithScrollPane(gui, panel); 073 } 074 075 @Override 076 public boolean ok() { 077 if (langCombo.getSelectedItem() == null) 078 return Config.getPref().put(LANGUAGE, null); 079 else 080 return Config.getPref().put(LANGUAGE, 081 LanguageInfo.getJOSMLocaleCode((Locale) langCombo.getSelectedItem())); 082 } 083 084 private static class LanguageComboBoxModel extends JosmComboBoxModel<Locale> { 085 private final List<Locale> data = new ArrayList<>(); 086 087 LanguageComboBoxModel() { 088 data.add(0, null); 089 I18n.getAvailableTranslations() 090 .sorted(Comparator.comparing(Locale::getDisplayLanguage)) 091 .forEachOrdered(data::add); 092 } 093 094 private void selectLanguage(String language) { 095 setSelectedItem(null); 096 if (language != null) { 097 String lang = LanguageInfo.getJavaLocaleCode(language); 098 data.stream() 099 .filter(locale -> locale != null && locale.toString().equals(lang)) 100 .findFirst() 101 .ifPresent(this::setSelectedItem); 102 } 103 } 104 105 @Override 106 public Locale getElementAt(int index) { 107 return data.get(index); 108 } 109 110 @Override 111 public int getSize() { 112 return data.size(); 113 } 114 } 115 116 private static class LanguageCellRenderer implements ListCellRenderer<Locale> { 117 private final DefaultListCellRenderer dispatch; 118 119 /** 120 * Constructs a new {@code LanguageCellRenderer}. 121 */ 122 LanguageCellRenderer() { 123 this.dispatch = new DefaultListCellRenderer(); 124 } 125 126 @Override 127 public Component getListCellRendererComponent(JList<? extends Locale> list, Locale l, 128 int index, boolean isSelected, boolean cellHasFocus) { 129 return dispatch.getListCellRendererComponent(list, 130 l == null 131 ? tr("Default (Auto determined)") 132 : LanguageInfo.getDisplayName(l), 133 index, isSelected, cellHasFocus); 134 } 135 } 136 137 @Override 138 public boolean isExpert() { 139 return false; 140 } 141 142 @Override 143 public String getHelpContext() { 144 return HelpUtil.ht("/Preferences/LanguagePreference"); 145 } 146}