/*
* Copyright (C) 2008, 2009 Quadduc <quadduc@gmail.com>
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.main;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
import org.lateralgm.util.SetTraverser;
public class UpdateSource
{
public final Object owner;
private WeakHashMap<UpdateListener,WeakReference<UpdateListener>> weakReferences;
private final HardListenerTraverser hardTraverser;
private final WeakListenerTraverser weakTraverser;
public UpdateSource(Object owner, UpdateTrigger t)
{
t.setSource(this);
this.owner = owner;
hardTraverser = new HardListenerTraverser();
weakTraverser = new WeakListenerTraverser();
}
public void addListener(UpdateListener l, boolean weak)
{
if (weak)
{
if (weakReferences == null)
weakReferences = new WeakHashMap<UpdateListener,WeakReference<UpdateListener>>();
else if (weakReferences.containsKey(l)) return;
WeakReference<UpdateListener> r = new WeakReference<UpdateListener>(l);
weakReferences.put(l,r);
weakTraverser.add(r);
}
else
hardTraverser.add(l);
}
public void addListener(UpdateListener l)
{
addListener(l,true);
}
public void removeListener(UpdateListener l)
{
if (weakReferences != null)
{
WeakReference<UpdateListener> r = weakReferences.remove(l);
if (r != null) weakTraverser.remove(r);
}
hardTraverser.remove(l);
}
private void fireUpdate(UpdateEvent e)
{
weakTraverser.traverse(e);
hardTraverser.traverse(e);
}
public static class UpdateEvent
{
public final UpdateSource source;
public final UpdateEvent cause;
public UpdateEvent(UpdateSource s)
{
this(s,null);
}
public UpdateEvent(UpdateSource s, UpdateEvent e)
{
source = s;
cause = e;
}
}
public static class UpdateTrigger
{
private UpdateSource source;
private UpdateEvent event;
private void setSource(UpdateSource s)
{
if (source != null) throw new IllegalStateException();
source = s;
}
public void fire()
{
if (event == null) event = new UpdateEvent(source);
source.fireUpdate(event);
}
public void fire(UpdateEvent e)
{
source.fireUpdate(e);
}
public UpdateEvent getEvent()
{
if (event == null) event = new UpdateEvent(source);
return event;
}
}
public interface UpdateListener
{
void updated(UpdateEvent e);
}
private class HardListenerTraverser extends SetTraverser<UpdateListener,UpdateEvent>
{
@Override
protected void visit(UpdateListener l, UpdateEvent e)
{
l.updated(e);
}
}
private class WeakListenerTraverser extends
SetTraverser<WeakReference<UpdateListener>,UpdateEvent>
{
@Override
protected void visit(WeakReference<UpdateListener> r, UpdateEvent e)
{
UpdateListener l = r.get();
if (l == null)
remove(r);
else
l.updated(e);
}
}
}