/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.bearsoft.gui.grid.rendering; import com.bearsoft.gui.grid.IconCache; import com.bearsoft.gui.grid.data.TableFront2TreedModel; import com.bearsoft.gui.grid.data.TableModelWrapper; import com.bearsoft.gui.grid.data.TreedModel; import java.awt.BorderLayout; import java.util.List; import javax.swing.Icon; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.table.TableModel; /** * Renderer, used as leading component for tree column rendering. * * @author Gala */ public class TreeColumnLeadingComponent<T> extends NonRepaintablePanel { protected static final int SPACE_UNITY_SIZE = 16; protected static Icon legsCollapsedIcon; protected static Icon legsExpandedIcon; protected TableModel model; protected TableFront2TreedModel<T> front; protected Integer operatingRow; protected PreferredBiasLabel centerLabel; protected NonRepaintableLabel rightLabel; // protected Icon folderIcon; protected Icon openFolderIcon; protected Icon leafIcon; protected boolean leaf; //frequent runtime protected Icon legsIcon; protected Icon nodeIcon; static { Object expandedIcon = UIManager.get("Tree.expandedIcon"); Object collapsedIcon = UIManager.get("Tree.collapsedIcon"); if (expandedIcon instanceof Icon) { legsExpandedIcon = (Icon) expandedIcon; } else { legsExpandedIcon = IconCache.getIcon("treeExpanded.png"); } if (collapsedIcon instanceof Icon) { legsCollapsedIcon = (Icon) collapsedIcon; } else { legsCollapsedIcon = IconCache.getIcon("treeCollapsed.png"); } } /** * Leading component constructor. * * @param aModel Model of the column's table. Typically it's table model * front to treed model. * @param aRepaintable A repaintable flag. It's considered, that repaintable * components are used in editors. So, if the flag is true, than component's * work will be optimized for cells editing, and for cells rendering * otherwise. */ public TreeColumnLeadingComponent(TableModel aModel, boolean aRepaintable, Icon aFolderIcon, Icon anOpenFolderIcon, Icon aLeafIcon) { super(aRepaintable); model = aModel; front = achieveTreeTableFront(model); centerLabel = new PreferredBiasLabel(aRepaintable); rightLabel = new NonRepaintableLabel(aRepaintable); //rightLabel.setText(" "); rightLabel.setOpaque(false); folderIcon = aFolderIcon; openFolderIcon = anOpenFolderIcon; leafIcon = aLeafIcon; centerLabel.setHorizontalAlignment(SwingConstants.RIGHT); centerLabel.setHorizontalTextPosition(SwingConstants.RIGHT); centerLabel.setOpaque(false); setOpaque(false); add(centerLabel, BorderLayout.CENTER); add(rightLabel, BorderLayout.EAST); } /** * Discardes all prepared information, related to row to be rendered or * edited. Typically this methos is called by editors, but not renderers. * * @see #prepareRow(int) */ public void unprepare() { operatingRow = null; } /** * Prepares a row to be rendered or edited. * * @param aRow A row number to be prepared. It is in model space. * @see #unprepare() */ public void prepareRow(int aRow) { if (operatingRow == null || operatingRow != aRow) { operatingRow = aRow; T elToRender = front.getElementAt(operatingRow); TreedModel<T> treedModel = front.unwrap(); T currElement = elToRender; int level = -1; while (currElement != null) { currElement = treedModel.getParentOf(currElement); level++; } boolean expanded = front.isExpanded(elToRender); legsIcon = legsCollapsedIcon; nodeIcon = folderIcon; if (expanded) { legsIcon = legsExpandedIcon; nodeIcon = openFolderIcon; } leaf = treedModel.isLeaf(elToRender); if (leaf) { nodeIcon = leafIcon; legsIcon = null; level++; } if (!leaf && expanded) {// lazy trees make us to do things like this List<T> children = treedModel.getChildrenOf(elToRender); if (children == null || children.isEmpty()) { nodeIcon = leafIcon; legsIcon = null; } } centerLabel.setBias(level * SPACE_UNITY_SIZE); centerLabel.setIcon(legsIcon); rightLabel.setIcon(nodeIcon); } } public boolean isLeaf() { return leaf; } public TableFront2TreedModel<T> getFront() { return front; } public static <T> TableFront2TreedModel<T> achieveTreeTableFront(TableModel aModel) { TableModel currentModel = aModel; while (!(currentModel instanceof TableFront2TreedModel<?>) && currentModel instanceof TableModelWrapper) { TableModelWrapper wrapper = (TableModelWrapper) currentModel; currentModel = wrapper.unwrap(); } if (currentModel instanceof TableFront2TreedModel<?>) { return (TableFront2TreedModel<T>) currentModel; } else { return null; } } public Icon getNodeIcon() { return nodeIcon; } public Icon getLegsIcon() { return legsIcon; } }