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.List;
010import java.util.Locale;
011
012import javax.swing.Box;
013import javax.swing.DefaultComboBoxModel;
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.Main;
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.tools.GBC;
028import org.openstreetmap.josm.tools.I18n;
029
030/**
031 * Language preferences.
032 */
033public class LanguagePreference implements SubPreferenceSetting {
034
035    /**
036     * Factory used to create a new {@code LanguagePreference}.
037     */
038    public static class Factory implements PreferenceSettingFactory {
039        @Override
040        public PreferenceSetting createPreferenceSetting() {
041            return new LanguagePreference();
042        }
043    }
044
045    /** the combo box with the available locales */
046    private JosmComboBox<Locale> langCombo;
047
048    @Override
049    public void addGui(final PreferenceTabbedPane gui) {
050        LanguageComboBoxModel model = new LanguageComboBoxModel();
051        // Selecting the language BEFORE the JComboBox listens to model changes speed up initialization by ~35ms (see #7386)
052        // See https://stackoverflow.com/questions/3194958/fast-replacement-for-jcombobox-basiccomboboxui
053        model.selectLanguage(Main.pref.get("language"));
054        langCombo = new JosmComboBox<>(model);
055        langCombo.setRenderer(new LanguageCellRenderer());
056
057        LafPreference lafPreference = gui.getSetting(LafPreference.class);
058        final JPanel panel = lafPreference.panel;
059        panel.add(new JLabel(tr("Language")), GBC.std().insets(20, 0, 0, 0));
060        panel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
061        panel.add(langCombo, GBC.eol().fill(GBC.HORIZONTAL));
062        panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH));
063
064        TabPreferenceSetting tabPref = lafPreference.getTabPreferenceSetting(gui);
065        tabPref.registerSubTab(this, tabPref.getSubTab(lafPreference));
066    }
067
068    @Override
069    public boolean ok() {
070        if(langCombo.getSelectedItem() == null)
071            return Main.pref.put("language", null);
072        else
073            return Main.pref.put("language",
074                    ((Locale)langCombo.getSelectedItem()).toString());
075    }
076
077    private static class LanguageComboBoxModel extends DefaultComboBoxModel<Locale> {
078        private final List<Locale> data = new ArrayList<>();
079
080        public LanguageComboBoxModel(){
081            data.add(0,null);
082            data.addAll(Arrays.asList(I18n.getAvailableTranslations()));
083        }
084
085        public void selectLanguage(String language) {
086            setSelectedItem(null);
087            if (language != null) {
088                for (Locale locale: data) {
089                    if (locale == null) {
090                        continue;
091                    }
092                    if (locale.toString().equals(language)) {
093                        setSelectedItem(locale);
094                        return;
095                    }
096                }
097            }
098        }
099
100        @Override
101        public Locale getElementAt(int index) {
102            return data.get(index);
103        }
104
105        @Override
106        public int getSize() {
107            return data.size();
108        }
109    }
110
111    private static class LanguageCellRenderer implements ListCellRenderer<Locale> {
112        private final DefaultListCellRenderer dispatch;
113        public LanguageCellRenderer() {
114            this.dispatch = new DefaultListCellRenderer();
115        }
116        @Override
117        public Component getListCellRendererComponent(JList<? extends Locale> list, Locale l, 
118                int index, boolean isSelected, boolean cellHasFocus) {
119            return dispatch.getListCellRendererComponent(list,
120                    l == null ? tr("Default (Auto determined)") : l.getDisplayName(l),
121                            index, isSelected, cellHasFocus);
122        }
123    }
124
125    @Override
126    public boolean isExpert() {
127        return false;
128    }
129
130    @Override
131    public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
132        return gui.getSetting(LafPreference.class).getTabPreferenceSetting(gui);
133    }
134}