001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.preferences;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.BorderLayout;
007 import java.awt.Component;
008 import java.awt.Container;
009 import java.awt.Dimension;
010 import java.awt.FlowLayout;
011 import java.awt.GridBagLayout;
012 import java.awt.Insets;
013 import java.awt.Toolkit;
014 import java.awt.event.ActionEvent;
015 import java.awt.event.ActionListener;
016 import java.awt.event.KeyEvent;
017 import java.awt.event.WindowAdapter;
018 import java.awt.event.WindowEvent;
019
020 import javax.swing.AbstractAction;
021 import javax.swing.BorderFactory;
022 import javax.swing.JCheckBox;
023 import javax.swing.JComponent;
024 import javax.swing.JDialog;
025 import javax.swing.JOptionPane;
026 import javax.swing.JPanel;
027 import javax.swing.KeyStroke;
028
029 import org.openstreetmap.josm.actions.ExpertToggleAction;
030 import org.openstreetmap.josm.gui.SideButton;
031 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
032 import org.openstreetmap.josm.gui.help.HelpUtil;
033 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.ValidationListener;
034 import org.openstreetmap.josm.gui.preferences.map.MapPreference;
035 import org.openstreetmap.josm.tools.GBC;
036 import org.openstreetmap.josm.tools.ImageProvider;
037 import org.openstreetmap.josm.tools.WindowGeometry;
038
039 public class PreferenceDialog extends JDialog {
040
041 private PreferenceTabbedPane tpPreferences;
042 private boolean canceled;
043
044 protected JPanel buildActionPanel() {
045 JPanel pnl = new JPanel(new GridBagLayout());
046
047 JCheckBox expert = new JCheckBox(tr("Expert mode"));
048 expert.setSelected(ExpertToggleAction.isExpert());
049 expert.addActionListener(new ActionListener() {
050 public void actionPerformed(ActionEvent e) {
051 ExpertToggleAction.getInstance().actionPerformed(null);
052 }
053 });
054
055 JPanel btns = new JPanel(new FlowLayout(FlowLayout.CENTER));
056 btns.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
057 btns.add(new SideButton(new OKAction()));
058 btns.add(new SideButton(new CancelAction()));
059 btns.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Action/Preferences"))));
060 pnl.add(expert, GBC.std().insets(5,0,0,0));
061 pnl.add(btns, GBC.std().fill(GBC.HORIZONTAL));
062 return pnl;
063 }
064
065 protected void build() {
066 Container c = getContentPane();
067 c.setLayout(new BorderLayout());
068 c.add(tpPreferences = new PreferenceTabbedPane(), BorderLayout.CENTER);
069 tpPreferences.buildGui();
070 tpPreferences.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
071 c.add(buildActionPanel(), BorderLayout.SOUTH);
072
073 addWindowListener(new WindowEventHandler());
074
075 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");
076 getRootPane().getActionMap().put("cancel", new CancelAction());
077 HelpUtil.setHelpContext(getRootPane(), HelpUtil.ht("/Action/Preferences"));
078 }
079
080 public PreferenceDialog(Component parent) {
081 super(JOptionPane.getFrameForComponent(parent), tr("Preferences"), ModalityType.DOCUMENT_MODAL);
082 build();
083 this.setMinimumSize(new Dimension(600, 350));
084 // set the maximum width to the current screen. If the dialog is opened on a
085 // smaller screen than before, this will reset the stored preference.
086 this.setMaximumSize( Toolkit.getDefaultToolkit().getScreenSize());
087 }
088
089 public boolean isCanceled() {
090 return canceled;
091 }
092
093 protected void setCanceled(boolean canceled) {
094 this.canceled = canceled;
095 }
096
097 @Override
098 public void setVisible(boolean visible) {
099 if (visible) {
100 // Make the pref window at most as large as the parent JOSM window
101 // Have to take window decorations into account or the windows will
102 // be too large
103 Insets i = this.getParent().getInsets();
104 Dimension p = this.getParent().getSize();
105 p = new Dimension(Math.min(p.width-i.left-i.right, 700),
106 Math.min(p.height-i.top-i.bottom, 800));
107 new WindowGeometry(
108 getClass().getName() + ".geometry",
109 WindowGeometry.centerInWindow(
110 getParent(),
111 p
112 )
113 ).applySafe(this);
114 } else if (!visible && isShowing()){
115 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
116 }
117 super.setVisible(visible);
118 }
119
120 public void selectPreferencesTabByName(String name) {
121 tpPreferences.selectTabByName(name);
122 }
123
124 public void selectPreferencesTabByClass(Class<? extends TabPreferenceSetting> clazz) {
125 tpPreferences.selectTabByPref(clazz);
126 }
127
128 class CancelAction extends AbstractAction {
129 public CancelAction() {
130 putValue(NAME, tr("Cancel"));
131 putValue(SMALL_ICON, ImageProvider.get("cancel"));
132 putValue(SHORT_DESCRIPTION, tr("Close the preferences dialog and discard preference updates"));
133 }
134
135 public void cancel() {
136 setCanceled(true);
137 setVisible(false);
138 tpPreferences.validationListeners.clear();
139 }
140
141 public void actionPerformed(ActionEvent evt) {
142 cancel();
143 }
144 }
145
146 class OKAction extends AbstractAction {
147 public OKAction() {
148 putValue(NAME, tr("OK"));
149 putValue(SMALL_ICON, ImageProvider.get("ok"));
150 putValue(SHORT_DESCRIPTION, tr("Save the preferences and close the dialog"));
151 }
152
153 public void actionPerformed(ActionEvent evt) {
154 for (ValidationListener listener: tpPreferences.validationListeners) {
155 if (!listener.validatePreferences())
156 return;
157 }
158
159 tpPreferences.savePreferences();
160 tpPreferences.validationListeners.clear();
161 setCanceled(false);
162 setVisible(false);
163 }
164 }
165
166 class WindowEventHandler extends WindowAdapter {
167 @Override
168 public void windowClosing(WindowEvent arg0) {
169 new CancelAction().cancel();
170 }
171 }
172
173 public void selectMapPaintPreferenceTab() {
174 tpPreferences.selectTabByPref(MapPreference.class);
175 tpPreferences.getMapPreference().mapcontent.setSelectedIndex(1);
176 }
177 }