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 }