/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2005-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.image.palette; import java.io.Serializable; import java.util.EventListener; import javax.swing.event.EventListenerList; import javax.imageio.ImageReader; import javax.imageio.ImageWriter; import javax.imageio.event.IIOReadUpdateListener; import javax.imageio.event.IIOReadWarningListener; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.event.IIOWriteWarningListener; import javax.imageio.event.IIOWriteProgressListener; import org.apache.sis.util.ArraysExt; /** * A container of image I/O listeners. This class provides a set of {@code addFooListener(...)} * and {@code removeFooListener(...)} methods for adding and removing various listeners, and a * {@code addListenersTo(...)} method for copying listeners to the an image reader. This class is * convenient when {@code ImageReader.addFooListener(...)} can't be invoked directly because the * {@link ImageReader} instance is not yet know or available. * * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.10 * * @since 2.1 * @module */ public class IIOListeners implements Serializable { /** * For compatibility with different versions. */ private static final long serialVersionUID = 3747976429353858766L; /** * The listener categories for read operations. */ private static final Class<?>[] READ = { IIOReadProgressListener.class, IIOReadWarningListener .class, IIOReadUpdateListener .class }; /** * The listener categories for read operations. */ private static final Class<?>[] WRITE = { IIOWriteProgressListener.class, IIOWriteWarningListener .class }; /** * The list of listeners, as a subclass which can copy its value from an other list of * listeners. We can safely takes the array reference without cloning it because every * methods modifying the list internally create a copy of the array and modify that copy. */ private static final class List extends EventListenerList { private static final long serialVersionUID = 3398556089737845953L; final void setTo(final EventListenerList other) { listenerList = other.getListenerList(); } } /** * List of listeners. */ private final List listeners = new List(); /** * Creates a new instance of {@code IIOListeners}. */ public IIOListeners() { } /** * Sets the list of listeners in this object to the same listeners than the given object. * Any listeners previously hold by this {@code IIOListeners} are discarded. * * @param other The other object from which to copy the list of listeners. * * @since 3.10 */ public void setListeners(final IIOListeners other) { listeners.setTo(other.listeners); } /** * Adds an {@code IIOReadProgressListener} to the list of registered progress listeners. * * @param listener The listener to add. */ public void addIIOReadProgressListener(final IIOReadProgressListener listener) { listeners.add(IIOReadProgressListener.class, listener); } /** * Removes an {@code IIOReadProgressListener} from the list of registered progress listeners. * * @param listener The listener to remove. * * @category Reader */ public void removeIIOReadProgressListener(final IIOReadProgressListener listener) { listeners.remove(IIOReadProgressListener.class, listener); } /** * Adds an {@code IIOReadUpdateListener} to the list of registered update listeners. * * @param listener The listener to add. * * @since 3.02 * @category Reader */ public void addIIOReadUpdateListener(final IIOReadUpdateListener listener) { listeners.add(IIOReadUpdateListener.class, listener); } /** * Removes an {@code IIOReadUpdateListener} from the list of registered update listeners. * * @param listener The listener to remove. * * @since 3.02 * @category Reader */ public void removeIIOReadUpdateListener(final IIOReadUpdateListener listener) { listeners.remove(IIOReadUpdateListener.class, listener); } /** * Adds an {@code IIOReadWarningListener} to the list of registered warning listeners. * * @param listener The listener to add. * * @category Reader */ public void addIIOReadWarningListener(final IIOReadWarningListener listener) { listeners.add(IIOReadWarningListener.class, listener); } /** * Removes an {@code IIOReadWarningListener} from the list of registered warning listeners. * * @param listener The listener to remove. * * @category Reader */ public void removeIIOReadWarningListener(final IIOReadWarningListener listener) { listeners.remove(IIOReadWarningListener.class, listener); } /** * Adds an {@code IIOWriteProgressListener} to the list of registered progress listeners. * * @param listener The listener to add. * * @since 3.02 * @category Writer */ public void addIIOWriteProgressListener(final IIOWriteProgressListener listener) { listeners.add(IIOWriteProgressListener.class, listener); } /** * Removes an {@code IIOWriteProgressListener} from the list of registered progress listeners. * * @param listener The listener to remove. * * @since 3.02 * @category Writer */ public void removeIIOWriteProgressListener(final IIOWriteProgressListener listener) { listeners.remove(IIOWriteProgressListener.class, listener); } /** * Adds an {@code IIOWriteWarningListener} to the list of registered warning listeners. * * @param listener The listener to add. * * @since 3.02 * @category Writer */ public void addIIOWriteWarningListener(final IIOWriteWarningListener listener) { listeners.add(IIOWriteWarningListener.class, listener); } /** * Removes an {@code IIOWriteWarningListener} from the list of registered warning listeners. * * @param listener The listener to remove. * * @since 3.02 * @category Writer */ public void removeIIOWriteWarningListener(final IIOWriteWarningListener listener) { listeners.remove(IIOWriteWarningListener.class, listener); } /** * Returns all {@linkplain IIOReadProgressListener read progress}, * {@linkplain IIOReadUpdateListener read update} and * {@linkplain IIOReadWarningListener read warning} listeners. * * @return All read listeners. * * @category Reader */ public EventListener[] getReadListeners() { return getListeners(READ); } /** * Returns all {@linkplain IIOWriteProgressListener write progress} and * {@linkplain IIOWriteWarningListener write warning} listeners. * * @return All read listeners. * * @since 3.02 * @category Writer */ public EventListener[] getWriteListeners() { return getListeners(WRITE); } /** * Returns all listeners of the given classes. */ private EventListener[] getListeners(final Class<?>[] categories) { int count = 0; final Object[] list = listeners.getListenerList(); final EventListener[] listeners = new EventListener[list.length/2]; add: for (int i=0; i<list.length; i+=2) { final Class<?> type = (Class<?>) list[i]; for (int j=categories.length; --j>=0;) { if (type.equals(categories[i])) { /* * Found a listener in one of the specified categories. * Ensure that it was not already added in the list. */ final EventListener candidate = (EventListener) list[i+1]; for (int k=count; --k>=0;) { if (listeners[k] == candidate) { // Avoid duplication. continue add; } } listeners[count++] = candidate; continue add; } } } return ArraysExt.resize(listeners, count); } /** * Adds all listeners registered in this object to the specified image reader. * * @param reader The reader on which to register the listeners. * * @category Reader */ public void addListenersTo(final ImageReader reader) { manageListeners(reader, true); } /** * Adds all listeners registered in this object to the specified image writer. * * @param writer The writer on which to register the listeners. * * @since 3.02 * @category Writer */ public void addListenersTo(final ImageWriter writer) { manageListeners(writer, true); } /** * Removes all listeners registered in this object from the specified image reader. * * @param reader The reader from which to unregister the listeners. * * @since 3.07 * @category Reader */ public void removeListenersFrom(final ImageReader reader) { manageListeners(reader, false); } /** * Removes all listeners registered in this object from the specified image writer. * * @param writer The writer from which to unregister the listeners. * * @since 3.07 * @category Writer */ public void removeListenersFrom(final ImageWriter writer) { manageListeners(writer, false); } /** * Adds or removes all listeners registered in this object to/from the specified image reader. * * @param reader The reader from which to (un)register the listeners. * @param add {@code true} for adding the listeners, or {@code false} for removing them. * * @category Reader */ private void manageListeners(final ImageReader reader, final boolean add) { final Object[] listeners = this.listeners.getListenerList(); for (int i=0; i<listeners.length;) { final Object classe = listeners[i++]; final Object listener = listeners[i++]; if (classe == IIOReadProgressListener.class) { final IIOReadProgressListener l = (IIOReadProgressListener) listener; reader.removeIIOReadProgressListener(l); // Ensure singleton if (add) reader.addIIOReadProgressListener(l); continue; } if (classe == IIOReadUpdateListener.class) { final IIOReadUpdateListener l = (IIOReadUpdateListener) listener; reader.removeIIOReadUpdateListener(l); // Ensure singleton if (add) reader.addIIOReadUpdateListener(l); continue; } if (classe == IIOReadWarningListener.class) { final IIOReadWarningListener l = (IIOReadWarningListener) listener; reader.removeIIOReadWarningListener(l); // Ensure singleton if (add) reader.addIIOReadWarningListener(l); continue; } } } /** * Adds or removes all listeners registered in this object to/from the specified image writer. * * @param writer The writer from which to (un)register the listeners. * @param add {@code true} for adding the listeners, or {@code false} for removing them. * * @category Writer */ private void manageListeners(final ImageWriter writer, final boolean add) { final Object[] listeners = this.listeners.getListenerList(); for (int i=0; i<listeners.length;) { final Object classe = listeners[i++]; final Object listener = listeners[i++]; if (classe == IIOWriteProgressListener.class) { final IIOWriteProgressListener l = (IIOWriteProgressListener) listener; writer.removeIIOWriteProgressListener(l); // Ensure singleton if (add) writer.addIIOWriteProgressListener(l); continue; } if (classe == IIOWriteWarningListener.class) { final IIOWriteWarningListener l = (IIOWriteWarningListener) listener; writer.removeIIOWriteWarningListener(l); // Ensure singleton if (add) writer.addIIOWriteWarningListener(l); continue; } } } }