/* * PopupManager.java * * Created on May 22, 2006, 10:48 AM */ package Current.manage.Popup; import Current.manage.*; import Current.*; import java.util.*; import org.pat.util.ClassComparator; import org.pat.util.StringComparator; import java.lang.reflect.*; import java.lang.ref.*; import java.awt.*; import java.awt.event.*; /** * * @author pat */ public class PopupManager implements HearingPopup { private class PopupData { /** list of weak references to objects of the right class */ LinkedList list; boolean supportMany; String title; public PopupData(String title) { this.title=title; list=new LinkedList(); supportMany=false; } public PopupData(boolean supportMany) { list=new LinkedList(); this.supportMany=supportMany; } public void checkAll() { Object obj=null; for (ListIterator it=list.listIterator(); it.hasNext();) { obj=((WeakReference)(it.next())).get(); if (obj==null) { it.remove(); System.err.println("Warning non-manual removal of a popup "+ "with title \""+title+"\""); } } } public boolean isUp() { checkAll(); if (supportMany) { return false; // more can be brought up } else { return (list.size()>0); } } public Object getFirst() { Object obj=null; for (ListIterator it=list.listIterator(); it.hasNext();) { obj=((WeakReference)(it.next())).get(); if (obj==null) { it.remove(); System.err.println("Warning non-manual removal of a popup "+ "with title \""+title+"\""); } else { return obj; } } return null; } } public class PopupDataList { public Class[] classes; public String[] titles; public boolean[] up; PopupDataList(int num) { classes=new Class[num]; titles=new String[num]; up=new boolean[num]; } } /** A token class to send as a message to any components that list popups * /* to indicate that something has changed */ public static class PopupManagerChange { public PopupManagerChange(){} } private Manager M; private TreeMap popups; private TreeMap alpha_popups; private static final Class[] constructor_args={Manager.class}; private Object[] arg; /** Creates a new instance of PopupManager */ public PopupManager(Manager M) { this.M=M; arg=new Object[1]; arg[0]=M; popups=new TreeMap(new ClassComparator()); alpha_popups=new TreeMap(new StringComparator()); } /** adds support for the following popup class given by C. Generally, you would * call this like "support(UnfoldContainer.class)" * @param title the name used to describe the popup */ public void support(Class C) { support(C,C.getName()); } /** adds support for the following popup class given by C. Generally, you would * call this like "support(UnfoldContainer.class)" * @param title the name used to describe the popup */ public void support(Class C, String title) { if (! popups.containsKey(C)) { popups.put(C, new PopupData(title)); alpha_popups.put(title,C); } } public boolean supports(Class C) { return popups.containsKey(C); } /** Add a manually constructed object to the popup list */ public void addObject(Object obj) { Class C=obj.getClass(); if (! supports(C)) { support(C); } if (isUp(C)) { System.err.println("Error: Popup "+C.getClass()+" is already up!"); return; } else { LinkedList ll=((PopupData)(popups.get(C))).list; ll.addLast(new WeakReference(obj)); // notify anyone who cares M.mcbSend(new PopupManagerChange()); } } /** Add a manually constructed object to the popup list and embed it in a * popup window */ public void createPopupFromObject(Object obj) { addObject(obj); if (obj != null) { new PopupWindow(((PopupData)(popups.get(obj.getClass()))).title, (Component)obj, this); } } /** returns the first popup in the class C, or null if none exists */ public Object getFirstObject(Class C) { return ((PopupData)(popups.get(C))).getFirst(); } public Object constructObject(Class C) { if (! supports(C)) { support(C); } if (isUp(C)) { System.err.println("Error: Popup "+C.getClass()+" is already up!"); return null; } else { LinkedList ll=((PopupData)(popups.get(C))).list; Constructor con=null; try { con=C.getConstructor(constructor_args); } catch (Throwable T) { System.err.println("Error: class \""+C.getName()+"\""+ " does not support a constructor with a Manager as its only argument."); T.printStackTrace(); System.exit(0); } Object obj=null; try { obj=con.newInstance(arg); } catch (Throwable T) { System.err.println("PopupManager: Error construction object of type "+ "\""+C.getName()+"\""); T.printStackTrace(); System.exit(0); } // ll.addLast(new WeakReference(obj,refQ)); ll.addLast(new WeakReference(obj)); // notify anyone who cares M.mcbSend(new PopupManagerChange()); return obj; } } public void constructPopup(Class C) { Object obj=constructObject(C); if (obj != null) { new PopupWindow(((PopupData)(popups.get(C))).title, (Component)obj, this); } } public void popupClosed(Component component){ PopupData PD=(PopupData)(popups.get(component.getClass())); Object obj=null; boolean removed=false; for (ListIterator it=PD.list.listIterator(); it.hasNext();) { obj=((WeakReference)(it.next())).get(); if (obj==null) { System.err.println("Warning non-manual removal of a popup "+ "of type \""+component.getClass()+"\""); it.remove(); removed=true; } else if (obj==component) { it.remove(); removed=true; //System.out.println("Removed a popup!"); } } if (removed) { M.cleanupObject((Object)component); M.mcbSend(new PopupManagerChange()); } } public boolean isUp(Class C) { return ((PopupData)(popups.get(C))).isUp(); } public PopupDataList getData() { PopupDataList list=new PopupDataList(popups.size()); int i=0; for (Iterator it=alpha_popups.entrySet().iterator(); it.hasNext(); ) { Class C=(Class)(((Map.Entry)(it.next())).getValue()); PopupData pd=(PopupData)(popups.get(C)); list.classes[i]=C; list.titles[i]=pd.title; list.up[i]=pd.isUp(); i++; } return list; } }