Package sim.display

Class GUIState

java.lang.Object
sim.display.GUIState

public abstract class GUIState extends Object
A wrapper for SimState and Schedule which provides additional functionality for GUI objects. This wrapper extends the functionality of SimState and Schedule through encapsulation, NOT subclassing. Why? Because the general idea is that SimState, and *anything* which hangs off of it, should be serializable out to a checkpoint and not know or care about whether or not it's running under a GUI or running headless.

Displays and Controllers (such as Display2D and the Console) do not care about the SimState, and make precious few calls to the Schedule. Instead, they generally only work with you through the GUIState class.

GUIState has the same start() and finish() methods as SimState, and indeed the default forms of these methods just call start() and finish() on the underlying SimState. Additionally, GUIState has init(Controller) and quit() methods. The init(Controller) method sets up the GUIState to work in an environment controlled by the specified Controller. The quit() method is called to tell the GUIState to shut down and free any of its resources (perhaps the simulation document is being closed in the GUI, or the GUI is quitting).

GUIState also has two methods used by the Controller to specify things about it. In particular, public static String getName(Class class) should return an intelligent name for the simulation, and public static Object getInfo(Class class) should return an HTML or textual description of the simulation either as a URL or a String.

You can create a global inspector for your model (as opposed to the individual per-object inspectors created by various portrayals). This is done by overriding either getInspector() or getSimulationInspectedObject().

GUIState has a wrapper step() method which in turn calls the Schedule's step(state) method. However, this wrapper lso provides a hook for objects such as displays to schedule themselves without using the Schedule. This hook is the scheduleImmediate(...) and scheduleImmediateRepeat(...) methods. There is also a reset() method which resets both the immediates and the underlying Schedule.

