001// License: GPL. See LICENSE file for details.
002package org.openstreetmap.josm.gui.widgets;
003
004import org.openstreetmap.josm.Main;
005import org.openstreetmap.josm.tools.GBC;
006
007import javax.swing.DefaultListModel;
008import javax.swing.JButton;
009import javax.swing.JList;
010import javax.swing.JOptionPane;
011import javax.swing.JPanel;
012import javax.swing.JScrollPane;
013import java.awt.BorderLayout;
014import java.awt.Dimension;
015import java.awt.GridBagLayout;
016import java.awt.event.ActionEvent;
017import java.awt.event.ActionListener;
018import java.util.ArrayList;
019import java.util.List;
020
021import static org.openstreetmap.josm.tools.I18n.tr;
022
023/**
024 * A {@link JList} containing items, and {@link JButton}s to add/edit/delete items.
025 */
026public class EditableList extends JPanel {
027
028    public final String title;
029    public final JList<String> sourcesList = new JList<>(new DefaultListModel<String>());
030    public final JButton addSrcButton = new JButton(tr("Add"));
031    public final JButton editSrcButton = new JButton(tr("Edit"));
032    public final JButton deleteSrcButton = new JButton(tr("Delete"));
033
034    /**
035     * Constructs a new {@code EditableList}.
036     * @param title The title displayed in input dialog
037     */
038    public EditableList(String title) {
039        this.title = title;
040        build();
041    }
042
043    protected final void build() {
044
045        setLayout(new BorderLayout());
046
047        addSrcButton.addActionListener(new ActionListener() {
048            @Override
049            public void actionPerformed(ActionEvent e) {
050                String source = JOptionPane.showInputDialog(
051                        Main.parent,
052                        title,
053                        title,
054                        JOptionPane.QUESTION_MESSAGE);
055                if (source != null) {
056                    ((DefaultListModel<String>) sourcesList.getModel()).addElement(source);
057                }
058                sourcesList.clearSelection();
059            }
060        });
061
062        editSrcButton.addActionListener(new ActionListener() {
063            @Override
064            public void actionPerformed(ActionEvent e) {
065                int row = sourcesList.getSelectedIndex();
066                if (row == -1 && sourcesList.getModel().getSize() == 1) {
067                    sourcesList.setSelectedIndex(0);
068                    row = 0;
069                }
070                if (row == -1) {
071                    if (sourcesList.getModel().getSize() == 0) {
072                        String source = JOptionPane.showInputDialog(Main.parent, title, title, JOptionPane.QUESTION_MESSAGE);
073                        if (source != null) {
074                            ((DefaultListModel<String>) sourcesList.getModel()).addElement(source);
075                        }
076                    } else {
077                        JOptionPane.showMessageDialog(
078                                Main.parent,
079                                tr("Please select the row to edit."),
080                                tr("Information"),
081                                JOptionPane.INFORMATION_MESSAGE
082                        );
083                    }
084                } else {
085                    String source = (String) JOptionPane.showInputDialog(Main.parent,
086                            title,
087                            title,
088                            JOptionPane.QUESTION_MESSAGE, null, null,
089                            sourcesList.getSelectedValue());
090                    if (source != null) {
091                        ((DefaultListModel<String>) sourcesList.getModel()).setElementAt(source, row);
092                    }
093                }
094                sourcesList.clearSelection();
095            }
096        });
097
098        deleteSrcButton.addActionListener(new ActionListener() {
099            @Override
100            public void actionPerformed(ActionEvent e) {
101                if (sourcesList.getSelectedIndex() == -1) {
102                    JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to delete."), tr("Information"), JOptionPane.QUESTION_MESSAGE);
103                } else {
104                    ((DefaultListModel<String>) sourcesList.getModel()).remove(sourcesList.getSelectedIndex());
105                }
106            }
107        });
108        sourcesList.setMinimumSize(new Dimension(300, 50));
109        sourcesList.setVisibleRowCount(3);
110
111        addSrcButton.setToolTipText(tr("Add a new source to the list."));
112        editSrcButton.setToolTipText(tr("Edit the selected source."));
113        deleteSrcButton.setToolTipText(tr("Delete the selected source from the list."));
114
115        final JPanel buttonPanel = new JPanel(new GridBagLayout());
116        buttonPanel.add(addSrcButton, GBC.std().insets(0, 5, 0, 0));
117        buttonPanel.add(editSrcButton, GBC.std().insets(5, 5, 5, 0));
118        buttonPanel.add(deleteSrcButton, GBC.std().insets(0, 5, 0, 0));
119
120        add(new JScrollPane(sourcesList), BorderLayout.CENTER);
121        add(buttonPanel, BorderLayout.SOUTH);
122        setPreferredSize(new Dimension(300, 50 + (int) buttonPanel.getPreferredSize().getHeight()));
123
124    }
125
126    public void setItems(final Iterable<String> items) {
127        for (String source : items) {
128            ((DefaultListModel<String>) sourcesList.getModel()).addElement(source);
129        }
130    }
131
132    public List<String> getItems() {
133        final List<String> items = new ArrayList<>(sourcesList.getModel().getSize());
134        for (int i = 0; i < sourcesList.getModel().getSize(); ++i) {
135            items.add(sourcesList.getModel().getElementAt(i));
136        }
137        return items;
138    }
139
140    public void setEnabled(boolean enabled) {
141        sourcesList.setEnabled(enabled);
142        addSrcButton.setEnabled(enabled);
143        editSrcButton.setEnabled(enabled);
144        deleteSrcButton.setEnabled(enabled);
145    }
146}