/*
* EquipmentModel.java
* Copyright 2010 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 Jul 7, 2010, 3:18:39 PM
*/
package pcgen.gui2.tabs.equip;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
import pcgen.facade.core.CharacterFacade;
import pcgen.facade.core.EquipmentFacade;
import pcgen.facade.core.EquipmentSetFacade;
import pcgen.facade.core.EquipmentSetFacade.EquipNode;
import pcgen.facade.core.EquipmentSetFacade.EquipNode.NodeType;
import pcgen.facade.util.event.ListEvent;
import pcgen.facade.util.event.ListListener;
import pcgen.facade.util.event.ReferenceEvent;
import pcgen.facade.util.event.ReferenceListener;
import pcgen.facade.util.ListFacade;
import pcgen.gui2.UIPropertyContext;
import pcgen.gui2.tabs.models.CharacterTreeCellRenderer;
import pcgen.gui2.util.FontManipulation;
import pcgen.gui2.util.JTreeTable;
/**
* The parent model for the selected panel. Maps the various equipment sets for
* a character.
*
* @author Connor Petty <cpmeister@users.sourceforge.net>
*/
public class EquipmentModel implements ListListener<EquipmentSetFacade>, ReferenceListener<EquipmentSetFacade>,
TableModelListener
{
private static Font normFont;
private static Font headerFont;
private static Font biggerFont;
private static Font lessFont;
private final CharacterFacade character;
private final TreeRenderer treeRenderer;
private final Map<EquipmentSetFacade, EquipmentTreeTableModel> equipsetMap;
private final ListFacade<EquipmentSetFacade> equipsets;
private EquipmentTreeTableModel selectedModel;
private final JTreeTable treeTable;
public EquipmentModel(CharacterFacade character, JTreeTable table)
{
this.character = character;
this.treeTable = table;
treeRenderer = (TreeRenderer) treeTable.getTreeCellRenderer();
equipsetMap = new HashMap<>();
equipsets = character.getEquipmentSets();
for (EquipmentSetFacade equipset : equipsets)
{
equipsetMap.put(equipset, new EquipmentTreeTableModel(character, equipset));
}
equipsets.addListListener(this);
}
public static void initializeTreeTable(JTreeTable treeTable)
{
treeTable.getTree().setRowHeight(0);
treeTable.setFocusable(false);
treeTable.getTree().putClientProperty("JTree.lineStyle", "Horizontal");
normFont = treeTable.getFont();
headerFont = FontManipulation.title(normFont);
biggerFont = FontManipulation.title(FontManipulation.xxlarge(normFont));
lessFont = FontManipulation.less(normFont);
treeTable.setAutoCreateColumnsFromModel(false);
{
DefaultTableColumnModel model = new DefaultTableColumnModel();
CellRenderer renderer = new CellRenderer();
TableColumn column = new TableColumn(0);
column.setResizable(true);
model.addColumn(column);
model.addColumn(createFixedColumn(1, 75, renderer));
model.addColumn(createFixedColumn(2, 75, renderer));
model.addColumn(createFixedColumn(3, 50, renderer));
model.addColumn(createFixedColumn(4, 50, renderer));
treeTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
treeTable.setColumnModel(model);
treeTable.getTableHeader().setResizingAllowed(false);
}
treeTable.setTreeCellRenderer(new TreeRenderer());
}
private static TableColumn createFixedColumn(int index, int width, CellRenderer renderer)
{
TableColumn column = new TableColumn(index, width, renderer, null);
column.setMaxWidth(width);
column.setResizable(false);
return column;
}
@Override
public void tableChanged(TableModelEvent e)
{
realignRowHeights();
}
@Override
public void elementModified(ListEvent<EquipmentSetFacade> e)
{
}
private static class CellRenderer extends DefaultTableCellRenderer
{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
EquipNode node = (EquipNode) table.getValueAt(row, 0);
if (node != null && node.getParent() == null)
{
FontManipulation.title(this);
setFont(headerFont);
Color line = UIManager.getColor("Tree.line");
setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, line));
}
else
{
setFont(normFont);
}
return this;
}
@Override
protected void setValue(Object value)
{
super.setValue(value);
setToolTipText(getText());
}
}
public void install()
{
treeRenderer.setCharacter(character);
selectedModel = equipsetMap.get(character.getEquipmentSetRef().get());
treeTable.setTreeTableModel(selectedModel);
treeTable.getModel().addTableModelListener(this);
realignRowHeights();
character.getEquipmentSetRef().addReferenceListener(this);
}
public void uninstall()
{
if (treeTable != null)
{
treeTable.getModel().removeTableModelListener(this);
}
character.getEquipmentSetRef().removeReferenceListener(this);
treeRenderer.setCharacter(null);
}
private void realignRowHeights()
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JTree tree = treeTable.getTree();
for (int row = 0; row < tree.getRowCount(); row++)
{
Rectangle bounds = tree.getRowBounds(row);
if (bounds != null)
{
if (treeTable.getRowHeight(row) != bounds.height)
{
treeTable.setRowHeight(row, bounds.height);
}
}
}
}
});
}
@Override
public void elementAdded(ListEvent<EquipmentSetFacade> e)
{
equipsetMap.put(e.getElement(), new EquipmentTreeTableModel(character, e.getElement()));
}
@Override
public void elementRemoved(ListEvent<EquipmentSetFacade> e)
{
equipsetMap.remove(e.getElement());
}
@Override
public void elementsChanged(ListEvent<EquipmentSetFacade> e)
{
equipsetMap.clear();
for (EquipmentSetFacade equipset : equipsets)
{
equipsetMap.put(equipset, new EquipmentTreeTableModel(character, equipset));
}
}
@Override
public void referenceChanged(ReferenceEvent<EquipmentSetFacade> e)
{
treeTable.getModel().removeTableModelListener(this);
selectedModel = equipsetMap.get(e.getNewReference());
treeTable.setTreeTableModel(selectedModel);
treeTable.getModel().addTableModelListener(this);
realignRowHeights();
}
private static class TreeRenderer extends CharacterTreeCellRenderer
{
private Map<String, ImageIcon> iconCache = new HashMap<>();
@Override
public Component getTreeCellRendererComponent(final JTree tree,
Object value, boolean sel, boolean expanded, boolean leaf,
final int row, boolean focus)
{
String text = String.valueOf(value);
boolean isEquipNode = value instanceof EquipNode;
boolean isPhantomSlot = isEquipNode && ((EquipNode) value).getNodeType()
== NodeType.PHANTOM_SLOT;
if (isPhantomSlot)
{
text = "Empty slot";
}
super.getTreeCellRendererComponent(tree, text, sel, expanded, leaf, row, focus);
if (isEquipNode && ((EquipNode) value).getParent() == null)
{
setFont(biggerFont);
setIcon(null);
}
else if (isPhantomSlot)
{
setFont(lessFont);
setForeground(Color.GRAY);
setIcon(null);
}
else
{
setFont(normFont);
EquipmentFacade equip = null;
if (!selected)
{
setForeground(UIPropertyContext.getQualifiedColor());
}
if (isEquipNode && ((EquipNode) value).getNodeType() == NodeType.EQUIPMENT)
{
equip = ((EquipNode) value).getEquipment();
String path = equip.getIcon().getAbsolutePath();
ImageIcon icon = iconCache.get(path);
if (icon == null)
{
icon = new ImageIcon(path);
iconCache.put(path, icon);
}
setIcon(icon);
if (!character.isQualifiedFor(equip))
{
setForeground(UIPropertyContext.getNotQualifiedColor());
}
}
}
return this;
}
}
}