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); } } } }