sim.portrayal.inspector.PropertyInspector Maven / Gradle / Ivy
Show all versions of mason Show documentation
/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.portrayal.inspector;
import sim.portrayal.*;
import java.awt.*;
import javax.swing.*;
import sim.display.*;
import sim.engine.*;
import sim.util.*;
import java.io.*;
import java.awt.event.*;
import sim.util.gui.*;
/** PropertyInspector is a subclass of Inspector which is intended for plug-in inspectors of a single property of an object.
Plug-in inspectors may be associated with a Frame. To create a PropertyInspector, you need to do several things:
- In your class, override the static method
public static String name()
to return the desired name to display for this inspector
in a pop-up chooser or menu.
- In your class, override the static method
public static Class[] types()
to return an array of valid types the inspector
is capable of inspecting. The inspector will be made available for any property which is a subtype of a type in this array.
If the array is set to null
, all types will be assumed valid.
- Add your full class name to the sim/portrayal/inspector/propertyinspector.classes file so you're listed among
the plug-ins to query.
- Override your constructor
public Foo(Properties properties, int index, Frame parent, GUIState simulation)
.
Immediately after this constructor is called, the system will call isValidInspector()
to test to see if the inspector created
is valid and ready to be used, or should be thrown away. Thus in your constructor you should query the user as appropriate,
and if the user wishes to go ahead with the inspector, then setValidInspector(true)
. By default isValidInspector()
returns false.
- If we have a valid inspector, the system may then ask if it should construct a JFrame and put the inspector in it. If
you are handling your own frames etc., you may turn down this request by having
public boolean shouldCreateFrame()
return false. By default this method always returns true.
- PropertyInspector is an Inspector: thus you may also wish to override createFrame(...) and reviseStopper(...).
Like any inspector, your PropertyInspector will be asked to update and refresh itself to reflect new data whenevever
public void updateInspector()
is called.
Similarly, your PropertyInspector will be provided a Stoppable which it can use to stop MASON from continuing to
send update requests. For example, if your PropertyInspector has a cancel button and the user has just clicked it,
you might wish to call stop() on that Stoppable. This Stoppable is not provided immediately on PropertyInspector
construction, but later when the system has built the Stoppable and is ready to go. When it does so, it will call the
method public void setStopper(Stoppable stopper)
to provide you with the Stoppable. You may override
this method to determine what the Stoppable is; but be sure to call super.setStopper(stopper)
. Note that
the Stoppable provided will be whatever was returned by reviseStopper(...).
*/
public abstract class PropertyInspector extends Inspector
{
public int index;
public Properties properties;
/* public Frame parent; */
public GUIState simulation;
static Bag classes = null;
boolean validInspector = false;
protected Stoppable stopper;
public void setStopper(Stoppable stopper)
{
this.stopper = stopper;
}
public Stoppable getStopper()
{
return stopper;
}
/** Sets whether the inspector is valid or not. */
protected void setValidInspector(boolean val) { validInspector = val; }
/** Returns true if the inspector is valid. By default this returns false. */
public boolean isValidInspector() { return validInspector; }
/** Returns a PropertyInspector ready to go, or null if the user cancelled or some
other event or error occurred which prevented the PropertyIinspector from being constructed. */
public static PropertyInspector makeInspector(Class inspectorClass, Properties properties, int index,
Frame parent, GUIState simulation)
{
synchronized(simulation.state.schedule)
{
try
{
PropertyInspector inspector = (PropertyInspector)(inspectorClass.getConstructor(
new Class[] {Properties.class, Integer.TYPE, Frame.class, GUIState.class}).newInstance(
new Object[] { properties, Integer.valueOf(index), parent, simulation}));
if (inspector.isValidInspector()) return inspector;
else return null; // failed -- perhaps the user cancelled
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}
/** A string which defines the task the user performs when constructing this Inspector: such as "Make Histogram" */
public static String name() { return "Name Not Set"; }
/** A list of data types this Inspector is capable of inspecting. */
public static Class[] types() { return new Class[0]; }
/** Create a PropertyInspector for a given property. The property is element #index in the provided Properties class. Also provided
are the simulation and a
'parent' (a Frame which serves as the location where dialog boxes will pop up as part of the PropertyInspector construction
process -- it's fine if you provide null for this). */
public PropertyInspector(Properties properties, int index, Frame parent, GUIState simulation)
{
this.properties = properties;
this.index = index;
/* this.parent = parent; */
this.simulation = simulation;
}
public static String getMenuNameForPropertyInspectorClass(String classname)
{
try
{
return (String)(Class.forName(classname, true, Thread.currentThread().getContextClassLoader()).getMethod("name", new Class[0]).invoke(null, new Object[0]));
}
catch(Throwable e)
{
e.printStackTrace();
return null;
}
}
static boolean typesForClassCompatable(String classname, Class type)
{
try
{
Class[] types = (Class[])(Class.forName(classname, true, Thread.currentThread().getContextClassLoader()).getMethod("types", new Class[0]).invoke(null, new Object[0]));
if (types==null) return true; // all types are legal
for(int x=0;x