/*******************************************************************************
* Copyright (c) 2007, 2010 Association for Decentralized Information Management
* in Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.g2d.image.impl;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.lang.ref.WeakReference;
import java.util.EnumSet;
import org.simantics.g2d.image.Image;
import org.simantics.scenegraph.Node;
import org.simantics.scenegraph.g2d.G2DParentNode;
import org.simantics.utils.datastructures.ListenerList;
/**
* ImageProxy keeps strong reference to an original image, but weak reference
* from original image to proxy image.
*
* Listeners attached to ImageProxy relays events from the original image.
*
* @author Toni Kalajainen
*/
public class ImageProxy implements Image {
ListenerList list = null;
/** Strong reference to the original image */
Image source;
Node node = null;
/** Listener for the original image */
WeakImageListener sourceListener;
public ImageProxy(Image original) {
if (original==null) throw new IllegalArgumentException("null arg");
this.source = original;
}
protected void notifyChanged()
{
ImageListener[] listeners;
synchronized(this) {
if (list==null) return;
listeners = list.getListeners();
}
for (ImageListener l : listeners)
l.onContentChangedNotification(this);
}
@Override
public synchronized void addImageListener(ImageListener listener) {
if (list==null) list = new ListenerList(ImageListener.class);
if (sourceListener==null) {
sourceListener = new WeakImageListener(this);
source.addImageListener(sourceListener);
}
list.add(listener);
}
@Override
public synchronized void removeImageListener(ImageListener listener) {
if (list==null) return;
list.remove(listener);
if (list.isEmpty()) {
source.removeImageListener(sourceListener);
}
}
static class WeakImageListener implements ImageListener {
WeakReference ref;
public WeakImageListener(ImageProxy img)
{
ref = new WeakReference(img);
}
@Override
public void onContentChangedNotification(Image image) {
ImageProxy i = ref.get();
if (i == null) {
image.removeImageListener(this);
} else {
i.notifyChanged();
}
}
}
@Override
public Rectangle2D getBounds() {
return source.getBounds();
}
@Override
public EnumSet getFeatures() {
return source.getFeatures();
}
@Override
public Shape getOutline() {
return source.getOutline();
}
@Override
public Node init(G2DParentNode parent) {
this.node = source.init(parent);
return this.node;
}
public synchronized void setSource(Image newSource) {
if (newSource==null) throw new IllegalArgumentException("null");
if (source == newSource) return;
Image oldSource = source;
if(node != null) {
node.remove(); // FIXME
node = null;
}
source = newSource;
if (sourceListener!=null) {
oldSource.removeImageListener(sourceListener);
newSource.addImageListener(sourceListener);
}
notifyChanged();
}
}