samer@0: /* samer@0: * JAppletShell.java samer@0: * samer@0: * Copyright (c) 2000, Samer Abdallah, King's College London. samer@0: * All rights reserved. samer@0: * samer@0: * This software is provided AS iS and WITHOUT ANY WARRANTY; samer@0: * without even the implied warranty of MERCHANTABILITY or samer@0: * FITNESS FOR A PARTICULAR PURPOSE. samer@0: */ samer@0: samer@0: package samer.applet; samer@0: samer@0: import java.applet.*; samer@0: import java.awt.*; samer@0: import java.awt.event.*; samer@0: import java.util.*; samer@0: import java.net.*; samer@0: import java.io.*; samer@0: samer@0: import samer.core.*; samer@0: import samer.core.util.heavy.*; samer@0: import samer.core.util.shell.*; samer@0: import samer.core.util.*; samer@0: import samer.core.Shell.*; samer@0: samer@0: import samer.core.util.heavy.Frame; samer@0: import samer.core.util.heavy.Dialog; samer@0: import samer.core.util.Properties; samer@0: import samer.core.NumberViewer; samer@0: import samer.core.viewers.*; samer@0: import samer.core.types.*; samer@0: samer@0: import samer.core.util.heavy.Console; samer@0: import java.util.Hashtable; samer@0: samer@0: /* samer@0: To do: samer@0: o 2 - Create optional output window samer@0: 3 - display commands in menu on Applet OR samer@0: 4 - commands on button bar in applet samer@0: samer@0: 6 - create Viewer to use Tools samer@0: 7 - manage agents samer@0: 8 - manage viewables samer@0: */ samer@0: samer@0: /** samer@0: This is a Shell that uses Applets to form a GUI. The basic idea is that samer@0: each applet that gets created on a web page registers itself with shell samer@0: as an available window, or perhaps as a special window like a console samer@0: or viewables container. Then, whenever a script or something asks for samer@0: a window, it gets to use one of the applets. samer@0: */ samer@0: samer@0: public class JAppletShell implements Shell.Interface, Agent samer@0: { samer@0: static JAppletShell instance=null; samer@0: private static Object mutex=new Object(); // to serialise Shell creation samer@0: samer@0: private AgentManager am; samer@0: private ViewableManager vm; samer@0: private Properties props; samer@0: private URL documentBase; samer@0: private Container confr=null; samer@0: private Console console=null; samer@0: private ButtonBar buttonBar=null; samer@0: private Vector windows=new Vector(); samer@0: private java.awt.Frame dialogOwner=null; samer@0: private Hashtable winmap=new Hashtable(); samer@0: samer@0: protected JAppletShell() samer@0: { samer@0: vm = new ViewableManager(); samer@0: am = new AgentManager(); samer@0: am.registerAgent(am); samer@0: am.registerAgent(this); samer@0: samer@0: props = new Properties(Shell.env()); samer@0: samer@0: put(VDouble.class,DoubleViewer.class); samer@0: put(VInteger.class,IntegerViewer.class); samer@0: put(VBoolean.class,BooleanViewer.class); samer@0: put(VString.class,StringViewer.class); samer@0: put(VParameter.class,ParameterViewer.class); samer@0: put(VFile.class,FileViewer.class); samer@0: put(VColor.class,ColorButton.class); samer@0: put(Variable.class,StringViewer.class); samer@0: put(Viewable.class,DefaultViewer.class); samer@0: } samer@0: samer@0: public static void initialise(Applet applet) samer@0: { samer@0: System.out.println("Initialising JAppletShell...\n"); samer@0: synchronized(mutex) { samer@0: if (instance==null) { samer@0: Shell.setShell(instance=new JAppletShell()); samer@0: } samer@0: instance.documentBase=applet.getDocumentBase(); samer@0: } samer@0: } samer@0: samer@0: public void getCommands(Agent.Registry r) { samer@0: r.add("load").add("save").add("run").add("expose"); samer@0: } samer@0: samer@0: public void execute(String cmd, Environment env) throws Exception samer@0: { samer@0: if (cmd.equals("load")) { samer@0: loadargs(new URL(documentBase, X.string(env.datum(),"args"))); samer@0: } else if (cmd.equals("save")) { samer@0: saveargs(new URL(documentBase, X.string(env.datum(),"args"))); samer@0: } else if (cmd.equals("run")) { samer@0: String scr=X.string(env.datum("script")); samer@0: runscript(new URL(documentBase, scr)); samer@0: } else if (cmd.equals("expose")) { samer@0: exposeViewables(); samer@0: } else if (cmd.equals("exit")) { samer@0: Shell.trace("Shell: exit"); samer@0: } samer@0: } samer@0: samer@0: public void exit() {} samer@0: samer@0: public synchronized void loadargs(URL url) throws Exception samer@0: { samer@0: Shell.print("loading args from "+url); samer@0: InputStream in=url.openConnection().getInputStream(); samer@0: try { props.load(new BufferedInputStream(in)); } samer@0: finally { in.close(); } samer@0: } samer@0: samer@0: public synchronized void saveargs(URL url) throws Exception samer@0: { samer@0: URLConnection con=url.openConnection(); samer@0: con.setDoOutput(true); samer@0: samer@0: OutputStream out=con.getOutputStream(); samer@0: try { samer@0: Shell.print("saving args to "+url); samer@0: props.save(out); samer@0: Shell.print("-- saved"); samer@0: } finally { out.close(); } samer@0: } samer@0: samer@0: public void runscript(URL url) throws Exception samer@0: { samer@0: InputStream in=url.openStream(); samer@0: try { Shell.interpret(new BufferedReader(new InputStreamReader(in))); } samer@0: finally { in.close(); } samer@0: } samer@0: samer@0: protected void put(Class a, Class b) { samer.core.Registry.put(a,b); } samer@0: samer@0: // ----------- Window registry ---------- samer@0: samer@0: public static void registerWindow(Shell.Window win, String name) samer@0: { samer@0: if (name!=null) { samer@0: Shell.trace("registering named window: "+name); samer@0: instance.winmap.put(name,win); samer@0: } else { samer@0: Shell.trace("registering anonymous window: "+win); samer@0: instance.windows.addElement(win); samer@0: } samer@0: } samer@0: samer@0: public static void deregisterWindow(Shell.Window win, String name) samer@0: { samer@0: Shell.trace("deregistering window "+name); samer@0: if (name!=null) { samer@0: Object o=instance.winmap.get(name); samer@0: if (win==o) instance.winmap.remove(name); samer@0: } else instance.windows.removeElement(win); samer@0: } samer@0: samer@0: public static java.awt.Frame dummyFrame() samer@0: { samer@0: if (instance.dialogOwner==null) { samer@0: instance.dialogOwner=new java.awt.Frame("DialogOwner"); samer@0: } samer@0: return instance.dialogOwner; samer@0: } samer@0: samer@0: public Shell.Dialog getDialog(String title) { samer@0: return new Dialog(dummyFrame(),title,true); samer@0: } samer@0: samer@0: public Shell.Window getWindow(String title) samer@0: { samer@0: Object win=instance.winmap.remove(title); samer@0: samer@0: if (win==null) { samer@0: // named window not found -- return first anonymous window samer@0: if (windows.size()>0) { samer@0: Shell.trace("looking for anonymous window"); samer@0: win=windows.firstElement(); samer@0: windows.removeElementAt(0); samer@0: Shell.trace("returning anonymous window"); samer@0: } samer@0: } else Shell.trace("returning named window: "+title); samer@0: samer@0: // if all else fails, create a new Frame window samer@0: if (win==null) win=new Frame(title); samer@0: samer@0: return (Shell.Window)win; samer@0: } samer@0: samer@0: public Viewer getViewerFor(Viewable v) { return null; } samer@0: samer@0: // different types of message samer@0: public void status(String msg) { print(msg); } samer@0: public void trace(String msg) { System.err.println(msg); } samer@0: public void print(String msg) samer@0: { samer@0: if (console!=null) console.write(msg+"\n"); samer@0: else System.out.println(msg); samer@0: } samer@0: samer@0: public PrintWriter getPrintWriter() { samer@0: if (console!=null) return new PrintWriter(console.getWriter(),true); samer@0: else return new PrintWriter(System.out); samer@0: } samer@0: samer@0: // agents and viewables samer@0: public void registerAgent(Agent a) { am.registerAgent(a); } samer@0: public void deregisterAgent(Agent a) { am.deregisterAgent(a); } samer@0: public void registerViewable(Viewable v) { vm.registerViewable(v); } samer@0: public void deregisterViewable(Viewable v) { vm.deregisterViewable(v); } samer@0: samer@0: public void registerButtons(Container c) { samer@0: buttonBar = new ButtonBar(c); samer@0: buttonBar.setBroadcaster(am.getBroadcaster()); samer@0: } samer@0: samer@0: public void deregisterButtons(Container c) { samer@0: if (buttonBar.container()==c) buttonBar=null; samer@0: } samer@0: samer@0: public Viewer createViewerPanel(Viewer vwr) { return new VPanel(vwr); } samer@0: public Component createLabel(String txt) { samer@0: Label l=new Label(txt); samer@0: l.addMouseListener(MouseRetarget.listener); samer@0: return l; samer@0: } samer@0: samer@0: public Container createButtonsFor(Agent agent) samer@0: { samer@0: ButtonBar bbar=new ButtonBar(); samer@0: bbar.setTarget(agent); samer@0: agent.getCommands(bbar); samer@0: return bbar.container(); samer@0: } samer@0: samer@0: public NumberViewer createNumberViewer(String label, int flags, NumberSink s) { samer@0: return new TextualNumberViewer(label,flags,s); samer@0: } samer@0: samer@0: public void exposeCommands( Agent agent) samer@0: { samer@0: // what happens if button container goes away? samer@0: samer@0: if (buttonBar!=null) { samer@0: buttonBar.setTarget(agent); // ?? or broadcast? samer@0: agent.getCommands(buttonBar); samer@0: buttonBar.container().getParent().validate(); samer@0: } samer@0: samer@0: // should we put buttons on console if no button bar? samer@0: } samer@0: samer@0: // ----------- Viewables management -------------- samer@0: samer@0: public static void expose() { instance.exposeViewables(); } samer@0: samer@0: public void exposeViewables() samer@0: { samer@0: if (!vm.hasViewerContainer()) { samer@0: // try to find window called "exposed" samer@0: Shell.Window win=(Shell.Window)instance.winmap.remove("exposed"); samer@0: if (win==null) { samer@0: // window not found-use new frame window samer@0: vm.exposeViewables(new VContainer(new Frame("exposed"))); samer@0: } else { samer@0: // use named window samer@0: vm.exposeViewables(new VContainer(win)); samer@0: } samer@0: } samer@0: } samer@0: samer@0: class VContainer extends WindowAdapter implements ViewableManager.ViewerContainer samer@0: { samer@0: Shell.Window win; samer@0: Frame frame; samer@0: samer@0: VContainer(Frame frame) { this((Shell.Window)frame); this.frame=frame; } samer@0: VContainer(Shell.Window win) samer@0: { samer@0: frame=null; samer@0: samer@0: this.win=win; samer@0: // let applet control this? samer@0: win.container().setLayout( new StackLayout()); samer@0: win.expose(); // redundant for applets samer@0: win.addWindowListener(this); // also redundant! samer@0: } samer@0: samer@0: public void add(java.util.Iterator components) samer@0: { samer@0: Shell.trace("VContainer: adding stuff"); samer@0: Container c=win.container(); samer@0: while (components.hasNext()) { samer@0: c.add((Component)(components.next())); samer@0: } samer@0: c.validate(); samer@0: if (frame!=null) frame.pack(); samer@0: } samer@0: samer@0: public void removeAll() { win.container().removeAll(); } samer@0: public void windowClosing(WindowEvent e) { samer@0: vm.releaseViewerContainer(); samer@0: win.dispose(); samer@0: } samer@0: } samer@0: samer@0: // --------------- Console management ------------- samer@0: samer@0: public void releaseConsoleContainer(Container c) samer@0: { samer@0: // if we're using this console container... samer@0: if (confr==c) { samer@0: confr.removeAll(); samer@0: confr=null; samer@0: samer@0: // should we destroy the console too? samer@0: // what about any outstanding PrintWriters? samer@0: } samer@0: } samer@0: samer@0: public void setConsoleContainer(Container c) samer@0: { samer@0: // we have a console container - don't need a new one samer@0: if (confr!=null) return; samer@0: confr = c; samer@0: samer@0: // create console if necessary samer@0: if (console==null) console = new Console(); samer@0: samer@0: // add console, command field and button bar according samer@0: // to current property set. samer@0: samer@0: confr.setLayout( new BorderLayout(3,3)); samer@0: confr.add(console, "Center"); samer@0: if (Shell.getBoolean("console.commandField",false)) { samer@0: confr.add( new CommandField(20), "South"); samer@0: } samer@0: samer@0: // add button bar if buttons not already showing. samer@0: if (buttonBar!=null && !buttonBar.container().isShowing()) { samer@0: confr.add( buttonBar.container(), "North"); samer@0: confr.validate(); samer@0: } samer@0: } samer@0: }