001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences;
003
004import java.awt.Component;
005import java.util.HashMap;
006import java.util.Map;
007
008import javax.swing.JPanel;
009import javax.swing.JTabbedPane;
010
011import org.openstreetmap.josm.gui.help.HelpUtil;
012import org.openstreetmap.josm.tools.GBC;
013import org.openstreetmap.josm.tools.Logging;
014
015/**
016 * Abstract base class for {@link TabPreferenceSetting} implementations.
017 *
018 * Support for common functionality, like icon, title and adding a tab ({@link SubPreferenceSetting}).
019 */
020public abstract class DefaultTabPreferenceSetting extends DefaultPreferenceSetting implements TabPreferenceSetting {
021
022    private final String iconName;
023    private final String description;
024    private final String title;
025    private final JTabbedPane tabpane;
026    private final Map<SubPreferenceSetting, Component> subSettingMap;
027
028    /**
029     * Constructs a new {@code DefaultTabPreferenceSetting}.
030     */
031    protected DefaultTabPreferenceSetting() {
032        this(null, null, null);
033    }
034
035    protected DefaultTabPreferenceSetting(String iconName, String title, String description) {
036        this(iconName, title, description, false);
037    }
038
039    protected DefaultTabPreferenceSetting(String iconName, String title, String description, boolean isExpert) {
040        this(iconName, title, description, isExpert, null);
041    }
042
043    protected DefaultTabPreferenceSetting(String iconName, String title, String description, boolean isExpert, JTabbedPane tabpane) {
044        super(isExpert);
045        this.iconName = iconName;
046        this.description = description;
047        this.title = title;
048        this.tabpane = tabpane;
049        this.subSettingMap = tabpane != null ? new HashMap<>() : null;
050        if (tabpane != null) {
051            tabpane.addMouseWheelListener(new PreferenceTabbedPane.WheelListener(tabpane));
052        }
053    }
054
055    @Override
056    public String getIconName() {
057        return iconName;
058    }
059
060    @Override
061    public String getTooltip() {
062        if (getDescription() != null) {
063            return "<html>"+getDescription()+"</html>";
064        } else {
065            return null;
066        }
067    }
068
069    @Override
070    public String getDescription() {
071        return description;
072    }
073
074    @Override
075    public String getTitle() {
076        return title;
077    }
078
079    /**
080     * Get the inner tab pane, if any.
081     * @return The JTabbedPane contained in this tab preference settings, or null if none is set.
082     * @since 5631
083     */
084    public final JTabbedPane getTabPane() {
085        return tabpane;
086    }
087
088    protected final void createPreferenceTabWithScrollPane(PreferenceTabbedPane gui, JPanel panel) {
089        GBC a = GBC.eol().insets(-5, 0, 0, 0);
090        a.anchor = GBC.EAST;
091
092        JPanel tab = gui.createPreferenceTab(this, true);
093        tab.add(panel, GBC.eol().fill(GBC.BOTH));
094        tab.add(GBC.glue(0, 10), a);
095    }
096
097    @Override
098    public boolean selectSubTab(SubPreferenceSetting subPref) {
099        if (tabpane != null && subPref != null) {
100            Component tab = getSubTab(subPref);
101            if (tab != null) {
102                try {
103                    tabpane.setSelectedComponent(tab);
104                    return true;
105                } catch (IllegalArgumentException e) {
106                    // Ignore exception and return false below
107                    Logging.debug(Logging.getErrorMessage(e));
108                }
109            }
110        }
111        return false;
112    }
113
114    @Override
115    public final void addSubTab(SubPreferenceSetting sub, String title, Component component) {
116        addSubTab(sub, title, component, null);
117    }
118
119    @Override
120    public final void addSubTab(SubPreferenceSetting sub, String title, Component component, String tip) {
121        if (tabpane != null && component != null) {
122            tabpane.addTab(title, null, component, tip);
123            registerSubTab(sub, component);
124        }
125    }
126
127    @Override
128    public final void registerSubTab(SubPreferenceSetting sub, Component component) {
129        if (subSettingMap != null && sub != null && component != null) {
130            subSettingMap.put(sub, component);
131        }
132    }
133
134    @Override
135    public final Component getSubTab(SubPreferenceSetting sub) {
136        return subSettingMap != null ? subSettingMap.get(sub) : null;
137    }
138
139    @Override
140    public Class<? extends SubPreferenceSetting> getSelectedSubTab() {
141        if (tabpane == null || subSettingMap == null) {
142            return null;
143        }
144        final Component selected = tabpane.getSelectedComponent();
145        return subSettingMap.entrySet().stream()
146                .filter(e -> e.getValue() == selected)
147                .map(e -> e.getKey().getClass())
148                .findFirst().orElse(null);
149    }
150
151    /**
152     * Determines whether this tab may be hidden (since it does not contain any relevant content)
153     * @return whether this tab may be hidden
154     */
155    protected boolean canBeHidden() {
156        return false;
157    }
158
159    @Override
160    public String getHelpContext() {
161        return HelpUtil.ht("/Action/Preferences");
162    }
163}