% jfig/doc/embedding.txt (14.10.2002)


How to integrate jfig as a viewer or editor into your own application:

1. General overview
2. The class hierarchy
3. Further reading
4. A complete example



1. General Overview

This document tries to present an overview on how to integrate
the jfig 2D graphics editor class libries into other applications.
As such, it assumes a solid working knowledge of Java and basic 
2D geometry operations. It also assumes a basic knowledge of
the FIG file format used by xfig, jfig, and several other tools.

As jfig started as a programming exercise to create a Java-based
clone of the "xfig 3.1" graphics editor on a Sun workstation,
many of the design decisions for jfig are based on the original
FIG 3.1 specification. Please check www.xfig.org for the latest
version of xfig and the xfig documentation.

Perhaps the most important design decision concern the FIG 3.x
coordinate system, which currently uses signed 32 bit integers
to store object coordinates.

Newer versions of the FIG specification allow a scale factor to
convert between integer coordinates and world coordinates, while
older files were restricted to a fixed resolution of 1200 dpi. 
However, jfig so far uses a fixed resolution of 2400 dpi, where 
coordinates are automatically converted during file parsing.
This resolution allows for pixel-accurate positioning of objects
on most output devices (like laser and inkjet printers) at page
sizes of up to +/- (2*31-1 dots)/(2400 dpi) = +/- 894784 inch.

The FIG file format also specifies the set of supported graphical
objects, namely

- axis-aligned rectangles
- circles and ellipses
- text objects with 31 Postscript or 5 LaTeX fonts
- embedded image objects
- open polylines w/o arrowheads
- closed polygons
- arc objects w/o arrowheads
- several types of splines, notably "X-splines"
- compound ("group") objects consisting of any of the above
- library objects realized as compound objects

and a set of attributes available for each of the object types.
The jfig class library currently supports all of the above object
types with all attributes except for the following:

- embedded Postscript/PDF objects are only available if the
  underlying Java virtual machine supports them. While it is
  possible to enable this, none of the commercially available
  Java virtual machines currently support Postscript or PDF input.

- the default set of fonts is restricted by the fonts available
  on your Java virtual machine (usually Times, Helvetica, Courier).
  The remaining fonts can be enabled if you have TrueType variants
  of these fonts.













2. The jfig Class Hierarchy

The jfig class hierarchy consists of several dozen classes in
five main Java packages:

* jfig.canvas       classes to render FIG objects to the screen,
                    in both AWT and Swing variants. Also includes
                    rubberbanding and the graphics transformation.

* jfig.command      classes that implement the individual editing
                    commands, e.g create polyline or move object.

* jfig.gui          general user-interface classes, including the
                    main viewer and editor, menus, dialog windows,
                    buttons, icons, etc.
 
* jfig.objects      defines the central FigObject interface and
                    the individual FIG graphical objects. Also
                    includes the FigParser and FigWriter classes.
      
* jfig.utils        several utility classes used by the other
                    packages, as well as some self-test classes.

Please download the class documentation for the jfig packages
and study it carefully.  The central part of the class hierarchy 
is the jfig.objects package, whose classes implement the graphical 
objects defined in the FIG file formats:

* jfig.objects.FigObject - this is the central interface that
  defines what 

* jfig.objects.FigBaseobject.   This convenience class provides
  default implementations of most methods from the FigObject
  interface. It is used as the common base class for all
  individual graphical object classes currently provided by jfig, 
  like FigArc, FigPolyline, FigText, etc.

  However, the viewer and editor classes never directly reference
  FigBaseobject but only FigObject. Therefore, if you add new
  object types to jfig, these new classes do not have to extend
  FigBaseobject.

* All graphical objects defined by the FIG 2.x and 3.x formats
  have concrete implementations as classes in the jfig.objects
  package:  

  - FigRectangle  (basic, axis-aligned rectangle)
  - FigImage      (embedded, axis-aligned image object, supported 
                   file formats include GIF, JPEG, XBM, PNG. 
                   Depending on the Java VM, other image types may
                   be supported, too. Postscript and PDF are not.)
  - FigText       (text object, left/center/right aligned, rotated)
  - FigEllipse    (circle or ellipse, rotated)

  - FigPolyline   (polyline, w/o arrows or polygon)
  - FigArc        (arc defined by three points, pie-wedge style)
  - FigSpline     (several variants of open or closed splines)
  - FigBezier
  - FigXSpline

