Splitting a VisAD application into data and UI pieces

The first step in making a VisAD application collaborative is to separate the code into a data/display initialization method (or methods) and a user interface creation method (or methods).

We need to do this because clients will fetch their Displays and data from the server and, if we want the server and clients to share code (always a good programming practice) we need to organize things to allow this.

Our sample application is so simple that this step is just a matter of moving the first piece of main() into a setupData() method and the second piece into a setupUI() method.

NOTE:    More complicated applications will often create a Display, add it to a JFrame, create a few ScalarMaps and add those to the Display, use one of the ScalarMaps to create a UI widget and add that to the Display, etc.
It will be a bit more difficult to reorganize these applications.

Don't forget to verify that the application still works after you've finished splitting things up.

Here is the sample application split into data and UI setup methods:
Prev Next
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.io.IOException;
import java.rmi.RemoteException;

import visad.*;
import visad.data.DefaultFamily;
import visad.java2d.DisplayImplJ2D;
import visad.util.ClientServer;

public class DisplayGIF
{
  // location of GIF file to be displayed
  private static final String fileURL = "http://www.ssec.wisc.edu/~billh/billh.gif";

  private static DisplayImpl setupData()
    throws IOException, RemoteException, VisADException
  {
    // create a display
    DisplayImpl dpy = new DisplayImplJ2D("display");

    // get the GIF file
    FlatField image = (FlatField )new DefaultFamily("dflt").open(fileURL);

    // compute ScalarMaps from type components
    FunctionType ftype = (FunctionType )image.getType();
    RealTupleType dtype = ftype.getDomain();
    RealTupleType rtype9 = (RealTupleType )ftype.getRange();
    dpy.addMap(new ScalarMap((RealType )dtype.getComponent(0),
                             Display.XAxis));
    dpy.addMap(new ScalarMap((RealType )dtype.getComponent(1),
                             Display.YAxis));
    dpy.addMap(new ScalarMap((RealType )rtype9.getComponent(0),
                             Display.Red));
    dpy.addMap(new ScalarMap((RealType )rtype9.getComponent(1),
                             Display.Green));
    dpy.addMap(new ScalarMap((RealType )rtype9.getComponent(2),
                             Display.Blue));

    // add the GIF data to the display
    DataReferenceImpl ref_image = new DataReferenceImpl("ref_image");
    ref_image.setData(image);
    dpy.addReference(ref_image, null);

    return dpy;
  }
 
  private static void setupUI(DisplayImpl dpy)
  {
    // create a frame
    JFrame jframe = new JFrame("GIF");
    jframe.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) { System.exit(0); }
      });

    // add display to frame
    jframe.setContentPane((Container )dpy.getComponent());

    // make frame visible
    jframe.pack();
    jframe.setVisible(true);
  }

  public static void main(String[] args)
    throws IOException, RemoteException, VisADException
  {
    DisplayImpl dpy = setupData();
    setupUI(dpy);
  }
}
    

Prev Next
Last modified: Wed Jul 12 10:56:07 CDT 2000