    001/* ===========================================================
    002 * Orson Charts : a 3D chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C)opyright 2013-2016, by Object Refinery Limited.  All rights reserved.
    006 *
    007 * http://www.object-refinery.com/orsoncharts/index.html
    008 *
    009 * This program is free software: you can redistribute it and/or modify
    010 * it under the terms of the GNU General Public License as published by
    011 * the Free Software Foundation, either version 3 of the License, or
    012 * (at your option) any later version.
    013 *
    014 * This program is distributed in the hope that it will be useful,
    015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    017 * GNU General Public License for more details.
    018 *
    019 * You should have received a copy of the GNU General Public License
    020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    021 *
    022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    023 * Other names may be trademarks of their respective owners.]
    024 *
    025 * If you do not wish to be bound by the terms of the GPL, an alternative
    026 * commercial license can be purchased.  For details, please see visit the
    027 * Orson Charts home page:
    028 *
    029 * http://www.object-refinery.com/orsoncharts/index.html
    030 *
    031 */
    032
    033package com.orsoncharts.data;
    034
    035import java.util.Arrays;
    036import java.util.EventListener;
    037import java.util.List;
    038import javax.swing.event.EventListenerList;
    039
    040/**
    041 * A base class that can be used to create new dataset classes.
    042 */
    043public class AbstractDataset3D implements Dataset3D {
    044
    045    /** Storage for registered change listeners. */
    046    private transient EventListenerList listenerList;
    047
    048    /**
    049     * A flag that controls whether or not the dataset will notify listeners
    050     * of changes (defaults to {@code true}, but sometimes it is useful
    051     * to disable this).
    052     */
    053    private boolean notify;
    054
    055    /**
    056     * Default constructor - allocates storage for listeners that can
    057     * be registered with the dataset.
    058     */
    059    protected AbstractDataset3D() {
    060        this.listenerList = new EventListenerList();
    061    }
    062
    063    /**
    064     * Returns a flag that controls whether or not change events are sent to
    065     * registered listeners.
    066     *
    067     * @return A boolean.
    068     *
    069     * @see #setNotify(boolean)
    070     */
    071    public boolean isNotify() {
    072        return this.notify;
    073    }
    074
    075    /**
    076     * Sets a flag that controls whether or not listeners receive
    077     * {@link Dataset3DChangeEvent} notifications.
    078     *
    079     * @param notify  a boolean.
    080     *
    081     * @see #isNotify()
    082     */
    083    public void setNotify(boolean notify) {
    084        this.notify = notify;
    085        // if the flag is being set to true, there may be queued up changes...
    086        if (notify) {
    087            fireChangeEvent();
    088        }
    089    }
    090
    091    /**
    092     * Registers an object to receive notification of changes to the dataset.
    093     *
    094     * @param listener  the object to register.
    095     *
    096     * @see #removeChangeListener(Dataset3DChangeListener)
    097     */
    098    @Override
    099    public void addChangeListener(Dataset3DChangeListener listener) {
    100        this.listenerList.add(Dataset3DChangeListener.class, listener);
    101    }
    102
    103    /**
    104     * Deregisters an object so that it no longer receives notification of
    105     * changes to the dataset.
    106     *
    107     * @param listener  the object to deregister.
    108     *
    109     * @see #addChangeListener(Dataset3DChangeListener)
    110     */
    111    @Override
    112    public void removeChangeListener(Dataset3DChangeListener listener) {
    113        this.listenerList.remove(Dataset3DChangeListener.class, listener);
    114    }
    115
    116    /**
    117     * Returns {@code true} if the specified object is registered with
    118     * the dataset as a listener.  Most applications won't need to call this
    119     * method, it exists mainly for use by unit testing code.
    120     *
    121     * @param listener  the listener.
    122     *
    123     * @return A boolean.
    124     *
    125     * @see #addChangeListener(Dataset3DChangeListener)
    126     * @see #removeChangeListener(Dataset3DChangeListener)
    127     */
    128    @Override
    129    public boolean hasListener(EventListener listener) {
    130        List<?> list = Arrays.asList(this.listenerList.getListenerList());
    131        return list.contains(listener);
    132    }
    133
    134    /**
    135     * Notifies all registered listeners that the dataset has changed.
    136     *
    137     * @see #addChangeListener(Dataset3DChangeListener)
    138     */
    139    protected void fireDatasetChanged() {
    140        notifyListeners(new Dataset3DChangeEvent(this, this));
    141    }
    142
    143    /**
    144     * Notifies all registered listeners that the dataset has changed, unless
    145     * the {@code notify} flag is set to {@code false} in which
    146     * case this method does nothing.
    147     *
    148     * @param event  contains information about the event that triggered the
    149     *               notification.
    150     *
    151     * @see #addChangeListener(Dataset3DChangeListener)
    152     * @see #removeChangeListener(Dataset3DChangeListener)
    153     */
    154    protected void notifyListeners(Dataset3DChangeEvent event) {
    155        // if the 'notify' flag has been switched to false, we don't notify
    156        // the listeners
    157        if (!this.notify) {
    158            return;
    159        }
    160        Object[] listeners = this.listenerList.getListenerList();
    161        for (int i = listeners.length - 2; i >= 0; i -= 2) {
    162            if (listeners[i] == Dataset3DChangeListener.class) {
    163                ((Dataset3DChangeListener) listeners[i + 1])
    164                        .datasetChanged(event);
    165            }
    166        }
    167    }
    168
    169    /**
    170     * Sends a {@link Dataset3DChangeEvent} to all registered listeners, unless
    171     * the {@code notify} flag is set to {@code false} in which
    172     * case this method does nothing.
    173     */
    174    protected void fireChangeEvent() {
    175        notifyListeners(new Dataset3DChangeEvent(this, this));
    176    }
    177
    178}