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