001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.plugin;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.FlowLayout;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.Insets;
010import java.util.EnumMap;
011import java.util.Locale;
012import java.util.Map;
013import java.util.Optional;
014
015import javax.swing.ButtonGroup;
016import javax.swing.JLabel;
017import javax.swing.JPanel;
018import javax.swing.JRadioButton;
019import javax.swing.event.ChangeEvent;
020import javax.swing.event.ChangeListener;
021
022import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
023import org.openstreetmap.josm.gui.widgets.JosmTextField;
024import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
025import org.openstreetmap.josm.plugins.PluginHandler;
026import org.openstreetmap.josm.spi.preferences.Config;
027
028/**
029 * A panel for configuring whether JOSM shall update plugins at startup.
030 *
031 */
032public class PluginUpdatePolicyPanel extends JPanel {
033
034    private enum Policy {
035        ASK("ask"),
036        ALWAYS("always"),
037        NEVER("never");
038
039        private final String preferenceValue;
040
041        Policy(String preferenceValue) {
042            this.preferenceValue = preferenceValue;
043        }
044
045        public String getPreferencesValue() {
046            return preferenceValue;
047        }
048
049        static Policy fromPreferenceValue(String preferenceValue) {
050            if (preferenceValue == null)
051                return null;
052            String prefValue = preferenceValue.trim().toLowerCase(Locale.ENGLISH);
053            for (Policy p: Policy.values()) {
054                if (p.getPreferencesValue().equals(prefValue))
055                    return p;
056            }
057            return null;
058        }
059    }
060
061    private transient Map<Policy, JRadioButton> rbVersionBasedUpatePolicy;
062    private transient Map<Policy, JRadioButton> rbTimeBasedUpatePolicy;
063    private final JosmTextField tfUpdateInterval = new JosmTextField(5);
064    private final JLabel lblUpdateInterval = new JLabel(tr("Update interval (in days):"));
065
066    /**
067     * Constructs a new {@code PluginUpdatePolicyPanel}.
068     */
069    public PluginUpdatePolicyPanel() {
070        build();
071        initFromPreferences();
072    }
073
074    protected JPanel buildVersionBasedUpdatePolicyPanel() {
075        JPanel pnl = new JPanel(new GridBagLayout());
076        GridBagConstraints gc = new GridBagConstraints();
077        gc.anchor = GridBagConstraints.NORTHWEST;
078        gc.fill = GridBagConstraints.HORIZONTAL;
079        gc.weightx = 1.0;
080
081        ButtonGroup bgVersionBasedUpdatePolicy = new ButtonGroup();
082        rbVersionBasedUpatePolicy = new EnumMap<>(Policy.class);
083        JRadioButton btn = new JRadioButton(tr("Ask before updating"));
084        rbVersionBasedUpatePolicy.put(Policy.ASK, btn);
085        bgVersionBasedUpdatePolicy.add(btn);
086
087        btn = new JRadioButton(tr("Always update without asking"));
088        rbVersionBasedUpatePolicy.put(Policy.ALWAYS, btn);
089        bgVersionBasedUpdatePolicy.add(btn);
090
091        btn = new JRadioButton(tr("Never update"));
092        rbVersionBasedUpatePolicy.put(Policy.NEVER, btn);
093        bgVersionBasedUpdatePolicy.add(btn);
094
095        JMultilineLabel lbl = new JMultilineLabel(
096                tr("Please decide whether JOSM shall automatically update active plugins at startup after an update of JOSM itself."));
097        gc.gridy = 0;
098        pnl.add(lbl, gc);
099        for (Policy p: Policy.values()) {
100            gc.gridy++;
101            pnl.add(rbVersionBasedUpatePolicy.get(p), gc);
102        }
103        return pnl;
104    }
105
106    protected JPanel buildUpdateIntervalPanel() {
107        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
108        pnl.add(lblUpdateInterval);
109        pnl.add(tfUpdateInterval);
110        lblUpdateInterval.setLabelFor(tfUpdateInterval);
111        SelectAllOnFocusGainedDecorator.decorate(tfUpdateInterval);
112        return pnl;
113    }
114
115    protected JPanel buildTimeBasedUpdatePolicyPanel() {
116        JPanel pnl = new JPanel(new GridBagLayout());
117        GridBagConstraints gc = new GridBagConstraints();
118        gc.anchor = GridBagConstraints.NORTHWEST;
119        gc.fill = GridBagConstraints.HORIZONTAL;
120        gc.weightx = 1.0;
121
122        TimeBasedPolicyChangeListener changeListener = new TimeBasedPolicyChangeListener();
123
124        ButtonGroup bgTimeBasedUpdatePolicy = new ButtonGroup();
125        rbTimeBasedUpatePolicy = new EnumMap<>(Policy.class);
126        JRadioButton btn = new JRadioButton(tr("Ask before updating"));
127        btn.addChangeListener(changeListener);
128        rbTimeBasedUpatePolicy.put(Policy.ASK, btn);
129        bgTimeBasedUpdatePolicy.add(btn);
130
131        btn = new JRadioButton(tr("Always update without asking"));
132        btn.addChangeListener(changeListener);
133        rbTimeBasedUpatePolicy.put(Policy.ALWAYS, btn);
134        bgTimeBasedUpdatePolicy.add(btn);
135
136        btn = new JRadioButton(tr("Never update"));
137        btn.addChangeListener(changeListener);
138        rbTimeBasedUpatePolicy.put(Policy.NEVER, btn);
139        bgTimeBasedUpdatePolicy.add(btn);
140
141        JMultilineLabel lbl = new JMultilineLabel(
142                tr("Please decide whether JOSM shall automatically update active plugins after a certain period of time."));
143        gc.gridy = 0;
144        pnl.add(lbl, gc);
145        for (Policy p: Policy.values()) {
146            gc.gridy++;
147            pnl.add(rbTimeBasedUpatePolicy.get(p), gc);
148        }
149        gc.gridy++;
150        pnl.add(buildUpdateIntervalPanel(), gc);
151        return pnl;
152    }
153
154    protected final void build() {
155        setLayout(new GridBagLayout());
156        GridBagConstraints gc = new GridBagConstraints();
157        gc.anchor = GridBagConstraints.NORTHWEST;
158        gc.fill = GridBagConstraints.HORIZONTAL;
159        gc.weightx = 1.0;
160        gc.insets = new Insets(5, 5, 10, 5);
161
162        add(buildVersionBasedUpdatePolicyPanel(), gc);
163        gc.gridy = 1;
164        add(buildTimeBasedUpdatePolicyPanel(), gc);
165
166        gc.gridy = 2;
167        gc.weighty = 1.0;
168        gc.fill = GridBagConstraints.BOTH;
169        add(new JPanel(), gc);
170    }
171
172    /**
173     * Loads the relevant preference values from the JOSM preferences
174     */
175    public final void initFromPreferences() {
176        rbVersionBasedUpatePolicy.get(
177                Optional.ofNullable(Policy.fromPreferenceValue(
178                        Config.getPref().get("pluginmanager.version-based-update.policy", "ask"))).orElse(Policy.ASK))
179                .setSelected(true);
180        rbTimeBasedUpatePolicy.get(
181                Optional.ofNullable(Policy.fromPreferenceValue(
182                        Config.getPref().get("pluginmanager.time-based-update.policy", "ask"))).orElse(Policy.ASK))
183                .setSelected(true);
184
185        int days = Config.getPref().getInt("pluginmanager.time-based-update.interval", PluginHandler.DEFAULT_TIME_BASED_UPDATE_INTERVAL);
186        tfUpdateInterval.setText(Integer.toString(days));
187    }
188
189    /**
190     * Remebers the update policy preference settings on the JOSM preferences
191     */
192    public void rememberInPreferences() {
193
194        // remember policy for version based update
195        //
196        for (Policy p: Policy.values()) {
197            if (rbVersionBasedUpatePolicy.get(p).isSelected()) {
198                Config.getPref().put("pluginmanager.version-based-update.policy", p.getPreferencesValue());
199                break;
200            }
201        }
202
203        // remember policy for time based update
204        //
205        for (Policy p: Policy.values()) {
206            if (rbTimeBasedUpatePolicy.get(p).isSelected()) {
207                Config.getPref().put("pluginmanager.time-based-update.policy", p.getPreferencesValue());
208                break;
209            }
210        }
211
212        // remember update interval
213        //
214        int days = 0;
215        try {
216            days = Integer.parseInt(tfUpdateInterval.getText().trim());
217            if (days <= 0) {
218                days = PluginHandler.DEFAULT_TIME_BASED_UPDATE_INTERVAL;
219            }
220        } catch (NumberFormatException e) {
221            days = PluginHandler.DEFAULT_TIME_BASED_UPDATE_INTERVAL;
222        }
223        Config.getPref().putInt("pluginmanager.time-based-update.interval", days);
224    }
225
226    class TimeBasedPolicyChangeListener implements ChangeListener {
227        @Override
228        public void stateChanged(ChangeEvent e) {
229            lblUpdateInterval.setEnabled(!rbTimeBasedUpatePolicy.get(Policy.NEVER).isSelected());
230            tfUpdateInterval.setEnabled(!rbTimeBasedUpatePolicy.get(Policy.NEVER).isSelected());
231        }
232    }
233
234}