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.util.ArrayList; 008import java.util.Arrays; 009import java.util.Comparator; 010import java.util.List; 011import java.util.Locale; 012 013import javax.swing.Box; 014import javax.swing.DefaultComboBoxModel; 015import javax.swing.DefaultListCellRenderer; 016import javax.swing.JLabel; 017import javax.swing.JList; 018import javax.swing.JPanel; 019import javax.swing.ListCellRenderer; 020 021import org.openstreetmap.josm.gui.preferences.PreferenceSetting; 022import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory; 023import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane; 024import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting; 025import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting; 026import org.openstreetmap.josm.gui.widgets.JosmComboBox; 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 implements SubPreferenceSetting { 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 /** the combo box with the available locales */ 051 private JosmComboBox<Locale> langCombo; 052 053 @Override 054 public void addGui(final PreferenceTabbedPane gui) { 055 LanguageComboBoxModel model = new LanguageComboBoxModel(); 056 // Selecting the language BEFORE the JComboBox listens to model changes speed up initialization by ~35ms (see #7386) 057 // See https://stackoverflow.com/questions/3194958/fast-replacement-for-jcombobox-basiccomboboxui 058 model.selectLanguage(Config.getPref().get(LANGUAGE)); 059 langCombo = new JosmComboBox<>(model); 060 langCombo.setRenderer(new LanguageCellRenderer()); 061 062 LafPreference lafPreference = gui.getSetting(LafPreference.class); 063 final JPanel panel = lafPreference.panel; 064 panel.add(new JLabel(tr("Language")), GBC.std().insets(20, 0, 0, 0)); 065 panel.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 066 panel.add(langCombo, GBC.eol().fill(GBC.HORIZONTAL)); 067 panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); 068 069 TabPreferenceSetting tabPref = lafPreference.getTabPreferenceSetting(gui); 070 tabPref.registerSubTab(this, tabPref.getSubTab(lafPreference)); 071 } 072 073 @Override 074 public boolean ok() { 075 if (langCombo.getSelectedItem() == null) 076 return Config.getPref().put(LANGUAGE, null); 077 else 078 return Config.getPref().put(LANGUAGE, 079 LanguageInfo.getJOSMLocaleCode((Locale) langCombo.getSelectedItem())); 080 } 081 082 private static class LanguageComboBoxModel extends DefaultComboBoxModel<Locale> { 083 private final List<Locale> data = new ArrayList<>(); 084 085 LanguageComboBoxModel() { 086 data.add(0, null); 087 List<Locale> locales = Arrays.asList(I18n.getAvailableTranslations()); 088 locales.sort(Comparator.comparing(Locale::getDisplayLanguage)); 089 data.addAll(locales); 090 } 091 092 private void selectLanguage(String language) { 093 setSelectedItem(null); 094 if (language != null) { 095 String lang = LanguageInfo.getJavaLocaleCode(language); 096 for (Locale locale: data) { 097 if (locale == null) { 098 continue; 099 } 100 if (locale.toString().equals(lang)) { 101 setSelectedItem(locale); 102 return; 103 } 104 } 105 } 106 } 107 108 @Override 109 public Locale getElementAt(int index) { 110 return data.get(index); 111 } 112 113 @Override 114 public int getSize() { 115 return data.size(); 116 } 117 } 118 119 private static class LanguageCellRenderer implements ListCellRenderer<Locale> { 120 private final DefaultListCellRenderer dispatch; 121 122 /** 123 * Constructs a new {@code LanguageCellRenderer}. 124 */ 125 LanguageCellRenderer() { 126 this.dispatch = new DefaultListCellRenderer(); 127 } 128 129 @Override 130 public Component getListCellRendererComponent(JList<? extends Locale> list, Locale l, 131 int index, boolean isSelected, boolean cellHasFocus) { 132 return dispatch.getListCellRendererComponent(list, 133 l == null 134 ? tr("Default (Auto determined)") 135 : LanguageInfo.getDisplayName(l), 136 index, isSelected, cellHasFocus); 137 } 138 } 139 140 @Override 141 public boolean isExpert() { 142 return false; 143 } 144 145 @Override 146 public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) { 147 return gui.getSetting(LafPreference.class).getTabPreferenceSetting(gui); 148 } 149}