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.core.util; samer@0: samer@0: import samer.core.*; samer@0: import samer.core.types.*; samer@0: import java.util.*; samer@0: import java.awt.*; samer@0: samer@0: /** samer@0: An Agent and Viewable that manages a IMap object - provides samer@0: a user interface for adjusting the domain. samer@0: */ samer@0: samer@0: public class VMap extends Viewable implements Agent samer@0: { samer@0: IMap map; samer@0: boolean symmetric; samer@0: samer@0: public static final Object NEW_MAP = new Object(); samer@0: samer@0: public VMap(IMap m) { this(m,true); } samer@0: public VMap(IMap m, Node node) { this(m,true,node); } samer@0: public VMap(IMap m, boolean init) { this(m,init,new Node("map")); } samer@0: samer@0: /** Construct a VMap from a given IMap and node. The boolean init flag specifies samer@0: whether or not the VMap should reinitialise the IMap from the current Environment samer@0: */ samer@0: samer@0: public VMap(IMap m, boolean init, Node node) samer@0: { samer@0: super(node); samer@0: setAgent(this); samer@0: samer@0: map = m; samer@0: symmetric = false; samer@0: samer@0: if (init) { samer@0: Shell.push(getNode()); samer@0: try { samer@0: boolean logmap = Shell.getBoolean("log", false); samer@0: samer@0: if (logmap) { map=new LogMap(); symmetric=false; } samer@0: else symmetric = Shell.getBoolean( "symmetric", symmetric); samer@0: samer@0: setDomain( samer@0: Shell.getDouble("minimum",map.getDomainMin()), samer@0: Shell.getDouble("maximum",map.getDomainMax()) samer@0: ); samer@0: } finally { Shell.pop(); } samer@0: } samer@0: } samer@0: samer@0: public void setMap( IMap m) { map=m; changed(NEW_MAP); } samer@0: public IMap getMap() { return map; } samer@0: samer@0: public String toString() { return super.toString()+"="+map.toString(); } samer@0: samer@0: // ........... Viewable bits ................ samer@0: samer@0: public void dispose() samer@0: { samer@0: Shell.deregisterAgent(this); samer@0: super.dispose(); samer@0: } samer@0: samer@0: public Viewer getViewer() { return new Adjuster(); } samer@0: samer@0: // ........... Agent Bits ................... samer@0: samer@0: public void getCommands(Agent.Registry r) { samer@0: r.add("domain").add("symmetric",symmetric); samer@0: r.add("linear").add("log"); samer@0: r.group(); samer@0: r.add("put").add("get"); samer@0: } samer@0: samer@0: public void execute(String c, Environment env) throws Exception samer@0: { samer@0: if (c.equals("domain")) { samer@0: Shell.showDialogFor(getViewer().getComponent(),Node.lastPart(node.fullName())); samer@0: } else if (c.equals("symmetric")) { samer@0: symmetric = X._bool(env.datum(),!symmetric); samer@0: setDomain( map.getDomainMin(), map.getDomainMax()); samer@0: changed(); samer@0: } else if (c.equals("linear")) { samer@0: IMap newmap = new LinearMap( ); samer@0: newmap.setDomain( map.getDomainMin(), map.getDomainMax()); samer@0: newmap.setIntRange( map.getIntRange()); samer@0: setMap(newmap); samer@0: } else if (c.equals("log")) { samer@0: double min=map.getDomainMin(); samer@0: double max=map.getDomainMax(); samer@0: samer@0: if (min<=0) min=max/1000; // default dynamic range samer@0: symmetric=false; samer@0: setMap(new LogMap(min,max,map.getIntRange())); samer@0: } else if (c.equals("put")) Shell.put("map",this); samer@0: else if (c.equals("get")) setMap(((VMap)Shell.get("map")).getMap().copy()); samer@0: /* or samer@0: } else if (c.equals("put")) Shell.put("map",this.getMap().copy()); samer@0: else if (c.equals("get")) setMap((IMap)Shell.get("map")); samer@0: */ samer@0: } samer@0: samer@0: public void setSymmetric(boolean f) { symmetric=f; } samer@0: public void setDomain( double min, double max) samer@0: { samer@0: if (map instanceof LogMap) { samer@0: if (min<=0) min=max/1000; samer@0: } else { samer@0: if (symmetric) { max=Math.max(max,-min); min=-max; } samer@0: } samer@0: // Shell.trace("new domain=["+min+","+max+")"); samer@0: map.setDomain(min,max); samer@0: } samer@0: samer@0: class Adjuster extends BaseViewer samer@0: { samer@0: VBoolean sym; samer@0: VDouble t1, t2; samer@0: samer@0: Adjuster() samer@0: { samer@0: super(VMap.this); samer@0: panel().setName(getLabel()); samer@0: Shell.push(getNode()); samer@0: samer@0: setLayout( new StackLayout()); samer@0: samer@0: t1 = new VDouble("maximum",map.getDomainMax(),Variable.NOINIT); samer@0: t2 = new VDouble("minimum",map.getDomainMin(),Variable.NOINIT); samer@0: sym= new VBoolean("symmetric",symmetric,Variable.NOINIT); samer@0: t1.addObserver(this); samer@0: t2.addObserver(this); samer@0: sym.addObserver(this); samer@0: samer@0: add(t1.getViewer().getComponent()); samer@0: add(t2.getViewer().getComponent()); samer@0: add(sym.getViewer().getComponent()); samer@0: samer@0: Shell.pop(); samer@0: } samer@0: samer@0: public void update(Observable o, Object src) samer@0: { samer@0: if (src==this) return; // &&& samer@0: if (VMap.this.equals(o)) { samer@0: // means someone has changed the map ... samer@0: // ... and if it wasn't us... samer@0: t1.value=map.getDomainMax(); t1.changed(this); samer@0: t2.value=map.getDomainMin(); t2.changed(this); samer@0: if (sym.value!=symmetric) { samer@0: sym.value=symmetric; sym.changed(this); samer@0: } samer@0: } else { samer@0: // Widget adjusted samer@0: // user has adjusted controls... samer@0: // must set map and notify any observers samer@0: if (sym==o) { samer@0: if (symmetric=sym.value) { samer@0: double max=Math.max(t1.value,-t2.value); samer@0: t1.value=max; t2.value=-max; samer@0: t1.changed(this); t2.changed(this); samer@0: } samer@0: } else { samer@0: if (symmetric) { samer@0: if (t1==o) { t2.value=-t1.value; t2.changed(this); } samer@0: else if (t2==o) { t1.value=-t2.value; t1.changed(this); } samer@0: } samer@0: } samer@0: map.setDomain(t2.value,t1.value); samer@0: changed(this); samer@0: // else, WE adjusted the controls to samer@0: // reflect reality, so do nothing samer@0: } samer@0: } samer@0: } samer@0: } samer@0: samer@0: