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    }