/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2014, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* 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; either version 2.1 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* --------------------------------------
* AbstractDatasetSelectionExtension.java
* --------------------------------------
* (C) Copyright 2013, 2014, by Michael Zinsmaier and Contributors.
*
* Original Author: Michael Zinsmaier;
* Contributor(s): David Gilbert (for Object Refinery Limited);
*
* Changes
* -------
* 17-Sep-2013 : Version 1 (MZ);
*
*/
package org.jfree.data.extension.impl;
import javax.swing.event.EventListenerList;
import org.jfree.chart.util.ParamChecks;
import org.jfree.data.extension.DatasetCursor;
import org.jfree.data.extension.DatasetExtension;
import org.jfree.data.extension.DatasetSelectionExtension;
import org.jfree.data.extension.WithChangeListener;
import org.jfree.data.general.Dataset;
import org.jfree.data.general.DatasetChangeListener;
import org.jfree.data.general.SelectionChangeEvent;
import org.jfree.data.general.SelectionChangeListener;
/**
* Base class for separate selection extension implementations. Provides
* notification handling and listener support.
*/
public abstract class AbstractDatasetSelectionExtension<CURSOR extends
DatasetCursor, DATASET extends Dataset> implements
DatasetSelectionExtension<CURSOR>, DatasetChangeListener {
/** a generated serial id */
private static final long serialVersionUID = 4206903652292146757L;
/** Storage for registered listeners. */
private transient EventListenerList listenerList = new EventListenerList();
/** notify flag {@link #isNotify()} */
private boolean notify;
/**
* dirty flag true if changes occurred is used to trigger a queued change
* event if notify is reset to true.
*/
private boolean dirty;
/** reference to the extended dataset */
private final DATASET dataset;
/**
* Creates a new instance.
*
* @param dataset the underlying dataset ({@code null} not permitted).
*/
public AbstractDatasetSelectionExtension(DATASET dataset) {
ParamChecks.nullNotPermitted(dataset, "dataset");
this.dataset = dataset;
this.dataset.addChangeListener(this);
}
/**
* {@link DatasetExtension#getDataset}
*/
@Override
public DATASET getDataset() {
return this.dataset;
}
/**
* {@link DatasetSelectionExtension#addChangeListener(
* java.util.EventListener)}
*/
@Override
public void addChangeListener(SelectionChangeListener<CURSOR> listener) {
this.notify = true;
this.listenerList.add(SelectionChangeListener.class, listener);
}
/**
* {@link WithChangeListener#removeChangeListener(EventListener)}
*/
@Override
public void removeChangeListener(SelectionChangeListener<CURSOR> listener) {
this.listenerList.remove(SelectionChangeListener.class, listener);
}
/**
* {@link WithChangeListener#setNotify(boolean)}
*/
@Override
public void setNotify(boolean notify) {
if (this.notify != notify) {
if (notify == false) {
//switch notification temporary off
this.dirty = false;
} else {
//switch notification on
if (this.dirty == true) {
notifyListeners();
}
}
this.notify = notify;
}
}
/**
* {@link WithChangeListener#isNotify()}
*/
@Override
public boolean isNotify() {
return this.notify;
}
/**
* can be called by subclasses to trigger notify events depending on the
* notify flag.
*/
protected void notifyIfRequired() {
if (this.notify) {
notifyListeners();
} else {
this.dirty = true;
}
}
/**
* notifies all registered listeners
* @param event
*/
@SuppressWarnings("unchecked") //add method accepts only SelectionChangeListeners<CURSOR>
private void notifyListeners() {
Object[] listeners = this.listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == SelectionChangeListener.class) {
((SelectionChangeListener<CURSOR>) listeners[i + 1])
.selectionChanged(new SelectionChangeEvent<CURSOR>(this));
}
}
}
}