/*
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 javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.awt.*;
import sim.util.Properties;
import sim.util.SimpleProperties;
import sim.display.*;
import sim.util.gui.*;
/** GroupedInspector is an Inspector which holds multiple subInspectors
in turn, allowing you to device complex inspector sets to be displayed
in a single window. You add Inspectors to the GroupedInspector with
addInspector(...), specifying the string for a group
in which the inspectors are displayed.
<p>Alternatively, Grouped will generate an inspector automatically for
an object with is Groupable.
<p>Volatility is an issue: if some of the subInspectors are volatile
and some are not, should GroupedInspector behave as if it's volatile?
We have chosen to enforce the rule that all subInspectors must have
the same volatility as the GroupedInspector itself.
<p>You can also specify, through setUpdatingAllInspectors(...), whether
or not the GroupedInspector updates <i>all</i> of its subinspectors
whenever it is in turn updated, or if only the currently-displayed
subinspector is updated (and when we switch to a new inspector, it's
updated as of the switch).
*/
public class GroupedInspector extends Inspector
{
/** The Properties list displayed -- this may change at any time */
LabelledList PropertiesList;
ArrayList inspectors = new ArrayList();
boolean updatingAllInspectors;
/** Creates a volatile GroupedInspector in which an object's properties are broken into
several groups, each under its own group, according to the object's Groupable interface.
The group names are provided with the object.provideGroupNames(), and the properties
under each group are provided by object.provideGroupProperties. object.showExtraProperties()
specifies whether additional properties not appearing among those in object.provideGroupNames()
should appear as ungrouped properties in the inspector.
The subinspectors under each group are SimpleInspectors. */
public GroupedInspector(Groupable object, GUIState state, String name)
{
Properties properties = Properties.getProperties(object);
if (properties instanceof SimpleProperties)
{
buildGroupedInspector((SimpleProperties)properties, state, name,
object.provideGroupProperties(), object.provideGroupNames(),
object.showExtraProperties());
}
else throw new RuntimeException("A Groupable Object must provide SimpleProperties.");
}
/** Creates a GroupedInspector in which the provided properties are broken into
several groups, each under its own group. The group names are provided with groupNames,
and the properties under each group are given with the corresponding PropertiesNames.
showExtraProperties specifies whether additional properties not appearing
among those in PropertiesNames should appear as ungrouped properties in the inspector.
The subinspectors under each group are SimpleInspectors. */
public GroupedInspector(SimpleProperties properties, GUIState state, String name,
String[][] PropertiesNames, String[] groupNames, boolean showExtraProperties)
{ buildGroupedInspector(properties, state, name, PropertiesNames, groupNames, showExtraProperties); }
/** Creates a GroupedInspector with separate grouped subinspectors for each of the
provided properties. The names of each of these subinspectors is provided in groupNames.
Additionaly if extraProperties is provided, its properties are shown
immediately before these groups. If a name is provided, then the entire GroupedInspector
will have a bordered layout with that given name. If a title is provided (and it generally
out to be), then this will serve as the GroupedInspector's title (which appears when it is
in windows or tabs).
*/
public GroupedInspector(Properties[] properties, Properties extraProperties,
GUIState state, String name, String title, String[] groupNames)
{ buildGroupedInspector(properties, extraProperties, state, name, title, groupNames); }
/** Creates a GroupedInspector with separate grouped subinspectors for each of the
provided objects. The names of each of these subinspectors is provided in groupNames.
Additionaly if extraObject is provided, its properties are shown
immediately before these groups. If a name is provided, then the entire GroupedInspector
will have a bordered layout with that given name. If a title is provided (and it generally
out to be), then this will serve as the GroupedInspector's title (which appears when it is
in windows or tabs).
*/
public GroupedInspector(Object[] objects, Object extraObject,
GUIState state, String name, String title, String[] groupNames)
{
if (objects == null)
throw new RuntimeException("Objects array provided is null.");
Properties[] properties = new SimpleProperties[objects.length];
Properties extraProperties = null;
if (extraObject != null)
extraProperties = Properties.getProperties(extraObject);
for(int i = 0; i < objects.length; i++)
properties[i] = Properties.getProperties(objects[i]);
buildGroupedInspector(properties, extraProperties, state, name, title, groupNames);
}
void buildGroupedInspector(Properties[] properties, Properties extraProperties,
GUIState state, String name, String title, String[] groupNames)
{
setVolatile(true);
setLayout(new BorderLayout());
setTitle(title);
PropertiesList = new LabelledList(name);
add(PropertiesList, BorderLayout.CENTER);
add(getHeader(), BorderLayout.NORTH);
if (properties == null)
throw new RuntimeException("Properties provided is null.");
if (groupNames == null)
throw new RuntimeException("Group names provided is null.");
if (groupNames.length != properties.length)
{
throw new RuntimeException("Properties and group names must have the same length.");
}
if (extraProperties != null)
{
SimpleInspector insp = new SimpleInspector(extraProperties, state, null);
PropertiesList.add(insp);
inspectors.add(insp);
insp.setVolatile(isVolatile());
insp.setShowsUpdate(false);
}
for(int i = 0; i < groupNames.length; i++)
{
SimpleInspector insp = new SimpleInspector(properties[i], state, groupNames[i]);
addInspector(insp, groupNames[i]);
}
}
void buildGroupedInspector(SimpleProperties properties, GUIState state, String name,
String[][] PropertiesNames, String[] groupNames, boolean showExtraProperties)
{
setVolatile(true);
setLayout(new BorderLayout());
setTitle("" + properties.getObject());
PropertiesList = new LabelledList(name);
add(PropertiesList, BorderLayout.CENTER);
add(getHeader(), BorderLayout.NORTH);
if (groupNames == null)
throw new RuntimeException("Group names provided is null.");
if (PropertiesNames == null)
throw new RuntimeException("Properties names provided is null.");
if (groupNames.length != PropertiesNames.length)
{
throw new RuntimeException("Properties names and group names must have the same length.");
}
if (showExtraProperties)
{
// flatten all properties
int count = 0;
for(int i = 0; i < PropertiesNames.length; i++)
count += PropertiesNames[i].length;
String[] group = new String[count];
count = 0;
for(int i = 0; i < PropertiesNames.length; i++)
{
System.arraycopy(PropertiesNames[i], 0, group, count, PropertiesNames[i].length);
count += PropertiesNames[i].length;
}
SimpleProperties simp = properties.getPropertiesSubset(group, false);
SimpleInspector insp = new SimpleInspector(simp, state, null);
PropertiesList.add(insp);
inspectors.add(insp);
insp.setVolatile(isVolatile());
insp.setShowsUpdate(false);
}
for(int i = 0; i < PropertiesNames.length; i++)
{
SimpleProperties simp = properties.getPropertiesSubset(PropertiesNames[i], true);
SimpleInspector insp = new SimpleInspector(simp, state, groupNames[i]);
addInspector(insp, groupNames[i]);
}
}
/** Sets all subinspectors to be volatile */
public void setVolatile(boolean val)
{
int len = inspectors.size();
for(int x=0;x<len;x++)
((Inspector)(inspectors.get(x))).setVolatile(val);
super.setVolatile(val);
}
public void updateInspector()
{
int len = inspectors.size();
for(int x=0;x<len;x++)
((Inspector)(inspectors.get(x))).updateInspector();
}
/** Adds an inspector. Inspector must already have its name field set. */
public void addInspector(Inspector i)
{
inspectors.add(i);
PropertiesList.add(new DisclosurePanel(i.getTitle(), i));
i.setVolatile(isVolatile());
i.setShowsUpdate(false);
}
/** Adds an inspector with the given group name. */
public void addInspector(Inspector i, String group)
{
i.setTitle(group);
addInspector(i);
}
}