001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Sergey Burlak
019: * @version $Revision$
020: */package javax.swing.plaf.metal;
021:
022: import java.awt.Color;
023: import java.awt.Graphics;
024: import java.awt.Insets;
025: import java.awt.Rectangle;
026: import java.beans.PropertyChangeEvent;
027: import java.beans.PropertyChangeListener;
028: import java.util.Hashtable;
029:
030: import javax.swing.JComponent;
031: import javax.swing.JTree;
032: import javax.swing.UIManager;
033: import javax.swing.plaf.ComponentUI;
034: import javax.swing.plaf.basic.BasicTreeUI;
035: import javax.swing.tree.AbstractLayoutCache;
036: import javax.swing.tree.TreePath;
037:
038: import org.apache.harmony.x.swing.TreeCommons;
039:
040: public class MetalTreeUI extends BasicTreeUI {
041: private static final String LINE_STYLE_PROPERTY = "JTree.lineStyle";
042: private static final int ANGLED = 1;
043: private static final int HORIZONTAL = 2;
044: private static final int NONE = 3;
045: private static int lineStyle = ANGLED;
046:
047: private PropertyChangeListener clientPropertyListener;
048: private Color lineColor;
049:
050: private TreeCommons.PaintTreeContext paintContext = new TreeCommons.PaintTreeContext() {
051: public JTree getTree() {
052: return tree;
053: }
054:
055: public Hashtable getDrawingCache() {
056: return drawingCache;
057: }
058:
059: public AbstractLayoutCache getLayoutCache() {
060: return treeState;
061: }
062:
063: public boolean paintHandles() {
064: return lineStyle == ANGLED;
065: }
066:
067: public boolean paintHorizontalSeparators() {
068: return lineStyle == HORIZONTAL;
069: }
070:
071: public boolean isEditing(final TreePath path) {
072: return MetalTreeUI.this .isEditing(tree)
073: && editingPath.equals(path);
074: }
075:
076: public void paintVerticalPartOfLeg(final Graphics g,
077: final Rectangle clipBounds, final Insets insets,
078: final TreePath path) {
079: MetalTreeUI.this .paintVerticalPartOfLeg(g, clipBounds,
080: insets, path);
081: }
082:
083: public void paintHorizontalPartOfLeg(final Graphics g,
084: final Rectangle clipBounds, final Insets insets,
085: final Rectangle bounds, final TreePath path,
086: final int row, final boolean isExpanded,
087: final boolean hasBeenExpanded, final boolean isLeaf) {
088: MetalTreeUI.this .paintHorizontalPartOfLeg(g, clipBounds,
089: insets, bounds, path, row, isExpanded,
090: hasBeenExpanded, isLeaf);
091: }
092:
093: public void paintExpandControl(final Graphics g,
094: final Rectangle clipBounds, final Insets insets,
095: final Rectangle bounds, final TreePath path,
096: final int row, final boolean isExpanded,
097: final boolean hasBeenExpanded, final boolean isLeaf) {
098: MetalTreeUI.this .paintExpandControl(g, clipBounds, insets,
099: bounds, path, row, isExpanded, hasBeenExpanded,
100: isLeaf);
101: }
102:
103: public void paintRow(final Graphics g,
104: final Rectangle clipBounds, final Insets insets,
105: final Rectangle bounds, final TreePath path,
106: final int row, final boolean isExpanded,
107: final boolean hasBeenExpanded, final boolean isLeaf) {
108: MetalTreeUI.this .paintRow(g, clipBounds, insets, bounds,
109: path, row, isExpanded, hasBeenExpanded, isLeaf);
110: }
111:
112: public void paintHorizontalSeparators(final Graphics g,
113: final JComponent tree) {
114: MetalTreeUI.this .paintHorizontalSeparators(g, tree);
115: }
116: };
117:
118: public static ComponentUI createUI(final JComponent c) {
119: return new MetalTreeUI();
120: }
121:
122: public void installUI(final JComponent c) {
123: super .installUI(c);
124:
125: lineColor = UIManager.getColor("Tree.line");
126:
127: clientPropertyListener = createClientPropertyChangeHandler();
128: tree.addPropertyChangeListener(clientPropertyListener);
129: }
130:
131: public void uninstallUI(final JComponent c) {
132: super .uninstallUI(c);
133: tree.removePropertyChangeListener(clientPropertyListener);
134: clientPropertyListener = null;
135: }
136:
137: protected int getHorizontalLegBuffer() {
138: return 4;
139: }
140:
141: protected void decodeLineStyle(final Object lineStyleFlag) {
142: if (lineStyleFlag == null) {
143: return;
144: }
145:
146: String lineStyleString = lineStyleFlag.toString();
147: if ("Angled".equals(lineStyleString)) {
148: lineStyle = ANGLED;
149: }
150: if ("Horizontal".equals(lineStyleString)) {
151: lineStyle = HORIZONTAL;
152: }
153: if ("None".equals(lineStyleString)) {
154: lineStyle = NONE;
155: }
156: }
157:
158: protected boolean isLocationInExpandControl(final int row,
159: final int rowLevel, final int mouseX, final int mouseY) {
160: int coordExp = 3;
161: TreePath path = tree.getPathForRow(rowLevel);
162:
163: if (treeModel == null || path == null
164: || treeModel.isLeaf(path.getLastPathComponent())) {
165: return false;
166: }
167:
168: Rectangle pathBounds = getPathBounds(tree, path);
169:
170: int expandIconWidth = expandedIcon != null ? expandedIcon
171: .getIconWidth() : 8;
172: int startExpandZone = pathBounds.x - rightChildIndent
173: - expandIconWidth / 2 - coordExp;
174: int endExpandZone = startExpandZone + expandIconWidth
175: + coordExp * 2;
176:
177: return mouseX >= startExpandZone && mouseX <= endExpandZone;
178: }
179:
180: public void paint(final Graphics g, final JComponent c) {
181: TreeCommons.paintTree(g, paintContext);
182: }
183:
184: protected void paintHorizontalSeparators(final Graphics g,
185: final JComponent c) {
186: g.setColor(lineColor);
187:
188: Rectangle bounds = tree.getBounds();
189: Insets insets = tree.getInsets();
190:
191: Object root = getModel().getRoot();
192: int rootChildCount = getModel().getChildCount(root);
193: if (rootChildCount == 0) {
194: return;
195: }
196:
197: TreePath rootPath = new TreePath(root);
198: for (int i = 0; i < rootChildCount; i++) {
199: TreePath path = rootPath.pathByAddingChild(getModel()
200: .getChild(root, i));
201: Rectangle pathBounds = tree.getPathBounds(path);
202: paintHorizontalLine(g, c, pathBounds.y, insets.left,
203: bounds.width - insets.right - 1);
204: }
205: }
206:
207: private PropertyChangeListener createClientPropertyChangeHandler() {
208: return new PropertyChangeListener() {
209: public void propertyChange(final PropertyChangeEvent e) {
210: if (LINE_STYLE_PROPERTY.equals(e.getPropertyName())) {
211: decodeLineStyle(e.getNewValue());
212: }
213: }
214: };
215: }
216: }
|