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