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 }