/* * AbilityTreeTableModel.java * Copyright 2011 Connor Petty <cpmeister@users.sourceforge.net> * * 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 Apr 11, 2011, 4:36:11 PM */ package pcgen.gui2.tabs.ability; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableCellRenderer; import javax.swing.tree.MutableTreeNode; import pcgen.facade.core.AbilityCategoryFacade; import pcgen.facade.core.AbilityFacade; import pcgen.facade.core.CharacterFacade; import pcgen.facade.util.event.ListEvent; import pcgen.facade.util.event.ListListener; import pcgen.facade.util.ListFacade; import pcgen.facade.util.SortedListFacade; import pcgen.gui2.tabs.Utilities; import pcgen.gui2.util.JTreeTable; import pcgen.gui2.util.table.Row; import pcgen.gui2.util.table.TableCellUtilities; import pcgen.gui2.util.treetable.AbstractTreeTableModel; import pcgen.gui2.util.treetable.DefaultSortableTreeTableNode; import pcgen.gui2.util.treetable.DefaultTreeTableNode; import pcgen.gui2.util.treetable.SortableTreeTableModel; import pcgen.gui2.util.treetable.TreeTableNode; import pcgen.system.LanguageBundle; import pcgen.util.Comparators; /** * The Class {@code AbilityTreeTableModel} is a model for the * selected abilities tree table. It lists the abilities held by the * character in a tree structure by category. * * <br> * * @author Connor Petty <cpmeister@users.sourceforge.net> */ public class AbilityTreeTableModel extends AbstractTreeTableModel implements SortableTreeTableModel { private final CharacterFacade character; //private final ListFacade<AbilityCategoryFacade> categories; public AbilityTreeTableModel(CharacterFacade character, ListFacade<AbilityCategoryFacade> categories) { this.character = character; //this.categories = categories; this.setRoot(new RootTreeTableNode(categories)); } /** * Initialise a tree table that will be backed by an AbilityTreeTableModel. * @param treeTable The tree table to be initialized. */ public static void initializeTreeTable(JTreeTable treeTable) { treeTable.getTree().putClientProperty("JTree.lineStyle", "Horizontal"); //$NON-NLS-1$ //$NON-NLS-2$ treeTable.setAutoCreateColumnsFromModel(false); DefaultTableColumnModel model = new DefaultTableColumnModel(); TableCellRenderer headerRenderer = treeTable.getTableHeader().getDefaultRenderer(); model.addColumn(Utilities.createTableColumn(0, "in_featSelectedAbilities", headerRenderer, true)); //$NON-NLS-1$ model.addColumn(Utilities.createTableColumn(1, "in_featChoices", //$NON-NLS-1$ headerRenderer, true)); treeTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); treeTable.setColumnModel(model); treeTable.setDefaultRenderer(String.class, new TableCellUtilities.AlignRenderer(SwingConstants.LEFT, true)); } @Override public Class<?> getColumnClass(int column) { if (column == 0) { return TreeTableNode.class; } return AbilityFacade.class; } @Override public String getColumnName(int column) { switch (column) { case 0: return LanguageBundle.getString("in_featSelectedAbilities"); //$NON-NLS-1$ case 1: return LanguageBundle.getString("in_featChoices"); //$NON-NLS-1$ default: return "Unknown column"; } } @Override public int getColumnCount() { return 2; } @Override public RootTreeTableNode getRoot() { return (RootTreeTableNode) super.getRoot(); } @Override public void sortModel(Comparator<Row> comparator) { getRoot().sortChildren(comparator); reload(); } private class RootTreeTableNode extends DefaultSortableTreeTableNode implements ListListener<AbilityCategoryFacade> { private ListFacade<AbilityCategoryFacade> cats; public RootTreeTableNode(ListFacade<AbilityCategoryFacade> cats) { super(Collections.singletonList(new Object())); this.cats = new SortedListFacade<>(Comparators.toStringIgnoreCaseComparator(), cats); addChildren(); cats.addListListener(this); } private void addChildren() { for (AbilityCategoryFacade category : cats) { add(new CategoryTreeTableNode(category)); } } @Override public void elementAdded(ListEvent<AbilityCategoryFacade> e) { insertNodeInto(new CategoryTreeTableNode(e.getElement()), this, e.getIndex()); } @Override public void elementRemoved(ListEvent<AbilityCategoryFacade> e) { removeNodeFromParent((MutableTreeNode) getChildAt(e.getIndex())); } @Override public void elementsChanged(ListEvent<AbilityCategoryFacade> e) { removeAllChildren(); addChildren(); AbilityTreeTableModel.this.nodeStructureChanged(this); } @Override public void elementModified(ListEvent<AbilityCategoryFacade> e) { } } private class CategoryTreeTableNode extends DefaultSortableTreeTableNode implements ListListener<AbilityFacade> { private final AbilityCategoryFacade category; private ListFacade<AbilityFacade> abilities; public CategoryTreeTableNode(AbilityCategoryFacade category) { this.category = category; setUserObject(category); setValues(Collections.singletonList(category)); this.abilities = new SortedListFacade<>(Comparators.toStringIgnoreCaseComparator(), character.getAbilities(category)); addChildren(); abilities.addListListener(this); } private void addChildren() { for (AbilityFacade ability : abilities) { DefaultTreeTableNode node = buildAbilityNode(ability); node.setUserObject(ability); add(node); } } private DefaultTreeTableNode buildAbilityNode(AbilityFacade ability) { List<Object> data = new ArrayList<>(2); data.add(ability); data.add(character.getInfoFactory().getChoices(ability)); DefaultTreeTableNode node = new DefaultSortableTreeTableNode(data); return node; } @Override public void elementAdded(ListEvent<AbilityFacade> e) { //Logging.errorPrint("Adding " + category + " - " + e.getElement()); DefaultTreeTableNode node = buildAbilityNode(e.getElement()); node.setUserObject(e.getElement()); insertNodeInto(node, this, e.getIndex()); } @Override public void elementRemoved(ListEvent<AbilityFacade> e) { //Logging.errorPrint("Removing " + category + " - " + e.getElement()); removeNodeFromParent((MutableTreeNode) getChildAt(e.getIndex())); } @Override public void elementsChanged(ListEvent<AbilityFacade> e) { //Logging.errorPrint("Changing " + category + " - " + e.getSource()); removeAllChildren(); addChildren(); AbilityTreeTableModel.this.nodeStructureChanged(this); } @Override public void elementModified(ListEvent<AbilityFacade> e) { //Logging.errorPrint("Modifying " + category + " - " + e.getElement()); MutableTreeNode oldNode = (MutableTreeNode) getChildAt(e.getIndex()); DefaultTreeTableNode node = buildAbilityNode(e.getElement()); node.setUserObject(e.getElement()); insertNodeInto(node, this, e.getIndex()); removeNodeFromParent(oldNode); } } }