package org.openswing.swing.tree.client;
import java.awt.event.*;
import java.awt.Dimension;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.Component;
import java.awt.Insets;
import java.lang.reflect.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import java.util.Vector;
import org.openswing.swing.util.client.ClientUtils;
import org.openswing.swing.util.client.ClientSettings;
import javax.swing.tree.TreeNode;
import org.openswing.swing.message.receive.java.ValueObject;
import org.openswing.swing.logger.client.Logger;
import java.awt.BorderLayout;
import javax.swing.tree.TreeCellEditor;
import java.util.EventObject;
import javax.swing.event.CellEditorListener;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import java.util.ArrayList;
import java.awt.FontMetrics;
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Tree node renderer.</p>
* <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
*
* <p> This file is part of OpenSwing Framework.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the (LGPL) Lesser General Public
* License as published by the Free Software Foundation;
*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
*
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be contacted at:
* maurocarniel@tin.it</p>
*
* @author Mauro Carniel
* @version 1.0
*/
public class TreeNodeRenderer extends DefaultTreeCellRenderer {
/** default folder icon */
private ImageIcon folderIcon = null;
/** default leaf icon */
private ImageIcon leafIcon = null;
/** tree panel that uses this renderer */
private TreePanel treePanel;
/** attribute name that contains the icon image name; default value: null; if defined, this attribute overrides "folderIcon"/"leafIcon" values */
private String iconAttributeName;
/** attribute name that contains the tool tip text for the node; default value: null */
private String tooltipAttributeName;
/** check-box showed when treePanel.isShowCheckBoxes is true */
private CheckBoxLabel checkBox = new CheckBoxLabel();
/** panel that contains check-box, image and description */
private JPanel panel = new JPanel();
/**
* Costructor.
* @param tree node container
*/
public TreeNodeRenderer(TreePanel treePanel,String folderIconName,String leavesImageName,String iconAttributeName,String tooltipAttributeName) {
try {
this.treePanel = treePanel;
this.iconAttributeName = iconAttributeName;
this.tooltipAttributeName = tooltipAttributeName;
folderIcon = new ImageIcon(ClientUtils.getImage(folderIconName));
leafIcon = new ImageIcon(ClientUtils.getImage(leavesImageName));
panel.setOpaque(false);
this.setOpaque(false);
checkBox.setOpaque(false);
panel.setLayout(new BorderLayout(0, 0));
panel.add(this, BorderLayout.CENTER);
if (treePanel.isShowCheckBoxes()) {
checkBox.setSize(14,14);
checkBox.setPreferredSize(new Dimension(14,14));
panel.add(checkBox, BorderLayout.BEFORE_LINE_BEGINS);
KeyListener kl= null;
ArrayList toRemove = new ArrayList();
for(int i=0;i<treePanel.getTree().getKeyListeners().length;i++) {
kl = treePanel.getTree().getKeyListeners()[i];
if (kl instanceof TreeNodeRendererListener)
toRemove.add(kl);
}
for(int i=0;i<toRemove.size();i++)
treePanel.getTree().removeKeyListener((KeyListener)toRemove.get(i));
MouseListener ml= null;
toRemove.clear();
for(int i=0;i<treePanel.getTree().getMouseListeners().length;i++) {
ml = treePanel.getTree().getMouseListeners()[i];
if (ml instanceof TreeNodeRendererListener)
toRemove.add(ml);
}
for(int i=0;i<toRemove.size();i++)
treePanel.getTree().removeMouseListener((MouseListener)toRemove.get(i));
TreeNodeRendererListener l = new TreeNodeRendererListener(treePanel);
treePanel.getTree().addKeyListener(l);
treePanel.getTree().addMouseListener(l);
}
this.setBackgroundNonSelectionColor(new java.awt.Color(0,0,0,0));
} catch (Exception ex) {
ex.printStackTrace();
}
}
private boolean isGrayCheckBox(TreeNode node) {
boolean gray = false;
if (treePanel.getCheckedNodes().contains(node))
for(int i=0;i<node.getChildCount();i++) {
if (!treePanel.getCheckedNodes().contains(node.getChildAt(i)) && treePanel.isShowCheckBoxes() ||
!treePanel.getCheckedNodes().contains(node.getChildAt(i)) && !node.getChildAt(i).isLeaf() && !treePanel.isShowCheckBoxes())
return true;
if (!node.getChildAt(i).isLeaf() || treePanel.isShowCheckBoxes())
gray = isGrayCheckBox(node.getChildAt(i));
if (gray)
return true;
}
return gray;
}
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
try {
super.getTreeCellRendererComponent(tree, value, sel,expanded, leaf, row,hasFocus);
checkBox.setEnabled(treePanel.isEnabled());
if (iconAttributeName==null) {
if (leaf)
setIcon(leafIcon);
else
setIcon(folderIcon);
}
} catch (Exception ex) {
ex.printStackTrace();
}
JLabel l = (JLabel)this;
if (value!=null && value.toString()!=null) {
FontMetrics fm = l.getFontMetrics(l.getFont());
int w = 0;
try {
w = fm.stringWidth(value.toString());
}
catch (Exception ex2) {
}
setBounds(0,0,w,l.getHeight());
}
DefaultMutableTreeNode node = null;
ValueObject vo = null;
try {
node = (DefaultMutableTreeNode) value;
if (treePanel.isShowCheckBoxes()) {
checkBox.setSelected(treePanel.getCheckedNodes().contains(node));
if (leaf && !treePanel.isShowCheckBoxesOnLeaves())
checkBox.setVisible(false);
else {
checkBox.setVisible(true);
checkBox.setGray( isGrayCheckBox(node) );
}
}
}
catch (ClassCastException ex1) {
Logger.error(this.getClass().getName(),"getTreeCellRendererComponent","Expected a node of type DefaultMutableTreeNode or some subclass",null);
}
try {
vo = (ValueObject) node.getUserObject();
}
catch (ClassCastException ex1) {
Logger.error(this.getClass().getName(),"getTreeCellRendererComponent","ValueObject expected inside the node of type DefaultMutableTreeNode",null);
}
try {
if (vo!=null) {
String attributeName = treePanel.getTreeDataLocator().getNodeNameAttribute();
if (attributeName!=null) {
Method getter = vo.getClass().getMethod("get"+attributeName.substring(0,1).toUpperCase()+attributeName.substring(1),new Class[0]);
value = getter.invoke(vo,new Object[0]);
if (value!=null) {
l.setText(value.toString());
}
else
l.setText("");
}
if (iconAttributeName!=null) {
Method getter = vo.getClass().getMethod("get"+iconAttributeName.substring(0,1).toUpperCase()+iconAttributeName.substring(1),new Class[0]);
value = getter.invoke(vo,new Object[0]);
if (value!=null) {
if (value instanceof byte[])
setIcon(new ImageIcon((byte[])value));
else if (value instanceof String)
setIcon(new ImageIcon(ClientUtils.getImage(value.toString())));
}
else if (leaf)
setIcon(leafIcon);
else
setIcon(folderIcon);
}
if (tooltipAttributeName!=null) {
Method getter = vo.getClass().getMethod("get"+tooltipAttributeName.substring(0,1).toUpperCase()+tooltipAttributeName.substring(1),new Class[0]);
value = getter.invoke(vo,new Object[0]);
if (value!=null && value instanceof String) {
l.setToolTipText(value.toString());
panel.setToolTipText(value.toString());
}
else if (value==null) {
l.setToolTipText("");
panel.setToolTipText("");
}
}
}
}
catch (Throwable ex1) {
Logger.error(this.getClass().getName(),"getTreeCellRendererComponent","ValueObject expected inside the node of type DefaultMutableTreeNode",ex1);
}
return panel;
}
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Inner class used to render the check-box.</p>
* <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
* <p> </p>
* @author Mauro Carniel
* @version 1.0
*/
class CheckBoxLabel extends JLabel {
private boolean sel;
private boolean gray;
public void setSelected(boolean sel) {
this.sel = sel;
repaint();
}
public void setGray(boolean gray) {
this.gray = gray;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.translate((int)this.getWidth()/2-6,this.getHeight()/2-5);
BasicGraphicsUtils.drawLoweredBezel(g,0,0,12,12,Color.darkGray,Color.black,Color.white,Color.gray);
if (gray) {
g.setColor(Color.lightGray);
g.fillRect(1,1,10,10);
}
if (sel) {
g.setColor(Color.black);
g.drawLine(3,5,5,7);
g.drawLine(3,6,5,8);
g.drawLine(3,7,5,9);
g.drawLine(6,6,9,3);
g.drawLine(6,7,9,4);
g.drawLine(6,8,9,5);
}
}
}
}