Last, GUIState has a wrapper function to make it convenient to read in a new SimState from a serialized file: readNewStateFromCheckpoint(). This function checks to see if the serialized file is valid for this simulation. To do this, it calls validSimState(), which is a hook that you should override to return TRUE if the provided state is a valid SimState for your simulation (usually this means that it's the right subclass of SimState for your purposes).

Generally speaking, if you have access to a GUIState, you should use GUIstate methods start(), finish(), step(), reset(), and readNewStateFromCheckpoint() instead of the underlying methods in the SimState and Controller. Otherwise, feel free to use the underlying methods (such as Schedule.getTime()).

Exception Handling. It's a common error to schedule a null event, or one with an invalid time. Like Schedule, GUIState previously returned false or null in such situations, but this leaves the burden on the programmer to check, and programmers are forgetful! We have changed GUIState and Schedule to throw exceptions by default instead. You can change them both back to returning false or null (perhaps if you want to handle the situations yourself more efficiently than catching an exception, or if you know what you're doing schedule-wise) by setting Schedule.setThrowingScheduleExceptions(false).

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected Steppable[]
     
    protected int
     
    protected Steppable[]
     
    protected int
     
    The controller for the GUIState.
    An additional random number generator available for GUI and drawing purposes, separate from the one used in the model.
    The underlying SimState
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    You may optionally override this constructor to call super(state) but you should be sure to override the no-argument GUIState() constructor as stipulated.
  • Method Summary

    Modifier and Type
    Method
    Description
    Creates and returns a controller ready for the user to manipulate.
    void
    Called either at the proper or a premature end to the simulation.
    static Object
    Override this method with a static method of your own in your subclass to provide an object (a URL or a String) describing information about your simulation; if you do not override this method, then the system will look for a file called index.html located next to your .class file and use a URL to that file as the information.
    static final Object
    getInfo(Class theClass)
    Returns either a String or a URL which provides descriptive information about the simulation hosted by the given class (which should be a GUIState subclass).
    By default returns a non-volatile Inspector which wraps around getSimulationInspectedObject(); if getSimulationInspectedObject() returns null, then getInspector() will return null also.
    int
     
    static String
    Override this method in your subclass to provide a descriptive name for your simulation; otherwise the default will be used: the short classname (that is, if your class is foo.bar.Baz, Baz will be used).
    static final String
    getName(Class theClass)
    Call this method to get the simulation name for any class.
    Returns an object with various property methods (getFoo(...), isFoo(...), setFoo(...)) whose properties will be accessible by the user.
    Override this to provide a custom Properties object for your simuation.
    static String
    Returns the short name of the class.
    protected Steppable[]
    Roughly doubles the array size, retaining the existing elements
    void
    init(Controller controller)
    Called to initialize (display) windows etc.
    boolean
    Deprecated. 
    void
    load(SimState state)
    Called by the Console when the user is loading in a new state from a checkpoint.
    void
    Called by the Console when the user is quitting the SimState.
    boolean
    Loads a new SimState from the provided file.
    protected void
    Don't call this unless you know what you're doing.
    boolean
    Schedules an item to occur when the user stops the simulator (when the stop() method is executed), when it stops on its own accord, or when the user has load()ed another simulation to replace it.
    boolean
    scheduleAtExtreme(Steppable event, boolean atEnd)
    Deprecated.
    use scheduleAtStart and scheduleAtEnd instead
    boolean
    Schedules an item to occur when the user starts the simulator (when the start() method is executed) or loads one (when load() is executed).
    boolean
    scheduleImmediate(boolean immediatelyAfter, Steppable event)
    Deprecated.
    use scheduleImmediatelyBefore and scheduleImmediatelyAfter instead
    boolean
    Schedules an item to occur (in no particular order) immediately after the schedule is stepped on the next time step (not including blank steps).
    boolean
    Schedules an item to occur (in no particular order) immediately before the schedule is stepped on the next time step (not including blank steps).
    scheduleImmediateRepeat(boolean immediatelyAfter, Steppable event)
    Deprecated.
    use scheduleRepeatingImmediatelyBefore and scheduleRepeatingImmediatelyAfter instead
    Schedules an item to occur (in no particular order) immediately after all future steps the Schedule takes (not including blank steps).
    Schedules an item to occur (in no particular order) immediately before all future steps the Schedule takes (not including blank steps).
    void
     
    boolean
    Returns FALSE if nothing was stepped -- the schedule is exhausted or time has run out.
    boolean
    This method should be set to return TRUE if state can be validly used -- mostly likely all you need to check is that it's the right class for this simulation.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • guirandom

      public MersenneTwisterFast guirandom
      An additional random number generator available for GUI and drawing purposes, separate from the one used in the model. If you use this generator to do things like specify the colors of agents on-screen, rather than use the model's generator, you can guarantee identical simulation results with the model regardless of whether it runs under the model or the GUI. Also, unlike state.random, using guirandom doesn't require synchronizing on state.schedule first.
    • state

      public SimState state
      The underlying SimState
    • controller

      public Controller controller
      The controller for the GUIState. This field may be null if there is no controller or no controller YET
    • storage

      public HashMap storage
    • before

      protected Steppable[] before
    • beforeSize

      protected int beforeSize
    • after

      protected Steppable[] after
    • afterSize

      protected int afterSize
  • Constructor Details

    • GUIState

      public GUIState(SimState state)
      You may optionally override this constructor to call super(state) but you should be sure to override the no-argument GUIState() constructor as stipulated.
  • Method Details

    • getTruncatedName

      public static String getTruncatedName(Class theClass)
      Returns the short name of the class. If the Class is foo.bar.baz.Quux, then Quux is returned.
    • getName

      public static final String getName(Class theClass)
      Call this method to get the simulation name for any class. If a class does not implement getName(), then the fully qualified classname is used instead. To provide a descriptive name for your class, override getName().
    • createController

      public Controller createController()
      Creates and returns a controller ready for the user to manipulate. By default this method creates a Console, sets it visible, and returns it. You can override this to provide some other kind of controller.
    • getName

      public static String getName()
      Override this method in your subclass to provide a descriptive name for your simulation; otherwise the default will be used: the short classname (that is, if your class is foo.bar.Baz, Baz will be used). That might not be very descriptive!

      Notice that this is a static method, and yet you're overriding it as if it were an instance method. This is because the method getInfo(Class) uses reflection to call the proper method on a per-class basis. Like magic!

    • getInfo

      public static final Object getInfo(Class theClass)
      Returns either a String or a URL which provides descriptive information about the simulation hosted by the given class (which should be a GUIState subclass). To change the information string about your own simulation, override the getInfo() method instead. If you don't override this method, MASON will look for a file called "index.html" in the same directory as the class file and use that. However if this then fails, Java will hunt for any "index.html" file and use that instead -- that's probably not what you wanted. Long story short, either override the getInfo() method, or provide an "index.html" file.
    • getInfo

      public static Object getInfo()
      Override this method with a static method of your own in your subclass to provide an object (a URL or a String) describing information about your simulation; if you do not override this method, then the system will look for a file called index.html located next to your .class file and use a URL to that file as the information. If there is no such file, Java may then go on a hunting expedition to find and return some file called index.html in your CLASSPATH; this is probably not what you intended, but we can't easily prevent it. If there's absolutely no such file, getInfo() will return a blank HTML page.

      Notice that this is a static method, and yet you're overriding it as if it were an instance method. This is because the method getInfo(Class) uses reflection to call the proper method on a per-class basis. Like magic!

    • getSimulationProperties

      public Properties getSimulationProperties()
      Override this to provide a custom Properties object for your simuation. This should be very rare: by default returns null.
    • getMaximumPropertiesForInspector

      public int getMaximumPropertiesForInspector()
    • getInspector

      public Inspector getInspector()
      By default returns a non-volatile Inspector which wraps around getSimulationInspectedObject(); if getSimulationInspectedObject() returns null, then getInspector() will return null also. Override this to provide a custom inspector as you see fit.
    • getSimulationInspectedObject

      public Object getSimulationInspectedObject()
      Returns an object with various property methods (getFoo(...), isFoo(...), setFoo(...)) whose properties will be accessible by the user. This gives you an easy way to allow the user to set certain global properties of your model from the GUI. If null is returned (the default), then nothing will be displayed to the user. One trick you should know about your object: it should be public, as well its property methods, and if it's anonymous, it should not introduce any property methods not defined in its superclass. Otherwise Java's reflection API can't access those methods -- they're considered private. GUIState also supports sim.util.Properties's domFoo(...) domain declarations to allow for sliders and pop-up lists.
    • isInspectorVolatile

      public boolean isInspectorVolatile()
      Deprecated.
      Use Inspector.isVolatile() instead. This method returns getInspector().isVolatile(). This is an expensive method and you should not use it.
    • init

      public void init(Controller controller)
      Called to initialize (display) windows etc. You can use this to set up the windows, then register them with the Controller so it can manage hiding, showing, and moving them. The default version of this method simply calls this.controller=controller;
    • start

      public void start()
    • finish

      public void finish()
      Called either at the proper or a premature end to the simulation. If the user quits the program, this function may not be called. Ordinarily, you wouldn't need to override this hook. Does nothing if the GUIState hasn't been started or loaded yet.
    • quit

      public void quit()
      Called by the Console when the user is quitting the SimState. A good place to stick stuff that you'd ordinarily put in a finalizer -- finalizers are tenuous at best. So here you'd put things like the code that closes the relevant display windows etc.
    • validSimState

      public boolean validSimState(SimState state)
      This method should be set to return TRUE if state can be validly used -- mostly likely all you need to check is that it's the right class for this simulation. The default returns TRUE if state is non-null and the same class as the current state; that's often sufficient.
    • load

      public void load(SimState state)
      Called by the Console when the user is loading in a new state from a checkpoint. The new state is passed in as an argument. You should override this, calling super.load(state) first, to reset your portrayals etc. to reflect the new state. state.start() will NOT be called. Thus anything you handled in start() that needs to be reset to accommodate the new state should be handled here. We recommend that you call repaint() on any Display2Ds.
    • readNewStateFromCheckpoint

      public boolean readNewStateFromCheckpoint(File file) throws IOException, ClassNotFoundException, OptionalDataException, ClassCastException, Exception
      Loads a new SimState from the provided file. Do not call this in an unthreadsafe situation -- it doesn't check. Returns false if the state was not valid. Returns various errors if bad things occurred trying to serialize in from the checkpoint. If false is returned or an error is thrown, the old SimState is retained.
      Throws:
      IOException
      ClassNotFoundException
      OptionalDataException
      ClassCastException
      Exception
    • resetQueues

      protected void resetQueues()
      Don't call this unless you know what you're doing.
    • step

      public boolean step()
      Returns FALSE if nothing was stepped -- the schedule is exhausted or time has run out.
    • increaseSubsteps

      protected Steppable[] increaseSubsteps(Steppable[] substeps)
      Roughly doubles the array size, retaining the existing elements
    • scheduleImmediatelyBefore

      public boolean scheduleImmediatelyBefore(Steppable event)
      Schedules an item to occur (in no particular order) immediately before the schedule is stepped on the next time step (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns false if the current time is AFTER_SIMULATION or if the event is null.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleImmediatelyAfter

      public boolean scheduleImmediatelyAfter(Steppable event)
      Schedules an item to occur (in no particular order) immediately after the schedule is stepped on the next time step (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns false if the current time is AFTER_SIMULATION or if the event is null.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleImmediate

      public boolean scheduleImmediate(boolean immediatelyAfter, Steppable event)
      Deprecated.
      use scheduleImmediatelyBefore and scheduleImmediatelyAfter instead
      Schedules an item to occur (in no particular order) immediately before or immediately after the schedule is stepped on the next time step (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns false if the current time is AFTER_SIMULATION or if the event is null.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleRepeatingImmediatelyBefore

      public Stoppable scheduleRepeatingImmediatelyBefore(Steppable event)
      Schedules an item to occur (in no particular order) immediately before all future steps the Schedule takes (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns a Stoppable, or null if the current time is AFTER_SIMULATION or if the event is null. The recurrence will continue until state.schedule.getTime() >= AFTER_SIMULATION, state.schedule is cleared out, or the Stoppable's stop() method is called, whichever happens first.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleRepeatingImmediatelyAfter

      public Stoppable scheduleRepeatingImmediatelyAfter(Steppable event)
      Schedules an item to occur (in no particular order) immediately after all future steps the Schedule takes (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns a Stoppable, or null if the current time is AFTER_SIMULATION or if the event is null. The recurrence will continue until state.schedule.getTime() >= AFTER_SIMULATION, state.schedule is cleared out, or the Stoppable's stop() method is called, whichever happens first.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleImmediateRepeat

      public Stoppable scheduleImmediateRepeat(boolean immediatelyAfter, Steppable event)
      Deprecated.
      use scheduleRepeatingImmediatelyBefore and scheduleRepeatingImmediatelyAfter instead
      Schedules an item to occur (in no particular order) immediately before or immediately after all future steps the Schedule takes (not including blank steps). Pass in FALSE to indicate you want to be immediately BEFORE the next timestep; pass in TRUE if you want to be immediately AFTER the next time step (the more common situation). Returns a Stoppable, or null if the current time is AFTER_SIMULATION or if the event is null. The recurrence will continue until state.schedule.getTime() >= AFTER_SIMULATION, state.schedule is cleared out, or the Stoppable's stop() method is called, whichever happens first.

      Why would you use this method? Primarily to get things scheduled which aren't stored in the Schedule itself, so it can be serialized out without them.

    • scheduleAtExtreme

      public boolean scheduleAtExtreme(Steppable event, boolean atEnd)
      Deprecated.
      use scheduleAtStart and scheduleAtEnd instead
      Schedules an item to occur when the user starts or stops the simulator, or when it stops on its own accord. If atEnd is TRUE, then the item is scheduled to occur when the finish() method is executed. If atEnd is FALSE, then the item is scheduled to occur when the start() method is executed. Returns true if scheduling succeeded.
    • scheduleAtStart

      public boolean scheduleAtStart(Steppable event)
      Schedules an item to occur when the user starts the simulator (when the start() method is executed) or loads one (when load() is executed). Identical to scheduleAtExtreme(event,false). Returns true if scheduling succeeded.
    • scheduleAtEnd

      public boolean scheduleAtEnd(Steppable event)
      Schedules an item to occur when the user stops the simulator (when the stop() method is executed), when it stops on its own accord, or when the user has load()ed another simulation to replace it. Identical to scheculeAtExtreme(event,false). Returns true if scheduling succeeded.