# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /home/beci/source/cdev2 # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: projectapi/apichanges.xml --- projectapi/apichanges.xml Base (BASE) +++ projectapi/apichanges.xml Locally Modified (Based On LOCAL) @@ -107,6 +107,23 @@ + + + Added ProjectIconAnnotator + + + + + +

+ A mechanism for changing the project node icon. + You can use it for example to add a badge to the project's icon. +

+
+ + +
+ Added MoveOrRenameOperationImplementation Index: projectapi/manifest.mf --- projectapi/manifest.mf Base (BASE) +++ projectapi/manifest.mf Locally Modified (Based On LOCAL) @@ -1,7 +1,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.projectapi/1 OpenIDE-Module-Install: org/netbeans/modules/projectapi/Installer.class -OpenIDE-Module-Specification-Version: 1.32 +OpenIDE-Module-Specification-Version: 1.33 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/projectapi/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/projectapi/layer.xml Index: projectapi/src/org/netbeans/api/project/ProjectUtils.java --- projectapi/src/org/netbeans/api/project/ProjectUtils.java Base (BASE) +++ projectapi/src/org/netbeans/api/project/ProjectUtils.java Locally Modified (Based On LOCAL) @@ -44,7 +44,11 @@ package org.netbeans.api.project; +import java.beans.PropertyChangeEvent; +import org.netbeans.spi.project.ProjectIconAnnotator; +import java.awt.Image; import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -64,8 +68,10 @@ import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.FileUtil; import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.Parameters; +import org.openide.util.WeakListeners; /** * Utility methods to get information about {@link Project}s. @@ -87,11 +93,11 @@ */ public static ProjectInformation getInformation(Project p) { ProjectInformation pi = p.getLookup().lookup(ProjectInformation.class); - if (pi != null) { - return pi; - } else { - return new BasicInformation(p); + if (pi == null) { + pi = new BasicInformation(p); } + ProjectInformation retVal = new AnnotateIconProxyProjectInformation(p, pi); + return retVal; } /** @@ -254,6 +260,66 @@ } + private static final class AnnotateIconProxyProjectInformation implements ProjectInformation { + + private final ProjectInformation pinfo; + private final Icon icon; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private final PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + pcs.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + }; + + public AnnotateIconProxyProjectInformation(Project p, ProjectInformation pi) { + this.pinfo = pi; + this.pinfo.addPropertyChangeListener(WeakListeners.propertyChange(listener, pinfo)); + if (pi.getIcon() != null) { + Image _icon = ImageUtilities.icon2Image(pi.getIcon()); + for (ProjectIconAnnotator pa : Lookup.getDefault().lookupAll(ProjectIconAnnotator.class)) { + _icon = pa.annotateIcon(p, _icon, false); + } + icon = ImageUtilities.image2Icon(_icon); + } else { + icon = null; + } + } + + @Override + public String getName() { + return pinfo.getName(); + } + + @Override + public String getDisplayName() { + return pinfo.getDisplayName(); + } + + @Override + public Icon getIcon() { + return icon; + } + + @Override + public Project getProject() { + return pinfo.getProject(); + } + + @Override + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + @Override + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + } + + /** * Find a way of storing extra configuration in a project. * If the project's {@linkplain Project#getLookup lookup} does not provide an instance, Index: projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java --- projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java Base (BASE) +++ projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java Locally New @@ -0,0 +1,89 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.spi.project; + +import java.awt.Image; +import org.netbeans.api.project.Project; + +/** + *

The interface provides a mechanism for changing the project node icon. + * You can use it for example to add a badge to the project's icon. Class implementing this + * interface should be registered using {@link org.openide.util.lookup.ServiceProvider}.

+ *
+ * @ServiceProvider(service=ProjectIconAnnotator.class)
+ * public class SampleProjectIconAnnotator implements ProjectIconAnnotator {
+ *
+ *   private static final Image badgeOpened = ImageUtilities.loadImage("org/samplepath/opened-badge.png");
+ *   private static final Image badgeClosed = ImageUtilities.loadImage("org/samplepath/closed-badge.png");
+ *   private static final String tooltip = "Sample tooltip."
+ *
+ *   Image annotateIcon(Project p, Image original, boolean openedNode) {
+ *       original = ImageUtilities.addToolTipToImage(original, tooltip);
+ *       if (openedNode) {
+ *           original = ImageUtilities.mergeImages(original, badgeOpened, 16, 0);
+ *       } else {
+ *           original = ImageUtilities.mergeImages(original, badgeClosed, 16, 0);
+ *       }
+ *       return original;
+ *   }
+ *
+ * }
+ * 
+ * @author petrdvorak + * @since 1.33 + */ +public interface ProjectIconAnnotator { + + /** + * Returns image representing annotated project icon. Return {@code original} if you do not + * intend to change the original icon (i.e. you just add a tooltip to the image). + * @param p Project whose icon is to be annotated + * @param original Image with the original icon + * @param openedNode Flag indicating if the node that uses the icon is in opened state or not + * @return Annotated project icon + */ + public Image annotateIcon(Project p, Image original, boolean openedNode); + +} Index: projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java --- projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java Base (BASE) +++ projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java Locally New @@ -0,0 +1,116 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.api.project; + +import java.io.IOException; +import org.netbeans.spi.project.ProjectIconAnnotator; +import java.awt.Image; +import javax.swing.Icon; +import org.junit.Test; +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.FileObject; +import org.openide.util.ImageUtilities; +import org.openide.util.test.MockLookup; + +/** + * + * @author petrdvorak + */ +public class ProjectIconAnnotatorTest extends NbTestCase { + + public ProjectIconAnnotatorTest() { + super("== ProjectIconAnnotatorTest =="); + } + + final static Image icon1 = ImageUtilities.loadImage("org/netbeans/api/project/resources/icon-1.png"); + + private FileObject scratch; + private FileObject goodproject; + private ProjectManager pm; + + @Override + protected void setUp() throws Exception { + super.setUp(); + scratch = TestUtil.makeScratchDir(this); + goodproject = scratch.createFolder("good"); + goodproject.createFolder("testproject"); + MockLookup.setInstances(TestUtil.testProjectFactory(), new ProjectIconAnnotatorImpl()); + pm = ProjectManager.getDefault(); + pm.reset(); + + } + + @Override + protected void tearDown() throws Exception { + scratch = null; + goodproject = null; + pm = null; + super.tearDown(); + } + + + /** + * Test of annotateIcon method, of class ProjectIconAnnotator. + */ + @Test + public void testAnnotateIcon() throws IOException { + Project p = pm.findProject(goodproject); + ProjectInformation pi = ProjectUtils.getInformation(p); + Icon img = pi.getIcon(); + assertEquals("Annotated image height should be 8", img.getIconHeight(), 8); + assertEquals("Annotated image width should be 8", img.getIconWidth(), 8); + } + + public static final class ProjectIconAnnotatorImpl implements ProjectIconAnnotator { + + public ProjectIconAnnotatorImpl() { + } + + public Image annotateIcon(Project p, Image original, boolean openedNode) { + return icon1; + } + } + +} \ No newline at end of file Index: projectapi/test/unit/src/org/netbeans/api/project/resources/icon-1.png --- projectapi/test/unit/src/org/netbeans/api/project/resources/icon-1.png Base (BASE) +++ projectapi/test/unit/src/org/netbeans/api/project/resources/icon-1.png Locally New Index: projectui/nbproject/project.xml --- projectui/nbproject/project.xml Base (BASE) +++ projectui/nbproject/project.xml Locally Modified (Based On LOCAL) @@ -91,7 +91,7 @@ 1 - 1.17 + 1.33 Index: projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java --- projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java Base (BASE) +++ projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java Locally Modified (Based On LOCAL) @@ -72,6 +72,7 @@ import javax.swing.event.ChangeListener; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ProjectIconAnnotator; import org.netbeans.api.project.ProjectManager; import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.SourceGroup; @@ -772,7 +773,13 @@ } catch (FileStateInvalidException e) { LOG.log(Level.INFO, null, e); } + Project p = getLookup().lookup(Project.class); + if (p != null) { + for (ProjectIconAnnotator pa : Lookup.getDefault().lookupAll(ProjectIconAnnotator.class)) { + img = pa.annotateIcon(p, img, false); } + } + } return img; } @@ -787,7 +794,13 @@ } catch (FileStateInvalidException e) { LOG.log(Level.INFO, null, e); } + Project p = getLookup().lookup(Project.class); + if (p != null) { + for (ProjectIconAnnotator pa : Lookup.getDefault().lookupAll(ProjectIconAnnotator.class)) { + img = pa.annotateIcon(p, img, true); } + } + } return img; } Index: projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java --- projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java Base (BASE) +++ projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java Locally New @@ -0,0 +1,173 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.modules.project.ui; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.beans.BeanInfo; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ProjectIconAnnotator; +import org.netbeans.junit.MockServices; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.project.ui.actions.TestSupport.TestProject; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileStatusEvent; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileSystem.HtmlStatus; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.MultiFileSystem; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; + +/** + * + * @author petrdvorak + */ +public class ProjectRootNodeIconTest extends NbTestCase { + + public ProjectRootNodeIconTest() { + super("ProjectRootNodeIconTest"); + } + + final static Image icon1 = ImageUtilities.loadImage("org/netbeans/modules/project/ui/resources/icon-1.png"); + final static Image icon2 = ImageUtilities.loadImage("org/netbeans/modules/project/ui/resources/icon-2.png"); + final static Image icon3 = ImageUtilities.loadImage("org/netbeans/modules/project/ui/resources/icon-3.png"); + + @Override + protected void setUp() throws Exception { + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testIconAnnotated() throws IOException, Exception { + class BadgedImage extends Image { + final Image original; + BadgedImage(Image original) {this.original = original;} + public @Override int getWidth(ImageObserver observer) {return original.getWidth(observer);} + public @Override int getHeight(ImageObserver observer) {return original.getHeight(observer);} + public @Override ImageProducer getSource() {return original.getSource();} + public @Override Graphics getGraphics() {return original.getGraphics();} + public @Override Object getProperty(String name, ImageObserver observer) {return original.getProperty(name, observer);} + public @Override void flush() {original.flush();} + } + class TestFS extends MultiFileSystem { + String nameBadge = ""; + String htmlBadge = ""; + boolean badging; + Set badgedFiles; + TestFS() throws Exception { + super(new FileSystem[] {FileUtil.createMemoryFileSystem()}); + } + public @Override Status getStatus() { + return new HtmlStatus() { + public String annotateName(String name, Set files) { + badgedFiles = files; + return name + nameBadge; + } + public String annotateNameHtml(String name, Set files) { + badgedFiles = files; + return name + htmlBadge; + } + public Image annotateIcon(Image icon, int iconType, Set files) { + badgedFiles = files; + return badging ? new BadgedImage(icon) : icon; + } + }; + } + void fireChange(boolean icon, boolean name, FileObject... files) { + fireFileStatusChanged(new FileStatusEvent(this, new HashSet(Arrays.asList(files)), icon, name)); + } + } + TestFS fs = new TestFS(); + FileObject root = fs.getRoot(); + Project prj = new TestProject(root, null); + assertNotNull(prj); + MockServices.setServices(ProjectIconAnnotatorImpl.class); + Collection lookupAll = Lookup.getDefault().lookupAll(ProjectIconAnnotator.class); + System.setProperty("test.nodelay", "true"); + ProjectsRootNode.BadgingNode node = new ProjectsRootNode.BadgingNode(null, new ProjectsRootNode.ProjectChildren.Pair(prj), + new AbstractNode(Children.LEAF, Lookups.singleton(prj)) { + public @Override String getDisplayName() {return "Prj";} + public @Override String getHtmlDisplayName() {return "Prj";} + }, false, true); + Set fos = new TreeSet(); + fos.add(prj.getProjectDirectory()); + node.setFiles(fos); + Image img = node.getIcon(BeanInfo.ICON_COLOR_16x16); + assertTrue("Icon is not the same as 'icon3'", img.equals(icon3)); + assertFalse("Icon is the same as 'icon2'", img.equals(icon2)); + img = node.getOpenedIcon(BeanInfo.ICON_COLOR_16x16); + assertTrue("Icon is not the same as 'icon2'", img.equals(icon2)); + assertFalse("Icon is the same as 'icon3'", img.equals(icon3)); + } + + public static final class ProjectIconAnnotatorImpl implements ProjectIconAnnotator { + + public ProjectIconAnnotatorImpl() { + } + + public Image annotateIcon(Project p, Image original, boolean openedNode) { + if (openedNode) + return icon2; + else + return icon3; + } + } + +} Index: projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-1.png --- projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-1.png Base (BASE) +++ projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-1.png Locally New Index: projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-2.png --- projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-2.png Base (BASE) +++ projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-2.png Locally New Index: projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-3.png --- projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-3.png Base (BASE) +++ projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-3.png Locally New