📄 visualization.java
字号:
package prefuse;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import prefuse.action.Action;
import prefuse.activity.Activity;
import prefuse.activity.ActivityMap;
import prefuse.data.Graph;
import prefuse.data.Node;
import prefuse.data.Schema;
import prefuse.data.Table;
import prefuse.data.Tree;
import prefuse.data.Tuple;
import prefuse.data.expression.Expression;
import prefuse.data.expression.Predicate;
import prefuse.data.expression.parser.ExpressionParser;
import prefuse.data.tuple.CompositeTupleSet;
import prefuse.data.tuple.DefaultTupleSet;
import prefuse.data.tuple.TupleManager;
import prefuse.data.tuple.TupleSet;
import prefuse.render.DefaultRendererFactory;
import prefuse.render.Renderer;
import prefuse.render.RendererFactory;
import prefuse.util.PrefuseConfig;
import prefuse.util.PrefuseLib;
import prefuse.util.collections.CompositeIterator;
import prefuse.visual.AggregateTable;
import prefuse.visual.VisualGraph;
import prefuse.visual.VisualItem;
import prefuse.visual.VisualTable;
import prefuse.visual.VisualTree;
import prefuse.visual.VisualTupleSet;
import prefuse.visual.expression.ValidatedPredicate;
import prefuse.visual.expression.VisiblePredicate;
import prefuse.visual.tuple.TableDecoratorItem;
import prefuse.visual.tuple.TableEdgeItem;
import prefuse.visual.tuple.TableNodeItem;
/**
* <p>Central data structure representing an interactive Visualization.
* This class is responsible for
* managing the mappings between source data and onscreen VisualItems,
* maintaining a list of {@link Display} instances responsible for rendering
* of and interaction with the contents of this visualization, and
* providing a collection of named Action instances for performing
* data processing such as layout, animation, and size, shape, and color
* assignment.</p>
*
* <p>The primary responsibility of the Visualization class is the creation
* of <em>visual abstractions</em> of input data. Regardless of the data
* structure (i.e., {@link prefuse.data.Table}, {@link prefuse.data.Graph},
* or {@link prefuse.data.Tree}), this class takes source data such as that
* loaded from a file (see {@link prefuse.data.io}) or from a relational
* database (see {@link prefuse.data.io.sql}) and creates a visual
* representation of the data. These visual representations of the data are
* data sets in their own right, providing access to the underlying source
* data to be visualized while also adding addition data fields specific to a
* visualization. These fields include spatial location (x, y
* coordinates and item bounds), color (for stroke, fill, and text), size,
* shape, and font. For a given input data set of type
* {@link prefuse.data.Table}, {@link prefuse.data.Graph}, or
* or {@link prefuse.data.Tree}, a corresponding instance of
* {@link prefuse.visual.VisualTable}, {@link prefuse.visual.VisualGraph}, or
* {@link prefuse.visual.VisualTree} is created and stored in the
* visualization. These data types inherit the data values of the source
* data (and indeed, manipulate it directly) while additionally providing
* the aforementioned visual variables unique to that generated
* visual abstraction. Similarly, all {@link prefuse.data.Tuple},
* {@link prefuse.data.Node}, or {@link prefuse.data.Edge}
* instances used to represent an entry in the source data have a
* corresponding {@link prefuse.visual.VisualItem},
* {@link prefuse.visual.NodeItem}, or {@link prefuse.visual.EdgeItem}
* representing the interactive, visual realization of the backing data.</p>
*
* <p>The mapping of source data to a visual abstraction is accomplished
* using {@link #add(String, TupleSet)} and the other "add" methods. These
* methods will automatically create the visual abstraction, and store it
* in this visualization, associating it with a provided <em>data group name
* </em>. This group name allows for queries to this visualization that
* consider only VisualItem instances from that particular group. This is
* quite useful when crafting {@link prefuse.action.Action} instances that
* process only a particular group of visual data. The Visualization class
* provides mechanisms for querying any or all groups within the visualization,
* using one or both of the group name or a filtering
* {@link prefuse.data.expression.Predicate} to determine the items to
* include (see {@link #items(Predicate)} for an examples). Source data
* may be added multiple times to a Visualization under different group
* names, allowing for multiple representations of the same backing data.</p>
*
* <p>Additionally, the Visualization class supports VisualItem instances
* that are not directly grounded in backing source data. Examples include
* {@link prefuse.visual.DecoratorItem} which "decorates" another pre-existing
* VisualItem with a separate interactive visual object, and
* {@link prefuse.visual.AggregateItem} which provides an interactive visual
* representation of an aggregated of other VisualItems. Methods for adding
* data groups of these kinds include {@link #addDecorators(String, String)}
* and {@link #addAggregates(String)}.</p>
*
* <p>All of the examples discussed above are examples of <em>primary, or
* visual, data groups</em> of VisualItems. Visualizations also support
* <em>secondary, or focus data groups</em> that maintain additional
* collections of the VisualItems stored in the primary groups. Examples
* include a set of focus items (such as those that have been clicked
* by the user), selected items (items selected by a user), or search
* items (all matches to a search query). The exact semantics of these
* groups and the mechanisms by which they are populated is determined by
* application creators, but some defaults are provided. The Visualization
* class includes some default group names, namely {@link #FOCUS_ITEMS},
* {@link #SELECTED_ITEMS}, and {@link #SEARCH_ITEMS} for the above
* mentioned tasks. By default, both the {@link #FOCUS_ITEMS},
* {@link #SELECTED_ITEMS} focus groups are included in the Visualization,
* represented using {@link prefuse.data.tuple.DefaultTupleSet} instances.
* Also, some of the interactive controls provided by the
* {@link prefuse.controls} package populate these sets by default. See
* {@link prefuse.controls.FocusControl} for an example.</p>
*
* <p>Visualizations also maintain references to all the {@link Display}
* instances providing interactive views of the content of this
* visualization. {@link Display} instances registers themselves with
* the visualization either in their constructor or through
* the {@link Display#setVisualization(Visualization)} method, so they
* do not otherwise need to be added manually. Displays can be configured
* to show all or only a subset of the data in the Visualization. A
* filtering {@link prefuse.data.expression.Predicate} can be used to
* control what items are drawn by the displaying, including limiting
* the Display to particular data groups (for example, using a
* {@link prefuse.visual.expression.InGroupPredicate}). The Visualization's
* {@link #repaint()} method will trigger a repaint on all Displays
* associated with the visualization.</p>
*
* <p>Finally, the Visualization class provides a map of named
* {@link prefuse.action.Action} instances that can be invoked to perform
* processing on the VisualItems contained in the visualization.
* Using the {@link #putAction(String, Action)} will add a named Action
* to the visualization, registering the Action such that a reference
* to this Visualization will be available within the scope of the
* Action's {@link prefuse.action.Action#run(double)} method. Processing
* Actions can later be invoked by name using the {@link #run(String)}
* method and other similar methods. This functionality not only
* provides a convenient means of organizing a Visualization-specific
* collection of processing Actions, it also allows for a layer of indirection
* between an Action and its name. This allows Actions to be dynamically
* swapped at runtime. For example, an application may make a call to
* invoke an Action named "layout", but the actual layout processing maybe
* be dynamically swapped by changing the Action that corresponds to that
* name. For more information on processing Actions, see the
* {@link prefuse.action} packages and the top-level
* {@link prefuse.action.Action} class.</p>
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class Visualization {
/** Data group name for indicating all groups */
public static final String ALL_ITEMS
= PrefuseConfig.get("visualization.allItems");
/** Default data group name for focus items */
public static final String FOCUS_ITEMS
= PrefuseConfig.get("visualization.focusItems");
/** Default data group name for selected items */
public static final String SELECTED_ITEMS
= PrefuseConfig.get("visualization.selectedItems");
/** Default data group name for search result items */
public static final String SEARCH_ITEMS
= PrefuseConfig.get("visualization.searchItems");
// visual abstraction
// filtered tables and groups
private Map m_visual;
private Map m_source;
private Map m_focus;
// actions
private ActivityMap m_actions;
// renderers
private RendererFactory m_renderers;
// displays
private ArrayList m_displays;
// ------------------------------------------------------------------------
// Constructor
/**
* Create a new, empty Visualization. Uses a DefaultRendererFactory.
*/
public Visualization() {
m_actions = new ActivityMap();
m_renderers = new DefaultRendererFactory();
m_visual = new LinkedHashMap();
m_source = new HashMap();
m_focus = new HashMap();
m_displays = new ArrayList();
addFocusGroup(Visualization.FOCUS_ITEMS, new DefaultTupleSet());
addFocusGroup(Visualization.SELECTED_ITEMS, new DefaultTupleSet());
}
// ------------------------------------------------------------------------
// Data Methods
/**
* Add a data set to this visualization, using the given data group name.
* A visual abstraction of the data will be created and registered with
* the visualization. An exception will be thrown if the group name is
* already in use.
* @param group the data group name for the visualized data
* @param data the data to visualize
* @return a visual abstraction of the input data, a VisualTupleSet
* instance
*/
public synchronized VisualTupleSet add(String group, TupleSet data) {
return add(group, data, null);
}
/**
* Add a data set to this visualization, using the given data group name.
* A visual abstraction of the data will be created and registered with
* the visualization. An exception will be thrown if the group name is
* already in use.
* @param group the data group name for the visualized data
* @param data the data to visualize
* @param filter a filter Predicate determining which data Tuples in the
* input data set are visualized
* @return a visual abstraction of the input data, a VisualTupleSet
* instance
*/
public synchronized VisualTupleSet add(
String group, TupleSet data, Predicate filter)
{
if ( data instanceof Table ) {
return addTable(group, (Table)data, filter);
} else if ( data instanceof Tree ) {
return addTree(group, (Tree)data, filter);
} else if ( data instanceof Graph ) {
return addGraph(group, (Graph)data, filter);
} else {
throw new IllegalArgumentException("Unsupported TupleSet type.");
}
}
protected void checkGroupExists(String group) {
if ( m_visual.containsKey(group) || m_focus.containsKey(group) ) {
throw new IllegalArgumentException(
"Group name \'"+group+"\' already in use");
}
}
protected void addDataGroup(String group, VisualTupleSet ts, TupleSet src) {
checkGroupExists(group);
m_visual.put(group, ts);
if ( src != null )
m_source.put(group, src);
}
// -- Tables --------------------------------------------------------------
/**
* Add an empty VisualTable to this visualization, using the given data
* group name. This adds a group of VisualItems that do not have a
* backing data set, useful for creating interactive visual objects
* that do not represent data. An exception will be thrown if the group
* name is already in use.
* @param group the data group name for the visualized data
* @return the added VisualTable
*/
public synchronized VisualTable addTable(String group) {
VisualTable vt = new VisualTable(this, group);
addDataGroup(group, vt, null);
return vt;
}
/**
* Add an empty VisualTable to this visualization, using the given data
* group name and table schema. This adds a group of VisualItems that do
* not have a backing data set, useful for creating interactive visual
* objects that do not represent data. An exception will be thrown if the
* group name is already in use.
* @param group the data group name for the visualized data
* @param schema the data schema to use for the VisualTable
* @return the added VisualTable
*/
public synchronized VisualTable addTable(String group, Schema schema) {
VisualTable vt = new VisualTable(this, group, schema);
addDataGroup(group, vt, null);
return vt;
}
/**
* Adds a data table to this visualization, using the given data group
* name. A visual abstraction of the data will be created and registered
* with the visualization. An exception will be thrown if the group name
* is already in use.
* @param group the data group name for the visualized data
* @param table the data table to visualize
*/
public synchronized VisualTable addTable(String group, Table table) {
return addTable(group, table, (Predicate)null);
}
/**
* Adds a data table to this visualization, using the given data group
* name. A visual abstraction of the data will be created and registered
* with the visualization. An exception will be thrown if the group name
* is already in use.
* @param group the data group name for the visualized data
* @param table the data table to visualize
* @param filter a filter Predicate determining which data Tuples in the
* input table are visualized
*/
public synchronized VisualTable addTable(
String group, Table table, Predicate filter)
{
VisualTable vt = new VisualTable(table, this, group, filter);
addDataGroup(group, vt, table);
return vt;
}
/**
* Adds a data table to this visualization, using the given data group
* name. A visual abstraction of the data will be created and registered
* with the visualization. An exception will be thrown if the group name
* is already in use.
* @param group the data group name for the visualized data
* @param table the data table to visualize
* @param schema the data schema to use for the created VisualTable
*/
public synchronized VisualTable addTable(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -