Skip navigation links

Package ucar.unidata.idv

The idv package.

See: Description

Package ucar.unidata.idv Description

The idv package.

Unidata Integrated Data Viewer (IDV)

The idv package provides the glue between the data sources within data package and the displays in the control package. The central class within this package is the IntegratedDataViewer (IDV).

How to add a new display, add a new data source, create a new gui.

Lions and tigers and bears...

Packages:

Data sources

Displays

Property files

Glue and Gui classes


The 30000 foot view

Initialization
So, now that we know a bit about what's what here is a short overview of how all of this gets glued together. It starts by the IDV reading in an xml file (datasource.xml) that defines the different DataSource-s available and what kinds of data (files, url) they manage and a property file (controls.xml) that defines the different DisplayControl-s that are available (and the kind of data they are applicable to).

GUI
The IDV creates a DataTree (JTree) to hold the list of instantiated DataSource-s and DataChoice-s. The actual GUI is not created by the IntegratedDataViewer class. Rather it is created by a concrete derived class of IntegratedDataViewer (e.g., DefaultIdv). This allows for us (in the future) to have different user interfaces.

Loading data
When the user picks a file or url to load the pertinent DataSource is found and instantiated. When the the DataSource is asked for its list of DataChoice-s some of the DataSource-s will also automatically add DerivedDataChoice-s to their list. The DataSource and its list of DataChoice-s are then added to the DataTree. Each DataChoice has a list of DataCategory-s that describe the flavor of data the DataChoice provides. For each DataChoice the DataTree uses the first DataCategory in this list to create a hierarchy of JTree nodes (each one representing a component of the DataCategory) in which to place the JTree node that represents the DataChoice.

Selecting data
When the user clicks on a particular DataChoice in the DataTree the list of control.DisplayControl-s is checked and those DisplayControl-s which are applicable to any of the DataChoice's DataCategory-s is shown (by default in a popup menu). When the user selects one of these DisplayControl-s it is instantiated (through the ControlDescriptor) with the DataChoice and a reference to the IDV (as a ControlContext interface object).

Displaying data
Typically, when a DisplayControl is created it may have its own DisplayMaster (e.g., control.ProfileControl) in its own window and/or it will want to display some Displayable within a common window (e.g., control.ThreeDSurfaceControl). For some cases (e.g., control.TextDisplayControl) there will be no use of the DisplayMaster/Displayable-s.

The DisplayControl-s don't actually deal with DisplayMaster-s. Rather, they deal with ViewManager-s which are wrappers aroung the DisplayMaster. For common display windows the DisplayControl asks the ControlContext for a ViewManager through the:
public ViewManager getViewManager (ViewDescriptor viewDescriptor);
method. This uses an instance of the ViewDescriptor to define what kind of ViewManager is needed. Currently we instantiate and use only one: MapViewManager.

The DisplayControl uses the DisplayInfo class to hold a reference to itself, its Displayable and the ViewManager in which the Displayable is displayed. This DisplayInfo object is also used by the ViewManager to keep a list of the DisplayControl-s that are being displayed within it. The ViewManager uses the DisplayControl method:
Component getLegendComponent ();
to retrieve an AWT component to place within its GUI. This AWT component typically contains a button to popup the DisplayControl's window and a checkbox for toggling the visibility of the DisplayControl's Displayable-s.

Whew!

Definining the data sources

The set of data sources available to the IDV is defined within the datasource.xml file. This file has the form:
data type.factory The java class name of the DataSourceFactory that is used to create data sources of this type
data type.label Text label used within the gui.
data type.patterns A set of comma separated regular expression patterns to determine if this data source is applicable for a given file or url
data type.default_display Name of a default display control to create when data sources of this type are loaded.
data type.show_in_tree Optional boolean that defines if data sources of this type are placed within the gui.

For example, for files or urls that are textual or html we have the TEXT data source type:

TEXT.label = Text or html files
TEXT.factory  = ucar.unidata.data.text.TextDataSource
TEXT.patterns=.htm$,.html$,.txt$,.text$,http
TEXT.default_display = textdisplay
TEXT.show_in_tree = false
This data source type is applicable to anything that ends with .htm, .html, .txt or .text (The $ used in the patterns represents the end of line character in a regular expression.). For this data source the IDV will automatically create a DisplayControl of type textdisplay and the data source will not be placed within the GUI (e.g., within the JTree of DataSource-s).

On initialization the IDV reads in the properties file and a set of PatternFileFilters are created which hold the regular expression patterns define in the properties file. These PatterFileFilters also hold an Object id attribute which the IDV uses to hold the String data type name.

This set of PatternFileFilters is used in two ways. The first way is when the user is selecting a local data set using a FileChooser. The PatternFileFilters are used as filters for the FileChooser.

Definining the display controls

The IDV reads in the controls.properties file to determine the set of DisplayControl-s available. This properties file holds a comma separated list (displays) of a set of display control names, e.g.:
displays=planviewflow, surface, profile, contourxs, contourcolor, planviewcontour, ...
These display control names are used to do subsequent lookups in the property file. We use this list (instead of enumerating across the keys of the Properties) so there is an ordering of the display controls when interacting with the user. It is important that when adding new displays to this list there are no line breaks.

Each control name in the list is used to look up the actual DisplayControl class name, its description and the data categories this DisplayControl is applicable to, e.g.:

windbarbplan.class=ucar.unidata.idv.control.FlowPlanViewControl
windbarbplan.label=Wind Barb Plan View
windbarbplan.desc = Add a wind barb plan view of flow vectors
windbarbplan.categories = macro.windvector
windbarbplan.properties = windbarbs=true;
Here we have a display control with id windbarbplan. It is implemented by the control.FlowPlanViewControl class. The windbarbplan.categories entry defines the data categories this display control is applicable to. Note the value is macro.windvector. This value is actually a reference to another entry in the properties file:
macro.windvector = *-windvector-*
In general, when the IDV deals with property files it uses a macro substitution mechanism (defined in Misc.getValue(java.lang.String, java.util.Hashtable)). The value of a property is scanned for anything of the form: macro.some_name. The value of the property macro.some_name is then used to do a textual substitution. Any macro's defined in the value of a macro property are not substituted. The value of the original property can hold any number of macro strings.

The categories field is a semi-colon (";") delimited set of data category strings. Each data category specification is a dash ("-") delimited set of category components. So a data category can be viewed as a hierarchy or path of components. For example, you could have a categories entry:

textdisplay.categories = text;html
This says that the textdisplay DisplayControl is applicable to any data which has data category of text or html. Now lets suppose we know there is data available that is html but has a more complex categorization, perhaps html that is weather related e.g.:
html.weather
In this case we might have a specialized display control that knows how to deal with these html-weather categorized data. In this case we would have a data category like:
special_html_display.categories= html-weather
This special category would only be applicable to the special "html-weather" data. However, this data is still "html" like data and we would also want the textdisplay DisplayControl to be able to display this data. To do this we can take advantage of the regular expression capability of data categories. Each component of a data category can also be a regular expression. So we could change the category of the textdisplay to be:
textdisplay.categories = *-text-*;*-html-*
This states that the textdisplay is applicable to any data that has a category that contains "text" as a component. This can be read as: 0 or more (arbitrary) components followed by a "text" component followed by 0 or more (arbitrary) components.
Another example:
2D-TIME-*
is read as any category that begins with the components "2D" and "TIME" and ends with 0 or more components.
We can also use the "+" to represent 1 or more and the "." to represent one, e.g.:
2D-TIME-+ (2D-TIME followed by one or more components)
2D-TIME-. (2D-TIME followed by one component)
2D-TIME-.-FOO (2D-TIME followed by one component followed by FOO)
One could also use richer regular expressions here but it has not been thouroughly tested (and needed) yet. Note: currently a string representation of a category is parsed (in DataCategory) using a StringTokenizer, breaking on "-". So if you use a regular expression that contains a "-" (e.g., [A-Z]+), this will break. Sometime in the future we'll tokenize smarter to allow for escapes, e.g.: [A\-Z]+.

The control data read in from the controls.properties is held in the ControlDescriptor class. This class has methods for testing whether the DisplayControl it represents is applicable to some DataCategory (ControlDescriptor.applicableTo) and for instantiating the DisplayControl (ControlDescriptor.doMakeDisplay).

Creating a new DataSource object

When the user selects some file or url the data type is found with the call to the IntegratedDataViewer method: private String getDataType (String file); This method iterates through the list of PatternFileFilters created with the datasource.properties to find the one that matches the file. If found then the id of the PatternFileFilter is returned. If no pattern matches the IDV has a special case of a url that points to an html file but does not match the ".html" pattern. If the string url begins with "http://" then it is assumed the data source of of type "TEXT".

Once the data type is found the factory class defined by the properties file is instantiated by the IDV method:

private DataSource createDataSource (Object dataName, String dataType, String globalId);

This method takes a specification of the data that is to be loaded in, Object dataName and the data type String dataType. The globalId is used for persistence and may evolve in the future. The dataName typically specifies a String file name or url but may hold anything (e.g., a list of images). The DataSource that handles this data is constructed using a reflection based factory pattern. The factory class name that creates this data source is found from the properties file.
String factoryClassName = (String) dataSourceProperties.get (dataType+".factory");
Class factoryClass = Class.forName (factoryClassName);

This class must provide a constructor that takes two arguments: a DataContext and the class of the dataName argument:
Constructor ctor = factory.getConstructor (new Class[]{DataContext.class, dataName.getClass()});
DataSourceFactory factory= (DataSourceFactory) ctor.newInstance (new Object[]{(DataContext)this, dataName});

The DataContext is an interface which the IDV implements. The data source is then retrieved:
DataSource dataSource = factory.getDataSource ();
It turns out that so far all of the DataSourceFactory-ies are actually the concrete DataSource classes (e.g., GeoGridDataSource, ImageDataSource). These classes all derive from DataSourceImpl which implements the DataSourceFactory interface by just returning "this" for the getDataSource method.

Once a DataSource has been instantiated the method IntegratedDataViewer.loadDataSource is called. This method does a couple of things. First it runs through the list of initial paramaters and displays (defined via the command line with the "-display" argument, see Command line arguments), creating the display for any matching parameters held by the DataSource.
Next, any default displays defined for that data source in the datasource.properties are created. Finally, the dataSource is added to the DataTree if the "show_in_tree" property for that dataSource (defined in the datasource.properties file) is true.

DataCategory

A data category is hierarchical and can be described as a string:
component1-component2-...-componentN
We use dashes ("-") to delimit each sub-component. An instance of a DataCategory class represents one of the sub-components. A DataCategory has a reference to a parent DataCategory and a child DataCategory. For example, the string FOO-BAR-ZOO is represented by three DataCategory objects:
 +-----+     +-----+     +-----+
 | FOO |-->  | BAR | --> | ZOO |
 +-----+     +-----+     +-----+
The DataCategory class has a number of static utility methods for parsing a string and returning a DataCategory object and for parsing a set of semi-colon delimited categories and returning a list of DataCategory objects.

How to...

Add a new display

Add a new data source

Create a new GUI

Skip navigation links