    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        this.notify = true;
    062    }
    063
    064    /**
    065     * Returns a flag that controls whether or not change events are sent to
    066     * registered listeners.
    067     *
    068     * @return A boolean.
    069     *
    070     * @see #setNotify(boolean)
    071     */
    072    public boolean isNotify() {
    073        return this.notify;
    074    }
    075
    076    /**
    077     * Sets a flag that controls whether or not listeners receive
    078     * {@link Dataset3DChangeEvent} notifications.
    079     *
    080     * @param notify  a boolean.
    081     *
    082     * @see #isNotify()
    083     */
    084    public void setNotify(boolean notify) {
    085        this.notify = notify;
    086        // if the flag is being set to true, there may be queued up changes...
    087        if (notify) {
    088            fireChangeEvent();
    089        }
    090    }
    091
    092    /**
    093     * Registers an object to receive notification of changes to the dataset.
    094     *
    095     * @param listener  the object to register.
    096     *
    097     * @see #removeChangeListener(Dataset3DChangeListener)
    098     */
    099    @Override
    100    public void addChangeListener(Dataset3DChangeListener listener) {
    101        this.listenerList.add(Dataset3DChangeListener.class, listener);
    102    }
    103
    104    /**
    105     * Deregisters an object so that it no longer receives notification of
    106     * changes to the dataset.
    107     *
    108     * @param listener  the object to deregister.
    109     *
    110     * @see #addChangeListener(Dataset3DChangeListener)
    111     */
    112    @Override
    113    public void removeChangeListener(Dataset3DChangeListener listener) {
    114        this.listenerList.remove(Dataset3DChangeListener.class, listener);
    115    }
    116
    117    /**
    118     * Returns {@code true} if the specified object is registered with
    119     * the dataset as a listener.  Most applications won't need to call this
    120     * method, it exists mainly for use by unit testing code.
    121     *
    122     * @param listener  the listener.
    123     *
    124     * @return A boolean.
    125     *
    126     * @see #addChangeListener(Dataset3DChangeListener)
    127     * @see #removeChangeListener(Dataset3DChangeListener)
    128     */
    129    @Override
    130    public boolean hasListener(EventListener listener) {
    131        List<?> list = Arrays.asList(this.listenerList.getListenerList());
    132        return list.contains(listener);
    133    }
    134
    135    /**
    136     * Notifies all registered listeners that the dataset has changed.
    137     *
    138     * @see #addChangeListener(Dataset3DChangeListener)
    139     */
    140    protected void fireDatasetChanged() {
    141        notifyListeners(new Dataset3DChangeEvent(this, this));
    142    }
    143
    144    /**
    145     * Notifies all registered listeners that the dataset has changed, unless
    146     * the {@code notify} flag is set to {@code false} in which
    147     * case this method does nothing.
    148     *
    149     * @param event  contains information about the event that triggered the
    150     *               notification.
    151     *
    152     * @see #addChangeListener(Dataset3DChangeListener)
    153     * @see #removeChangeListener(Dataset3DChangeListener)
    154     */
    155    protected void notifyListeners(Dataset3DChangeEvent event) {
    156        // if the 'notify' flag has been switched to false, we don't notify
    157        // the listeners
    158        if (!this.notify) {
    159            return;
    160        }
    161        Object[] listeners = this.listenerList.getListenerList();
    162        for (int i = listeners.length - 2; i >= 0; i -= 2) {
    163            if (listeners[i] == Dataset3DChangeListener.class) {
    164                ((Dataset3DChangeListener) listeners[i + 1])
    165                        .datasetChanged(event);
    166            }
    167        }
    168    }
    169
    170    /**
    171     * Sends a {@link Dataset3DChangeEvent} to all registered listeners, unless
    172     * the {@code notify} flag is set to {@code false} in which
    173     * case this method does nothing.
    174     */
    175    protected void fireChangeEvent() {
    176        notifyListeners(new Dataset3DChangeEvent(this, this));
    177    }
    178
    179}