view src/samer/core_/util/VMap.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
/*
 *	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.core.util;

import   samer.core.*;
import	samer.core.types.*;
import	java.util.*;
import	java.awt.*;

/**
	An Agent and Viewable that manages a IMap object - provides
	a user interface for adjusting the domain.
 */

public class VMap extends Viewable implements Agent
{
	IMap		map;
	boolean	symmetric;

	public static final Object NEW_MAP = new Object();

	public VMap(IMap m) { this(m,true); }
	public VMap(IMap m, Node node) { this(m,true,node); }
	public VMap(IMap m, boolean init) { this(m,init,new Node("map")); }

	/** Construct a VMap from a given IMap and node. The boolean init flag specifies
		whether or not the VMap should reinitialise the IMap from the current Environment
	*/
	
	public VMap(IMap m, boolean init, Node node)
	{
		super(node);
		setAgent(this);

		map = m;
		symmetric = false;

		if (init) {
			Shell.push(getNode());
			try {
				boolean logmap = Shell.getBoolean("log", false);

				if (logmap) { map=new LogMap(); symmetric=false; }
				else symmetric = Shell.getBoolean( "symmetric", symmetric);

				setDomain(
					Shell.getDouble("minimum",map.getDomainMin()),
					Shell.getDouble("maximum",map.getDomainMax())
				);
			} finally { Shell.pop(); }
		}
	}

	public void setMap( IMap m) { map=m; changed(NEW_MAP); }
	public IMap getMap() { return map; }

	public String toString() { return super.toString()+"="+map.toString(); }
	
	// ........... Viewable bits ................

	public void dispose()
	{
		Shell.deregisterAgent(this);
		super.dispose();
	}

	public Viewer	getViewer() { return new Adjuster(); }

	// ........... Agent Bits ...................

	public void getCommands(Agent.Registry r) {
		r.add("domain").add("symmetric",symmetric);
		r.add("linear").add("log");
		r.group();
		r.add("put").add("get");
	}

	public void execute(String c, Environment env) throws Exception
	{
		if (c.equals("domain"))	{
			Shell.showDialogFor(getViewer().getComponent(),Node.lastPart(node.fullName()));
		} else if (c.equals("symmetric")) {
			symmetric = X._bool(env.datum(),!symmetric);
			setDomain( map.getDomainMin(), map.getDomainMax());
			changed();
		} else if (c.equals("linear")) {
			IMap newmap = new LinearMap( );
			newmap.setDomain( map.getDomainMin(), map.getDomainMax());
			newmap.setIntRange( map.getIntRange());
			setMap(newmap);
		} else if (c.equals("log")) {
			double min=map.getDomainMin();
			double max=map.getDomainMax();

			if (min<=0) min=max/1000; // default dynamic range
			symmetric=false;
			setMap(new LogMap(min,max,map.getIntRange()));
		} else if (c.equals("put")) Shell.put("map",this);
		else if (c.equals("get")) setMap(((VMap)Shell.get("map")).getMap().copy());
		/* or
			} else if (c.equals("put")) Shell.put("map",this.getMap().copy());
			else if (c.equals("get")) setMap((IMap)Shell.get("map"));
		*/
	}

	public void setSymmetric(boolean f) { symmetric=f; }
	public void setDomain( double min, double max)
	{
		if (map instanceof LogMap) {
			if (min<=0) min=max/1000;
		} else {
			if (symmetric) { max=Math.max(max,-min); min=-max; }
		}
		// Shell.trace("new domain=["+min+","+max+")");
		map.setDomain(min,max);
	}

	class Adjuster extends BaseViewer
	{
		VBoolean		sym;
		VDouble		t1, t2;

		Adjuster()
		{
			super(VMap.this);
			panel().setName(getLabel());
			Shell.push(getNode());

			setLayout( new StackLayout());

			t1 = new VDouble("maximum",map.getDomainMax(),Variable.NOINIT);
			t2 = new VDouble("minimum",map.getDomainMin(),Variable.NOINIT);
			sym= new VBoolean("symmetric",symmetric,Variable.NOINIT);
			t1.addObserver(this);
			t2.addObserver(this);
			sym.addObserver(this);

			add(t1.getViewer().getComponent());
			add(t2.getViewer().getComponent());
			add(sym.getViewer().getComponent());

			Shell.pop();
		}

		public void update(Observable o, Object src)
		{
			if (src==this) return; // &&&
			if (VMap.this.equals(o)) {
				// means someone has changed the map ...
				// ... and if it wasn't us...
				t1.value=map.getDomainMax(); t1.changed(this);
				t2.value=map.getDomainMin(); t2.changed(this);
				if (sym.value!=symmetric) {
					sym.value=symmetric; sym.changed(this);
				}
			} else {
				// Widget adjusted
				// user has adjusted controls...
				// must set map and notify any observers
				if (sym==o) {
					if (symmetric=sym.value) {
						double max=Math.max(t1.value,-t2.value);
						t1.value=max; t2.value=-max;
						t1.changed(this); t2.changed(this);
					}
				} else {
					if (symmetric) {
						if (t1==o)      { t2.value=-t1.value; t2.changed(this); }
						else if (t2==o) {	t1.value=-t2.value; t1.changed(this); }
					}
				}
				map.setDomain(t2.value,t1.value);
				changed(this);
				// else, WE adjusted the controls to
				// reflect reality, so do nothing
			}
		}
	}
}