view src/samer/applet/JAppletShell.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents bf79fb79ee13
children
line wrap: on
line source
/*
 *	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();
		}
	}
}