Source Code Cross Referenced for SubstanceTreeUI.java in  » Swing-Library » substance-look-feel » org » jvnet » substance » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » substance look feel » org.jvnet.substance 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without
0005:         * modification, are permitted provided that the following conditions are met:
0006:         *
0007:         *  o Redistributions of source code must retain the above copyright notice,
0008:         *    this list of conditions and the following disclaimer.
0009:         *
0010:         *  o Redistributions in binary form must reproduce the above copyright notice,
0011:         *    this list of conditions and the following disclaimer in the documentation
0012:         *    and/or other materials provided with the distribution.
0013:         *
0014:         *  o Neither the name of Substance Kirill Grouchnikov nor the names of
0015:         *    its contributors may be used to endorse or promote products derived
0016:         *    from this software without specific prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0020:         * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0021:         * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0022:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
0025:         * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0026:         * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0027:         * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0028:         * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029:         */
0030:        package org.jvnet.substance;
0031:
0032:        import java.awt.*;
0033:        import java.awt.event.*;
0034:        import java.beans.PropertyChangeEvent;
0035:        import java.beans.PropertyChangeListener;
0036:        import java.util.*;
0037:
0038:        import javax.swing.*;
0039:        import javax.swing.event.TreeSelectionEvent;
0040:        import javax.swing.event.TreeSelectionListener;
0041:        import javax.swing.plaf.ComponentUI;
0042:        import javax.swing.plaf.IconUIResource;
0043:        import javax.swing.plaf.basic.BasicTreeUI;
0044:        import javax.swing.tree.*;
0045:
0046:        import org.jvnet.lafwidget.animation.*;
0047:        import org.jvnet.lafwidget.layout.TransitionLayout;
0048:        import org.jvnet.lafwidget.utils.LookUtils;
0049:        import org.jvnet.substance.painter.highlight.SubstanceHighlightUtils;
0050:        import org.jvnet.substance.painter.text.SubstanceTextPainter;
0051:        import org.jvnet.substance.theme.SubstanceTheme;
0052:        import org.jvnet.substance.utils.*;
0053:        import org.jvnet.substance.utils.icon.SubstanceIconFactory;
0054:
0055:        /**
0056:         * UI for lists in <b>Substance</b> look and feel.
0057:         * 
0058:         * @author Kirill Grouchnikov
0059:         */
0060:        public class SubstanceTreeUI extends BasicTreeUI {
0061:            /**
0062:             * Holds the list of currently selected paths.
0063:             */
0064:            protected Map<TreePathId, Object> selectedPaths;
0065:
0066:            /**
0067:             * Holds the currently rolled-over path or <code>null</code> if none such.
0068:             */
0069:            protected TreePathId currRolloverPathId;
0070:
0071:            /**
0072:             * Delegate for painting the background of list rows.
0073:             */
0074:            private static SubstanceFillBackgroundDelegate backgroundDelegate = new SubstanceFillBackgroundDelegate();
0075:
0076:            /**
0077:             * Listener that listens to changes on tree properties.
0078:             */
0079:            protected PropertyChangeListener substancePropertyChangeListener;
0080:
0081:            /**
0082:             * Listener for selection animations.
0083:             */
0084:            protected TreeSelectionListener substanceSelectionFadeListener;
0085:
0086:            /**
0087:             * Listener for fade animations on tree rollovers.
0088:             */
0089:            protected RolloverFadeListener substanceFadeRolloverListener;
0090:
0091:            /**
0092:             * Listener for selection of an entire row.
0093:             */
0094:            protected MouseListener substanceRowSelectionListener;
0095:
0096:            /**
0097:             * If <code>true</code>, the mouse pointer is in the bounds of the
0098:             * associated tree.
0099:             */
0100:            private boolean isInside = false;
0101:
0102:            /**
0103:             * Map of previous fade states (for state-aware theme transitions).
0104:             */
0105:            private Map<TreePathId, ComponentState> prevStateMap;
0106:
0107:            /**
0108:             * Map of next fade states (for state-aware theme transitions).
0109:             */
0110:            private Map<TreePathId, ComponentState> nextStateMap;
0111:
0112:            /*
0113:             * (non-Javadoc)
0114:             * 
0115:             * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
0116:             */
0117:            public static ComponentUI createUI(JComponent tree) {
0118:                return new SubstanceTreeUI();
0119:            }
0120:
0121:            /**
0122:             * Creates a UI delegate for tree.
0123:             */
0124:            public SubstanceTreeUI() {
0125:                super ();
0126:                this .selectedPaths = new HashMap<TreePathId, Object>();
0127:                this .prevStateMap = new HashMap<TreePathId, ComponentState>();
0128:                this .nextStateMap = new HashMap<TreePathId, ComponentState>();
0129:            }
0130:
0131:            /*
0132:             * (non-Javadoc)
0133:             * 
0134:             * @see javax.swing.plaf.basic.BasicTreeUI#installDefaults()
0135:             */
0136:            @Override
0137:            protected void installDefaults() {
0138:                super .installDefaults();
0139:                if (SubstanceCoreUtilities.toBleedWatermark(this .tree))
0140:                    this .tree.setOpaque(false);
0141:
0142:                if (this .tree.getSelectionPaths() != null) {
0143:                    for (TreePath selectionPath : this .tree.getSelectionPaths()) {
0144:                        TreePathId pathId = new TreePathId(selectionPath);
0145:                        selectedPaths.put(pathId, selectionPath
0146:                                .getLastPathComponent());
0147:                        prevStateMap.put(pathId, ComponentState.SELECTED);
0148:                    }
0149:                }
0150:
0151:                setExpandedIcon(new IconUIResource(SubstanceIconFactory
0152:                        .getTreeIcon(this .tree, false)));
0153:                setCollapsedIcon(new IconUIResource(SubstanceIconFactory
0154:                        .getTreeIcon(this .tree, true)));
0155:            }
0156:
0157:            /*
0158:             * (non-Javadoc)
0159:             * 
0160:             * @see javax.swing.plaf.basic.BasicTreeUI#uninstallDefaults()
0161:             */
0162:            @Override
0163:            protected void uninstallDefaults() {
0164:                this .selectedPaths.clear();
0165:                super .uninstallDefaults();
0166:            }
0167:
0168:            /*
0169:             * (non-Javadoc)
0170:             * 
0171:             * @see javax.swing.plaf.basic.BasicTreeUI#paintRow(java.awt.Graphics,
0172:             *      java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0173:             *      javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0174:             */
0175:            @Override
0176:            protected void paintRow(Graphics g, Rectangle clipBounds,
0177:                    Insets insets, Rectangle bounds, TreePath path, int row,
0178:                    boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
0179:                // Don't paint the renderer if editing this row.
0180:                if ((this .editingComponent != null) && (this .editingRow == row))
0181:                    return;
0182:
0183:                int leadIndex;
0184:
0185:                if (this .tree.hasFocus()) {
0186:                    TreePath leadPath = this .tree.getLeadSelectionPath();
0187:                    leadIndex = this .getRowForPath(this .tree, leadPath);
0188:                } else {
0189:                    leadIndex = -1;
0190:                }
0191:
0192:                final Component renderer = this .currentCellRenderer
0193:                        .getTreeCellRendererComponent(this .tree, path
0194:                                .getLastPathComponent(), this .tree
0195:                                .isRowSelected(row), isExpanded, isLeaf, row,
0196:                                (leadIndex == row));
0197:
0198:                // // second part - fix for defect 214 (rollover effects on non-opaque
0199:                // // trees resulted in inconsistent behaviour)
0200:                // boolean isWatermarkBleed = SubstanceCoreUtilities
0201:                // .toBleedWatermark(tree)
0202:                // || !tree.isOpaque();
0203:
0204:                TreePathId pathId = new TreePathId(path);
0205:
0206:                // Respect the current composite set on the graphics - for
0207:                // JXPanel alpha channel
0208:                float currFactor = 1.0f;
0209:                Composite currComposite = ((Graphics2D) g).getComposite();
0210:                if (currComposite instanceof  AlphaComposite) {
0211:                    AlphaComposite ac = (AlphaComposite) currComposite;
0212:                    if (ac.getRule() == AlphaComposite.SRC_OVER)
0213:                        currFactor = ac.getAlpha();
0214:                }
0215:
0216:                Graphics2D g2d = (Graphics2D) g.create();
0217:                // fix for issue 183 - passing the original Graphics context
0218:                // to compute the alpha composite. If the tree is in a JXPanel
0219:                // (component from SwingX) and it has custom alpha value set,
0220:                // then the original graphics context will have a SRC_OVER
0221:                // alpha composite applied to it.
0222:                g2d.setComposite(TransitionLayout.getAlphaComposite(this .tree,
0223:                        currFactor));
0224:
0225:                Color background = renderer.getBackground();
0226:                if (background == null)
0227:                    background = tree.getBackground();
0228:
0229:                final ComponentState prevState = this .getPrevPathState(pathId);
0230:                final ComponentState currState = this .getPathState(pathId);
0231:
0232:                final SubstanceTheme prevTheme = SubstanceThemeUtilities
0233:                        .getHighlightTheme(tree, prevState);
0234:                final SubstanceTheme currTheme = SubstanceThemeUtilities
0235:                        .getHighlightTheme(tree, currState);
0236:
0237:                // Compute the alpha values for the animation.
0238:                float startAlpha = SubstanceThemeUtilities.getHighlightAlpha(
0239:                        this .tree, prevState);
0240:                float endAlpha = SubstanceThemeUtilities.getHighlightAlpha(
0241:                        this .tree, currState);
0242:
0243:                FadeState state = SubstanceFadeUtilities.getFadeState(
0244:                        this .tree, pathId, FadeKind.SELECTION,
0245:                        FadeKind.ROLLOVER);
0246:                float totalAlpha = endAlpha;
0247:                float fadeCoef = 0.0f;
0248:                if (state != null) {
0249:                    fadeCoef = state.getFadePosition();
0250:
0251:                    // compute the total alpha of the overlays.
0252:                    if (state.isFadingIn()) {
0253:                        totalAlpha = startAlpha + (endAlpha - startAlpha)
0254:                                * fadeCoef / 10.0f;
0255:                    } else {
0256:                        totalAlpha = startAlpha + (endAlpha - startAlpha)
0257:                                * (10.0f - fadeCoef) / 10.0f;
0258:                    }
0259:
0260:                    if (state.isFadingIn())
0261:                        fadeCoef = 10.0f - fadeCoef;
0262:                }
0263:
0264:                // System.out.println(row + ":" + prevTheme.getDisplayName() + "["
0265:                // + alphaForPrevBackground + "]:" + currTheme.getDisplayName()
0266:                // + "[" + alphaForCurrBackground + "]");
0267:
0268:                // The DefaultTreeCellRenderer overrides the isOpaque method
0269:                // so that there is no point in trying to make it non-opaque.
0270:                // Fix for defect 181.
0271:                final boolean canHaveSubstanceEffects = !(renderer instanceof  DefaultTreeCellRenderer);
0272:                SubstanceTextPainter textPainter = SubstanceLookAndFeel
0273:                        .getCurrentTextPainter();
0274:                if (canHaveSubstanceEffects && (totalAlpha > 0.0f)) {
0275:                    g2d.setComposite(TransitionLayout.getAlphaComposite(
0276:                            this .tree, currFactor * totalAlpha, g));
0277:                    // Fix for defect 180 - painting the
0278:                    // highlight beneath the entire row
0279:                    SubstanceHighlightUtils.paintHighlight(g2d, renderer,
0280:                            new Rectangle(this .tree.getInsets().left, bounds.y,
0281:                                    this .tree.getWidth()
0282:                                            - this .tree.getInsets().right
0283:                                            - this .tree.getInsets().left,
0284:                                    bounds.height), 0.8f, null, currTheme
0285:                                    .getColorScheme(), prevTheme
0286:                                    .getColorScheme(), fadeCoef);
0287:                    g2d.setComposite(TransitionLayout.getAlphaComposite(
0288:                            this .tree, currFactor));
0289:                }
0290:
0291:                // System.out.println("Painting row " + row);
0292:                final boolean isWatermarkBleed = SubstanceCoreUtilities
0293:                        .toBleedWatermark(this .tree);
0294:                if (textPainter.needsBackgroundImage()) {
0295:                    final float finalTotalAlpha = totalAlpha;
0296:                    final float finalCurrFactor = currFactor;
0297:                    final float finalFadeCoef = fadeCoef;
0298:                    final Rectangle cellRect = new Rectangle(this .tree
0299:                            .getInsets().left
0300:                            - bounds.x, 0, this .tree.getWidth()
0301:                            - this .tree.getInsets().right
0302:                            - this .tree.getInsets().left, bounds.height);
0303:                    textPainter.init(this .tree, cellRect, true);
0304:                    textPainter.setBackgroundFill(this .tree, background, true,
0305:                            bounds.x, bounds.y);
0306:
0307:                    textPainter
0308:                            .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
0309:                                public void paintBackground(Graphics g) {
0310:                                    Graphics2D g2d = (Graphics2D) g.create();
0311:                                    if (!isWatermarkBleed) {
0312:                                        // fill with the renderer
0313:                                        // background color
0314:                                        g2d.setColor(renderer.getBackground());
0315:                                        g2d.fillRect(0, 0, cellRect.width,
0316:                                                cellRect.height);
0317:                                    } else {
0318:                                        backgroundDelegate.fillAndWatermark(
0319:                                                g2d, tree, renderer
0320:                                                        .getBackground(),
0321:                                                cellRect);
0322:                                    }
0323:                                    g2d.dispose();
0324:                                }
0325:                            });
0326:
0327:                    textPainter
0328:                            .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
0329:                                public void paintBackground(Graphics g) {
0330:                                    Graphics2D g2d = (Graphics2D) g.create();
0331:                                    if (canHaveSubstanceEffects
0332:                                            && (finalTotalAlpha > 0.0f)) {
0333:                                        g2d
0334:                                                .setComposite(TransitionLayout
0335:                                                        .getAlphaComposite(
0336:                                                                tree,
0337:                                                                finalCurrFactor
0338:                                                                        * finalTotalAlpha,
0339:                                                                g));
0340:                                        // Fix for defect 180 - painting the
0341:                                        // highlight beneath the entire row
0342:                                        SubstanceHighlightUtils.paintHighlight(
0343:                                                g2d, renderer, cellRect, 0.8f,
0344:                                                null, currTheme
0345:                                                        .getColorScheme(),
0346:                                                prevTheme.getColorScheme(),
0347:                                                finalFadeCoef);
0348:                                        g2d.setComposite(TransitionLayout
0349:                                                .getAlphaComposite(tree,
0350:                                                        finalCurrFactor));
0351:                                    }
0352:                                }
0353:                            });
0354:                } else {
0355:                }
0356:
0357:                this .tree.putClientProperty(
0358:                        SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND,
0359:                        Boolean.TRUE);
0360:                if (renderer instanceof  JComponent) {
0361:                    // Play with opacity to make our own gradient background
0362:                    // on selected elements to show.
0363:                    JComponent jRenderer = (JComponent) renderer;
0364:                    synchronized (jRenderer) {
0365:                        boolean newOpaque = !this .tree.isRowSelected(row);
0366:                        if (SubstanceCoreUtilities.toBleedWatermark(this .tree))
0367:                            newOpaque = false;
0368:
0369:                        // fix for defect 181 - no highlight on renderers
0370:                        // that extend DefaultTreeCellRenderer
0371:                        newOpaque = newOpaque && canHaveSubstanceEffects;
0372:
0373:                        Map<Component, Boolean> opacity = new HashMap<Component, Boolean>();
0374:                        if (!newOpaque)
0375:                            SubstanceCoreUtilities.makeNonOpaque(jRenderer,
0376:                                    opacity);
0377:                        this .rendererPane.paintComponent(g2d, renderer,
0378:                                this .tree, bounds.x, bounds.y, Math.max(
0379:                                        this .tree.getWidth()
0380:                                                - this .tree.getInsets().right
0381:                                                - this .tree.getInsets().left
0382:                                                - bounds.x, bounds.width),
0383:                                bounds.height, true);
0384:                        if (!newOpaque)
0385:                            SubstanceCoreUtilities.restoreOpaque(jRenderer,
0386:                                    opacity);
0387:                    }
0388:                } else {
0389:                    this .rendererPane.paintComponent(g2d, renderer, this .tree,
0390:                            bounds.x, bounds.y, Math.max(clipBounds.width,
0391:                                    bounds.width), bounds.height, true);
0392:                }
0393:                this .tree.putClientProperty(
0394:                        SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND, null);
0395:
0396:                // Paint the expand control now after the row background has been
0397:                // overlayed by the highlight background on selected and rolled over
0398:                // rows. See comments on paintExpandControlEnforce().
0399:                if (shouldPaintExpandControl(path, row, isExpanded,
0400:                        hasBeenExpanded, isLeaf)) {
0401:                    if (!this .tree.getComponentOrientation().isLeftToRight()
0402:                            && LookUtils.IS_JAVA_5) {
0403:                        bounds.x -= 4;
0404:                    }
0405:                    paintExpandControlEnforce(g2d, clipBounds, insets, bounds,
0406:                            path, row, isExpanded, hasBeenExpanded, isLeaf);
0407:                }
0408:
0409:                g2d.dispose();
0410:            }
0411:
0412:            /*
0413:             * (non-Javadoc)
0414:             * 
0415:             * @see javax.swing.plaf.basic.BasicTreeUI#paintExpandControl(java.awt.Graphics,
0416:             *      java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0417:             *      javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0418:             */
0419:            @Override
0420:            protected void paintExpandControl(Graphics g, Rectangle clipBounds,
0421:                    Insets insets, Rectangle bounds, TreePath path, int row,
0422:                    boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
0423:                // This does nothing. The base implementation of paint() paints
0424:                // the tree lines and tree expand controls *before* painting the
0425:                // renderer. In Substance, the highlights are painted in the
0426:                // paintRow, and thus would overlay the expand controls. This results
0427:                // in expand controls being much less visible under most of the skins.
0428:                // So, Substance paints the expand controls *after* painting the
0429:                // highlights (and the renderer which doesn't overlap with the expand
0430:                // controls in any case). This is done in paintRow() by calling
0431:                // the paintExpandControlEnforce() instead (that eventually calls the
0432:                // super implementation of paintExpandControl().
0433:            }
0434:
0435:            protected void paintExpandControlEnforce(Graphics g,
0436:                    Rectangle clipBounds, Insets insets, Rectangle bounds,
0437:                    TreePath path, int row, boolean isExpanded,
0438:                    boolean hasBeenExpanded, boolean isLeaf) {
0439:                boolean toPaint = (!this .tree.isEnabled())
0440:                        || this .isInside
0441:                        || !FadeConfigurationManager
0442:                                .getInstance()
0443:                                .fadeAllowed(
0444:                                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0445:                                        tree);
0446:
0447:                SubstanceTheme theme = SubstanceThemeUtilities
0448:                        .getTheme(this .tree);
0449:                float alpha = theme.getThemeAlpha(this .tree, this .tree
0450:                        .isEnabled() ? ComponentState.DEFAULT
0451:                        : ComponentState.DISABLED_UNSELECTED);
0452:
0453:                Graphics2D graphics = (Graphics2D) g.create();
0454:                if (FadeTracker.getInstance().isTracked(this .tree,
0455:                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0456:                    toPaint = true;
0457:                    alpha *= FadeTracker
0458:                            .getInstance()
0459:                            .getFade10(
0460:                                    this .tree,
0461:                                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0462:                }
0463:                if (toPaint) {
0464:                    graphics.setComposite(TransitionLayout.getAlphaComposite(
0465:                            this .tree, alpha, g));
0466:                    super .paintExpandControl(graphics, clipBounds, insets,
0467:                            bounds, path, row, isExpanded, hasBeenExpanded,
0468:                            isLeaf);
0469:                }
0470:                graphics.dispose();
0471:            }
0472:
0473:            /*
0474:             * (non-Javadoc)
0475:             * 
0476:             * @see javax.swing.plaf.basic.BasicTreeUI#paintHorizontalPartOfLeg(java.awt.Graphics,
0477:             *      java.awt.Rectangle, java.awt.Insets, java.awt.Rectangle,
0478:             *      javax.swing.tree.TreePath, int, boolean, boolean, boolean)
0479:             */
0480:            @Override
0481:            protected void paintHorizontalPartOfLeg(Graphics g,
0482:                    Rectangle clipBounds, Insets insets, Rectangle bounds,
0483:                    TreePath path, int row, boolean isExpanded,
0484:                    boolean hasBeenExpanded, boolean isLeaf) {
0485:                Graphics2D graphics = (Graphics2D) g.create();
0486:                float strokeWidth = SubstanceSizeUtils
0487:                        .getBorderStrokeWidth(SubstanceSizeUtils
0488:                                .getComponentFontSize(this .tree));
0489:                graphics.setStroke(new BasicStroke(strokeWidth,
0490:                        BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
0491:                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0492:                        RenderingHints.VALUE_ANTIALIAS_ON);
0493:
0494:                boolean toPaint = (!this .tree.isEnabled())
0495:                        || this .isInside
0496:                        || !FadeConfigurationManager
0497:                                .getInstance()
0498:                                .fadeAllowed(
0499:                                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0500:                                        tree);
0501:
0502:                SubstanceTheme theme = SubstanceThemeUtilities
0503:                        .getTheme(this .tree);
0504:                float alpha = theme.getThemeAlpha(this .tree, this .tree
0505:                        .isEnabled() ? ComponentState.DEFAULT
0506:                        : ComponentState.DISABLED_UNSELECTED);
0507:
0508:                if (FadeTracker.getInstance().isTracked(this .tree,
0509:                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0510:                    toPaint = true;
0511:                    alpha *= FadeTracker
0512:                            .getInstance()
0513:                            .getFade10(
0514:                                    this .tree,
0515:                                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0516:                }
0517:                if (toPaint) {
0518:                    graphics.setComposite(TransitionLayout.getAlphaComposite(
0519:                            this .tree, alpha, g));
0520:                    super .paintHorizontalPartOfLeg(graphics, clipBounds,
0521:                            insets, bounds, path, row, isExpanded,
0522:                            hasBeenExpanded, isLeaf);
0523:                }
0524:                graphics.dispose();
0525:            }
0526:
0527:            /*
0528:             * (non-Javadoc)
0529:             * 
0530:             * @see javax.swing.plaf.basic.BasicTreeUI#paintVerticalPartOfLeg(java.awt.Graphics,
0531:             *      java.awt.Rectangle, java.awt.Insets, javax.swing.tree.TreePath)
0532:             */
0533:            @Override
0534:            protected void paintVerticalPartOfLeg(Graphics g,
0535:                    Rectangle clipBounds, Insets insets, TreePath path) {
0536:                Graphics2D graphics = (Graphics2D) g.create();
0537:                float strokeWidth = SubstanceSizeUtils
0538:                        .getBorderStrokeWidth(SubstanceSizeUtils
0539:                                .getComponentFontSize(this .tree));
0540:                graphics.setStroke(new BasicStroke(strokeWidth,
0541:                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
0542:                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0543:                        RenderingHints.VALUE_ANTIALIAS_ON);
0544:
0545:                boolean toPaint = (!this .tree.isEnabled())
0546:                        || this .isInside
0547:                        || !FadeConfigurationManager
0548:                                .getInstance()
0549:                                .fadeAllowed(
0550:                                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0551:                                        tree);
0552:
0553:                SubstanceTheme theme = SubstanceThemeUtilities
0554:                        .getTheme(this .tree);
0555:                float alpha = theme.getThemeAlpha(this .tree, this .tree
0556:                        .isEnabled() ? ComponentState.DEFAULT
0557:                        : ComponentState.DISABLED_UNSELECTED);
0558:
0559:                if (FadeTracker.getInstance().isTracked(this .tree,
0560:                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
0561:                    toPaint = true;
0562:                    alpha *= FadeTracker
0563:                            .getInstance()
0564:                            .getFade10(
0565:                                    this .tree,
0566:                                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f;
0567:                }
0568:                if (toPaint) {
0569:                    graphics.setComposite(TransitionLayout.getAlphaComposite(
0570:                            this .tree, alpha, g));
0571:                    super .paintVerticalPartOfLeg(graphics, clipBounds, insets,
0572:                            path);
0573:                }
0574:                graphics.dispose();
0575:            }
0576:
0577:            /*
0578:             * (non-Javadoc)
0579:             * 
0580:             * @see javax.swing.plaf.basic.BasicTreeUI#createDefaultCellRenderer()
0581:             */
0582:            @Override
0583:            protected TreeCellRenderer createDefaultCellRenderer() {
0584:                return new SubstanceDefaultTreeCellRenderer();
0585:            }
0586:
0587:            /*
0588:             * (non-Javadoc)
0589:             * 
0590:             * @see javax.swing.plaf.basic.BasicTreeUI#installListeners()
0591:             */
0592:            @Override
0593:            protected void installListeners() {
0594:                super .installListeners();
0595:                this .substancePropertyChangeListener = new PropertyChangeListener() {
0596:                    public void propertyChange(PropertyChangeEvent evt) {
0597:                        if (SubstanceLookAndFeel.WATERMARK_TO_BLEED.equals(evt
0598:                                .getPropertyName())) {
0599:                            tree.setOpaque(!SubstanceCoreUtilities
0600:                                    .toBleedWatermark(tree));
0601:                        }
0602:                        if ("font".equals(evt.getPropertyName())) {
0603:                            SwingUtilities.invokeLater(new Runnable() {
0604:                                public void run() {
0605:                                    tree.updateUI();
0606:                                }
0607:                            });
0608:                        }
0609:                    }
0610:                };
0611:                this .tree
0612:                        .addPropertyChangeListener(this .substancePropertyChangeListener);
0613:
0614:                this .substanceSelectionFadeListener = new MyTreeSelectionListener();
0615:                this .tree.getSelectionModel().addTreeSelectionListener(
0616:                        this .substanceSelectionFadeListener);
0617:
0618:                this .substanceRowSelectionListener = new RowSelectionListener();
0619:                this .tree.addMouseListener(this .substanceRowSelectionListener);
0620:
0621:                // Add listener for the fade animation
0622:                this .substanceFadeRolloverListener = new RolloverFadeListener();
0623:                this .tree
0624:                        .addMouseMotionListener(this .substanceFadeRolloverListener);
0625:                this .tree.addMouseListener(this .substanceFadeRolloverListener);
0626:            }
0627:
0628:            /*
0629:             * (non-Javadoc)
0630:             * 
0631:             * @see javax.swing.plaf.basic.BasicTreeUI#uninstallListeners()
0632:             */
0633:            @Override
0634:            protected void uninstallListeners() {
0635:                this .tree
0636:                        .removeMouseListener(this .substanceRowSelectionListener);
0637:                this .substanceRowSelectionListener = null;
0638:
0639:                this .tree.getSelectionModel().removeTreeSelectionListener(
0640:                        this .substanceSelectionFadeListener);
0641:                this .substanceSelectionFadeListener = null;
0642:
0643:                this .tree
0644:                        .removePropertyChangeListener(this .substancePropertyChangeListener);
0645:                this .substancePropertyChangeListener = null;
0646:
0647:                // Remove listener for the fade animation
0648:                this .tree
0649:                        .removeMouseMotionListener(this .substanceFadeRolloverListener);
0650:                this .tree
0651:                        .removeMouseListener(this .substanceFadeRolloverListener);
0652:                this .substanceFadeRolloverListener = null;
0653:
0654:                super .uninstallListeners();
0655:            }
0656:
0657:            /**
0658:             * ID of a single tree path.
0659:             * 
0660:             * @author Kirill Grouchnikov
0661:             */
0662:            @SuppressWarnings("unchecked")
0663:            protected static class TreePathId implements  Comparable {
0664:                /**
0665:                 * Tree path.
0666:                 */
0667:                protected TreePath path;
0668:
0669:                /**
0670:                 * Creates a tree path ID.
0671:                 * 
0672:                 * @param path
0673:                 *            Tree path.
0674:                 */
0675:                public TreePathId(TreePath path) {
0676:                    this .path = path;
0677:                }
0678:
0679:                /*
0680:                 * (non-Javadoc)
0681:                 * 
0682:                 * @see java.lang.Comparable#compareTo(java.lang.Object)
0683:                 */
0684:                public int compareTo(Object o) {
0685:                    if (o instanceof  TreePathId) {
0686:                        TreePathId otherId = (TreePathId) o;
0687:                        if ((this .path == null) && (otherId.path != null))
0688:                            return 1;
0689:                        if ((otherId.path == null) && (this .path != null))
0690:                            return -1;
0691:                        Object[] path1Objs = this .path.getPath();
0692:                        Object[] path2Objs = otherId.path.getPath();
0693:                        if (path1Objs.length != path2Objs.length)
0694:                            return 1;
0695:                        for (int i = 0; i < path1Objs.length; i++)
0696:                            if (!path1Objs[i].equals(path2Objs[i]))
0697:                                return 1;
0698:                        return 0;
0699:                    }
0700:                    return -1;
0701:                }
0702:
0703:                /*
0704:                 * (non-Javadoc)
0705:                 * 
0706:                 * @see java.lang.Object#equals(java.lang.Object)
0707:                 */
0708:                @Override
0709:                public boolean equals(Object obj) {
0710:                    return this .compareTo(obj) == 0;
0711:                }
0712:
0713:                /*
0714:                 * (non-Javadoc)
0715:                 * 
0716:                 * @see java.lang.Object#hashCode()
0717:                 */
0718:                @Override
0719:                public int hashCode() {
0720:                    if (this .path == null)
0721:                        return 0;
0722:                    Object[] pathObjs = this .path.getPath();
0723:                    int result = pathObjs[0].hashCode();
0724:                    for (int i = 1; i < pathObjs.length; i++)
0725:                        result = result ^ pathObjs[i].hashCode();
0726:                    return result;
0727:                }
0728:            }
0729:
0730:            /**
0731:             * Selection listener for selection animation effects.
0732:             * 
0733:             * @author Kirill Grouchnikov
0734:             */
0735:            protected class MyTreeSelectionListener implements 
0736:                    TreeSelectionListener {
0737:                /*
0738:                 * (non-Javadoc)
0739:                 * 
0740:                 * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
0741:                 */
0742:                @SuppressWarnings("unchecked")
0743:                public void valueChanged(TreeSelectionEvent e) {
0744:                    // Map<TreePathId, Object> currSelected = (Map<TreePathId, Object>)
0745:                    // tree
0746:                    // .getClientProperty(SELECTED_INDICES);
0747:                    if (tree.getSelectionPaths() != null) {
0748:                        for (TreePath selectionPath : tree.getSelectionPaths()) {
0749:                            TreePathId pathId = new TreePathId(selectionPath);
0750:
0751:                            // check if was selected before
0752:                            if (!selectedPaths.containsKey(pathId)) {
0753:                                // start fading in
0754:                                // System.out.println("Fade in on index " + i);
0755:                                FadeTracker.getInstance().trackFadeIn(
0756:                                        FadeKind.SELECTION,
0757:                                        tree,
0758:                                        pathId,
0759:                                        false,
0760:                                        new PathRepaintCallback(tree,
0761:                                                selectionPath));
0762:                                selectedPaths.put(pathId, selectionPath
0763:                                        .getLastPathComponent());
0764:                            }
0765:                        }
0766:                    }
0767:
0768:                    for (Iterator<Map.Entry<TreePathId, Object>> it = selectedPaths
0769:                            .entrySet().iterator(); it.hasNext();) {
0770:                        Map.Entry<TreePathId, Object> entry = it.next();
0771:                        if (tree.getSelectionModel().isPathSelected(
0772:                                entry.getKey().path))
0773:                            continue;
0774:                        // fade out for deselected path
0775:                        FadeTracker.getInstance().trackFadeOut(
0776:                                FadeKind.SELECTION,
0777:                                tree,
0778:                                entry.getKey(),
0779:                                false,
0780:                                new PathRepaintCallback(tree,
0781:                                        entry.getKey().path));
0782:                        it.remove();
0783:                    }
0784:                }
0785:            }
0786:
0787:            /**
0788:             * Repaints a single path during the fade animation cycle.
0789:             * 
0790:             * @author Kirill Grouchnikov
0791:             */
0792:            protected class PathRepaintCallback extends FadeTrackerAdapter {
0793:                /**
0794:                 * Associated tree.
0795:                 */
0796:                protected JTree tree;
0797:
0798:                /**
0799:                 * Associated (animated) path.
0800:                 */
0801:                protected TreePath treePath;
0802:
0803:                /**
0804:                 * Creates a new animation repaint callback.
0805:                 * 
0806:                 * @param tree
0807:                 *            Associated tree.
0808:                 * @param treePath
0809:                 *            Associated (animated) path.
0810:                 */
0811:                public PathRepaintCallback(JTree tree, TreePath treePath) {
0812:                    super ();
0813:                    this .tree = tree;
0814:                    this .treePath = treePath;
0815:                }
0816:
0817:                /*
0818:                 * (non-Javadoc)
0819:                 * 
0820:                 * @see org.jvnet.lafwidget.utils.FadeTracker$FadeTrackerCallback#fadeEnded(org.jvnet.lafwidget.utils.FadeTracker.FadeKind)
0821:                 */
0822:                @Override
0823:                public void fadeEnded(FadeKind fadeKind) {
0824:                    if (SubstanceTreeUI.this .tree == tree) {
0825:                        TreePathId pathId = new TreePathId(treePath);
0826:                        ComponentState currState = getPathState(pathId);
0827:                        if (currState == ComponentState.DEFAULT) {
0828:                            prevStateMap.remove(pathId);
0829:                            nextStateMap.remove(pathId);
0830:                        } else {
0831:                            prevStateMap.put(pathId, currState);
0832:                            nextStateMap.put(pathId, currState);
0833:                        }
0834:                        // System.out.println(tabIndex + "->"
0835:                        // + prevStateMap.get(tabIndex).name());
0836:                    }
0837:                    this .repaintPath();
0838:                }
0839:
0840:                /*
0841:                 * (non-Javadoc)
0842:                 * 
0843:                 * @see org.jvnet.lafwidget.utils.FadeTracker$FadeTrackerCallback#fadePerformed(org.jvnet.lafwidget.utils.FadeTracker.FadeKind,
0844:                 *      float)
0845:                 */
0846:                @Override
0847:                public void fadePerformed(FadeKind fadeKind, float fade10) {
0848:                    if (SubstanceTreeUI.this .tree == tree) {
0849:                        TreePathId pathId = new TreePathId(treePath);
0850:                        nextStateMap.put(pathId, getPathState(pathId));
0851:                    }
0852:                    this .repaintPath();
0853:                }
0854:
0855:                /*
0856:                 * (non-Javadoc)
0857:                 * 
0858:                 * @see org.jvnet.lafwidget.animation.FadeTrackerAdapter#fadeReversed(org.jvnet.lafwidget.animation.FadeKind,
0859:                 *      boolean, float)
0860:                 */
0861:                @Override
0862:                public void fadeReversed(FadeKind fadeKind, boolean isFadingIn,
0863:                        float fadeCycle10) {
0864:                    if (SubstanceTreeUI.this .tree == tree) {
0865:                        TreePathId pathId = new TreePathId(treePath);
0866:                        ComponentState nextState = nextStateMap.get(pathId);
0867:                        if (nextState == null) {
0868:                            prevStateMap.remove(pathId);
0869:                        } else {
0870:                            prevStateMap.put(pathId, nextState);
0871:                        }
0872:                        // System.out.println(tabIndex + "->"
0873:                        // + prevStateMap.get(tabIndex).name());
0874:                    }
0875:                    this .repaintPath();
0876:                }
0877:
0878:                /**
0879:                 * Repaints the associated path.
0880:                 */
0881:                private void repaintPath() {
0882:                    SwingUtilities.invokeLater(new Runnable() {
0883:                        public void run() {
0884:                            if (SubstanceTreeUI.this .tree == null) {
0885:                                // may happen if the LAF was switched in the meantime
0886:                                return;
0887:                            }
0888:
0889:                            Rectangle boundsBuffer = new Rectangle();
0890:                            Rectangle bounds = treeState.getBounds(treePath,
0891:                                    boundsBuffer);
0892:
0893:                            if (bounds != null) {
0894:                                // still visible
0895:
0896:                                // fix for defect 180 - refresh the entire row
0897:                                bounds.x = 0;
0898:                                bounds.width = tree.getWidth();
0899:
0900:                                // fix for defect 188 - rollover effects for trees
0901:                                // with insets
0902:                                Insets insets = tree.getInsets();
0903:                                bounds.x += insets.left;
0904:                                bounds.y += insets.top;
0905:
0906:                                tree.repaint(bounds);
0907:                            }
0908:                        }
0909:                    });
0910:                }
0911:            }
0912:
0913:            /**
0914:             * Listener for rollover animation effects.
0915:             * 
0916:             * @author Kirill Grouchnikov
0917:             */
0918:            private class RolloverFadeListener implements  MouseListener,
0919:                    MouseMotionListener {
0920:
0921:                public void mouseClicked(MouseEvent e) {
0922:                }
0923:
0924:                public void mouseEntered(MouseEvent e) {
0925:                    if (!tree.isEnabled())
0926:                        return;
0927:                    isInside = true;
0928:                    if (FadeConfigurationManager
0929:                            .getInstance()
0930:                            .fadeAllowed(
0931:                                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0932:                                    tree)) {
0933:                        FadeTracker
0934:                                .getInstance()
0935:                                .trackFadeIn(
0936:                                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0937:                                        tree, false, null);
0938:                    }
0939:                }
0940:
0941:                public void mousePressed(MouseEvent e) {
0942:                }
0943:
0944:                public void mouseReleased(MouseEvent e) {
0945:                }
0946:
0947:                public void mouseExited(MouseEvent e) {
0948:                    if (!tree.isEnabled())
0949:                        return;
0950:                    isInside = false;
0951:                    if (FadeConfigurationManager
0952:                            .getInstance()
0953:                            .fadeAllowed(
0954:                                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0955:                                    tree)) {
0956:                        FadeTracker
0957:                                .getInstance()
0958:                                .trackFadeOut(
0959:                                        SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
0960:                                        tree, false, null);
0961:                    }
0962:                    this .fadeOut();
0963:                    // System.out.println("Nulling RO index");
0964:                    currRolloverPathId = null;
0965:                }
0966:
0967:                public void mouseMoved(MouseEvent e) {
0968:                    if (!tree.isEnabled())
0969:                        return;
0970:                    isInside = true;
0971:                    handleMove(e);
0972:                }
0973:
0974:                public void mouseDragged(MouseEvent e) {
0975:                    if (!tree.isEnabled())
0976:                        return;
0977:                    handleMove(e);
0978:                }
0979:
0980:                /**
0981:                 * Handles various mouse move events and initiates the fade animation if
0982:                 * necessary.
0983:                 * 
0984:                 * @param e
0985:                 *            Mouse event.
0986:                 */
0987:                private void handleMove(MouseEvent e) {
0988:                    TreePath closestPath = tree.getClosestPathForLocation(e
0989:                            .getX(), e.getY());
0990:                    Rectangle bounds = tree.getPathBounds(closestPath);
0991:                    if (bounds == null) {
0992:                        this .fadeOut();
0993:                        currRolloverPathId = null;
0994:                        return;
0995:                    }
0996:                    if ((e.getY() < bounds.y)
0997:                            || (e.getY() > (bounds.y + bounds.height))) {
0998:                        this .fadeOut();
0999:                        currRolloverPathId = null;
1000:                        return;
1001:                    }
1002:                    // check if this is the same index
1003:                    TreePathId newPathId = new TreePathId(closestPath);
1004:                    if ((currRolloverPathId != null)
1005:                            && newPathId.equals(currRolloverPathId)) {
1006:                        // System.out.println("Same location " +
1007:                        // System.currentTimeMillis());
1008:                        // System.out.print("Current : ");
1009:                        // for (Object o1 : currPathId.path.getPath()) {
1010:                        // System.out.print(o1);
1011:                        // }
1012:                        // System.out.println("");
1013:                        // System.out.print("Closest : ");
1014:                        // for (Object o2 : newPathId.path.getPath()) {
1015:                        // System.out.print(o2);
1016:                        // }
1017:                        // System.out.println("");
1018:                        return;
1019:                    }
1020:
1021:                    this .fadeOut();
1022:                    FadeTracker.getInstance().trackFadeIn(FadeKind.ROLLOVER,
1023:                            tree, newPathId, false,
1024:                            new PathRepaintCallback(tree, closestPath));
1025:                    // System.out.println("Setting RO index to " + roIndex);
1026:                    currRolloverPathId = newPathId;
1027:                }
1028:
1029:                /**
1030:                 * Initiates the fade out effect.
1031:                 */
1032:                private void fadeOut() {
1033:                    if (currRolloverPathId == null)
1034:                        return;
1035:
1036:                    FadeTracker.getInstance().trackFadeOut(
1037:                            FadeKind.ROLLOVER,
1038:                            tree,
1039:                            currRolloverPathId,
1040:                            false,
1041:                            new PathRepaintCallback(tree,
1042:                                    currRolloverPathId.path));
1043:                }
1044:            }
1045:
1046:            /**
1047:             * Listener for selecting the entire rows.
1048:             * 
1049:             * @author Kirill Grouchnikov
1050:             */
1051:            private class RowSelectionListener extends MouseAdapter {
1052:                /*
1053:                 * (non-Javadoc)
1054:                 * 
1055:                 * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
1056:                 */
1057:                @Override
1058:                public void mousePressed(MouseEvent e) {
1059:                    if (!tree.isEnabled())
1060:                        return;
1061:                    TreePath closestPath = tree.getClosestPathForLocation(e
1062:                            .getX(), e.getY());
1063:                    if (closestPath == null)
1064:                        return;
1065:                    Rectangle bounds = tree.getPathBounds(closestPath);
1066:                    // Process events outside the immediate bounds - fix for defect
1067:                    // 19 on substance-netbeans. This properly handles Ctrl and Shift
1068:                    // selections on trees.
1069:                    if ((e.getY() >= bounds.y)
1070:                            && (e.getY() < (bounds.y + bounds.height))
1071:                            && ((e.getX() < bounds.x) || (e.getX() > (bounds.x + bounds.width)))) {
1072:                        // tree.setSelectionPath(closestPath);
1073:
1074:                        // fix - don't select a node if the click was on the
1075:                        // expand control
1076:                        if (isLocationInExpandControl(closestPath, e.getX(), e
1077:                                .getY()))
1078:                            return;
1079:                        selectPathForEvent(closestPath, e);
1080:                    }
1081:                }
1082:            }
1083:
1084:            /**
1085:             * Returns the pivot X for the cells rendered in the specified area. Used
1086:             * for the smart tree scroll ({@link SubstanceLookAndFeel#TREE_SMART_SCROLL_ANIMATION_KIND}).
1087:             * 
1088:             * @param paintBounds
1089:             *            Area bounds.
1090:             * @return Pivot X for the cells rendered in the specified area
1091:             */
1092:            public int getPivotRendererX(Rectangle paintBounds) {
1093:                TreePath initialPath = getClosestPathForLocation(tree, 0,
1094:                        paintBounds.y);
1095:                Enumeration<?> paintingEnumerator = treeState
1096:                        .getVisiblePathsFrom(initialPath);
1097:                int endY = paintBounds.y + paintBounds.height;
1098:
1099:                int totalY = 0;
1100:                int count = 0;
1101:
1102:                if (initialPath != null && paintingEnumerator != null) {
1103:                    boolean done = false;
1104:                    Rectangle boundsBuffer = new Rectangle();
1105:                    Rectangle bounds;
1106:                    TreePath path;
1107:                    Insets insets = tree.getInsets();
1108:
1109:                    while (!done && paintingEnumerator.hasMoreElements()) {
1110:                        path = (TreePath) paintingEnumerator.nextElement();
1111:                        if (path != null) {
1112:                            bounds = treeState.getBounds(path, boundsBuffer);
1113:                            bounds.x += insets.left;
1114:                            bounds.y += insets.top;
1115:
1116:                            int currMedianX = bounds.x;// + bounds.width / 2;
1117:                            totalY += currMedianX;
1118:                            count++;
1119:                            if ((bounds.y + bounds.height) >= endY)
1120:                                done = true;
1121:                        } else {
1122:                            done = true;
1123:                        }
1124:                    }
1125:                }
1126:                if (count == 0)
1127:                    return -1;
1128:                return totalY
1129:                        / count
1130:                        - 2
1131:                        * SubstanceSizeUtils.getTreeIconSize(SubstanceSizeUtils
1132:                                .getComponentFontSize(tree));
1133:            }
1134:
1135:            /**
1136:             * Returns the previous state for the specified path.
1137:             * 
1138:             * @param pathId
1139:             *            Path index.
1140:             * @return The previous state for the specified path.
1141:             */
1142:            public ComponentState getPrevPathState(TreePathId pathId) {
1143:                if (this .prevStateMap.containsKey(pathId))
1144:                    return this .prevStateMap.get(pathId);
1145:                return ComponentState.DEFAULT;
1146:            }
1147:
1148:            /**
1149:             * Returns the current state for the specified path.
1150:             * 
1151:             * @param pathId
1152:             *            Path index.
1153:             * @return The current state for the specified path.
1154:             */
1155:            public ComponentState getPathState(TreePathId pathId) {
1156:                ButtonModel synthModel = new DefaultButtonModel();
1157:                synthModel.setEnabled(this .tree.isEnabled());
1158:                synthModel.setRollover((this .currRolloverPathId != null)
1159:                        && pathId.equals(this .currRolloverPathId));
1160:                int rowIndex = this .tree.getRowForPath(pathId.path);
1161:                synthModel.setSelected(this .tree.isRowSelected(rowIndex));
1162:                return ComponentState.getState(synthModel, null);
1163:            }
1164:
1165:            /*
1166:             * (non-Javadoc)
1167:             * 
1168:             * @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
1169:             *      javax.swing.JComponent)
1170:             */
1171:            @Override
1172:            public void update(Graphics g, JComponent c) {
1173:                SubstanceFillBackgroundDelegate.GLOBAL_INSTANCE.updateIfOpaque(
1174:                        g, c);
1175:
1176:                // Should never happen if installed for a UI
1177:                if (treeState == null) {
1178:                    return;
1179:                }
1180:
1181:                Rectangle paintBounds = g.getClipBounds();
1182:                Insets insets = tree.getInsets();
1183:
1184:                TreePath initialPath = getClosestPathForLocation(tree, 0,
1185:                        paintBounds.y);
1186:                Enumeration paintingEnumerator = treeState
1187:                        .getVisiblePathsFrom(initialPath);
1188:                int row = treeState.getRowForPath(initialPath);
1189:                int endY = paintBounds.y + paintBounds.height;
1190:
1191:                // second part - fix for defect 214 (rollover effects on non-opaque
1192:                // trees resulted in inconsistent behaviour)
1193:                boolean isWatermarkBleed = SubstanceCoreUtilities
1194:                        .toBleedWatermark(tree)
1195:                        || !tree.isOpaque();
1196:
1197:                Graphics2D g2d = (Graphics2D) g.create();
1198:
1199:                if (initialPath != null && paintingEnumerator != null) {
1200:                    boolean done = false;
1201:                    Rectangle boundsBuffer = new Rectangle();
1202:                    Rectangle bounds;
1203:                    TreePath path;
1204:
1205:                    while (!done && paintingEnumerator.hasMoreElements()) {
1206:                        path = (TreePath) paintingEnumerator.nextElement();
1207:                        if (path != null) {
1208:                            // respect the background color of the renderer.
1209:                            boolean isLeaf = treeModel.isLeaf(path
1210:                                    .getLastPathComponent());
1211:                            boolean isExpanded = isLeaf ? false : treeState
1212:                                    .getExpandedState(path);
1213:                            Component renderer = this .currentCellRenderer
1214:                                    .getTreeCellRendererComponent(
1215:                                            this .tree,
1216:                                            path.getLastPathComponent(),
1217:                                            this .tree.isRowSelected(row),
1218:                                            isExpanded,
1219:                                            isLeaf,
1220:                                            row,
1221:                                            tree.hasFocus() ? (tree
1222:                                                    .getLeadSelectionRow() == row)
1223:                                                    : false);
1224:                            Color background = renderer.getBackground();
1225:                            if (background == null)
1226:                                background = tree.getBackground();
1227:                            bounds = treeState.getBounds(path, boundsBuffer);
1228:                            bounds.x += insets.left;
1229:                            bounds.y += insets.top;
1230:                            if (!isWatermarkBleed) {
1231:                                g2d.setColor(background);
1232:                                g2d.fillRect(paintBounds.x, bounds.y,
1233:                                        paintBounds.width, bounds.height);
1234:                            } else {
1235:                                if (this .tree.getComponentOrientation()
1236:                                        .isLeftToRight()) {
1237:                                    backgroundDelegate.fillAndWatermark(g2d,
1238:                                            this .tree, background,
1239:                                            new Rectangle(paintBounds.x,
1240:                                                    bounds.y,
1241:                                                    paintBounds.width,
1242:                                                    bounds.height));
1243:                                } else {
1244:                                    backgroundDelegate.fillAndWatermark(g2d,
1245:                                            this .tree, background,
1246:                                            new Rectangle(paintBounds.x,
1247:                                                    bounds.y,
1248:                                                    paintBounds.width,
1249:                                                    bounds.height));
1250:                                }
1251:                            }
1252:                            if ((bounds.y + bounds.height) >= endY)
1253:                                done = true;
1254:                        } else {
1255:                            done = true;
1256:                        }
1257:                        row++;
1258:                    }
1259:                }
1260:
1261:                this .paint(g2d, c);
1262:                g2d.dispose();
1263:            }
1264:
1265:            /*
1266:             * (non-Javadoc)
1267:             * 
1268:             * @see javax.swing.plaf.basic.BasicTreeUI#getHashColor()
1269:             */
1270:            @Override
1271:            protected Color getHashColor() {
1272:                SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
1273:                        this .tree,
1274:                        this .tree.isEnabled() ? ComponentState.DEFAULT
1275:                                : ComponentState.DISABLED_UNSELECTED);
1276:                Color curr = theme.getLineColor();
1277:
1278:                // // support for enhancement 256 - colorization of controls.
1279:                // boolean hasColorization = SubstanceCoreUtilities
1280:                // .hasColorization(this.tree);
1281:                // if (hasColorization) {
1282:                // Color backgr = this.tree.getBackground();
1283:                // if (!(backgr instanceof UIResource)) {
1284:                // double colorizationFactor = SubstanceCoreUtilities
1285:                // .getColorizationFactor(this.tree);
1286:                // if (!tree.isEnabled())
1287:                // colorizationFactor /= 2.0;
1288:                // Color toShiftTo = SubstanceColorUtilities.deriveByBrightness(
1289:                // backgr, curr);
1290:                // curr = SubstanceColorUtilities.getInterpolatedColor(toShiftTo,
1291:                // curr, colorizationFactor);
1292:                // }
1293:                // }
1294:
1295:                return curr;
1296:            }
1297:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.