238 lines · 8.1 KB · Java
RawDownload
/* * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.metal; import javax.swing.*;import javax.swing.event.*;import java.awt.*;import java.awt.event.*;import java.beans.*;import java.io.*;import java.util.*;import javax.swing.plaf.*;import javax.swing.tree.*; import javax.swing.plaf.basic.*; /** * The metal look and feel implementation of <code>TreeUI</code>. * <p> * <code>MetalTreeUI</code> allows for configuring how to * visually render the spacing and delineation between nodes. The following * hints are supported: * * <table summary="Descriptions of supported hints: Angled, Horizontal, and None"> *  <tr> *    <th><p align="left">Angled</p></th> *    <td>A line is drawn connecting the child to the parent. For handling *          of the root node refer to *          {@link javax.swing.JTree#setRootVisible} and *          {@link javax.swing.JTree#setShowsRootHandles}. *    </td> *  </tr> *  <tr> *     <th><p align="left">Horizontal</p></th> *     <td>A horizontal line is drawn dividing the children of the root node.</td> *  </tr> *  <tr> *      <th><p align="left">None</p></th> *      <td>Do not draw any visual indication between nodes.</td> *  </tr> * </table> * * <p> * As it is typically impratical to obtain the <code>TreeUI</code> from * the <code>JTree</code> and cast to an instance of <code>MetalTreeUI</code> * you enable this property via the client property * <code>JTree.lineStyle</code>. For example, to switch to * <code>Horizontal</code> style you would do: * <code>tree.putClientProperty("JTree.lineStyle", "Horizontal");</code> * <p> * The default is <code>Angled</code>. * * @author Tom Santos * @author Steve Wilson (value add stuff) */public class MetalTreeUI extends BasicTreeUI {     private static Color lineColor;     private static final String LINE_STYLE = "JTree.lineStyle";     private static final String LEG_LINE_STYLE_STRING = "Angled";    private static final String HORIZ_STYLE_STRING = "Horizontal";    private static final String NO_STYLE_STRING = "None";     private static final int LEG_LINE_STYLE = 2;    private static final int HORIZ_LINE_STYLE = 1;    private static final int NO_LINE_STYLE = 0;     private int lineStyle = LEG_LINE_STYLE;    private PropertyChangeListener lineStyleListener = new LineListener();     // Boilerplate    public static ComponentUI createUI(JComponent x) {        return new MetalTreeUI();    }     public MetalTreeUI()    {        super();    }     protected int getHorizontalLegBuffer()      {          return 3;      }     public void installUI( JComponent c ) {        super.installUI( c );        lineColor = UIManager.getColor( "Tree.line" );         Object lineStyleFlag = c.getClientProperty( LINE_STYLE );        decodeLineStyle(lineStyleFlag);        c.addPropertyChangeListener(lineStyleListener);     }     public void uninstallUI( JComponent c) {         c.removePropertyChangeListener(lineStyleListener);         super.uninstallUI(c);    }     /** this function converts between the string passed into the client property      * and the internal representation (currently and int)      *      */    protected void decodeLineStyle(Object lineStyleFlag) {      if ( lineStyleFlag == null ||                    lineStyleFlag.equals(LEG_LINE_STYLE_STRING)){        lineStyle = LEG_LINE_STYLE; // default case      } else {          if ( lineStyleFlag.equals(NO_STYLE_STRING) ) {              lineStyle = NO_LINE_STYLE;          } else if ( lineStyleFlag.equals(HORIZ_STYLE_STRING) ) {              lineStyle = HORIZ_LINE_STYLE;          }      }     }     protected boolean isLocationInExpandControl(int row, int rowLevel,                                                int mouseX, int mouseY) {        if(tree != null && !isLeaf(row)) {            int                     boxWidth;             if(getExpandedIcon() != null)                boxWidth = getExpandedIcon().getIconWidth() + 6;            else                boxWidth = 8;             Insets i = tree.getInsets();            int    boxLeftX = (i != null) ? i.left : 0;              boxLeftX += (((rowLevel + depthOffset - 1) * totalChildIndent) +                        getLeftChildIndent()) - boxWidth/2;             int boxRightX = boxLeftX + boxWidth;             return mouseX >= boxLeftX && mouseX <= boxRightX;        }        return false;    }     public void paint(Graphics g, JComponent c) {        super.paint( g, c );          // Paint the lines        if (lineStyle == HORIZ_LINE_STYLE && !largeModel) {            paintHorizontalSeparators(g,c);        }    }     protected void paintHorizontalSeparators(Graphics g, JComponent c) {        g.setColor( lineColor );         Rectangle clipBounds = g.getClipBounds();         int beginRow = getRowForPath(tree, getClosestPathForLocation                                     (tree, 0, clipBounds.y));        int endRow = getRowForPath(tree, getClosestPathForLocation                             (tree, 0, clipBounds.y + clipBounds.height - 1));         if ( beginRow <= -1 || endRow <= -1 ) {            return;        }         for ( int i = beginRow; i <= endRow; ++i ) {            TreePath        path = getPathForRow(tree, i);             if(path != null && path.getPathCount() == 2) {                Rectangle       rowBounds = getPathBounds(tree,getPathForRow                                                          (tree, i));                 // Draw a line at the top                if(rowBounds != null)                    g.drawLine(clipBounds.x, rowBounds.y,                               clipBounds.x + clipBounds.width, rowBounds.y);            }        }     }     protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,                                          Insets insets, TreePath path) {        if (lineStyle == LEG_LINE_STYLE) {            super.paintVerticalPartOfLeg(g, clipBounds, insets, path);        }    }     protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,                                            Insets insets, Rectangle bounds,                                            TreePath path, int row,                                            boolean isExpanded,                                            boolean hasBeenExpanded, boolean                                            isLeaf) {        if (lineStyle == LEG_LINE_STYLE) {            super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds,                                           path, row, isExpanded,                                           hasBeenExpanded, isLeaf);        }    }     /** This class listens for changes in line style */    class LineListener implements PropertyChangeListener {        public void propertyChange(PropertyChangeEvent e) {            String name = e.getPropertyName();            if ( name.equals( LINE_STYLE ) ) {                decodeLineStyle(e.getNewValue());            }        }    } // end class PaletteListener }