/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import java.util.*;
/**
* Keeps a list of all pathways for a given LWMap. Also tracks the
* current pathway selected for the given map. Provides for
* aggregating all the events that happen within the pathways and
* their contents, and rebroadcasting them to interested parties, such
* as the PathwayTableModel.
*
* @version $Revision: 1.37 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $
* @author Scott Fraize
*
*/
public class LWPathwayList implements LWComponent.Listener, Iterable<LWPathway>
{
private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(LWPathwayList.class);
private List<LWPathway> mPathways = new java.util.ArrayList();
private LWMap mMap = null;
private LWPathway mActive = null;
private LWPathway mRevealer = null; // currently active "revealer" pathway, if any
private LWChangeSupport mChangeSupport = new LWChangeSupport(this);
public LWPathwayList(LWMap map) {
setMap(map);
// Always include an untitled example pathway for new maps
LWPathway defaultPath = new LWPathway(map,VueResources.getString("pathways.defaultPathway.label"));
VUE.setActive(LWPathway.class, this, defaultPath);
//defaultPath.setVisible(false);
add(defaultPath);
}
public LWPathway getRevealer() {
return mRevealer;
}
public void setRevealer(LWPathway newRevealer) {
if (mRevealer == newRevealer)
return;
Object old = mRevealer;
if (mRevealer != null)
mRevealer.setRevealer(false);
mRevealer = newRevealer;
if (newRevealer != null)
newRevealer.setRevealer(true);
notify(newRevealer, "pathway.revealer", new Undoable(old) { void undo() { setRevealer((LWPathway)old); }});
}
public int getRevealerIndex() {
return mRevealer == null ? -1 : indexOf(mRevealer);
}
public void setRevealerIndex(int i) {
if (mInRestore)
mRevealerIndex = i;
else {
if (i >= 0 && i < size())
mRevealer = (LWPathway) get(i);
else
mRevealer = null;
}
}
public void setMap(LWMap map){
mMap = map;
}
public LWMap getMap() {
return mMap;
}
void completeXMLRestore(LWMap map)
{
if (DEBUG.INIT || DEBUG.IO || DEBUG.XML) Log.debug(this + " completeXMLRestore");
setMap(map);
Iterator i = iterator();
while (i.hasNext()) {
LWPathway p = (LWPathway) i.next();
p.completeXMLRestore(getMap());
p.addLWCListener(this);
}
if (mActive == null && mPathways.size() > 0)
setActivePathway(getFirst());
mInRestore = false;
setRevealerIndex(mRevealerIndex);
}
/**
* Add a listener for our children. The LWPathwayList
* listeners for and just rebroadcasts any events
* from it's LWPathways.
*/
public void addListener(LWComponent.Listener l) {
mChangeSupport.addListener(l);
}
public void removeListener(LWComponent.Listener l) {
mChangeSupport.removeListener(l);
}
private void notify(LWPathway changingPathway, String propertyKeyName, Object oldValue) {
LWCEvent e = new LWCEvent(this, changingPathway, propertyKeyName, oldValue);
// dispatch the event to map for it's listeners, particularly an undo manager if present
getMap().notifyProxy(e);
// dispatch the event to any direct listeners of this LWPathwayList
// (such as the Pathway gui code in PathwayTableModel)
mChangeSupport.dispatchEvent(e);
}
public Collection<LWPathway> getElementList() {
return mPathways;
}
public LWPathway getActivePathway() {
return mActive;
}
/**
* If this LWPathwayList is from the VUE active map, this sets
* the VUE application master for the active pathway.
*/
public void setActivePathway(LWPathway pathway) {
if (mActive != pathway) {
mActive = pathway;
notify(pathway, "pathway.list.active", LWCEvent.NO_OLD_VALUE);
}
}
private Object get(int i) { return mPathways.get(i); }
public int size() { return mPathways.size(); }
public Iterator<LWPathway> iterator() { return mPathways.iterator(); }
//public List<LWPathway> getList() { return mPathways; } // todo: should be unmodifiable
public int indexOf(Object o) { return mPathways.indexOf(o); }
public LWPathway getFirst(){
if (size() != 0)
return (LWPathway) get(0);
else
return null;
}
public LWPathway getLast(){
if (size() != 0)
return (LWPathway) get(size() - 1);
else
return null;
}
public void add(LWPathway p) {
p.setMap(getMap());
mPathways.add(p);
// we don't need to worry about calling removeFromModel on remove, as a created pathway will always
// be empty by the time we get to undo it's create (because we'll have undone any child add's first).
notify(p, "pathway.created", new Undoable(p) { void undo() { remove((LWPathway)old); }});
setActivePathway(p);
p.addLWCListener(this);
}
public void addPathway(LWPathway pathway){
add(pathway);
}
public void remove(LWPathway p)
{
p.removeFromModel();
if (!mPathways.remove(p))
throw new IllegalStateException(this + " didn't contain " + p + " for removal");
notify(p, "pathway.deleted",
new Undoable(p) {
void undo() {
LWPathway p = (LWPathway) old;
p.restoreToModel();
add(p);
}
});
if (mActive == p)
{
if (getFirst() == null)
VUE.setActive(LWPathway.class, this, null);
else
setActivePathway(getFirst());
}
if (mRevealer == p)
setRevealer(null);
}
public void LWCChanged(LWCEvent e) {
//if (DEBUG.PATHWAY) System.out.println(this + " " + e + " REBROADCASTING");
mChangeSupport.dispatchEvent(e);
}
public int getCurrentIndex() {
return indexOf(mActive);
}
public void setCurrentIndex(int index)
{
try {
setActivePathway((LWPathway) get(index));
} catch (IndexOutOfBoundsException ie){
setActivePathway(getFirst());
}
}
public String toString()
{
return "LWPathwayList[n=" + size()
+ " map=" + (getMap()==null?"null":getMap().getLabel())
+ "]";
}
/** @deprecated - persistance constructor only */
private transient boolean mInRestore;
private transient int mRevealerIndex = -1;
public LWPathwayList() {
mInRestore = true;
}
}