Source for javax.swing.plaf.metal.MetalTreeUI

   1: /* MetalTreeUI.java
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.plaf.metal;
  40: 
  41: import java.awt.Graphics;
  42: import java.awt.Insets;
  43: import java.awt.Rectangle;
  44: import java.awt.event.ComponentListener;
  45: import java.awt.event.FocusListener;
  46: import java.awt.event.KeyListener;
  47: import java.awt.event.MouseListener;
  48: import java.beans.PropertyChangeListener;
  49: import java.util.Hashtable;
  50: 
  51: import javax.swing.JComponent;
  52: import javax.swing.JTree;
  53: import javax.swing.UIDefaults;
  54: import javax.swing.UIManager;
  55: import javax.swing.tree.TreeCellEditor;
  56: import javax.swing.tree.TreeModel;
  57: import javax.swing.tree.TreePath;
  58: import javax.swing.event.CellEditorListener;
  59: import javax.swing.event.TreeExpansionListener;
  60: import javax.swing.event.TreeModelListener;
  61: import javax.swing.event.TreeSelectionListener;
  62: import javax.swing.plaf.ComponentUI;
  63: import javax.swing.plaf.basic.BasicTreeUI;
  64: 
  65: /**
  66:  * A UI delegate for the {@link JTree} component.
  67:  */
  68: public class MetalTreeUI extends BasicTreeUI
  69: {
  70: 
  71:   /** Listeners */
  72:   private PropertyChangeListener propertyChangeListener;
  73:   private FocusListener focusListener;
  74:   private TreeSelectionListener treeSelectionListener;
  75:   private MouseListener mouseListener;
  76:   private KeyListener keyListener;
  77:   private PropertyChangeListener selectionModelPropertyChangeListener;
  78:   private ComponentListener componentListener;
  79:   private CellEditorListener cellEditorListener;
  80:   private TreeExpansionListener treeExpansionListener;
  81:   private TreeModelListener treeModelListener;
  82:     
  83:   /**
  84:    * Constructs a new instance of <code>MetalTreeUI</code>.
  85:    */
  86:   public MetalTreeUI()
  87:   {
  88:     super();
  89:   }
  90: 
  91:   /**
  92:    * Returns a new instance of <code>MetalTreeUI</code>.
  93:    *
  94:    * @param component the component for which we return an UI instance
  95:    *
  96:    * @return A new instance of <code>MetalTreeUI</code>.
  97:    */
  98:   public static ComponentUI createUI(JComponent component)
  99:   {
 100:     return new MetalTreeUI();
 101:   }
 102:   
 103:   /**
 104:    * The horizontal element of legs between nodes starts at the right of the
 105:    * left-hand side of the child node by default. This method makes the
 106:    * leg end before that.
 107:    */
 108:   protected int getHorizontalLegBuffer()
 109:   {
 110:     return super.getHorizontalLegBuffer();
 111:   }
 112: 
 113:   /**
 114:    * Configures the specified component appropriate for the look and feel.
 115:    * This method is invoked when the ComponentUI instance is being installed 
 116:    * as the UI delegate on the specified component. This method should completely 
 117:    * configure the component for the look and feel, including the following:
 118:    * 1. Install any default property values for color, fonts, borders, icons, 
 119:    *    opacity, etc. on the component. Whenever possible, property values
 120:    *    initialized by the client program should not be overridden.
 121:    * 2. Install a LayoutManager on the component if necessary.
 122:    * 3. Create/add any required sub-components to the component.
 123:    * 4. Create/install event listeners on the component.
 124:    * 5. Create/install a PropertyChangeListener on the component in order 
 125:    *    to detect and respond to component property changes appropriately.
 126:    * 6. Install keyboard UI (mnemonics, traversal, etc.) on the component.
 127:    * 7. Initialize any appropriate instance data. 
 128:    */
 129:   public void installUI(JComponent c)
 130:   {
 131:     tree = (JTree) c;
 132:     configureLayoutCache();
 133:     
 134:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 135:     tree.setFont(defaults.getFont("Tree.font"));
 136:     tree.setForeground(defaults.getColor("Tree.foreground"));
 137:     tree.setBackground(defaults.getColor("Tree.background"));
 138:     tree.setOpaque(true);
 139:     tree.setScrollsOnExpand(defaults.getBoolean("Tree.scrollsOnExpand"));
 140:     rightChildIndent = defaults.getInt("Tree.rightChildIndent");
 141:     leftChildIndent = defaults.getInt("Tree.leftChildIndent");
 142:     setRowHeight(defaults.getInt("Tree.rowHeight"));
 143:     tree.setRowHeight(defaults.getInt("Tree.rowHeight"));
 144:     tree.requestFocusInWindow(false);
 145:     
 146:     setExpandedIcon(defaults.getIcon("Tree.expandedIcon"));
 147:     setCollapsedIcon(defaults.getIcon("Tree.collapsedIcon"));
 148:     
 149:     currentCellRenderer = createDefaultCellRenderer();
 150:     rendererPane = createCellRendererPane();
 151:     createdRenderer = true;
 152:     setCellEditor(createDefaultCellEditor());
 153:     createdCellEditor = true;
 154:     TreeModel mod = tree.getModel();
 155:     setModel(mod);
 156: 
 157:     treeSelectionModel = tree.getSelectionModel();
 158:     drawingCache = new Hashtable();
 159:     nodeDimensions = createNodeDimensions();
 160:     
 161:     propertyChangeListener = createPropertyChangeListener();
 162:     focusListener = createFocusListener();
 163:     treeSelectionListener = createTreeSelectionListener();
 164:     mouseListener = createMouseListener();
 165:     keyListener = createKeyListener();
 166:     selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
 167:     componentListener = createComponentListener();
 168:     cellEditorListener = createCellEditorListener();
 169:     treeExpansionListener = createTreeExpansionListener();
 170:     treeModelListener = createTreeModelListener();
 171: 
 172:     editingRow = -1;
 173:     lastSelectedRow = -1;
 174:     
 175:     installKeyboardActions();
 176:     
 177:     tree.addPropertyChangeListener(propertyChangeListener);
 178:     tree.addFocusListener(focusListener);
 179:     tree.addTreeSelectionListener(treeSelectionListener);
 180:     tree.addMouseListener(mouseListener);
 181:     tree.addKeyListener(keyListener);
 182:     tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
 183:     tree.addComponentListener(componentListener);
 184:     tree.addTreeExpansionListener(treeExpansionListener);
 185:     if (treeModel != null)
 186:       treeModel.addTreeModelListener(treeModelListener);
 187:     
 188:     if (mod != null)
 189:       {
 190:         TreePath path = new TreePath(mod.getRoot());
 191:         if (!tree.isExpanded(path))
 192:           toggleExpandState(path);
 193:       }
 194:     
 195:     completeUIInstall();
 196:   }
 197:   
 198:   /**
 199:    * Reverses configuration which was done on the specified component during 
 200:    * installUI. This method is invoked when this UIComponent instance is being 
 201:    * removed as the UI delegate for the specified component. This method should 
 202:    * undo the configuration performed in installUI, being careful to leave the 
 203:    * JComponent instance in a clean state (no extraneous listeners, 
 204:    * look-and-feel-specific property objects, etc.). This should include 
 205:    * the following:
 206:    * 1. Remove any UI-set borders from the component.
 207:    * 2. Remove any UI-set layout managers on the component.
 208:    * 3. Remove any UI-added sub-components from the component.
 209:    * 4. Remove any UI-added event/property listeners from the component.
 210:    * 5. Remove any UI-installed keyboard UI from the component.
 211:    * 6. Nullify any allocated instance data objects to allow for GC. 
 212:    */
 213:   public void uninstallUI(JComponent c)
 214:   {
 215:     tree.setFont(null);
 216:     tree.setForeground(null);
 217:     tree.setBackground(null);
 218:     
 219:     uninstallKeyboardActions();
 220:     
 221:     tree.removePropertyChangeListener(propertyChangeListener);
 222:     tree.removeFocusListener(focusListener);
 223:     tree.removeTreeSelectionListener(treeSelectionListener);
 224:     tree.removeMouseListener(mouseListener);
 225:     tree.removeKeyListener(keyListener);
 226:     tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
 227:     tree.removeComponentListener(componentListener);
 228:     tree.removeTreeExpansionListener(treeExpansionListener);
 229: 
 230:     TreeCellEditor tce = tree.getCellEditor();
 231:     if (tce != null)
 232:       tce.removeCellEditorListener(cellEditorListener);
 233:     TreeModel tm = tree.getModel();
 234:     if (tm != null)
 235:       tm.removeTreeModelListener(treeModelListener);
 236:     
 237:     tree = null;
 238:     uninstallComponents();
 239:     completeUIUninstall();
 240:   }
 241:   
 242:   /**
 243:    * This function converts between the string passed into the client
 244:    * property and the internal representation (currently an int).
 245:    * 
 246:    * @param lineStyleFlag - String representation
 247:    */     
 248:   protected void decodeLineStyle(Object lineStyleFlag)
 249:   {
 250:     // FIXME: not implemented
 251:   }
 252: 
 253:   /**
 254:    * Checks if the location is in expand control.
 255:    * 
 256:    * @param row - current row
 257:    * @param rowLevel - current level
 258:    * @param mouseX - current x location of the mouse click
 259:    * @param mouseY - current y location of the mouse click
 260:    */
 261:   protected boolean isLocationInExpandControl(int row, int rowLevel,
 262:                                           int mouseX, int mouseY)
 263:   {
 264:     return super.isLocationInExpandControl(tree.getPathForRow(row), 
 265:                                            mouseX, mouseY);
 266:   }
 267:   
 268:   /**
 269:    * Paints the specified component appropriate for the look and feel. 
 270:    * This method is invoked from the ComponentUI.update method when the 
 271:    * specified component is being painted. Subclasses should override this 
 272:    * method and use the specified Graphics object to render the content of 
 273:    * the component.
 274:    * 
 275:    * @param g - the current graphics configuration.
 276:    * @param c - the current component to draw
 277:    */
 278:   public void paint(Graphics g, JComponent c)
 279:   {
 280:     // Calls BasicTreeUI's paint since it takes care of painting all
 281:     // types of icons. 
 282:     super.paint(g, c);
 283:   }
 284:   
 285:   /**
 286:    * Paints the horizontal separators.
 287:    * 
 288:    * @param g - the current graphics configuration.
 289:    * @param c - the current component to draw
 290:    */
 291:   protected void paintHorizontalSeparators(Graphics g, JComponent c)
 292:   {
 293:     // FIXME: not implemented
 294:   }
 295: 
 296:   
 297:   /**
 298:    * Paints the vertical part of the leg. The receiver should NOT modify 
 299:    * clipBounds, insets.
 300:    * 
 301:    * @param g - the current graphics configuration.
 302:    * @param clipBounds -
 303:    * @param insets - 
 304:    * @param path - the current path
 305:    */
 306:   protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
 307:                                     Insets insets, TreePath path)
 308:   {
 309:     super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
 310:   }
 311: 
 312:   /**
 313:    * Paints the horizontal part of the leg. The receiver should NOT \
 314:    * modify clipBounds, or insets.
 315:    * NOTE: parentRow can be -1 if the root is not visible.
 316:    */
 317:   protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
 318:                                         Insets insets, Rectangle bounds,
 319:                                         TreePath path, int row,
 320:                                         boolean isExpanded, boolean hasBeenExpanded,
 321:                                         boolean isLeaf)
 322:   {
 323:     super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, 
 324:                                    isExpanded, hasBeenExpanded, isLeaf);
 325:   }
 326: }