diff --git a/projectapi/apichanges.xml b/projectapi/apichanges.xml --- a/projectapi/apichanges.xml +++ b/projectapi/apichanges.xml @@ -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 diff --git a/projectapi/manifest.mf b/projectapi/manifest.mf --- a/projectapi/manifest.mf +++ b/projectapi/manifest.mf @@ -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 diff --git a/projectapi/src/org/netbeans/api/project/ProjectUtils.java b/projectapi/src/org/netbeans/api/project/ProjectUtils.java --- a/projectapi/src/org/netbeans/api/project/ProjectUtils.java +++ b/projectapi/src/org/netbeans/api/project/ProjectUtils.java @@ -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,14 @@ import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.FileUtil; import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; import org.openide.util.Mutex; import org.openide.util.Parameters; +import org.openide.util.WeakListeners; +import org.openide.util.WeakSet; /** * Utility methods to get information about {@link Project}s. @@ -87,11 +97,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; } /** @@ -253,6 +263,92 @@ } } + + private static final class AnnotateIconProxyProjectInformation implements ProjectInformation { + + private final ProjectInformation pinfo; + private Icon icon; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private final Set pias = new WeakSet(); + private final PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (ProjectIconAnnotator.PROP_ICON.equals(evt.getPropertyName())) { + updateIcon(pinfo, getProject()); + pcs.firePropertyChange(pinfo.PROP_ICON, null, getIcon()); + } else { + if (pinfo.PROP_ICON.equals(evt.getPropertyName())) { + updateIcon(pinfo, getProject()); + } + pcs.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + } + }; + + public AnnotateIconProxyProjectInformation(Project p, ProjectInformation pi) { + this.pinfo = pi; + this.pinfo.addPropertyChangeListener(WeakListeners.propertyChange(listener, pinfo)); + final Result lookupResult = Lookup.getDefault().lookupResult(ProjectIconAnnotator.class); + lookupResult.addLookupListener(new LookupListener() { + @Override + public void resultChanged(LookupEvent ev) { + initIconAnnotations(lookupResult); + } + }); + initIconAnnotations(lookupResult); + updateIcon(pi, p); + } + + private void initIconAnnotations(Result lookupResult) { + for (ProjectIconAnnotator pa : lookupResult.allInstances()) { + if (!pias.contains(pa)) { + pa.addPropertyChangeListener(WeakListeners.propertyChange(listener, pa)); + pias.add(pa); + } + } + } + + private void updateIcon(ProjectInformation pi, Project p) { + Image _icon = ImageUtilities.icon2Image(pi.getIcon()); + for (ProjectIconAnnotator pa : Lookup.getDefault().lookupAll(ProjectIconAnnotator.class)) { + _icon = pa.annotateIcon(p, _icon, false); + } + icon = ImageUtilities.image2Icon(_icon); + } + + @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. diff --git a/projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java b/projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java new file mode 100644 --- /dev/null +++ b/projectapi/src/org/netbeans/spi/project/ProjectIconAnnotator.java @@ -0,0 +1,123 @@ +/* + * 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 java.beans.PropertyChangeListener; +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."
+ *   private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+ *
+ *   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;
+ *   }
+ *
+ *    @Override
+ *    public void addPropertyChangeListener(PropertyChangeListener listener) {
+ *        pcs.addPropertyChangeListener(listener);
+ *    }
+ *
+ *    @Override
+ *    public void removePropertyChangeListener(PropertyChangeListener listener) {
+ *        pcs.removePropertyChangeListener(listener);
+ *    }
+ *
+ *    public void updateMyBadges() {
+ *        pcs.firePropertyChange(PROP_ICON, null, null);
+ *    }
+ *
+ * }
+ * 
+ * @author petrdvorak + * @since 1.33 + */ +public interface ProjectIconAnnotator { + + /** Property name fired when the project icon annotation changes. */ + public final String PROP_ICON = "annotation_icon"; + + /** + * Returns image representing annotated project icon. Return {@code original} if you do not + * intend to change the original icon. + * @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); + + /** + * Add a listener to property changes. + * Only {@link #PROP_ICON} may be fired. + * old and new values are undefined + * @param listener a listener to add + */ + public void addPropertyChangeListener(PropertyChangeListener listener); + + + /** + * Remove a listener to property changes. + * @param listener a listener to remove + */ + public void removePropertyChangeListener(PropertyChangeListener listener); + +} diff --git a/projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java b/projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java new file mode 100644 --- /dev/null +++ b/projectapi/test/unit/src/org/netbeans/api/project/ProjectIconAnnotatorTest.java @@ -0,0 +1,149 @@ +/* + * 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.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import org.netbeans.spi.project.ProjectIconAnnotator; +import java.awt.Image; +import java.beans.PropertyChangeSupport; +import javax.swing.Icon; +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(String name) { + super(name); + } + + final static Image icon1 = ImageUtilities.loadImage("org/netbeans/api/project/resources/icon-1.png"); + + private FileObject scratch; + private FileObject goodproject; + private ProjectManager pm; + private ProjectIconAnnotatorImpl pia; + private String testEventName; + + @Override + protected void setUp() throws Exception { + super.setUp(); + scratch = TestUtil.makeScratchDir(this); + goodproject = scratch.createFolder("good"); + goodproject.createFolder("testproject"); + MockLookup.setInstances(TestUtil.testProjectFactory(), pia = new ProjectIconAnnotatorImpl()); + pm = ProjectManager.getDefault(); + pm.reset(); + + } + + @Override + protected void tearDown() throws Exception { + scratch = null; + goodproject = null; + pm = null; + testEventName = null; + pia = null; + super.tearDown(); + } + + + /** + * Test of annotateIcon method, of class ProjectIconAnnotator. + */ + 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); + pi.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + testEventName=evt.getPropertyName(); + } + }); + + pia.updateBadges(); + assertEquals("Event not fired properly", pi.PROP_ICON, testEventName); + } + + public static final class ProjectIconAnnotatorImpl implements ProjectIconAnnotator { + + + private PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public ProjectIconAnnotatorImpl() { + } + + @Override + public Image annotateIcon(Project p, Image original, boolean openedNode) { + return icon1; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void updateBadges() { + pcs.firePropertyChange(PROP_ICON, null, null); + } + } + +} \ No newline at end of file diff --git a/projectapi/test/unit/src/org/netbeans/api/project/resources/icon-1.png b/projectapi/test/unit/src/org/netbeans/api/project/resources/icon-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a71aca13ab1f2db8aa685a0f2dd85eec6786ba5b GIT binary patch literal 336 zc%17D@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|*pj^6T^Rl| zJY-nm%=LC3P=vFv0mG>Zt*Qw5f8@}$yOdUr6z%t z7iTiKtG_>&xmQqJ$d&(E`u10w^Wp-off9UGvTu$~E|h 1 - 1.17 + 1.33 diff --git a/projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java b/projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java --- a/projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java +++ b/projectui/src/org/netbeans/modules/project/ui/ProjectsRootNode.java @@ -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,6 +773,12 @@ } 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,6 +794,12 @@ } 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; diff --git a/projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java b/projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java new file mode 100644 --- /dev/null +++ b/projectui/test/unit/src/org/netbeans/modules/project/ui/ProjectRootNodeIconTest.java @@ -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.beans.PropertyChangeListener; +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(String name) { + super(name); + } + + 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"); + + 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; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + } + } + +} diff --git a/projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-1.png b/projectui/test/unit/src/org/netbeans/modules/project/ui/resources/icon-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a71aca13ab1f2db8aa685a0f2dd85eec6786ba5b GIT binary patch literal 336 zc%17D@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|*pj^6T^Rl| zJY-nm%=LC3P=vFv0mG>Zt*Qw5f8@}$yOdUr6z%t z7iTiKtG_>&xmQqJ$d&(E`u10w^Wp-off9UGvTu$~E|hv0mG>Zt*Qw5f8@}$yOdUr6z%t z7iTiKtG_>&xmQqJ$d&(E`u10w^Wp-off9UGvTu$~E|hv0mG>Zt*Qw5f8@}$yOdUr6z%t z7iTiKtG_>&xmQqJ$d&(E`u10w^Wp-off9UGvTu$~E|h