/** * Copyright (C) 2002-2012 The FreeCol Team * * This file is part of FreeCol. * * FreeCol is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * FreeCol is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FreeCol. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.freecol.client.gui.option; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.logging.Logger; import org.freecolandroid.repackaged.java.awt.Color; import org.freecolandroid.repackaged.java.awt.event.ActionEvent; import org.freecolandroid.repackaged.java.awt.event.ActionListener; import org.freecolandroid.repackaged.javax.swing.BorderFactory; import org.freecolandroid.repackaged.javax.swing.DefaultListModel; import org.freecolandroid.repackaged.javax.swing.JButton; import org.freecolandroid.repackaged.javax.swing.JLabel; import org.freecolandroid.repackaged.javax.swing.JList; import org.freecolandroid.repackaged.javax.swing.JPanel; import org.freecolandroid.repackaged.javax.swing.JScrollPane; import org.freecolandroid.repackaged.javax.swing.event.ListSelectionEvent; import org.freecolandroid.repackaged.javax.swing.event.ListSelectionListener; import net.miginfocom.swing.MigLayout; import net.sf.freecol.client.FreeColClient; import net.sf.freecol.client.gui.GUI; import net.sf.freecol.client.gui.i18n.Messages; import net.sf.freecol.client.gui.panel.FreeColDialog; import net.sf.freecol.common.option.AbstractOption; import net.sf.freecol.common.option.ListOption; import net.sf.freecol.common.option.Option; /** * This class provides visualization for a List of {@link * net.sf.freecol.common.option.AbstractOption<T>}s. In order to * enable values to be both seen and changed. * */ public final class ListOptionUI<T> extends OptionUI<ListOption<T>> implements ListSelectionListener { private static Logger logger = Logger.getLogger(ListOptionUI.class.getName()); private JPanel panel = new JPanel(); private JList list; private DefaultListModel model; private JButton editButton = new JButton(Messages.message("list.edit")); private JButton addButton = new JButton(Messages.message("list.add")); private JButton removeButton = new JButton(Messages.message("list.remove")); private JButton upButton = new JButton(Messages.message("list.up")); private JButton downButton = new JButton(Messages.message("list.down")); private JButton[] buttons = new JButton[] { editButton, addButton, removeButton, upButton, downButton }; private FreeColClient freeColClient; /** * Creates a new <code>ListOptionUI</code> for the given * <code>ListOption</code>. * * @param option * @param editable boolean whether user can modify the setting */ public ListOptionUI(FreeColClient freeColClient, final GUI gui, final ListOption<T> option, boolean editable) { super(gui, option, editable); panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), super.getLabel().getText())); panel.setLayout(new MigLayout("wrap 2, fill", "[fill, grow]20[fill]")); model = new DefaultListModel(); for (AbstractOption<T> o : option.getValue()) { try { model.addElement(o.clone()); } catch(CloneNotSupportedException e) { logger.warning(e.toString()); } } list = new JList(model); AbstractOption<T> o = option.getValue().isEmpty() ? option.getTemplate() : option.getValue().get(0); if (o != null) { OptionUI ui = OptionUI.getOptionUI(freeColClient, gui, o, editable); if (ui != null && ui.getListCellRenderer() != null) { list.setCellRenderer(ui.getListCellRenderer()); } } list.setVisibleRowCount(4); JScrollPane pane = new JScrollPane(list); panel.add(pane, "grow, spany 5"); for (JButton button : buttons) { button.setEnabled(editable); panel.add(button); } addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Option oldValue = (Option) list.getSelectedValue(); if (oldValue == null) { oldValue = getOption().getTemplate(); } try { Option value = oldValue.clone(); if (showEditDialog(gui, value)) { model.addElement(value); list.setSelectedValue(value, true); list.repaint(); } } catch(CloneNotSupportedException ex) { logger.warning(ex.toString()); } } }); editButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Object object = list.getSelectedValue(); if (object != null) { if (showEditDialog(gui, (Option) object)) { list.repaint(); } } } }); removeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { model.removeElementAt(list.getSelectedIndex()); } }); upButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (list.getSelectedIndex() == 0) { return; } final int index = list.getSelectedIndex(); final Object temp = model.getElementAt(index); model.setElementAt(model.getElementAt(index-1), index); model.setElementAt(temp, index-1); list.setSelectedIndex(index-1); } }); downButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (list.getSelectedIndex() == model.getSize() - 1) { return; } final int index = list.getSelectedIndex(); final Object temp = model.getElementAt(index); model.setElementAt(model.getElementAt(index+1), index); model.setElementAt(temp, index+1); list.setSelectedIndex(index+1); } }); editButton.setEnabled(false); removeButton.setEnabled(false); upButton.setEnabled(false); downButton.setEnabled(false); list.addListSelectionListener(this); initialize(); } private boolean showEditDialog(GUI gui, Option option) { final EditDialog editDialog = new EditDialog(freeColClient, gui, option); boolean result = gui.getCanvas().showFreeColDialog(editDialog); editDialog.requestFocus(); return result; } private class EditDialog extends FreeColDialog<Boolean> { private OptionUI ui; public EditDialog(FreeColClient freeColClient, GUI gui, Option option) { super(freeColClient, gui); setLayout(new MigLayout()); ui = OptionUI.getOptionUI(freeColClient, gui, option, editable); if (ui.getLabel() == null) { add(ui.getLabel(), "split 2"); } add(ui.getComponent()); add(okButton, "newline, split 2, tag ok"); add(cancelButton, "tag cancel"); } @Override public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); if (OK.equals(command)) { ui.updateOption(); setResponse(true); } else { setResponse(false); } } } /** * Returns <code>null</code>, since this OptionUI does not require * an external label. * * @return null */ @Override public final JLabel getLabel() { return null; } /** * {@inheritDoc} */ public JPanel getComponent() { return panel; } /** * Updates the value of the {@link net.sf.freecol.common.getOption().Option} this object keeps. */ public void updateOption() { getOption().setValue(getValue()); } @SuppressWarnings("unchecked") private List<AbstractOption<T>> getValue() { List<AbstractOption<T>> result = new ArrayList<AbstractOption<T>>(); for (Enumeration e = model.elements(); e.hasMoreElements();) { result.add((AbstractOption<T>) e.nextElement()); } return result; } /** * Reset with the value from the Option. */ public void reset() { model.clear(); for (AbstractOption<T> o : getOption().getValue()) { model.addElement(o); } } public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting() == false) { boolean enabled = (isEditable() && list.getSelectedValue() != null); editButton.setEnabled(enabled); removeButton.setEnabled(enabled); upButton.setEnabled(enabled); downButton.setEnabled(enabled); } } }