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