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();
+		}
+	}
+}