/* * KitPanel.java * Copyright James Dempsey, 2012 * * This library 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 2.1 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Created on 01/03/2012 8:01:51 AM * * $Id$ */ package pcgen.gui2.kits; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import pcgen.facade.core.CharacterFacade; import pcgen.facade.core.KitFacade; import pcgen.facade.util.event.ListEvent; import pcgen.facade.util.event.ListListener; import pcgen.facade.util.DefaultListFacade; import pcgen.facade.util.ListFacade; import pcgen.gui2.filter.Filter; import pcgen.gui2.filter.FilterBar; import pcgen.gui2.filter.FilterButton; import pcgen.gui2.filter.FilterUtilities; import pcgen.gui2.filter.FilteredListFacade; import pcgen.gui2.filter.FilteredTreeViewTable; import pcgen.gui2.filter.SearchFilterPanel; import pcgen.gui2.tabs.models.QualifiedTreeCellRenderer; import pcgen.gui2.tools.FlippingSplitPane; import pcgen.gui2.tools.Icons; import pcgen.gui2.tools.InfoPane; import pcgen.gui2.util.treeview.DataView; import pcgen.gui2.util.treeview.DataViewColumn; import pcgen.gui2.util.treeview.DefaultDataViewColumn; import pcgen.gui2.util.treeview.TreeView; import pcgen.gui2.util.treeview.TreeViewModel; import pcgen.gui2.util.treeview.TreeViewPath; import pcgen.system.LanguageBundle; /** * The Class {@code KitPanel} displays an available/selected table pair to * allow the allocation of kit to the currently selected character. * * <br> * * @author James Dempsey <jdempsey@users.sourceforge.net> */ @SuppressWarnings("serial") public class KitPanel extends FlippingSplitPane { private final FilteredTreeViewTable<Object, KitFacade> availableTable; private final FilteredTreeViewTable<Object, KitFacade> selectedTable; private final JButton addButton; private final InfoPane infoPane; private final CharacterFacade character; private QualifiedTreeCellRenderer renderer; private AddAction addAction; private final FilterButton<Object, KitFacade> qFilterButton; /** * Create a new instance of KitPanel for a character. * @param character The character being displayed. */ public KitPanel(CharacterFacade character) { super("kit"); this.character = character; this.availableTable = new FilteredTreeViewTable<>(); this.selectedTable = new FilteredTreeViewTable<>(); this.addButton = new JButton(); this.infoPane = new InfoPane(LanguageBundle.getString("in_kitInfo")); //$NON-NLS-1$ this.renderer = new QualifiedTreeCellRenderer(); this.addAction = new AddAction(character); this.qFilterButton = new FilterButton<>("KitQualified"); initComponents(); initDefaults(); } private void initComponents() { renderer.setCharacter(character); FlippingSplitPane topPane = new FlippingSplitPane("kitTop"); setTopComponent(topPane); setOrientation(VERTICAL_SPLIT); FilterBar<Object, KitFacade> bar = new FilterBar<>(); bar.addDisplayableFilter(new SearchFilterPanel()); qFilterButton.setText(LanguageBundle.getString("in_igQualFilter")); //$NON-NLS-1$ bar.addDisplayableFilter(qFilterButton); availableTable.setTreeViewModel(new KitTreeViewModel(character, true)); availableTable.setTreeCellRenderer(renderer); JPanel availPanel = FilterUtilities.configureFilteredTreeViewPane(availableTable, bar); Box box = Box.createHorizontalBox(); box.add(Box.createHorizontalGlue()); addButton.setHorizontalTextPosition(SwingConstants.LEADING); addButton.setAction(addAction); box.add(addButton); box.add(Box.createHorizontalStrut(5)); box.setBorder(new EmptyBorder(0, 0, 5, 0)); availPanel.add(box, BorderLayout.SOUTH); topPane.setLeftComponent(availPanel); JPanel selPanel = new JPanel(new BorderLayout()); FilterBar<Object, KitFacade> filterBar = new FilterBar<>(); filterBar.addDisplayableFilter(new SearchFilterPanel()); selectedTable.setDisplayableFilter(filterBar); selectedTable.setTreeViewModel(new KitTreeViewModel(character, false)); selectedTable.setTreeCellRenderer(renderer); selPanel.add(new JScrollPane(selectedTable), BorderLayout.CENTER); topPane.setRightComponent(selPanel); setBottomComponent(infoPane); setResizeWeight(0.75); } /** * */ private void initDefaults() { InfoHandler infoHandler = new InfoHandler(character); availableTable.getSelectionModel().addListSelectionListener(infoHandler); selectedTable.getSelectionModel().addListSelectionListener(infoHandler); KitFilterHandler kitFilterHandler = new KitFilterHandler(character); kitFilterHandler.install(); availableTable.addActionListener(addAction); } private class KitFilterHandler { private final Filter<Object, KitFacade> qFilter = new Filter<Object, KitFacade>() { @Override public boolean accept(Object context, KitFacade element) { return character.isQualifiedFor(element); } }; private final CharacterFacade character; public KitFilterHandler(CharacterFacade character) { this.character = character; } public void install() { qFilterButton.setFilter(qFilter); } } private class InfoHandler implements ListSelectionListener { private CharacterFacade character; public InfoHandler(CharacterFacade character) { this.character = character; } @Override public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { Object obj = null; if (e.getSource() == availableTable.getSelectionModel()) { int selectedRow = availableTable.getSelectedRow(); if (selectedRow != -1) { obj = availableTable.getModel().getValueAt(selectedRow, 0); } } else { int selectedRow = selectedTable.getSelectedRow(); if (selectedRow != -1) { obj = selectedTable.getModel().getValueAt(selectedRow, 0); } } if (obj instanceof KitFacade) { infoPane.setText(character.getInfoFactory().getHTMLInfo((KitFacade) obj)); } } } } private class AddAction extends AbstractAction { private CharacterFacade character; public AddAction(CharacterFacade character) { super(LanguageBundle.getString("in_kitApply")); //$NON-NLS-1$ this.character = character; putValue(SMALL_ICON, Icons.Forward16.getImageIcon()); } @Override public void actionPerformed(ActionEvent e) { List<Object> data = availableTable.getSelectedData(); for (Object kit : data) { if (kit instanceof KitFacade) { character.addKit((KitFacade) kit); return; } } } } private static class KitTreeViewModel implements TreeViewModel<KitFacade>, DataView<KitFacade>, Filter<CharacterFacade, KitFacade>, ListListener<KitFacade> { private static final DefaultListFacade<? extends TreeView<KitFacade>> treeViews = new DefaultListFacade<TreeView<KitFacade>>(Arrays.asList(KitTreeView.values())); private final List<DefaultDataViewColumn> columns; private final CharacterFacade character; private final boolean isAvailModel; private FilteredListFacade<CharacterFacade, KitFacade> kits; public KitTreeViewModel(CharacterFacade character, boolean isAvailModel) { this.character = character; this.isAvailModel = isAvailModel; if (isAvailModel) { kits = new FilteredListFacade<>(); kits.setContext(character); kits.setFilter(this); ListFacade<KitFacade> kitList = new DefaultListFacade<>(character.getAvailableKits()); kits.setDelegate(kitList); character.getKits().addListListener(this); columns = Arrays.asList(new DefaultDataViewColumn("in_descrip", String.class, false), //$NON-NLS-1$ new DefaultDataViewColumn("in_source", String.class, false)); //$NON-NLS-1$ } else { kits = null; columns = Arrays.asList(new DefaultDataViewColumn("in_descrip", String.class, false), //$NON-NLS-1$ new DefaultDataViewColumn("in_source", String.class, false)); //$NON-NLS-1$ } } @Override public ListFacade<? extends TreeView<KitFacade>> getTreeViews() { return treeViews; } @Override public int getDefaultTreeViewIndex() { return 0; } @Override public DataView<KitFacade> getDataView() { return this; } @Override public ListFacade<KitFacade> getDataModel() { if (isAvailModel) { return kits; } else { return character.getKits(); } } @Override public Object getData(KitFacade element, int column) { switch(column){ case 0: return character.getInfoFactory().getDescription(element); case 1: return element.getSource(); default: return null; } } @Override public void setData(Object value, KitFacade element, int column) { } @Override public List<? extends DataViewColumn> getDataColumns() { return columns; } @Override public void elementAdded(ListEvent<KitFacade> e) { kits.refilter(); } @Override public void elementRemoved(ListEvent<KitFacade> e) { kits.refilter(); } @Override public void elementsChanged(ListEvent<KitFacade> e) { kits.refilter(); } @Override public void elementModified(ListEvent<KitFacade> e) { kits.refilter(); } @Override public boolean accept(CharacterFacade context, KitFacade element) { return !element.isPermanent() || !context.getKits().containsElement(element); } @Override public String getPrefsKey() { return isAvailModel ? "KitTreeAvail" : "KitTreeSelected"; //$NON-NLS-1$//$NON-NLS-2$ } } private enum KitTreeView implements TreeView<KitFacade> { NAME(LanguageBundle.getString("in_nameLabel")), //$NON-NLS-1$ TYPE_NAME(LanguageBundle.getString("in_typeName")), //$NON-NLS-1$ SOURCE_NAME(LanguageBundle.getString("in_sourceName")); //$NON-NLS-1$ private final String name; private KitTreeView(String name) { this.name = name; } @Override public String getViewName() { return name; } @SuppressWarnings("unchecked") @Override public List<TreeViewPath<KitFacade>> getPaths(KitFacade pobj) { switch (this) { case NAME: return Collections.singletonList(new TreeViewPath<>(pobj)); case TYPE_NAME: TreeViewPath<KitFacade> path = createTreeViewPath(pobj, (Object[]) pobj .getDisplayType().split("\\.")); //$NON-NLS-1$ return Arrays.asList(path); case SOURCE_NAME: return Collections.singletonList(new TreeViewPath<>(pobj, pobj.getSource())); default: throw new InternalError(); } } /** * Create a TreeViewPath for the kit and paths. * @param pobj The skill * @param path The paths under which the kit should be shown. * @return The TreeViewPath. */ private static TreeViewPath<KitFacade> createTreeViewPath(KitFacade pobj, Object... path) { if (path.length == 0) { return new TreeViewPath<>(pobj); } return new TreeViewPath<>(pobj, path); } } }