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