* jfig.objects.FigAttribs  defines the object attributes from
  the FIG file formats, e.g. line styles (solid, dashed, dotted),
  line width, arrow mode and arrow types, fill style, text fonts,
  text alignment, layers. It also provides convenience methods
  to copy and update attributes.

  Each FigObject has a reference to a FigAttribs object which
  defines the current object's attributes.

* Use the getPoints() and setPoints() to access the world 
  coordinate points of an object: the corners of a rectangle,
  polyline and polygon vertices, spline control points, and
  the text reference point. The polyline and spline objects
  also support a set of methods to insert or delete vertices.

* Use the getAttributes() and setAttributes() methods to 
  access the attribute parameters of a FigObject. 
  After changing attribute values, you may have to call
  rebuild() to inform the editor or viewer that the object
  has been changed.

  The update() method directly implements the xfig update
  attributes operation; it takes a "master attribute" objects
  and checks the update mask values in order to decide which
  individual attributes to update from the master values.

* jfig.objects.FigObjectlist implements the depth (=layer)-
  sorted data structure to manage a set of FigObjects.
  For redrawing, the FigObjectlist returns an Enumeration
  that starts with the deepest lying objects.
  



3. Source Code Examples in jfig.jar

Currently, the source code for jfig is not in the public domain.
However, a few source code examples are included in the jfig.jar
archive with the main jfig editor application. These files should
help you when trying to integrate jfig with your own application.
Use your favorite Zip packer tool or the jar application from the
JDK/JRE to extract the source files from the jfig.jar archive.


* jfig/utils/MakePieChart.java

  This code example shows how to use and manipulate FIG objects
  via Java calls to create a pie chart.

* jfig/gui/UserEditor.java

  Presents an example on how to add new functions and user interface
  controls to the default jfig editor.

* jfig/gui/FigDemo.java    

  This file shows how to integrate a simple FIG viewer component 
  into your user interface. This example is explained below.

* jfig/gui/SimpleFigApplet.java

  This is the source code for the "simple FIG applet" that allows
  to embed FIG graphics into web pages. The example is very similar
  to FigDemo.java, but adds a popup-menu to the object canvas and
  includes several callbacks.

* jfig/gui/ExportOptionsDialog.java

  The full source code for the "export options" dialog in the 
  jfig editor. This file is not included for its didactic value,
  but rather to allow someone else to correct and rewrite the code. 
  
  


4. A Complete Example

The following code (from jfig/gui/FigDemo.java) shows a simple but
complete example on how to use jfig to display a FIG file inside 
your own code. It creates an AWT frame with BorderLayout, that holds
a central FIG object canvas and a single button to reload a FIG file.
The file starts with the usual package and import declarations:


package jfig.gui;                // target package

import jfig.canvas.*;            // the canvas and transformation
import jfig.objects.*;           // FigObject, FigParser, ...
import jfig.utils.*;             // not always required
import java.awt.*;             
import java.awt.event.*;
import java.util.Enumeration;

public class FigDemo {
...                              // the following code snippets go here
}


Next the class declares a few member variables. The FigObjectList
provides the data structure to manage FIG object which are to be
displayed on the FigCanvas GUI component. The sublcass used here,
PresentationViewerCanvas, provides a few utility methods useful
later on (like doZoomFit()). We also need one instance of FigAttribs
which is required during initialization: 

  ...
  Frame           frame;         // your main application window
  Button          loadButton;    // your GUI components
  ...

  FigObjectList   objectList;    // data structure to manage FIG objects
  FigAttribs      attribs;       // default FIG attributes (include page setup)
  FigParser       parser;        // FIG file parser
  PresentationViewerCanvas objectCanvas;  // component to display a FIG drawing
  ...


