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