/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package es.eucm.ead.editor.view.generic.table; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import es.eucm.ead.editor.control.Command; import es.eucm.ead.editor.control.commands.ChangeFieldCommand; import es.eucm.ead.editor.control.commands.ListCommand; import es.eucm.ead.editor.model.nodes.DependencyNode; import es.eucm.ead.editor.view.generic.AbstractOption; import es.eucm.ead.editor.view.generic.accessors.Accessor; import es.eucm.ead.editor.view.generic.accessors.IntrospectingAccessor; import es.eucm.ead.editor.view.generic.table.TableSupport.DeleteButtonWidget; import es.eucm.ead.editor.view.generic.table.TableSupport.DeleteIt; import es.eucm.ead.editor.view.generic.table.TableSupport.MoveButtonWidget; import es.eucm.ead.editor.view.generic.table.TableSupport.MoveIt; import es.eucm.ead.editor.view.generic.table.TableSupport.Row; import org.jdesktop.swingx.JXTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import es.eucm.ead.model.elements.extra.EAdList; /** * An option that allows a list of elements to be manipulated. * * @author mfreire * @param <T> */ public class ListOption<T> extends AbstractOption<EAdList<T>> implements TableLikeControl<T, Integer> { static private Logger logger = LoggerFactory.getLogger(ListOption.class); private JPanel controlPanel; private JXTable tableControl; private JButton chooseMoreButton; private ListTableModel tableModel; private final Class<?> contentClass; public ListOption(String title, String toolTipText, Object object, String fieldName, Class<?> contentClass, DependencyNode... changed) { super(title, toolTipText, new IntrospectingAccessor<EAdList<T>>(object, fieldName), changed); this.contentClass = contentClass; } @SuppressWarnings("unchecked") public ColumnSpec<T, Integer>[] getExtraColumns() { return (ColumnSpec<T, Integer>[]) new ColumnSpec[] { new ColumnSpec<T, Integer>( "Value", contentClass, false, -1) }; } /** * Model used to represent the list. Looks directly at oldValue; which must * always be updated. */ private class ListTableModel extends TableSupport.AbstractRowTableModel<T, Integer> { @SuppressWarnings("unchecked") public ListTableModel() { super(ListOption.this); ColumnSpec<T, Integer> upDown = new ColumnSpec<T, Integer>("", MoveIt.class, true, 16); upDown.setEditor(new MoveButtonWidget(ListOption.this)); upDown.setRenderer(new MoveButtonWidget(ListOption.this)); ColumnSpec<T, Integer> delete = new ColumnSpec<T, Integer>("", DeleteIt.class, true, 20); delete.setEditor(new DeleteButtonWidget(ListOption.this)); delete.setRenderer(new DeleteButtonWidget(ListOption.this)); ColumnSpec<T, Integer>[] user = (ColumnSpec<T, Integer>[]) getExtraColumns(); cols = (ColumnSpec<T, Integer>[]) new ColumnSpec[user.length + 2]; cols[0] = upDown; cols[cols.length - 1] = delete; System.arraycopy(user, 0, cols, 1, user.length); reindex(); } @Override @SuppressWarnings("unchecked") public void reindex() { rows = new Row[oldValue.size()]; for (int i = 0; i < oldValue.size(); i++) { rows[i] = new Row<T, Integer>(oldValue.get(i), i); } } @Override @SuppressWarnings("unchecked") public void setValueAt(Object value, int rowIndex, int columnIndex) { Row<T, Integer> r = rows[rowIndex]; Accessor a = cols[columnIndex].getAccessor(r, columnIndex); if (a == null) { performCommand(new ChangeFieldCommand(value, a, changed)); } } } @Override protected JComponent createControl() { oldValue = accessor.read(); tableModel = new ListTableModel(); tableControl = new JXTable(tableModel); for (int i = 0; i < tableModel.cols.length; i++) { ColumnSpec<T, Integer> c = tableModel.cols[i]; if (c.getRenderer() != null) { tableControl.setDefaultRenderer(c.getClazz(), c.getRenderer()); } if (c.getEditor() != null) { tableControl.setDefaultEditor(c.getClazz(), c.getEditor()); } if (c.getWidth() != -1) { tableControl.getColumn(i).setMinWidth(c.getWidth()); tableControl.getColumn(i).setMaxWidth(c.getWidth()); } } tableControl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tableControl.setColumnControlVisible(false); tableControl.setSortable(false); tableControl.setAutoResizeMode(JXTable.AUTO_RESIZE_ALL_COLUMNS); tableControl.setRowHeight(32); tableControl.setColumnMargin(5); chooseMoreButton = new JButton("+"); chooseMoreButton.setToolTipText(Messages.options_table_add); chooseMoreButton.setPreferredSize(new Dimension(50, 16)); chooseMoreButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { T choice = chooseElementToAdd(); if (choice != null) { add(choice, oldValue.size() - 1); } } }); controlPanel = new JPanel(new BorderLayout()); JScrollPane tableScroll = new JScrollPane(tableControl); tableScroll.setMinimumSize(new Dimension(0, 120)); tableScroll.setPreferredSize(new Dimension(0, 120)); controlPanel.add(tableScroll, BorderLayout.CENTER); controlPanel.add(chooseMoreButton, BorderLayout.SOUTH); return controlPanel; } @Override public EAdList<T> getControlValue() { return accessor.read(); } @Override protected void setControlValue(EAdList<T> newValue) { tableModel.fireTableDataChanged(); } @Override public void remove(Integer index) { T o = oldValue.get(index); logger.info("Removing {} (at {})", new Object[] { o, index }); Command c = new ListCommand.RemoveFromList<T>(oldValue, o, changed); performCommand(c); } @Override public T chooseElementToAdd() { logger.info("User wants to CHOOSE something to ADD! Madness!!"); return null; } /** * Launches UI prompt to add a key to a list element */ @Override public Integer chooseKeyToAdd() { throw new UnsupportedOperationException(); } @Override public void add(T added, Integer index) { logger.info("Adding {}", oldValue); Command c = new ListCommand.AddToList<T>(oldValue, added, oldValue .size(), changed); performCommand(c); } public void performCommand(Command c) { manager.performCommand(c); } /** * Moves an object one position up. Triggered either externally or via * button-click. */ @Override public void moveUp(Integer index) { T o = oldValue.get(index); logger.info("MovingUp {} (at {})", new Object[] { o, index }); if (index == 0) { logger.warn("You should NOT allow people to try to move above 0"); return; } Command c = new ListCommand.ReorderInList<T>(oldValue, o, index, index - 1, changed); performCommand(c); } /** * Removes an object from the list. Triggered either externally or via * button-click. */ @Override public void moveDown(Integer index) { T o = oldValue.get(index); logger.info("MovingDown {} (at {})", new Object[] { o, index }); if (index == tableModel.getRowCount() - 1) { logger.warn("You should NOT allow people to try to move below end"); return; } Command c = new ListCommand.ReorderInList<T>(oldValue, o, index, index + 1, changed); performCommand(c); } /** * Returns the key for a given row */ @Override public Integer keyForRow(int row) { return row; } /** * Consider contents to have changed, even if the list-reference does not * change. * * @param oldValue * @param newValue * @return */ @Override protected boolean changeConsideredRelevant(EAdList<T> oldValue, EAdList<T> newValue) { return true; } }