The following method shows how to setup the jfig classes and to
create an object canvas component with user-selected settings:


  ...
  public void createFigCanvas() {
    attribs      = new FigAttribs();     // required to initalize jfig
    objectList   = new FigObjectList();  // stores and manages FIG objects
    objectCanvas = new PresentationViewerCanvas(); // the canvas
    objectCanvas.showRulers( false );
    objectCanvas.getTrafo().setGridMode( FigTrafo2D.MEDIUM_GRID );
    objectCanvas.getTrafo().setSnapRelative( FigTrafo2D.COARSE_SNAP );
    objectCanvas.setObjectEnumerator( new FigEnumerator() );
  }
  ...


Note that the objectCanvas nees a "FigDrawableEnumerator" instance
that provides it with the objects to display. In an editor, this
allows to modify the set of objects to be displayed, e.g. to hide
some objects during specific editing operations. In our case, we
add a simple inner class that retrieves the complete set of objects
from the objectList:


  ...
  class FigEnumerator implements FigDrawableEnumerator {
    public Enumeration getDrawableObjects() { return objectList.elements(); }
    public FigDrawable getTmpObject() { return null; }
  }
  ...


Now that we have the objectCanvas, we continue to build the user-
interface. In this small example, we use a single Frame with a 
single button below the central objectCanvas:


  ...
  public void createAndShowGUI() {
    frame = new Frame( "FIG viewer demonstration" );
    loadButton = new Button( "load random file" );
    frame.add( "Center", objectCanvas.getComponent() );
    frame.add( "South",  loadButton );
    frame.setSize( 400, 600 );
    frame.show();
  }
  ...


The next methods parser a FIG file from the specified File.
The rather complex parameters to the "parse" methods in
class FigParser are a relict from the first version of jfig,
which also includes a threaded variant that uses its own
deamon Thread to parse FIG data asynchronously in the background.

Just pass in an InputStream with the FIG data, three boolean 
parameters as shown, a default FigAttribs instance, the default 
coordinate transformation, and the objectList that is to be filled:


  ...
  public void parseFigFile( String filename ) {
    try {  
      objectList.deleteAll();
      parser = new FigParser();
      parser.setObjectPainter( objectCanvas );
      parser.parse_fig_file_not_threaded( 
        new java.io.FileInputStream( filename ),
        true, false, false, // toplevel, inside nested compound, merge
        attribs, objectCanvas.getTrafo(), objectList 
      );
      doZoomFit();
    }
    catch( Exception e ) { System.out.println( e ); }
  }


  public void doZoomFit() {
    FigBbox bbox = BoundingBoxCalculator.getBoundingBox(objectList.elements());
    objectCanvas.doZoomRegionFree( bbox );
  }
  ...


The convenience method doZoomRegionFree() from PresentationViewerCanvas
zooms into the specified region and sets the zoom factor and origin
correspondingly. The individual subclasses from package jfig.canvas
implement different zoom strategies for the doZoomRegion() method;
for example, the standard jfig editor restricts the zoom factor to
multiples of Math.sqrt(2).

At this point, you have a working user interface and can begin to
use callbacks to modify the FIG objects and the objectCanvas 
display parameters. The following method adds a calback to the
loadButton, so that a new FIG file is loaded every time the button
is clicked:
 

  ...
  public void addDemoCallback() {
    loadButton.addActionListener( new ActionListener() {
      String names[] = { "welcome.fig", "gold.fig", "watch.fig" };
      int    index = 0;

      public void actionPerformed( ActionEvent evt ) {
        index = (index+1) % names.length;
        parseFigFile( "examples/" + names[index] );
      }
    });
  }
  ...


The following main() method allows to run the FigDemo class
as a standalone application:


  ...
  public static void main( String argv[] ) {
    FigDemo fd = new FigDemo();
    fd.createFigCanvas();
    fd.createAndShowGUI();
    fd.parseFigFile( "examples/welcome.fig" );   // hard-coded
    fd.addDemoCallback();
  }
  ...

