Index: apichanges.xml =================================================================== RCS file: /cvs/openide/util/apichanges.xml,v retrieving revision 1.22 diff -u -r1.22 apichanges.xml --- apichanges.xml 11 Jan 2007 14:08:21 -0000 1.22 +++ apichanges.xml 5 Mar 2007 21:02:54 -0000 @@ -27,6 +27,24 @@ + + + Added ChangeSupport + + + + + +

+ Added a ChangeSupport class to simplify + the management of ChangeListeners and the + firing of ChangeEvents. +

+
+ + +
+ Added Utilities.isMac() method Index: nbproject/project.properties =================================================================== RCS file: /cvs/openide/util/nbproject/project.properties,v retrieving revision 1.25 diff -u -r1.25 project.properties --- nbproject/project.properties 11 Jan 2007 14:08:22 -0000 1.25 +++ nbproject/project.properties 5 Mar 2007 21:02:54 -0000 @@ -19,7 +19,7 @@ javac.source=1.5 module.jar.dir=lib -spec.version.base=7.7.0 +spec.version.base=7.8.0 # For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4: Index: src/org/openide/util/ChangeSupport.java =================================================================== RCS file: src/org/openide/util/ChangeSupport.java diff -N src/org/openide/util/ChangeSupport.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/openide/util/ChangeSupport.java 5 Mar 2007 21:02:54 -0000 @@ -0,0 +1,113 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (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.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * 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. + */ + +package org.openide.util; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * A simple equivalent of {@link java.beans.PropertyChangeSupport} for + * {@link ChangeListener}s. This class is not serializable. + * + * @since 7.8 + * @author Andrei Badea + */ +public final class ChangeSupport { + + // not private because used in unit tests + final List listeners = new CopyOnWriteArrayList(); + private final Object source; + + /** + * Creates a new ChangeSupport + * + * @param source the instance to be given as the source for events. + */ + public ChangeSupport(Object source) { + this.source = source; + } + + /** + * Adds a ChangeListener to the listener list. The same + * listener object may be added more than once, and will be called + * as many times as it is added. If listener is null, + * no exception is thrown and no action is taken. + * + * @param listener the ChangeListener to be added. + */ + public void addChangeListener(ChangeListener listener) { + if (listener == null) { + return; + } + listeners.add(listener); + } + + /** + * Removes a ChangeListener from the listener list. + * If listener was added more than once, + * it will be notified one less time after being removed. + * If listener is null, or was never added, no exception is + * thrown and no action is taken. + * + * @param listener the ChangeListener to be removed. + */ + public void removeChangeListener(ChangeListener listener) { + if (listener == null) { + return; + } + listeners.remove(listener); + } + + /** + * Fires a change event to all registered listeners. + */ + public void fireChange() { + if (listeners.isEmpty()) { + return; + } + fireChange(new ChangeEvent(source)); + } + + /** + * Fires the specified ChangeEvent to all registered + * listeners. If event is null, no exception is thrown + * and no action is taken. + * + * @param event the ChangeEvent to be fired. + */ + private void fireChange(ChangeEvent event) { + assert event != null; + for (ChangeListener listener : listeners) { + listener.stateChanged(event); + } + } + + /** + * Checks if there are any listeners registered to thisChangeSupport. + * + * @return true if there are one or more listeners for the given property, + * false otherwise. + */ + public boolean hasListeners() { + return !listeners.isEmpty(); + } +} Index: test/unit/src/org/openide/util/ChangeSupportTest.java =================================================================== RCS file: test/unit/src/org/openide/util/ChangeSupportTest.java diff -N test/unit/src/org/openide/util/ChangeSupportTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ test/unit/src/org/openide/util/ChangeSupportTest.java 5 Mar 2007 21:02:54 -0000 @@ -0,0 +1,106 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (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.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * 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. + */ + +package org.openide.util; + +import java.util.HashSet; +import java.util.Set; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.netbeans.junit.NbTestCase; + +/** + * + * @author Andrei Badea + */ +public class ChangeSupportTest extends NbTestCase { + + public ChangeSupportTest(String testName) { + super(testName); + } + + public void testChangeSupport() { + final int[] changeCount = { 0 }; + class Listener implements ChangeListener { + private int notified; + private ChangeEvent lastEvent; + public void stateChanged(ChangeEvent event) { + lastEvent = event; + notified++; + } + public int getNotifiedAndReset() { + try { + return notified; + } finally { + notified = 0; + } + } + public ChangeEvent getLastEvent() { + return lastEvent; + } + } + ChangeSupport support = new ChangeSupport(this); + Listener listener1 = new Listener(), listener2 = new Listener(); + + support.addChangeListener(null); + assertFalse(support.hasListeners()); + + support.removeChangeListener(null); + assertFalse(support.hasListeners()); + + support.addChangeListener(listener1); + support.addChangeListener(listener2); + assertTrue(support.hasListeners()); + Set listeners = new HashSet(support.listeners); + assertEquals(2, listeners.size()); + assertTrue(listeners.contains(listener1)); + assertTrue(listeners.contains(listener2)); + + support.fireChange(); + assertEquals(1, listener1.getNotifiedAndReset()); + assertEquals(1, listener2.getNotifiedAndReset()); + assertSame(this, listener1.getLastEvent().getSource()); + + support.removeChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + } + }); + support.fireChange(); + assertEquals(1, listener1.getNotifiedAndReset()); + assertEquals(1, listener2.getNotifiedAndReset()); + + support.removeChangeListener(listener1); + support.fireChange(); + assertEquals(0, listener1.getNotifiedAndReset()); + assertEquals(1, listener2.getNotifiedAndReset()); + + support.addChangeListener(listener2); + support.fireChange(); + assertEquals(2, listener2.getNotifiedAndReset()); + + support.removeChangeListener(listener2); + support.fireChange(); + assertEquals(1, listener2.getNotifiedAndReset()); + + support.removeChangeListener(listener2); + support.fireChange(); + assertEquals(0, listener2.getNotifiedAndReset()); + assertFalse(support.hasListeners()); + } +}