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