001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.io; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.awt.BorderLayout; 007 import java.awt.Dimension; 008 import java.awt.FlowLayout; 009 import java.awt.event.ActionEvent; 010 import java.awt.event.KeyEvent; 011 import java.awt.event.WindowAdapter; 012 import java.awt.event.WindowEvent; 013 import java.util.ArrayList; 014 import java.util.Collection; 015 016 import javax.swing.AbstractAction; 017 import javax.swing.BorderFactory; 018 import javax.swing.DefaultListModel; 019 import javax.swing.JComponent; 020 import javax.swing.JDialog; 021 import javax.swing.JLabel; 022 import javax.swing.JList; 023 import javax.swing.JOptionPane; 024 import javax.swing.JPanel; 025 import javax.swing.JScrollPane; 026 import javax.swing.KeyStroke; 027 import javax.swing.event.ListSelectionEvent; 028 import javax.swing.event.ListSelectionListener; 029 030 import org.openstreetmap.josm.Main; 031 import org.openstreetmap.josm.data.osm.Changeset; 032 import org.openstreetmap.josm.gui.SideButton; 033 import org.openstreetmap.josm.tools.ImageProvider; 034 import org.openstreetmap.josm.tools.InputMapUtils; 035 import org.openstreetmap.josm.tools.WindowGeometry; 036 037 /** 038 * This dialog lets the user select changesets from a list of changesets. 039 * 040 */ 041 public class CloseChangesetDialog extends JDialog { 042 043 /** the list */ 044 private JList lstOpenChangesets; 045 /** true if the user canceled the dialog */ 046 private boolean canceled; 047 /** the list model */ 048 private DefaultListModel model; 049 050 private SideButton btnCloseChangesets; 051 052 protected JPanel buildTopPanel() { 053 JPanel pnl = new JPanel(); 054 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 055 pnl.setLayout(new BorderLayout()); 056 pnl.add(new JLabel(tr("<html>Please select the changesets you want to close</html>")), BorderLayout.CENTER); 057 return pnl; 058 } 059 060 protected JPanel buildCenterPanel() { 061 JPanel pnl = new JPanel(); 062 pnl.setLayout(new BorderLayout()); 063 model = new DefaultListModel(); 064 pnl.add(new JScrollPane(lstOpenChangesets = new JList(model)), BorderLayout.CENTER); 065 lstOpenChangesets.setCellRenderer(new ChangesetCellRenderer()); 066 return pnl; 067 } 068 069 protected JPanel buildSouthPanel() { 070 JPanel pnl = new JPanel(); 071 pnl.setLayout(new FlowLayout(FlowLayout.CENTER)); 072 073 // -- close action 074 CloseAction closeAction = new CloseAction(); 075 lstOpenChangesets.addListSelectionListener(closeAction); 076 pnl.add(btnCloseChangesets = new SideButton(closeAction)); 077 InputMapUtils.enableEnter(btnCloseChangesets); 078 079 // -- cancel action 080 SideButton btn; 081 pnl.add(btn = new SideButton(new CancelAction())); 082 btn.setFocusable(true); 083 return pnl; 084 } 085 086 protected void build() { 087 setTitle(tr("Open changesets")); 088 getContentPane().setLayout(new BorderLayout()); 089 getContentPane().add(buildTopPanel(), BorderLayout.NORTH); 090 getContentPane().add(buildCenterPanel(), BorderLayout.CENTER); 091 getContentPane().add(buildSouthPanel(), BorderLayout.SOUTH); 092 093 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "escape"); 094 getRootPane().getActionMap().put("escape", new CancelAction()); 095 addWindowListener(new WindowEventHandler()); 096 } 097 098 @Override 099 public void setVisible(boolean visible) { 100 if (visible) { 101 new WindowGeometry( 102 getClass().getName() + ".geometry", 103 WindowGeometry.centerInWindow(Main.parent, new Dimension(300,300)) 104 ).applySafe(this); 105 } else { 106 new WindowGeometry(this).remember(getClass().getName() + ".geometry"); 107 } 108 super.setVisible(visible); 109 } 110 111 public CloseChangesetDialog() { 112 super(JOptionPane.getFrameForComponent(Main.parent), ModalityType.DOCUMENT_MODAL); 113 build(); 114 } 115 116 class CloseAction extends AbstractAction implements ListSelectionListener { 117 public CloseAction() { 118 putValue(NAME, tr("Close changesets")); 119 putValue(SMALL_ICON, ImageProvider.get("closechangeset")); 120 putValue(SHORT_DESCRIPTION, tr("Close the selected open changesets")); 121 refreshEnabledState(); 122 } 123 124 public void actionPerformed(ActionEvent e) { 125 setCanceled(false); 126 setVisible(false); 127 } 128 129 protected void refreshEnabledState() { 130 setEnabled(lstOpenChangesets.getSelectedValues() != null && lstOpenChangesets.getSelectedValues().length > 0); 131 } 132 133 public void valueChanged(ListSelectionEvent e) { 134 refreshEnabledState(); 135 } 136 } 137 138 class CancelAction extends AbstractAction { 139 140 public CancelAction() { 141 putValue(NAME, tr("Cancel")); 142 putValue(SMALL_ICON, ImageProvider.get("cancel")); 143 putValue(SHORT_DESCRIPTION, tr("Cancel closing of changesets")); 144 } 145 146 public void cancel() { 147 setCanceled(true); 148 setVisible(false); 149 } 150 151 public void actionPerformed(ActionEvent e) { 152 cancel(); 153 } 154 } 155 156 class WindowEventHandler extends WindowAdapter { 157 158 @Override 159 public void windowActivated(WindowEvent arg0) { 160 btnCloseChangesets.requestFocusInWindow(); 161 } 162 163 @Override 164 public void windowClosing(WindowEvent arg0) { 165 new CancelAction().cancel(); 166 } 167 168 } 169 170 /** 171 * Replies true if this dialog was canceled 172 * @return true if this dialog was canceled 173 */ 174 public boolean isCanceled() { 175 return canceled; 176 } 177 178 /** 179 * Sets whether this dialog is canceled 180 * 181 * @param canceled true, if this dialog is canceld 182 */ 183 protected void setCanceled(boolean canceled) { 184 this.canceled = canceled; 185 } 186 187 /** 188 * Sets the collection of changesets to be displayed 189 * 190 * @param changesets the collection of changesets. Assumes an empty collection if null 191 */ 192 public void setChangesets(Collection<Changeset> changesets) { 193 if (changesets == null) { 194 changesets = new ArrayList<Changeset>(); 195 } 196 model.removeAllElements(); 197 for (Changeset cs: changesets) { 198 model.addElement(cs); 199 } 200 if (!changesets.isEmpty()) { 201 lstOpenChangesets.getSelectionModel().setSelectionInterval(0, changesets.size()-1); 202 } 203 } 204 205 /** 206 * Replies a collection with the changesets the user selected. 207 * Never null, but may be empty. 208 * 209 * @return a collection with the changesets the user selected. 210 */ 211 public Collection<Changeset> getSelectedChangesets() { 212 Object [] sel = lstOpenChangesets.getSelectedValues(); 213 ArrayList<Changeset> ret = new ArrayList<Changeset>(); 214 for (Object o: sel) { 215 ret.add((Changeset)o); 216 } 217 return ret; 218 } 219 }