source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java@ 3669

Last change on this file since 3669 was 3669, checked in by bastiK, 13 years ago

add validator plugin to josm core. Original author: Francisco R. Santos (frsantos); major contributions by bilbo, daeron, delta_foxtrot, imi, jttt, jrreid, gabriel, guggis, pieren, rrankin, skela, stoecker, stotz and others

  • Property svn:eol-style set to native
File size: 12.1 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.preferences;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Font;
7import java.awt.GridBagLayout;
8import java.awt.ScrollPane;
9import java.awt.event.MouseWheelEvent;
10import java.awt.event.MouseWheelListener;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Iterator;
14import java.util.LinkedList;
15import java.util.List;
16import java.util.logging.Logger;
17
18import javax.swing.BorderFactory;
19import javax.swing.JComponent;
20import javax.swing.JLabel;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
23import javax.swing.JScrollPane;
24import javax.swing.JTabbedPane;
25import javax.swing.SwingUtilities;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.plugins.PluginDownloadTask;
29import org.openstreetmap.josm.plugins.PluginHandler;
30import org.openstreetmap.josm.plugins.PluginInformation;
31import org.openstreetmap.josm.tools.BugReportExceptionHandler;
32import org.openstreetmap.josm.tools.GBC;
33import org.openstreetmap.josm.tools.I18n;
34import org.openstreetmap.josm.tools.ImageProvider;
35
36/**
37 * The preference settings.
38 *
39 * @author imi
40 */
41public class PreferenceTabbedPane extends JTabbedPane implements MouseWheelListener {
42 @SuppressWarnings("unused")
43 static private final Logger logger = Logger.getLogger(PreferenceTabbedPane.class.getName());
44
45 /**
46 * Allows PreferenceSettings to do validation of entered values when ok was pressed.
47 * If data is invalid then event can return false to cancel closing of preferences dialog.
48 *
49 */
50 public interface ValidationListener {
51 /**
52 *
53 * @return True if preferences can be saved
54 */
55 boolean validatePreferences();
56 }
57
58 private final static Collection<PreferenceSettingFactory> settingsFactory = new LinkedList<PreferenceSettingFactory>();
59 private final List<PreferenceSetting> settings = new ArrayList<PreferenceSetting>();
60
61 // some common tabs
62 public final JPanel display = createPreferenceTab("display", tr("Display Settings"), tr("Various settings that influence the visual representation of the whole program."));
63 public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."),false);
64 public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation."));
65 public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers."));
66 public final JPanel plugins = createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false);
67
68 public final javax.swing.JTabbedPane displaycontent = new javax.swing.JTabbedPane();
69 public final javax.swing.JTabbedPane mapcontent = new javax.swing.JTabbedPane();
70
71 List<ValidationListener> validationListeners = new ArrayList<ValidationListener>();
72
73 /**
74 * Add validation listener to currently open preferences dialog. Calling to removeValidationListener is not necessary, all listeners will
75 * be automatically removed when dialog is closed
76 * @param validationListener
77 */
78 public void addValidationListener(ValidationListener validationListener) {
79 validationListeners.add(validationListener);
80 }
81
82 /**
83 * Construct a JPanel for the preference settings. Layout is GridBagLayout
84 * and a centered title label and the description are added. The panel
85 * will be shown inside a {@link ScrollPane}
86 * @param icon The name of the icon.
87 * @param title The title of this preference tab.
88 * @param desc A description in one sentence for this tab. Will be displayed
89 * italic under the title.
90 * @return The created panel ready to add other controls.
91 */
92 public JPanel createPreferenceTab(String icon, String title, String desc) {
93 return createPreferenceTab(icon, title, desc, false);
94 }
95
96 /**
97 * Construct a JPanel for the preference settings. Layout is GridBagLayout
98 * and a centered title label and the description are added.
99 * @param icon The name of the icon.
100 * @param title The title of this preference tab.
101 * @param desc A description in one sentence for this tab. Will be displayed
102 * italic under the title.
103 * @param inScrollPane if <code>true</code> the added tab will show scroll bars
104 * if the panel content is larger than the available space
105 * @return The created panel ready to add other controls.
106 */
107 public JPanel createPreferenceTab(String icon, String title, String desc, boolean inScrollPane) {
108 JPanel p = new JPanel(new GridBagLayout());
109 p.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
110 p.add(new JLabel(title), GBC.eol().insets(0,5,0,10).anchor(GBC.NORTHWEST));
111
112 JLabel descLabel = new JLabel("<html>"+desc+"</html>");
113 descLabel.setFont(descLabel.getFont().deriveFont(Font.ITALIC));
114 p.add(descLabel, GBC.eol().insets(5,0,5,20).fill(GBC.HORIZONTAL));
115
116 JComponent tab = p;
117 if (inScrollPane) {
118 JScrollPane sp = new JScrollPane(p);
119 tab = sp;
120 }
121 addTab(null, ImageProvider.get("preferences", icon), tab);
122 setToolTipTextAt(getTabCount()-1, "<html>"+desc+"</html>");
123 return p;
124 }
125
126 protected PluginPreference getPluginPreference() {
127 for (PreferenceSetting setting: settings) {
128 if (setting instanceof PluginPreference)
129 return (PluginPreference) setting;
130 }
131 return null;
132 }
133
134 public void savePreferences() {
135 if(Main.applet)
136 return;
137 // create a task for downloading plugins if the user has activated, yet not downloaded,
138 // new plugins
139 //
140 final PluginPreference preference = getPluginPreference();
141 final List<PluginInformation> toDownload = preference.getPluginsScheduledForUpdateOrDownload();
142 final PluginDownloadTask task;
143 if (! toDownload.isEmpty()) {
144 task = new PluginDownloadTask(this, toDownload, tr("Download plugins"));
145 } else {
146 task = null;
147 }
148
149 // this is the task which will run *after* the plugins are downloaded
150 //
151 final Runnable continuation = new Runnable() {
152 public void run() {
153 boolean requiresRestart = false;
154 if (task != null && !task.isCanceled()) {
155 if (!task.getDownloadedPlugins().isEmpty()) {
156 requiresRestart = true;
157 }
158 }
159
160 for (PreferenceSetting setting : settings) {
161 if (setting.ok()) {
162 requiresRestart = true;
163 }
164 }
165
166 // build the messages. We only display one message, including the status
167 // information from the plugin download task and - if necessary - a hint
168 // to restart JOSM
169 //
170 StringBuilder sb = new StringBuilder();
171 sb.append("<html>");
172 if (task != null && !task.isCanceled()) {
173 sb.append(PluginPreference.buildDownloadSummary(task));
174 }
175 if (requiresRestart) {
176 sb.append(tr("You have to restart JOSM for some settings to take effect."));
177 }
178 sb.append("</html>");
179
180 // display the message, if necessary
181 //
182 if ((task != null && !task.isCanceled()) || requiresRestart) {
183 JOptionPane.showMessageDialog(
184 Main.parent,
185 sb.toString(),
186 tr("Warning"),
187 JOptionPane.WARNING_MESSAGE
188 );
189 }
190 Main.parent.repaint();
191 }
192 };
193
194 if (task != null) {
195 // if we have to launch a plugin download task we do it asynchronously, followed
196 // by the remaining "save preferences" activites run on the Swing EDT.
197 //
198 Main.worker.submit(task);
199 Main.worker.submit(
200 new Runnable() {
201 public void run() {
202 SwingUtilities.invokeLater(continuation);
203 }
204 }
205 );
206 } else {
207 // no need for asynchronous activities. Simply run the remaining "save preference"
208 // activities on this thread (we are already on the Swing EDT
209 //
210 continuation.run();
211 }
212 }
213
214 /**
215 * If the dialog is closed with Ok, the preferences will be stored to the preferences-
216 * file, otherwise no change of the file happens.
217 */
218 public PreferenceTabbedPane() {
219 super(JTabbedPane.LEFT, JTabbedPane.SCROLL_TAB_LAYOUT);
220 super.addMouseWheelListener(this);
221 }
222
223 public void buildGui() {
224 for (PreferenceSettingFactory factory : settingsFactory) {
225 // logger.info("creating settings: " + factory);
226 PreferenceSetting setting = factory.createPreferenceSetting();
227 if (setting != null) {
228 settings.add(factory.createPreferenceSetting());
229 }
230 }
231
232 display.add(displaycontent, GBC.eol().fill(GBC.BOTH));
233 map.add(mapcontent, GBC.eol().fill(GBC.BOTH));
234 for (Iterator<PreferenceSetting> it = settings.iterator(); it.hasNext();) {
235 try {
236 PreferenceSetting settings = it.next();
237 //logger.info("adding gui: " + settings);
238 settings.addGui(this);
239 } catch (SecurityException e) {
240 it.remove();
241 } catch (Throwable e) {
242 /* allow to change most settings even if e.g. a plugin fails */
243 BugReportExceptionHandler.handleException(e);
244 }
245 }
246 }
247
248 public List<PreferenceSetting> getSettings() {
249 return settings;
250 }
251
252 @SuppressWarnings("unchecked")
253 public <T> T getSetting(Class<? extends T> clazz) {
254 for (PreferenceSetting setting:settings) {
255 if (clazz.isAssignableFrom(setting.getClass()))
256 return (T)setting;
257 }
258 return null;
259 }
260
261 static {
262 // order is important!
263 settingsFactory.add(new DrawingPreference.Factory());
264 settingsFactory.add(new ColorPreference.Factory());
265 settingsFactory.add(new LafPreference.Factory());
266 settingsFactory.add(new LanguagePreference.Factory());
267 settingsFactory.add(new ServerAccessPreference.Factory());
268 settingsFactory.add(new ProjectionPreference.Factory());
269 settingsFactory.add(new MapPaintPreference.Factory());
270 settingsFactory.add(new TaggingPresetPreference.Factory());
271 settingsFactory.add(new BackupPreference.Factory());
272 if(!Main.applet) {
273 settingsFactory.add(new PluginPreference.Factory());
274 }
275 settingsFactory.add(Main.toolbar);
276 settingsFactory.add(new AudioPreference.Factory());
277 settingsFactory.add(new ShortcutPreference.Factory());
278 settingsFactory.add(new ValidatorPreference.Factory());
279
280 PluginHandler.getPreferenceSetting(settingsFactory);
281
282 // always the last: advanced tab
283 settingsFactory.add(new AdvancedPreference.Factory());
284 }
285
286 /**
287 * This mouse wheel listener reacts when a scroll is carried out over the
288 * tab strip and scrolls one tab/down or up, selecting it immediately.
289 */
290 public void mouseWheelMoved(MouseWheelEvent wev) {
291 // Ensure the cursor is over the tab strip
292 if(super.indexAtLocation(wev.getPoint().x, wev.getPoint().y) < 0)
293 return;
294
295 // Get currently selected tab
296 int newTab = super.getSelectedIndex() + wev.getWheelRotation();
297
298 // Ensure the new tab index is sound
299 newTab = newTab < 0 ? 0 : newTab;
300 newTab = newTab >= super.getTabCount() ? super.getTabCount() - 1 : newTab;
301
302 // select new tab
303 super.setSelectedIndex(newTab);
304 }
305}
Note: See TracBrowser for help on using the repository browser.