Experimental breadcrumbs for Java.
authorJan Lahoda <jlahoda@netbeans.org>
Wed, 08 Aug 2012 15:09:00 +0200
changeset 178533f4828222756
parent 17852 187963701a8c
child 17854 6f7530aa42b8
Experimental breadcrumbs for Java.
java.breadcrumbs/build.xml
java.breadcrumbs/manifest.mf
java.breadcrumbs/nbproject/project.properties
java.breadcrumbs/nbproject/project.xml
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/BreadCrumbComponent.java
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/BreadCrumbsScanningTask.java
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/Bundle.properties
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/HolderImpl.java
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/NodeImpl.java
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/SideBarFactoryImpl.java
java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/layer.xml
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java.breadcrumbs/build.xml	Wed Aug 08 15:09:00 2012 +0200
     1.3 @@ -0,0 +1,5 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<project basedir="." default="netbeans" name="contrib/java.breadcrumbs">
     1.6 +    <description>Builds, tests, and runs the project org.netbeans.modules.java.breadcrumbs</description>
     1.7 +    <import file="../../nbbuild/templates/projectized.xml"/>
     1.8 +</project>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/java.breadcrumbs/manifest.mf	Wed Aug 08 15:09:00 2012 +0200
     2.3 @@ -0,0 +1,6 @@
     2.4 +Manifest-Version: 1.0
     2.5 +OpenIDE-Module: org.netbeans.modules.java.breadcrumbs
     2.6 +OpenIDE-Module-Implementation-Version: 1
     2.7 +OpenIDE-Module-Layer: org/netbeans/modules/java/breadcrumbs/layer.xml
     2.8 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/breadcrumbs/Bundle.properties
     2.9 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/java.breadcrumbs/nbproject/project.properties	Wed Aug 08 15:09:00 2012 +0200
     3.3 @@ -0,0 +1,4 @@
     3.4 +javac.source=1.6
     3.5 +javac.compilerargs=-Xlint -Xlint:-serial
     3.6 +spec.version.base=1.0
     3.7 +spec.version.base.fatal.warning=false
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/java.breadcrumbs/nbproject/project.xml	Wed Aug 08 15:09:00 2012 +0200
     4.3 @@ -0,0 +1,137 @@
     4.4 +<?xml version="1.0" encoding="UTF-8"?>
     4.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
     4.6 +    <type>org.netbeans.modules.apisupport.project</type>
     4.7 +    <configuration>
     4.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
     4.9 +            <code-name-base>org.netbeans.modules.java.breadcrumbs</code-name-base>
    4.10 +            <module-dependencies>
    4.11 +                <dependency>
    4.12 +                    <code-name-base>org.netbeans.libs.javacapi</code-name-base>
    4.13 +                    <build-prerequisite/>
    4.14 +                    <compile-dependency/>
    4.15 +                    <run-dependency>
    4.16 +                        <specification-version>7.9</specification-version>
    4.17 +                    </run-dependency>
    4.18 +                </dependency>
    4.19 +                <dependency>
    4.20 +                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
    4.21 +                    <build-prerequisite/>
    4.22 +                    <compile-dependency/>
    4.23 +                    <run-dependency>
    4.24 +                        <release-version>3</release-version>
    4.25 +                        <specification-version>3.18</specification-version>
    4.26 +                    </run-dependency>
    4.27 +                </dependency>
    4.28 +                <dependency>
    4.29 +                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
    4.30 +                    <build-prerequisite/>
    4.31 +                    <compile-dependency/>
    4.32 +                    <run-dependency>
    4.33 +                        <release-version>1</release-version>
    4.34 +                        <specification-version>1.25</specification-version>
    4.35 +                    </run-dependency>
    4.36 +                </dependency>
    4.37 +                <dependency>
    4.38 +                    <code-name-base>org.netbeans.modules.java.lexer</code-name-base>
    4.39 +                    <build-prerequisite/>
    4.40 +                    <compile-dependency/>
    4.41 +                    <run-dependency>
    4.42 +                        <release-version>1</release-version>
    4.43 +                        <specification-version>1.17</specification-version>
    4.44 +                    </run-dependency>
    4.45 +                </dependency>
    4.46 +                <dependency>
    4.47 +                    <code-name-base>org.netbeans.modules.java.navigation</code-name-base>
    4.48 +                    <run-dependency>
    4.49 +                        <release-version>1</release-version>
    4.50 +                        <specification-version>1.26</specification-version>
    4.51 +                    </run-dependency>
    4.52 +                </dependency>
    4.53 +                <dependency>
    4.54 +                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
    4.55 +                    <build-prerequisite/>
    4.56 +                    <compile-dependency/>
    4.57 +                    <run-dependency>
    4.58 +                        <specification-version>0.92</specification-version>
    4.59 +                    </run-dependency>
    4.60 +                </dependency>
    4.61 +                <dependency>
    4.62 +                    <code-name-base>org.netbeans.modules.java.sourceui</code-name-base>
    4.63 +                    <build-prerequisite/>
    4.64 +                    <compile-dependency/>
    4.65 +                    <run-dependency>
    4.66 +                        <release-version>1</release-version>
    4.67 +                        <specification-version>1.28</specification-version>
    4.68 +                    </run-dependency>
    4.69 +                </dependency>
    4.70 +                <dependency>
    4.71 +                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
    4.72 +                    <build-prerequisite/>
    4.73 +                    <compile-dependency/>
    4.74 +                    <run-dependency>
    4.75 +                        <release-version>2</release-version>
    4.76 +                        <specification-version>1.43</specification-version>
    4.77 +                    </run-dependency>
    4.78 +                </dependency>
    4.79 +                <dependency>
    4.80 +                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
    4.81 +                    <build-prerequisite/>
    4.82 +                    <compile-dependency/>
    4.83 +                    <run-dependency>
    4.84 +                        <release-version>1</release-version>
    4.85 +                        <specification-version>1.50</specification-version>
    4.86 +                    </run-dependency>
    4.87 +                </dependency>
    4.88 +                <dependency>
    4.89 +                    <code-name-base>org.openide.awt</code-name-base>
    4.90 +                    <build-prerequisite/>
    4.91 +                    <compile-dependency/>
    4.92 +                    <run-dependency>
    4.93 +                        <specification-version>7.40</specification-version>
    4.94 +                    </run-dependency>
    4.95 +                </dependency>
    4.96 +                <dependency>
    4.97 +                    <code-name-base>org.openide.explorer</code-name-base>
    4.98 +                    <build-prerequisite/>
    4.99 +                    <compile-dependency/>
   4.100 +                    <run-dependency>
   4.101 +                        <specification-version>6.41</specification-version>
   4.102 +                    </run-dependency>
   4.103 +                </dependency>
   4.104 +                <dependency>
   4.105 +                    <code-name-base>org.openide.filesystems</code-name-base>
   4.106 +                    <build-prerequisite/>
   4.107 +                    <compile-dependency/>
   4.108 +                    <run-dependency>
   4.109 +                        <specification-version>7.55</specification-version>
   4.110 +                    </run-dependency>
   4.111 +                </dependency>
   4.112 +                <dependency>
   4.113 +                    <code-name-base>org.openide.nodes</code-name-base>
   4.114 +                    <build-prerequisite/>
   4.115 +                    <compile-dependency/>
   4.116 +                    <run-dependency>
   4.117 +                        <specification-version>7.26</specification-version>
   4.118 +                    </run-dependency>
   4.119 +                </dependency>
   4.120 +                <dependency>
   4.121 +                    <code-name-base>org.openide.util</code-name-base>
   4.122 +                    <build-prerequisite/>
   4.123 +                    <compile-dependency/>
   4.124 +                    <run-dependency>
   4.125 +                        <specification-version>8.20</specification-version>
   4.126 +                    </run-dependency>
   4.127 +                </dependency>
   4.128 +                <dependency>
   4.129 +                    <code-name-base>org.openide.util.lookup</code-name-base>
   4.130 +                    <build-prerequisite/>
   4.131 +                    <compile-dependency/>
   4.132 +                    <run-dependency>
   4.133 +                        <specification-version>8.12</specification-version>
   4.134 +                    </run-dependency>
   4.135 +                </dependency>
   4.136 +            </module-dependencies>
   4.137 +            <public-packages/>
   4.138 +        </data>
   4.139 +    </configuration>
   4.140 +</project>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/BreadCrumbComponent.java	Wed Aug 08 15:09:00 2012 +0200
     5.3 @@ -0,0 +1,345 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2011-2012 Oracle and/or its affiliates. All rights reserved.
     5.8 + *
     5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    5.10 + * Other names may be trademarks of their respective owners.
    5.11 + *
    5.12 + * The contents of this file are subject to the terms of either the GNU
    5.13 + * General Public License Version 2 only ("GPL") or the Common
    5.14 + * Development and Distribution License("CDDL") (collectively, the
    5.15 + * "License"). You may not use this file except in compliance with the
    5.16 + * License. You can obtain a copy of the License at
    5.17 + * http://www.netbeans.org/cddl-gplv2.html
    5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.19 + * specific language governing permissions and limitations under the
    5.20 + * License.  When distributing the software, include this License Header
    5.21 + * Notice in each file and include the License file at
    5.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    5.23 + * particular file as subject to the "Classpath" exception as provided
    5.24 + * by Oracle in the GPL Version 2 section of the License file that
    5.25 + * accompanied this code. If applicable, add the following below the
    5.26 + * License Header, with the fields enclosed by brackets [] replaced by
    5.27 + * your own identifying information:
    5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    5.29 + *
    5.30 + * If you wish your version of this file to be governed by only the CDDL
    5.31 + * or only the GPL Version 2, indicate your decision by adding
    5.32 + * "[Contributor] elects to include this software in this distribution
    5.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    5.34 + * single choice of license, a recipient has the option to distribute
    5.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    5.36 + * to extend the choice of license to its licensees as provided above.
    5.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    5.38 + * Version 2 license, then the option applies only if the new code is
    5.39 + * made subject to such option by the copyright holder.
    5.40 + *
    5.41 + * Contributor(s):
    5.42 + *
    5.43 + * Portions Copyrighted 2011-2012 Sun Microsystems, Inc.
    5.44 + */
    5.45 +package org.netbeans.modules.java.breadcrumbs;
    5.46 +
    5.47 +import java.awt.AWTEvent;
    5.48 +import java.awt.BorderLayout;
    5.49 +import java.awt.Color;
    5.50 +import java.awt.Component;
    5.51 +import java.awt.Dimension;
    5.52 +import java.awt.Graphics;
    5.53 +import java.awt.Graphics2D;
    5.54 +import java.awt.LayoutManager;
    5.55 +import java.awt.Point;
    5.56 +import java.awt.RenderingHints;
    5.57 +import java.awt.Toolkit;
    5.58 +import java.awt.event.AWTEventListener;
    5.59 +import java.awt.event.MouseAdapter;
    5.60 +import java.awt.event.MouseEvent;
    5.61 +import java.beans.PropertyChangeEvent;
    5.62 +import java.beans.PropertyChangeListener;
    5.63 +import java.util.ArrayList;
    5.64 +import java.util.Collections;
    5.65 +import java.util.List;
    5.66 +import javax.swing.JComponent;
    5.67 +import javax.swing.JList;
    5.68 +import javax.swing.JPanel;
    5.69 +import javax.swing.Popup;
    5.70 +import javax.swing.PopupFactory;
    5.71 +import javax.swing.SwingUtilities;
    5.72 +import javax.swing.border.LineBorder;
    5.73 +import org.openide.explorer.ExplorerManager;
    5.74 +import org.openide.explorer.view.ListView;
    5.75 +import org.openide.explorer.view.NodeRenderer;
    5.76 +import org.openide.nodes.Node;
    5.77 +
    5.78 +/**
    5.79 + *
    5.80 + * @author lahvac
    5.81 + */
    5.82 +public class BreadCrumbComponent extends JComponent implements PropertyChangeListener {
    5.83 +
    5.84 +    public BreadCrumbComponent() {
    5.85 +        setPreferredSize(new Dimension(Integer.MAX_VALUE, 24));
    5.86 +        addMouseListener(new MouseAdapter() {
    5.87 +            @Override public void mouseClicked(MouseEvent e) {
    5.88 +                expand(e);
    5.89 +            }
    5.90 +        });
    5.91 +    }
    5.92 +
    5.93 +    private static final int INSET_HEIGHT = 2;
    5.94 +    private static final int SEPARATOR_INSETS = 10;
    5.95 +    private static final int START_INSET = 10;
    5.96 +    private static final int MAX_ROWS_IN_POP_UP = 20;
    5.97 +
    5.98 +    private ExplorerManager seenManager;
    5.99 +
   5.100 +    private ExplorerManager findManager() {
   5.101 +        ExplorerManager manager = ExplorerManager.find(this);
   5.102 +
   5.103 +        if (seenManager != manager) {
   5.104 +            if (seenManager != null) {
   5.105 +                seenManager.removePropertyChangeListener(this);
   5.106 +            }
   5.107 +            if (manager != null) {
   5.108 +                manager.addPropertyChangeListener(this);
   5.109 +            }
   5.110 +            seenManager = manager;
   5.111 +        }
   5.112 +
   5.113 +        assert manager != null;
   5.114 +
   5.115 +        return manager;
   5.116 +    }
   5.117 +    
   5.118 +    @Override
   5.119 +    protected void paintComponent(Graphics g) {
   5.120 +        if (nodes == null) measurePrepaint();
   5.121 +
   5.122 +        int x = START_INSET;
   5.123 +
   5.124 +        int height = getHeight();
   5.125 +        int insetHeight = (int) ((height - this.height) / 2);
   5.126 +        
   5.127 +        ((Graphics2D) g).addRenderingHints(Collections.singletonMap(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
   5.128 +        for (int i = 0; i < nodes.length; i++) {
   5.129 +            Component rendered = renderer.getListCellRendererComponent(fakeList, nodes[i], i, false, false);
   5.130 +            g.translate(x, insetHeight);
   5.131 +            rendered.setSize(rendered.getPreferredSize());
   5.132 +            rendered.paint(g);
   5.133 +            g.translate(-x, -insetHeight);
   5.134 +
   5.135 +            double angleX = height / 4;
   5.136 +
   5.137 +            x += sizes[i];
   5.138 +            
   5.139 +            g.drawLine(x + SEPARATOR_INSETS, INSET_HEIGHT, (int) (x + angleX + SEPARATOR_INSETS), (int) (height / 2));
   5.140 +            g.drawLine((int) (x + angleX + SEPARATOR_INSETS), (int) (height / 2), x + SEPARATOR_INSETS, (int) (height));
   5.141 +
   5.142 +            x += SEPARATOR_INSETS * 2 + angleX;
   5.143 +        }
   5.144 +    }
   5.145 +
   5.146 +    private final JList fakeList = new JList();
   5.147 +    private final NodeRenderer renderer = new NodeRenderer();
   5.148 +    private Node[] nodes;
   5.149 +    private double[] sizes;
   5.150 +    private double height;
   5.151 +
   5.152 +    private void measurePrepaint() {
   5.153 +        List<Node> path = computeNodePath();
   5.154 +
   5.155 +        int i = 0;
   5.156 +        
   5.157 +        nodes = path.toArray(new Node[path.size()]);
   5.158 +        sizes = new double[path.size()];
   5.159 +        
   5.160 +        int xTotal = 0;
   5.161 +        
   5.162 +        height = /*XXX*/0;
   5.163 +
   5.164 +        for (Node n : nodes) {
   5.165 +            Component rendered = renderer.getListCellRendererComponent(fakeList, n, i, false, false);
   5.166 +            Dimension preferedSize = rendered.getPreferredSize();
   5.167 +            xTotal += sizes[i] = preferedSize.width;
   5.168 +            
   5.169 +            height = Math.max(height, preferedSize.height);
   5.170 +
   5.171 +            i++;
   5.172 +        }
   5.173 +
   5.174 +        double angleX = height / 4;
   5.175 +        
   5.176 +        setPreferredSize(new Dimension((int) (xTotal + (nodes.length - 1) * (SEPARATOR_INSETS * 2 + angleX) + START_INSET), (int) (height + 2 * INSET_HEIGHT)));
   5.177 +    }
   5.178 +    
   5.179 +//    private static final int ICON_INSET = 5;
   5.180 +//    @Override
   5.181 +//    protected void paintComponent(Graphics g) {
   5.182 +//        if (names == null) measurePrepaint();
   5.183 +//
   5.184 +//        int x = START_INSET;
   5.185 +//
   5.186 +//        ((Graphics2D) g).addRenderingHints(Collections.singletonMap(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
   5.187 +//        for (int i = 0; i < names.length; i++) {
   5.188 +//            String dn = names[i];
   5.189 +//            Image icon = icons[i];
   5.190 +//            g.drawImage(icon, x, INSET_HEIGHT, null);
   5.191 +//            x += icon.getWidth(null) + ICON_INSET;
   5.192 +//            x += HtmlRenderer.renderString(dn, g, x, baseline, Integer.MAX_VALUE, getPreferredSize().height, g.getFont(), Color.BLACK, 0, true);
   5.193 +//
   5.194 +//            int angleX = fontHeight / 4;
   5.195 +//
   5.196 +//            g.drawLine(x + SEPARATOR_INSETS, INSET_HEIGHT, x + angleX + SEPARATOR_INSETS, INSET_HEIGHT + fontHeight / 2);
   5.197 +//            g.drawLine(x + angleX + SEPARATOR_INSETS, INSET_HEIGHT + fontHeight / 2, x + SEPARATOR_INSETS, INSET_HEIGHT + fontHeight);
   5.198 +//
   5.199 +//            x += SEPARATOR_INSETS * 2 + angleX;
   5.200 +//        }
   5.201 +//    }
   5.202 +//
   5.203 +//    private String[] names;
   5.204 +//    private Image[] icons;
   5.205 +//    private double[] sizes;
   5.206 +//    private int fontHeight;
   5.207 +//    private int baseline;
   5.208 +//
   5.209 +//    private void measurePrepaint() {
   5.210 +//        //TODO: from CompletionJList:
   5.211 +//        Graphics cellPreferredSizeGraphics = null;
   5.212 +//        if (cellPreferredSizeGraphics == null) {
   5.213 +//            // CompletionJList.this.getGraphics() is null
   5.214 +//            cellPreferredSizeGraphics = java.awt.GraphicsEnvironment.
   5.215 +//                    getLocalGraphicsEnvironment().getDefaultScreenDevice().
   5.216 +//                    getDefaultConfiguration().createCompatibleImage(1, 1).getGraphics();
   5.217 +//            assert (cellPreferredSizeGraphics != null);
   5.218 +//        }
   5.219 +//        
   5.220 +//        FontMetrics fm = cellPreferredSizeGraphics.getFontMetrics(getFont());
   5.221 +//        fontHeight = fm.getHeight();
   5.222 +//        baseline = fm.getAscent() + fm.getLeading() + INSET_HEIGHT;
   5.223 +//        List<Node> path = computeNodePath();
   5.224 +//
   5.225 +//        int i = 0;
   5.226 +//        int xTotal = START_INSET;
   5.227 +//        
   5.228 +//        names = new String[path.size()];
   5.229 +//        icons = new Image[path.size()];
   5.230 +//        sizes = new double[path.size()];
   5.231 +//
   5.232 +//        for (Node n : path) {
   5.233 +//            String html = n.getHtmlDisplayName();
   5.234 +//            icons[i] = n.getIcon(BeanInfo.ICON_COLOR_16x16);
   5.235 +//            int iconSize = icons[i].getWidth(null) + ICON_INSET;
   5.236 +//            if (html != null) {
   5.237 +//                names[i] = "<html>" + html;
   5.238 +//                xTotal += sizes[i] = HtmlRenderer.renderHTML(html, cellPreferredSizeGraphics, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, getFont(), Color.BLACK, 0, true) + iconSize;
   5.239 +//            } else {
   5.240 +//                String dn = n.getDisplayName();
   5.241 +//                names[i] = dn;
   5.242 +//                xTotal += sizes[i] = HtmlRenderer.renderPlainString(dn, cellPreferredSizeGraphics, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, getFont(), Color.BLACK, 0, true) + iconSize;
   5.243 +//            }
   5.244 +//
   5.245 +//            i++;
   5.246 +//        }
   5.247 +//
   5.248 +//        int angleX = fontHeight / 4;
   5.249 +//        setPreferredSize(new Dimension(xTotal + (names.length - 1) * (SEPARATOR_INSETS * 2 + angleX), fontHeight + 2 * INSET_HEIGHT));
   5.250 +//    }
   5.251 +
   5.252 +    @Override
   5.253 +    public void propertyChange(PropertyChangeEvent evt) {
   5.254 +        SwingUtilities.invokeLater(new Runnable() {
   5.255 +            @Override public void run() {
   5.256 +                measurePrepaint();
   5.257 +                repaint();
   5.258 +            }
   5.259 +        });
   5.260 +        
   5.261 +    }
   5.262 +
   5.263 +    private void expand(MouseEvent e) {
   5.264 +        int clickX = e.getPoint().x;
   5.265 +        int elemX = START_INSET;
   5.266 +
   5.267 +        for (int i = 0; i < sizes.length; i++) {
   5.268 +            int startX = elemX;
   5.269 +            elemX += sizes[i];
   5.270 +
   5.271 +            double angleX = height / 4;
   5.272 +
   5.273 +            elemX += SEPARATOR_INSETS + angleX;
   5.274 +            
   5.275 +            if (clickX <= elemX) {
   5.276 +                //found:
   5.277 +                List<Node> path = computeNodePath();
   5.278 +                expand(startX, path.get(i));
   5.279 +                return ;
   5.280 +            }
   5.281 +            
   5.282 +            elemX += SEPARATOR_INSETS;
   5.283 +        }
   5.284 +    }
   5.285 +
   5.286 +    private List<Node> computeNodePath() {
   5.287 +        ExplorerManager manager = findManager();
   5.288 +        List<Node> path = new ArrayList<Node>();
   5.289 +        Node sel = manager.getExploredContext();
   5.290 +
   5.291 +        while (sel != null) {
   5.292 +            path.add(sel);
   5.293 +            sel = sel.getParentNode();
   5.294 +        }
   5.295 +
   5.296 +        path.remove(path.size() - 1); //XXX
   5.297 +
   5.298 +        Collections.reverse(path);
   5.299 +        
   5.300 +        return path;
   5.301 +    }
   5.302 +
   5.303 +    private void expand(int startX, final Node what) {
   5.304 +        if (what.getChildren().getNodesCount() == 0) return ;
   5.305 +        
   5.306 +        final ExplorerManager expandManager = new ExplorerManager();
   5.307 +        class Expanded extends JPanel implements ExplorerManager.Provider {
   5.308 +            public Expanded(LayoutManager layout) {
   5.309 +                super(layout);
   5.310 +            }
   5.311 +            @Override public ExplorerManager getExplorerManager() {
   5.312 +                return expandManager;
   5.313 +            }
   5.314 +        }
   5.315 +        final JPanel expanded = new Expanded(new BorderLayout());
   5.316 +        expanded.setBorder(new LineBorder(Color.BLACK, 1));
   5.317 +        expanded.add(new ListView() {
   5.318 +            {
   5.319 +                list.setVisibleRowCount(Math.min(what.getChildren().getNodesCount(), MAX_ROWS_IN_POP_UP));
   5.320 +            }
   5.321 +        }, BorderLayout.CENTER);
   5.322 +        expandManager.setRootContext(what);
   5.323 +        
   5.324 +        Point place = new Point(startX, 0);
   5.325 +        
   5.326 +        SwingUtilities.convertPointToScreen(place, this);
   5.327 +        
   5.328 +        expanded.validate();
   5.329 +        
   5.330 +        final Popup popup = PopupFactory.getSharedInstance().getPopup(this, expanded, place.x, place.y - expanded.getPreferredSize().height);
   5.331 +        
   5.332 +        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
   5.333 +            @Override public void eventDispatched(AWTEvent event) {
   5.334 +                if (event instanceof MouseEvent && ((MouseEvent) event).getClickCount() > 0) {
   5.335 +                    Object source = event.getSource();
   5.336 +                    while (source instanceof Component) {
   5.337 +                        if (source == expanded) return ; //accept
   5.338 +                        source = ((Component) source).getParent();
   5.339 +                    }
   5.340 +                    popup.hide();
   5.341 +                    Toolkit.getDefaultToolkit().removeAWTEventListener(this);
   5.342 +                }
   5.343 +            }
   5.344 +        }, AWTEvent.MOUSE_EVENT_MASK);
   5.345 +        
   5.346 +        popup.show();
   5.347 +    }
   5.348 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/BreadCrumbsScanningTask.java	Wed Aug 08 15:09:00 2012 +0200
     6.3 @@ -0,0 +1,164 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2011-2012 Oracle and/or its affiliates. All rights reserved.
     6.8 + *
     6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    6.10 + * Other names may be trademarks of their respective owners.
    6.11 + *
    6.12 + * The contents of this file are subject to the terms of either the GNU
    6.13 + * General Public License Version 2 only ("GPL") or the Common
    6.14 + * Development and Distribution License("CDDL") (collectively, the
    6.15 + * "License"). You may not use this file except in compliance with the
    6.16 + * License. You can obtain a copy of the License at
    6.17 + * http://www.netbeans.org/cddl-gplv2.html
    6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    6.19 + * specific language governing permissions and limitations under the
    6.20 + * License.  When distributing the software, include this License Header
    6.21 + * Notice in each file and include the License file at
    6.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    6.23 + * particular file as subject to the "Classpath" exception as provided
    6.24 + * by Oracle in the GPL Version 2 section of the License file that
    6.25 + * accompanied this code. If applicable, add the following below the
    6.26 + * License Header, with the fields enclosed by brackets [] replaced by
    6.27 + * your own identifying information:
    6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    6.29 + *
    6.30 + * If you wish your version of this file to be governed by only the CDDL
    6.31 + * or only the GPL Version 2, indicate your decision by adding
    6.32 + * "[Contributor] elects to include this software in this distribution
    6.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    6.34 + * single choice of license, a recipient has the option to distribute
    6.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    6.36 + * to extend the choice of license to its licensees as provided above.
    6.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    6.38 + * Version 2 license, then the option applies only if the new code is
    6.39 + * made subject to such option by the copyright holder.
    6.40 + *
    6.41 + * Contributor(s):
    6.42 + *
    6.43 + * Portions Copyrighted 2011-2012 Sun Microsystems, Inc.
    6.44 + */
    6.45 +package org.netbeans.modules.java.breadcrumbs;
    6.46 +
    6.47 +import com.sun.source.util.TreePath;
    6.48 +import java.util.ArrayList;
    6.49 +import java.util.Collection;
    6.50 +import java.util.Collections;
    6.51 +import java.util.List;
    6.52 +import java.util.concurrent.atomic.AtomicBoolean;
    6.53 +import javax.swing.text.Document;
    6.54 +import org.netbeans.api.editor.mimelookup.MimeRegistration;
    6.55 +import org.netbeans.api.java.source.CompilationInfo;
    6.56 +import org.netbeans.api.java.source.JavaParserResultTask;
    6.57 +import org.netbeans.api.java.source.JavaSource.Phase;
    6.58 +import org.netbeans.api.java.source.support.CaretAwareJavaSourceTaskFactory;
    6.59 +import org.netbeans.modules.parsing.api.Snapshot;
    6.60 +import org.netbeans.modules.parsing.spi.CursorMovedSchedulerEvent;
    6.61 +import org.netbeans.modules.parsing.spi.Parser.Result;
    6.62 +import org.netbeans.modules.parsing.spi.Scheduler;
    6.63 +import org.netbeans.modules.parsing.spi.SchedulerEvent;
    6.64 +import org.netbeans.modules.parsing.spi.SchedulerTask;
    6.65 +import org.netbeans.modules.parsing.spi.TaskFactory;
    6.66 +import org.openide.explorer.ExplorerManager;
    6.67 +import org.openide.nodes.Node;
    6.68 +
    6.69 +/**
    6.70 + *
    6.71 + * @author lahvac
    6.72 + */
    6.73 +public final class BreadCrumbsScanningTask extends JavaParserResultTask {
    6.74 +
    6.75 +    private static final String COLOR = "#707070";
    6.76 +    private final AtomicBoolean cancel = new AtomicBoolean();
    6.77 +
    6.78 +    private BreadCrumbsScanningTask() {
    6.79 +        super(Phase.RESOLVED);
    6.80 +    }
    6.81 +
    6.82 +    @Override
    6.83 +    public void run(Result result, SchedulerEvent event) {
    6.84 +        cancel.set(false);
    6.85 +
    6.86 +        CompilationInfo info = CompilationInfo.get(result);
    6.87 +        if (info == null) {
    6.88 +            return;
    6.89 +        }
    6.90 +
    6.91 +        Document doc = info.getSnapshot().getSource().getDocument(false);
    6.92 +        if (doc == null) {
    6.93 +            return;
    6.94 +        }
    6.95 +
    6.96 +        int caretPosition = event instanceof CursorMovedSchedulerEvent
    6.97 +                ? ((CursorMovedSchedulerEvent) event).getCaretOffset()
    6.98 +                : CaretAwareJavaSourceTaskFactory.getLastPosition(result.getSnapshot().getSource().getFileObject()); //XXX
    6.99 +
   6.100 +        if (cancel.get()) {
   6.101 +            return;
   6.102 +        }
   6.103 +
   6.104 +        TreePath path = info.getTreeUtilities().pathFor(caretPosition);
   6.105 +
   6.106 +        if (cancel.get()) {
   6.107 +            return;
   6.108 +        }
   6.109 +
   6.110 +        List<TreePath> pathList = new ArrayList<TreePath>();
   6.111 +
   6.112 +        while (path != null) {
   6.113 +            pathList.add(path);
   6.114 +            path = path.getParentPath();
   6.115 +        }
   6.116 +
   6.117 +        Collections.reverse(pathList);
   6.118 +
   6.119 +        Node root = null;
   6.120 +        Node lastNode = null;
   6.121 +
   6.122 +        for (TreePath curr : pathList) {
   6.123 +            if (root == null) {
   6.124 +                lastNode = root = NodeImpl.createBreadcrumbs(info, curr);
   6.125 +            } else {
   6.126 +                Node[] children = lastNode.getChildren().getNodes(true);
   6.127 +                int pos = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), curr.getLeaf());
   6.128 +
   6.129 +                for (Node child : children) {
   6.130 +                    if (Integer.valueOf(pos).equals(child.getLookup().lookup(Integer.class))) {
   6.131 +                        lastNode = child;
   6.132 +                        break;
   6.133 +                    }
   6.134 +                }
   6.135 +            }
   6.136 +        }
   6.137 +
   6.138 +        ExplorerManager manager = HolderImpl.get(result.getSnapshot().getSource().getDocument(false)).getManager();
   6.139 +
   6.140 +        manager.setRootContext(root);
   6.141 +        manager.setExploredContext(lastNode);
   6.142 +    }
   6.143 +
   6.144 +    @Override
   6.145 +    public int getPriority() {
   6.146 +        return 100;
   6.147 +    }
   6.148 +
   6.149 +    @Override
   6.150 +    public Class<? extends Scheduler> getSchedulerClass() {
   6.151 +        return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
   6.152 +    }
   6.153 +
   6.154 +    @Override
   6.155 +    public void cancel() {
   6.156 +        cancel.set(true);
   6.157 +    }
   6.158 +
   6.159 +    @MimeRegistration(mimeType="text/x-java", service=TaskFactory.class)
   6.160 +    public static final class Factory extends TaskFactory {
   6.161 +
   6.162 +        @Override
   6.163 +        public Collection<? extends SchedulerTask> create(Snapshot snapshot) {
   6.164 +            return Collections.singleton(new BreadCrumbsScanningTask());
   6.165 +        }
   6.166 +    }
   6.167 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/Bundle.properties	Wed Aug 08 15:09:00 2012 +0200
     7.3 @@ -0,0 +1,1 @@
     7.4 +OpenIDE-Module-Name=Java Breadcrumbs
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/HolderImpl.java	Wed Aug 08 15:09:00 2012 +0200
     8.3 @@ -0,0 +1,68 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2011-2012 Oracle and/or its affiliates. All rights reserved.
     8.8 + *
     8.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    8.10 + * Other names may be trademarks of their respective owners.
    8.11 + *
    8.12 + * The contents of this file are subject to the terms of either the GNU
    8.13 + * General Public License Version 2 only ("GPL") or the Common
    8.14 + * Development and Distribution License("CDDL") (collectively, the
    8.15 + * "License"). You may not use this file except in compliance with the
    8.16 + * License. You can obtain a copy of the License at
    8.17 + * http://www.netbeans.org/cddl-gplv2.html
    8.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    8.19 + * specific language governing permissions and limitations under the
    8.20 + * License.  When distributing the software, include this License Header
    8.21 + * Notice in each file and include the License file at
    8.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    8.23 + * particular file as subject to the "Classpath" exception as provided
    8.24 + * by Oracle in the GPL Version 2 section of the License file that
    8.25 + * accompanied this code. If applicable, add the following below the
    8.26 + * License Header, with the fields enclosed by brackets [] replaced by
    8.27 + * your own identifying information:
    8.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    8.29 + *
    8.30 + * If you wish your version of this file to be governed by only the CDDL
    8.31 + * or only the GPL Version 2, indicate your decision by adding
    8.32 + * "[Contributor] elects to include this software in this distribution
    8.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.34 + * single choice of license, a recipient has the option to distribute
    8.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.36 + * to extend the choice of license to its licensees as provided above.
    8.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.38 + * Version 2 license, then the option applies only if the new code is
    8.39 + * made subject to such option by the copyright holder.
    8.40 + *
    8.41 + * Contributor(s):
    8.42 + *
    8.43 + * Portions Copyrighted 2011-2012 Sun Microsystems, Inc.
    8.44 + */
    8.45 +package org.netbeans.modules.java.breadcrumbs;
    8.46 +
    8.47 +import javax.swing.text.Document;
    8.48 +import org.openide.explorer.ExplorerManager;
    8.49 +
    8.50 +/**
    8.51 + *
    8.52 + * @author lahvac
    8.53 + */
    8.54 +public class HolderImpl {
    8.55 +
    8.56 +    public static HolderImpl get(Document doc) {
    8.57 +        HolderImpl instance = (HolderImpl) doc.getProperty(HolderImpl.class);
    8.58 +
    8.59 +        if (instance == null) {
    8.60 +            doc.putProperty(HolderImpl.class, instance = new HolderImpl());
    8.61 +        }
    8.62 +
    8.63 +        return instance;
    8.64 +    }
    8.65 +
    8.66 +    private final ExplorerManager manager = new ExplorerManager();
    8.67 +
    8.68 +    public ExplorerManager getManager() {
    8.69 +        return manager;
    8.70 +    }
    8.71 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/NodeImpl.java	Wed Aug 08 15:09:00 2012 +0200
     9.3 @@ -0,0 +1,332 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2011-2012 Oracle and/or its affiliates. All rights reserved.
     9.8 + *
     9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    9.10 + * Other names may be trademarks of their respective owners.
    9.11 + *
    9.12 + * The contents of this file are subject to the terms of either the GNU
    9.13 + * General Public License Version 2 only ("GPL") or the Common
    9.14 + * Development and Distribution License("CDDL") (collectively, the
    9.15 + * "License"). You may not use this file except in compliance with the
    9.16 + * License. You can obtain a copy of the License at
    9.17 + * http://www.netbeans.org/cddl-gplv2.html
    9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.19 + * specific language governing permissions and limitations under the
    9.20 + * License.  When distributing the software, include this License Header
    9.21 + * Notice in each file and include the License file at
    9.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    9.23 + * particular file as subject to the "Classpath" exception as provided
    9.24 + * by Oracle in the GPL Version 2 section of the License file that
    9.25 + * accompanied this code. If applicable, add the following below the
    9.26 + * License Header, with the fields enclosed by brackets [] replaced by
    9.27 + * your own identifying information:
    9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.29 + *
    9.30 + * If you wish your version of this file to be governed by only the CDDL
    9.31 + * or only the GPL Version 2, indicate your decision by adding
    9.32 + * "[Contributor] elects to include this software in this distribution
    9.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.34 + * single choice of license, a recipient has the option to distribute
    9.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.36 + * to extend the choice of license to its licensees as provided above.
    9.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.38 + * Version 2 license, then the option applies only if the new code is
    9.39 + * made subject to such option by the copyright holder.
    9.40 + *
    9.41 + * Contributor(s):
    9.42 + *
    9.43 + * Portions Copyrighted 2011-2012 Sun Microsystems, Inc.
    9.44 + */
    9.45 +package org.netbeans.modules.java.breadcrumbs;
    9.46 +
    9.47 +import com.sun.source.tree.CaseTree;
    9.48 +import com.sun.source.tree.CatchTree;
    9.49 +import com.sun.source.tree.ClassTree;
    9.50 +import com.sun.source.tree.DoWhileLoopTree;
    9.51 +import com.sun.source.tree.EnhancedForLoopTree;
    9.52 +import com.sun.source.tree.ExpressionTree;
    9.53 +import com.sun.source.tree.ForLoopTree;
    9.54 +import com.sun.source.tree.IfTree;
    9.55 +import com.sun.source.tree.MethodTree;
    9.56 +import com.sun.source.tree.SwitchTree;
    9.57 +import com.sun.source.tree.SynchronizedTree;
    9.58 +import com.sun.source.tree.Tree;
    9.59 +import com.sun.source.tree.VariableTree;
    9.60 +import com.sun.source.tree.WhileLoopTree;
    9.61 +import com.sun.source.util.SourcePositions;
    9.62 +import com.sun.source.util.TreePath;
    9.63 +import com.sun.source.util.TreeScanner;
    9.64 +import com.sun.source.util.Trees;
    9.65 +import java.awt.Image;
    9.66 +import java.awt.datatransfer.Transferable;
    9.67 +import java.io.CharConversionException;
    9.68 +import java.io.IOException;
    9.69 +import java.util.List;
    9.70 +import javax.lang.model.element.Element;
    9.71 +import javax.swing.Action;
    9.72 +import javax.swing.Icon;
    9.73 +import org.netbeans.api.java.source.CompilationController;
    9.74 +import org.netbeans.api.java.source.CompilationInfo;
    9.75 +import org.netbeans.api.java.source.JavaSource;
    9.76 +import org.netbeans.api.java.source.JavaSource.Phase;
    9.77 +import org.netbeans.api.java.source.Task;
    9.78 +import org.netbeans.api.java.source.TreePathHandle;
    9.79 +import org.netbeans.api.java.source.ui.ElementIcons;
    9.80 +import org.openide.filesystems.FileObject;
    9.81 +import org.openide.filesystems.FileUtil;
    9.82 +import org.openide.nodes.AbstractNode;
    9.83 +import org.openide.nodes.ChildFactory;
    9.84 +import org.openide.nodes.Children;
    9.85 +import org.openide.nodes.Node;
    9.86 +import org.openide.util.Exceptions;
    9.87 +import org.openide.util.ImageUtilities;
    9.88 +import org.openide.util.datatransfer.PasteType;
    9.89 +import org.openide.util.lookup.Lookups;
    9.90 +import org.openide.xml.XMLUtil;
    9.91 +
    9.92 +/**
    9.93 + *
    9.94 + * @author Dusan Balek
    9.95 + */
    9.96 +public class NodeImpl extends AbstractNode {
    9.97 +
    9.98 +    private static final String COLOR = "#707070";
    9.99 +    private final Image icon;
   9.100 +    private String htmlDisplayName;
   9.101 +//    private OpenAction openAction;
   9.102 +
   9.103 +    public NodeImpl(TreePathHandle tph, Image icon, String htmlDisplayName, FileObject fileObject, int pos) {
   9.104 +        super(Children.create(new ChildrenFactoryImpl(tph), false), Lookups.fixed(tph, Integer.valueOf(pos)));
   9.105 +        this.icon = icon;
   9.106 +        this.htmlDisplayName = htmlDisplayName;
   9.107 +//        this.openAction = new OpenAction(fileObject, pos);
   9.108 +    }
   9.109 +
   9.110 +    @Override
   9.111 +    public String getHtmlDisplayName() {
   9.112 +        return htmlDisplayName;
   9.113 +    }
   9.114 +
   9.115 +    @Override
   9.116 +    public Action getPreferredAction() {
   9.117 +        return null;//openAction;
   9.118 +    }
   9.119 +
   9.120 +    @Override
   9.121 +    public boolean canCopy() {
   9.122 +        return false;
   9.123 +    }
   9.124 +
   9.125 +    @Override
   9.126 +    public boolean canCut() {
   9.127 +        return false;
   9.128 +    }
   9.129 +
   9.130 +    @Override
   9.131 +    public boolean canDestroy() {
   9.132 +        return false;
   9.133 +    }
   9.134 +
   9.135 +    @Override
   9.136 +    public boolean canRename() {
   9.137 +        return false;
   9.138 +    }
   9.139 +
   9.140 +    @Override
   9.141 +    public PasteType getDropType(Transferable t, int action, int index) {
   9.142 +        return null;
   9.143 +    }
   9.144 +
   9.145 +    @Override
   9.146 +    public Transferable drag() throws IOException {
   9.147 +        return null;
   9.148 +    }
   9.149 +
   9.150 +    @Override
   9.151 +    protected void createPasteTypes(Transferable t, List<PasteType> s) {
   9.152 +        // Do nothing
   9.153 +    }
   9.154 +
   9.155 +    @Override
   9.156 +    public Image getIcon(int type) {
   9.157 +        if (icon != null) return icon;
   9.158 +        return super.getIcon(type);
   9.159 +    }
   9.160 +
   9.161 +    @Override
   9.162 +    public Image getOpenedIcon(int type) {
   9.163 +        if (icon != null) return icon;
   9.164 +        return super.getOpenedIcon(type);
   9.165 +    }
   9.166 +
   9.167 +    public static Node createBreadcrumbs(final CompilationInfo info, TreePath path) {
   9.168 +        final Trees trees = info.getTrees();
   9.169 +        final SourcePositions sp = trees.getSourcePositions();
   9.170 +        int pos = (int) sp.getStartPosition(path.getCompilationUnit(), path.getLeaf());
   9.171 +        TreePathHandle tph = TreePathHandle.create(path, info);
   9.172 +            final Tree leaf = path.getLeaf();
   9.173 +            switch (leaf.getKind()) {
   9.174 +                case COMPILATION_UNIT:
   9.175 +                    return new NodeImpl(tph, null, FileUtil.getFileDisplayName(info.getFileObject()), info.getFileObject(), pos);
   9.176 +                case CLASS:
   9.177 +                case INTERFACE:
   9.178 +                case ENUM:
   9.179 +                case ANNOTATION_TYPE:
   9.180 +                    return new NodeImpl(tph, iconFor(info, path), ((ClassTree) leaf).getSimpleName().toString(), info.getFileObject(), pos);
   9.181 +                case METHOD:
   9.182 +                    return new NodeImpl(tph, iconFor(info, path), ((MethodTree) leaf).getName().toString(), info.getFileObject(), pos);
   9.183 +                case VARIABLE:
   9.184 +                    return new NodeImpl(tph, iconFor(info, path), ((VariableTree) leaf).getName().toString(), info.getFileObject(), pos);
   9.185 +                case CASE:
   9.186 +                    ExpressionTree expr = ((CaseTree) leaf).getExpression();
   9.187 +                    StringBuilder sb = new StringBuilder(expr == null ? "default:" : "case "); //NOI18N
   9.188 +                    if (expr != null) {
   9.189 +                        sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.190 +                        sb.append(escape(((CaseTree) leaf).getExpression().toString()));
   9.191 +                        sb.append(":"); //NOI18N
   9.192 +                        sb.append("</font>"); //NOI18N
   9.193 +                    }
   9.194 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.195 +                case CATCH:
   9.196 +                    sb = new StringBuilder("catch "); //NOI18N
   9.197 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.198 +                    sb.append(escape(((CatchTree) leaf).getParameter().toString()));
   9.199 +                    sb.append("</font>"); //NOI18N
   9.200 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.201 +                case DO_WHILE_LOOP:
   9.202 +                    sb = new StringBuilder("do ... while "); //NOI18N
   9.203 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.204 +                    sb.append(escape(((DoWhileLoopTree) leaf).getCondition().toString()));
   9.205 +                    sb.append("</font>"); //NOI18N
   9.206 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.207 +                case ENHANCED_FOR_LOOP:
   9.208 +                    sb = new StringBuilder("for "); //NOI18N
   9.209 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.210 +                    sb.append("("); //NOI18N
   9.211 +                    sb.append(escape(((EnhancedForLoopTree) leaf).getVariable().toString()));
   9.212 +                    sb.append(" : "); //NOI18N
   9.213 +                    sb.append(escape(((EnhancedForLoopTree) leaf).getExpression().toString()));
   9.214 +                    sb.append(")"); //NOI18N
   9.215 +                    sb.append("</font>"); //NOI18N
   9.216 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.217 +                case FOR_LOOP:
   9.218 +                    sb = new StringBuilder("for "); //NOI18N
   9.219 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.220 +                    sb.append("("); //NOI18N
   9.221 +                    sb.append(escape(((ForLoopTree) leaf).getInitializer().toString()));
   9.222 +                    sb.append("; "); //NOI18N
   9.223 +                    sb.append(escape(((ForLoopTree) leaf).getCondition().toString()));
   9.224 +                    sb.append("; "); //NOI18N
   9.225 +                    sb.append(escape(((ForLoopTree) leaf).getUpdate().toString()));
   9.226 +                    sb.append(")"); //NOI18N
   9.227 +                    sb.append("</font>"); //NOI18N
   9.228 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.229 +                case IF:
   9.230 +                    sb = new StringBuilder("if "); //NOI18N
   9.231 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.232 +                    sb.append(escape(((IfTree) leaf).getCondition().toString()));
   9.233 +                    sb.append("</font>"); //NOI18N
   9.234 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.235 +                case SWITCH:
   9.236 +                    sb = new StringBuilder("switch "); //NOI18N
   9.237 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.238 +                    sb.append("("); //NOI18N
   9.239 +                    sb.append(escape(((SwitchTree) leaf).getExpression().toString()));
   9.240 +                    sb.append(")"); //NOI18N
   9.241 +                    sb.append("</font>"); //NOI18N
   9.242 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.243 +                case SYNCHRONIZED:
   9.244 +                    sb = new StringBuilder("synchronized "); //NOI18N
   9.245 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.246 +                    sb.append("("); //NOI18N
   9.247 +                    sb.append(escape(((SynchronizedTree) leaf).getExpression().toString()));
   9.248 +                    sb.append(")"); //NOI18N
   9.249 +                    sb.append("</font>"); //NOI18N
   9.250 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.251 +                case TRY:
   9.252 +                    sb = new StringBuilder("try"); //NOI18N
   9.253 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.254 +                case WHILE_LOOP:
   9.255 +                    sb = new StringBuilder("while "); //NOI18N
   9.256 +                    sb.append("<font color=").append(COLOR).append(">"); // NOI18N
   9.257 +                    sb.append("("); //NOI18N
   9.258 +                    sb.append(escape(((WhileLoopTree) leaf).getCondition().toString()));
   9.259 +                    sb.append(")"); //NOI18N
   9.260 +                    sb.append("</font>"); //NOI18N
   9.261 +                    return new NodeImpl(tph, null, sb.toString(), info.getFileObject(), (int) sp.getStartPosition(path.getCompilationUnit(), leaf));
   9.262 +            }
   9.263 +
   9.264 +            return null;
   9.265 +    }
   9.266 +
   9.267 +    static String escape(String s) {
   9.268 +        if (s != null) {
   9.269 +            try {
   9.270 +                return XMLUtil.toAttributeValue(s);
   9.271 +            } catch (CharConversionException ex) {
   9.272 +            }
   9.273 +        }
   9.274 +        return null;
   9.275 +    }
   9.276 +    
   9.277 +    private static Image iconFor(CompilationInfo info, TreePath path) {
   9.278 +        Element el = info.getTrees().getElement(path);
   9.279 +        if (el == null) return null;
   9.280 +        Icon icon = ElementIcons.getElementIcon(el.getKind(), el.getModifiers());
   9.281 +        if (icon == null) return null;
   9.282 +        return ImageUtilities.icon2Image(icon);
   9.283 +    }
   9.284 +    
   9.285 +    private static final class ChildrenFactoryImpl extends ChildFactory<Node> {
   9.286 +
   9.287 +        private final TreePathHandle tph;
   9.288 +
   9.289 +        public ChildrenFactoryImpl(TreePathHandle tph) {
   9.290 +            this.tph = tph;
   9.291 +        }
   9.292 +
   9.293 +        @Override
   9.294 +        protected boolean createKeys(final List<Node> toPopulate) {
   9.295 +            try {
   9.296 +                JavaSource.forFileObject(tph.getFileObject()).runUserActionTask(new Task<CompilationController>() {
   9.297 +                    @Override public void run(final CompilationController cc) throws Exception {
   9.298 +                        cc.toPhase(Phase.RESOLVED); //XXX: resolved?
   9.299 +
   9.300 +                        final TreePath tp = tph.resolve(cc);
   9.301 +                        
   9.302 +                        if (tp == null) {
   9.303 +                             //XXX: log
   9.304 +                            return;
   9.305 +                        }
   9.306 +
   9.307 +                        tp.getLeaf().accept(new TreeScanner<Void, TreePath>() {
   9.308 +                            @Override public Void scan(Tree node, TreePath p) {
   9.309 +                                if (node == null) return null;
   9.310 +                                p = new TreePath(p, node);
   9.311 +                                Node n = createBreadcrumbs(cc, p);
   9.312 +                                if (n != null) {
   9.313 +                                    toPopulate.add(n);
   9.314 +                                } else {
   9.315 +                                    return super.scan(node, p);
   9.316 +                                }
   9.317 +                                return null;
   9.318 +                            }
   9.319 +                        }, tp);
   9.320 +                    }
   9.321 +                }, true);
   9.322 +            } catch (IOException ex) {
   9.323 +                Exceptions.printStackTrace(ex);
   9.324 +            }
   9.325 +
   9.326 +            return true;
   9.327 +        }
   9.328 +
   9.329 +        @Override
   9.330 +        protected Node createNodeForKey(Node key) {
   9.331 +            return key;
   9.332 +        }
   9.333 +        
   9.334 +    }
   9.335 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/SideBarFactoryImpl.java	Wed Aug 08 15:09:00 2012 +0200
    10.3 @@ -0,0 +1,76 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2011-2012 Oracle and/or its affiliates. All rights reserved.
    10.8 + *
    10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   10.10 + * Other names may be trademarks of their respective owners.
   10.11 + *
   10.12 + * The contents of this file are subject to the terms of either the GNU
   10.13 + * General Public License Version 2 only ("GPL") or the Common
   10.14 + * Development and Distribution License("CDDL") (collectively, the
   10.15 + * "License"). You may not use this file except in compliance with the
   10.16 + * License. You can obtain a copy of the License at
   10.17 + * http://www.netbeans.org/cddl-gplv2.html
   10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.19 + * specific language governing permissions and limitations under the
   10.20 + * License.  When distributing the software, include this License Header
   10.21 + * Notice in each file and include the License file at
   10.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   10.23 + * particular file as subject to the "Classpath" exception as provided
   10.24 + * by Oracle in the GPL Version 2 section of the License file that
   10.25 + * accompanied this code. If applicable, add the following below the
   10.26 + * License Header, with the fields enclosed by brackets [] replaced by
   10.27 + * your own identifying information:
   10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.29 + *
   10.30 + * If you wish your version of this file to be governed by only the CDDL
   10.31 + * or only the GPL Version 2, indicate your decision by adding
   10.32 + * "[Contributor] elects to include this software in this distribution
   10.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.34 + * single choice of license, a recipient has the option to distribute
   10.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.36 + * to extend the choice of license to its licensees as provided above.
   10.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.38 + * Version 2 license, then the option applies only if the new code is
   10.39 + * made subject to such option by the copyright holder.
   10.40 + *
   10.41 + * Contributor(s):
   10.42 + *
   10.43 + * Portions Copyrighted 2011-2012 Sun Microsystems, Inc.
   10.44 + */
   10.45 +package org.netbeans.modules.java.breadcrumbs;
   10.46 +
   10.47 +import java.awt.BorderLayout;
   10.48 +import javax.swing.JComponent;
   10.49 +import javax.swing.JPanel;
   10.50 +import javax.swing.text.Document;
   10.51 +import javax.swing.text.JTextComponent;
   10.52 +import org.netbeans.editor.SideBarFactory;
   10.53 +import org.openide.explorer.ExplorerManager;
   10.54 +
   10.55 +/**
   10.56 + *
   10.57 + * @author lahvac
   10.58 + */
   10.59 +public class SideBarFactoryImpl implements SideBarFactory {
   10.60 +
   10.61 +    @Override
   10.62 +    public JComponent createSideBar(JTextComponent target) {
   10.63 +        final Document doc = target.getDocument();
   10.64 +
   10.65 +        class P extends JPanel implements ExplorerManager.Provider {
   10.66 +            @Override public ExplorerManager getExplorerManager() {
   10.67 +                return HolderImpl.get(doc).getManager();
   10.68 +            }
   10.69 +        }
   10.70 +
   10.71 +        P result = new P();
   10.72 +
   10.73 +        result.setLayout(new BorderLayout());
   10.74 +        result.add(new BreadCrumbComponent(), BorderLayout.CENTER);
   10.75 +
   10.76 +        return result;
   10.77 +    }
   10.78 +
   10.79 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/java.breadcrumbs/src/org/netbeans/modules/java/breadcrumbs/layer.xml	Wed Aug 08 15:09:00 2012 +0200
    11.3 @@ -0,0 +1,13 @@
    11.4 +<?xml version="1.0" encoding="UTF-8"?>
    11.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
    11.6 +<filesystem>
    11.7 +    <folder name="Editors">
    11.8 +        <folder name="SideBar">
    11.9 +            <file name="org-netbeans-modules-java-breadcrumbs-SideBarFactoryImpl.instance">
   11.10 +                <attr name="location" stringvalue="South"/>
   11.11 +                <attr name="position" intvalue="4000"/>
   11.12 +                <attr name="scrollable" boolvalue="false"/>
   11.13 +            </file>
   11.14 +        </folder>
   11.15 +    </folder>
   11.16 +</filesystem>