diff --git a/uk/ac/sanger/artemis/components/BasePlotGroup.java b/uk/ac/sanger/artemis/components/BasePlotGroup.java
index 09a5bbaaf0660be9a74113fa1a9d6c21cb301f87..23a16292ac56a20ab5a68dd0326777acdd431c2c 100644
--- a/uk/ac/sanger/artemis/components/BasePlotGroup.java
+++ b/uk/ac/sanger/artemis/components/BasePlotGroup.java
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/BasePlotGroup.java,v 1.1 2004-06-09 09:46:05 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/BasePlotGroup.java,v 1.2 2004-11-09 14:24:41 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.components;
@@ -42,11 +42,12 @@ import javax.swing.*;
  *  which can toggled off and on.
  *
  *  @author Kim Rutherford
- *  @version $Id: BasePlotGroup.java,v 1.1 2004-06-09 09:46:05 tjc Exp $
+ *  @version $Id: BasePlotGroup.java,v 1.2 2004-11-09 14:24:41 tjc Exp $
  **/
 
 public class BasePlotGroup extends JPanel
-  implements DisplayAdjustmentListener {
+                           implements DisplayAdjustmentListener 
+{
   /**
    *  Create a new BasePlotGroup component for the given EntryGroup.
    *  @param selection Used to set and display the current selection in the
@@ -55,20 +56,21 @@ public class BasePlotGroup extends JPanel
    *    This allows the user to double click on a base in a BasePlot and have
    *    the FeatureDisplay follow.
    **/
-  public BasePlotGroup (final EntryGroup entry_group,
-                        final Component owning_component,
-                        final Selection selection,
-                        final GotoEventSource goto_event_source) {
+  public BasePlotGroup(final EntryGroup entry_group,
+                       final Component owning_component,
+                       final Selection selection,
+                       final GotoEventSource goto_event_source) 
+  {
     this.owning_component = owning_component;
     this.entry_group = entry_group;
     this.selection = selection;
     this.goto_event_source = goto_event_source;
 
     final Strand forward_strand =
-      entry_group.getBases ().getForwardStrand ();
+      entry_group.getBases().getForwardStrand();
 
     final Strand reverse_strand =
-      entry_group.getBases ().getReverseStrand ();
+      entry_group.getBases().getReverseStrand();
 
     // the following arrays are from failed tests
     final float [] [] test_weights = {
@@ -114,12 +116,12 @@ public class BasePlotGroup extends JPanel
       1.0F,   0.02F,  0.002F, 0.004F
     };
 
-//    plot_algorithms_temp.add (new CAIWindowAlgorithm (forward_strand, cai_test));
-//    plot_algorithms_temp.add (new UserBaseAlgorithm (forward_strand, "test", test_weights));
-//    plot_algorithms_temp.add (new UserBaseAlgorithm (forward_strand, "test2", test_weights2));
-//    plot_algorithms_temp.add (new UserBaseAlgorithm (forward_strand, "test3", test_weights3));
+//    plot_algorithms_temp.add(new CAIWindowAlgorithm(forward_strand, cai_test));
+//    plot_algorithms_temp.add(new UserBaseAlgorithm(forward_strand, "test", test_weights));
+//    plot_algorithms_temp.add(new UserBaseAlgorithm(forward_strand, "test2", test_weights2));
+//    plot_algorithms_temp.add(new UserBaseAlgorithm(forward_strand, "test3", test_weights3));
 
-    setLayout (gridbag);
+    setLayout(gridbag);
 
     c.fill = GridBagConstraints.HORIZONTAL;
     c.anchor = GridBagConstraints.NORTH;
@@ -128,32 +130,54 @@ public class BasePlotGroup extends JPanel
     c.weightx = 1;
     c.weighty = 0;
 
-    c.insets = new Insets (0,0,5,0);
-
-    addAlgorithm (new GCWindowAlgorithm (forward_strand));
-    addAlgorithm (new GCSDWindowAlgorithm (forward_strand));
-    addAlgorithm (new AGWindowAlgorithm (forward_strand));
-    addAlgorithm (new GCFrameAlgorithm (forward_strand));
-    addAlgorithm (new GCFrameAlgorithm (reverse_strand));
-    addAlgorithm (new Codon12CorrelationAlgorithm(forward_strand));
-    addAlgorithm (new Codon12CorrelationAlgorithm(reverse_strand));
-    addAlgorithm (new GCDeviationAlgorithm (forward_strand));
-    addAlgorithm (new ATDeviationAlgorithm (forward_strand));
-    addAlgorithm (new KarlinSigAlgorithm (forward_strand));
+    c.insets = new Insets(0,0,5,0);
+
+    addAlgorithm(new GCWindowAlgorithm(forward_strand));
+    addAlgorithm(new GCSDWindowAlgorithm(forward_strand));
+    addAlgorithm(new AGWindowAlgorithm(forward_strand));
+    addAlgorithm(new GCFrameAlgorithm(forward_strand));
+    addAlgorithm(new GCFrameAlgorithm(reverse_strand));
+    addAlgorithm(new Codon12CorrelationAlgorithm(forward_strand));
+    addAlgorithm(new Codon12CorrelationAlgorithm(reverse_strand));
+    addAlgorithm(new GCDeviationAlgorithm(forward_strand));
+    addAlgorithm(new ATDeviationAlgorithm(forward_strand));
+    addAlgorithm(new KarlinSigAlgorithm(forward_strand));
   }
 
+ 
+  /**
+  * 
+  * Routine for printing graphs in artemis
+  *
+  */
+  protected void printComponent(Graphics g)
+  {
+    final Component[] children = getComponents();
+    for(int i = 0 ; i<children.length ; ++i)
+      if(children[i] instanceof BasePlot)
+      {
+        BasePlot bp = (BasePlot)children[i];
+        if(!bp.isVisible())
+          continue;
+        bp.paintCanvas(g);
+        g.translate(0,bp.getHeight());
+      }
+  }
+
+
   /**
    *  Implementation of the DisplayAdjustmentListener interface.  Invoked when
    *  a component (FeatureDisplay) scrolls or changes the scale.  Sends the
    *  event to all the BasePlot components in this BasePlotGroup.
    **/
-  public void displayAdjustmentValueChanged (DisplayAdjustmentEvent event) {
-    final Component [] children = getComponents ();
-
-    for (int i = 0 ; i < children.length ; ++i) {
-      if (children[i] instanceof BasePlot) {
-        ((BasePlot)children[i]).displayAdjustmentValueChanged (event);
-      }
+  public void displayAdjustmentValueChanged(DisplayAdjustmentEvent event) 
+  {
+    final Component[] children = getComponents();
+
+    for(int i = 0 ; i<children.length ; ++i)
+    {
+      if(children[i] instanceof BasePlot) 
+        ((BasePlot)children[i]).displayAdjustmentValueChanged(event);
     }
   }
 
@@ -161,24 +185,26 @@ public class BasePlotGroup extends JPanel
    *  Add a new BasePlot component for the given algorithm.
    *  @return The new BasePlot
    **/
-  public BasePlot addAlgorithm (final BaseAlgorithm algorithm) {
-    plot_value_producers.addElement (algorithm);
+  public BasePlot addAlgorithm(final BaseAlgorithm algorithm) 
+  {
+    plot_value_producers.addElement(algorithm);
 
-    return makePlot (algorithm, gridbag, c);
+    return makePlot(algorithm, gridbag, c);
   }
 
   /**
    *  Return the first CodonUsageAlgorithm or null if there isn't one in the
    *  group.
    **/
-  public CodonUsageAlgorithm getCodonUsageAlgorithm () {
-    for (int i = 0 ; i < plot_value_producers.size () ; ++i) {
+  public CodonUsageAlgorithm getCodonUsageAlgorithm() 
+  {
+    for(int i = 0 ; i < plot_value_producers.size() ; ++i) 
+    {
       final BaseAlgorithm this_algorithm =
-        (BaseAlgorithm) plot_value_producers.elementAt (i);
+        (BaseAlgorithm) plot_value_producers.elementAt(i);
 
-      if (this_algorithm instanceof CodonUsageAlgorithm) {
+      if(this_algorithm instanceof CodonUsageAlgorithm) 
         return (CodonUsageAlgorithm) this_algorithm;
-      }
     }
 
     return null;
@@ -188,11 +214,13 @@ public class BasePlotGroup extends JPanel
    *  Return an array containing the Algorithm objects of the BasePlot
    *  components in this BasePlotGroup.
    **/
-  public BaseAlgorithm [] getPlotAlgorithms () {
-    final BaseAlgorithm [] return_array =
-      new BaseAlgorithm [plot_value_producers.size ()];
+  public BaseAlgorithm[] getPlotAlgorithms() 
+  {
+    final BaseAlgorithm[] return_array =
+      new BaseAlgorithm[plot_value_producers.size ()];
 
-    for (int i = 0 ; i < plot_value_producers.size () ; ++i) {
+    for(int i = 0 ; i < plot_value_producers.size () ; ++i) 
+    {
       final BaseAlgorithm this_algorithm =
         (BaseAlgorithm) plot_value_producers.elementAt (i);
       return_array[i] = this_algorithm;
@@ -205,9 +233,9 @@ public class BasePlotGroup extends JPanel
    *  Return true if and only if the BasePlot for the given Algorithm is
    *  visible.
    **/
-  public boolean basePlotIsVisible (final Algorithm algorithm) {
-    final Component base_plot = findPlotByAlgorithm (algorithm);
-
+  public boolean basePlotIsVisible(final Algorithm algorithm) 
+  {
+    final Component base_plot = findPlotByAlgorithm(algorithm);
     return base_plot.isVisible ();
   }
 
@@ -215,11 +243,12 @@ public class BasePlotGroup extends JPanel
    *  Given an Algorithm, find and set the visibility of the corresponding
    *  BasePlot component.
    **/
-  public void setVisibleByAlgorithm (final Algorithm algorithm,
-                                     final boolean visible) {
-    final JComponent base_plot = findPlotByAlgorithm (algorithm);
+  public void setVisibleByAlgorithm(final Algorithm algorithm,
+                                    final boolean visible) 
+  {
+    final JComponent base_plot = findPlotByAlgorithm(algorithm);
 
-    base_plot.setVisible (visible);
+    base_plot.setVisible(visible);
     if (getParent () != null) {
       // XXX change to revalidate().
       getParent ().validate ();
@@ -230,22 +259,25 @@ public class BasePlotGroup extends JPanel
    *  Find the BasePlot component in this BasePlotGroup object that is
    *  plotting the given Algorithm or null if no such BasePlot object exists.
    **/
-  private JComponent findPlotByAlgorithm (final Algorithm algorithm) {
-    final Component [] children = getComponents ();
-
-    for (int i = 0 ; i < children.length ; ++i) {
-      if (children[i] instanceof BasePlot) {
+  private JComponent findPlotByAlgorithm(final Algorithm algorithm) 
+  {
+    final Component[] children = getComponents();
+
+    for(int i = 0 ; i < children.length ; ++i) 
+    {
+      if(children[i] instanceof BasePlot) 
+      {
         final Algorithm component_algorithm =
-          ((BasePlot)children[i]).getAlgorithm ();
-        if (component_algorithm == algorithm) {
+                           ((BasePlot)children[i]).getAlgorithm ();
+        if(component_algorithm == algorithm)
           return (JComponent)children[i];
-        }
       }
     }
 
     return null;
   }
 
+
   /**
    *  Create a Plot component for the given Algorithm and then make a button
    *  for it so that it can be shown and hidden.  Note that button making is
@@ -256,18 +288,18 @@ public class BasePlotGroup extends JPanel
    *    Plot components.
    *  @return The new BasePlot
    **/
-  private BasePlot makePlot (BaseAlgorithm algorithm,
-                             GridBagLayout gridbag,
-                             GridBagConstraints constraints) {
-
+  private BasePlot makePlot(BaseAlgorithm algorithm,
+                            GridBagLayout gridbag,
+                            GridBagConstraints constraints) 
+  {
     final BasePlot new_base_plot =
-      new BasePlot (algorithm, getSelection (), getGotoEventSource ());
+      new BasePlot(algorithm, getSelection(), getGotoEventSource());
 
-    gridbag.setConstraints (new_base_plot, constraints);
-    add (new_base_plot);
-    new_base_plot.setVisible (false);
+    gridbag.setConstraints(new_base_plot, constraints);
+    add(new_base_plot);
+    new_base_plot.setVisible(false);
 
-    getSelection ().addSelectionChangeListener (new_base_plot);
+    getSelection().addSelectionChangeListener(new_base_plot);
 
     if (getParent () != null) {
       // XXX change to revalidate().
@@ -280,21 +312,24 @@ public class BasePlotGroup extends JPanel
   /**
    *  Return the Selection object that was passed to the constructor.
    **/
-  private Selection getSelection () {
+  private Selection getSelection() 
+  {
     return selection;
   }
 
   /**
    *  Return the EntryGroup object that was passed to the constructor.
    **/
-  private EntryGroup getEntryGroup () {
+  private EntryGroup getEntryGroup() 
+  {
     return entry_group;
   }
 
   /**
    *  Return the GotoEventSource object that was passed to the constructor.
    **/
-  private GotoEventSource getGotoEventSource () {
+  private GotoEventSource getGotoEventSource()
+  {
     return goto_event_source;
   }
 
diff --git a/uk/ac/sanger/artemis/components/EntryEdit.java b/uk/ac/sanger/artemis/components/EntryEdit.java
index af5d8619287e672694aa391e7050ba9be3a64042..3a20fd2350e2b4fab767cf9ecb204b1a7ccd7ae2 100644
--- a/uk/ac/sanger/artemis/components/EntryEdit.java
+++ b/uk/ac/sanger/artemis/components/EntryEdit.java
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/EntryEdit.java,v 1.3 2004-07-29 08:44:16 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/EntryEdit.java,v 1.4 2004-11-09 14:24:41 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.components;
@@ -51,7 +51,7 @@ import javax.swing.border.BevelBorder;
  *  Each object of this class is used to edit an EntryGroup object.
  *
  *  @author Kim Rutherford
- *  @version $Id: EntryEdit.java,v 1.3 2004-07-29 08:44:16 tjc Exp $
+ *  @version $Id: EntryEdit.java,v 1.4 2004-11-09 14:24:41 tjc Exp $
  *
  */
 
@@ -94,7 +94,9 @@ public class EntryEdit extends JFrame
   **/
   private EntrySourceVector entry_sources;
 
+  private SelectionInfoDisplay selection_info;
 
+   
   /**
    *  Create a new EntryEdit object and JFrame.
    *  @param entry_group The EntryGroup object that this component is editing.
@@ -158,7 +160,7 @@ public class EntryEdit extends JFrame
     
     menu_bar.setFont(default_font);
 
-    SelectionInfoDisplay selection_info =
+    selection_info =
       new SelectionInfoDisplay(getEntryGroup(), getSelection());
     box_panel.add(selection_info);
 
@@ -213,7 +215,6 @@ public class EntryEdit extends JFrame
     one_line_per_entry_display.addDisplayAdjustmentListener(feature_display);
 
     box_panel.add(feature_display);
-
     feature_display.setVisible(true);
 
     base_display =
@@ -283,6 +284,82 @@ public class EntryEdit extends JFrame
     Utilities.centreFrame(this);
   }
 
+
+  /**
+  *
+  * Retrieve the feature list object.
+  *
+  */
+  protected FeatureList getFeatureList()
+  {
+    return feature_list;
+  }
+
+
+  /**
+  *
+  * Retrieve the base display object.
+  *
+  */
+  protected FeatureDisplay getBaseDisplay()
+  {
+    return base_display;
+  }
+
+  /**
+  *
+  * Retrieve the one line per entry object.
+  *
+  */
+  protected FeatureDisplay getOneLinePerEntryDisplay()
+  {
+    return one_line_per_entry_display;
+  }
+
+
+  /**
+  *
+  * Retrieve the base plot display object.
+  *
+  */
+  protected BasePlotGroup getBasePlotGroup()
+  {
+    return base_plot_group;
+  }
+
+
+  /**
+  *
+  * Retrieve the entry group display object.
+  *
+  */
+  protected EntryGroupDisplay getEntryGroupDisplay()
+  {
+    return group_display;
+  }
+
+
+  /**
+  *
+  * Retrieve the selection info display object.
+  *
+  */
+  protected SelectionInfoDisplay getSelectionInfoDisplay()
+  {
+    return selection_info;
+  }
+
+
+  /**
+  *
+  * Retrieve the feature display object.
+  *
+  */
+  protected FeatureDisplay getFeatureDisplay()
+  {
+    return feature_display;
+  }
+
   /**
    *  If there are no unsaved changes, close this EntryEdit.  Otherwise ask
    *  the user first.
@@ -1084,7 +1161,8 @@ public class EntryEdit extends JFrame
 
     file_menu.add(clone_entry_edit);
     file_menu.addSeparator();
-
+    printMenu();
+    file_menu.addSeparator();
 
     final JMenuItem close = new JMenuItem("Close");
     close.addActionListener(new ActionListener() 
@@ -1098,6 +1176,34 @@ public class EntryEdit extends JFrame
     file_menu.add(close);
   }
 
+  private void printMenu()
+  {
+    JMenuItem printImage = new JMenuItem("Print Image Files (png/jpeg)...");
+    printImage.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        PrintArtemis part = new PrintArtemis(EntryEdit.this);
+        part.print();
+      }
+    });
+    file_menu.add(printImage);
+
+// print preview
+    JMenuItem printPreview = new JMenuItem("Print Preview");
+    file_menu.add(printPreview);
+    printPreview.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        PrintArtemis part = new PrintArtemis(EntryEdit.this);
+        part.printPreview();
+      }
+    });
+
+  }
+
+
   /**
    *  Read an entry
    **/
diff --git a/uk/ac/sanger/artemis/components/EntryGroupDisplay.java b/uk/ac/sanger/artemis/components/EntryGroupDisplay.java
index a37b6f6cff2cecd3a651d1665ec68aa876fdcf35..bceed251f59842520dfb1c4c8714ea0c805ad38d 100644
--- a/uk/ac/sanger/artemis/components/EntryGroupDisplay.java
+++ b/uk/ac/sanger/artemis/components/EntryGroupDisplay.java
@@ -20,14 +20,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/EntryGroupDisplay.java,v 1.1 2004-06-09 09:46:29 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/EntryGroupDisplay.java,v 1.2 2004-11-09 14:24:41 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.components;
 
 import uk.ac.sanger.artemis.*;
-import java.awt.FlowLayout;
-import java.awt.Color;
+import java.awt.*;
 import java.awt.event.*;
 import java.util.Vector;
 
@@ -38,7 +37,7 @@ import javax.swing.*;
  *  objects in an EntryGroup.
  *
  *  @author Kim Rutherford
- *  @version $Id: EntryGroupDisplay.java,v 1.1 2004-06-09 09:46:29 tjc Exp $
+ *  @version $Id: EntryGroupDisplay.java,v 1.2 2004-11-09 14:24:41 tjc Exp $
  **/
 
 public class EntryGroupDisplay extends JPanel
@@ -93,6 +92,13 @@ public class EntryGroupDisplay extends JPanel
     setBackground(background_colour);
   }
 
+ 
+  protected void printComponent(Graphics g)
+  {
+    super.paintComponent(g);
+    super.printChildren(g);
+  }
+
 
   /**
    *  Implementation of the EntryGroupChangeListener interface.  We listen to
diff --git a/uk/ac/sanger/artemis/components/FeatureDisplay.java b/uk/ac/sanger/artemis/components/FeatureDisplay.java
index c4f8c047122cf918530ec9c4d556dc8b40827487..8a36c42d24622350248b1315745f3c5ca2eaabb2 100644
--- a/uk/ac/sanger/artemis/components/FeatureDisplay.java
+++ b/uk/ac/sanger/artemis/components/FeatureDisplay.java
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeatureDisplay.java,v 1.7 2004-10-28 13:06:41 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeatureDisplay.java,v 1.8 2004-11-09 14:24:41 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.components;
@@ -44,7 +44,7 @@ import javax.swing.JComponent;
  *  This component is used for displaying an Entry.
  *
  *  @author Kim Rutherford
- *  @version $Id: FeatureDisplay.java,v 1.7 2004-10-28 13:06:41 tjc Exp $
+ *  @version $Id: FeatureDisplay.java,v 1.8 2004-11-09 14:24:41 tjc Exp $
  **/
 
 public class FeatureDisplay extends EntryGroupPanel
@@ -4458,6 +4458,12 @@ public class FeatureDisplay extends EntryGroupPanel
   }
 
 
+  protected int getDisplayWidth()
+  {
+    return getWidth() - scale_changer.getWidth();
+  }
+
+
   /**
    *  Return the display line that contains the given point, or -1 if
    *  the point is off screen.
diff --git a/uk/ac/sanger/artemis/components/PrintArtemis.java b/uk/ac/sanger/artemis/components/PrintArtemis.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ebf9d7dfecd7b5720b5538cc9c45e1751d94f4a
--- /dev/null
+++ b/uk/ac/sanger/artemis/components/PrintArtemis.java
@@ -0,0 +1,442 @@
+/* PrintACT.java
+ *
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.components;
+
+import java.awt.*;
+import java.awt.print.Paper;
+import java.awt.print.PageFormat;
+import java.awt.print.PrinterJob;
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.*;
+import java.io.*;
+import javax.swing.border.*;
+import javax.imageio.*;
+import javax.imageio.stream.*;
+
+import uk.ac.sanger.artemis.editor.ScrollPanel;
+
+/**
+*
+* Use to print images from Artemis
+*
+*/
+public class PrintArtemis extends ScrollPanel
+{
+
+  /** act display to create image from */
+  private JCheckBox demisrawLabels = new JCheckBox("Show labels on alignment");
+  private EntryEdit entry;
+
+  private JCheckBox selectDisplay   = new JCheckBox("Show Selection Header",true);
+  private JCheckBox featDisplay     = new JCheckBox("Show Feature Display",true);
+  private JCheckBox groupsDisplay   = new JCheckBox("Show Entries Loaded",true);
+  private JCheckBox plotsDisplay    = new JCheckBox("Show Graphs",true);
+  private JCheckBox onelineDisplay  = new JCheckBox("Show One Line Display",true);
+  private JCheckBox baseDisplay     = new JCheckBox("Show Bases Display",true);
+  private JCheckBox featListDisplay = new JCheckBox("Show Feature List",true);
+  private int width;
+  private int height;
+
+  public PrintArtemis(EntryEdit entry)
+  {
+    this.entry = entry;
+  }
+
+
+  public void paintComponent(Graphics g)
+  {
+// let UI delegate paint first (incl. background filling)
+    super.paintComponent(g);
+    Graphics2D g2d = (Graphics2D)g.create();
+
+    // selection info
+    if(selectDisplay.isSelected())
+    {
+      entry.getSelectionInfoDisplay().paintComponent(g2d);
+      g2d.translate(0,entry.getSelectionInfoDisplay().getHeight());
+    }
+
+    // entry groups
+    if(groupsDisplay.isSelected())
+    {
+      entry.getEntryGroupDisplay().printComponent(g2d);
+      g2d.translate(0,entry.getEntryGroupDisplay().getHeight());
+    }
+
+    // plots
+    if(plotsDisplay.isSelected())
+      entry.getBasePlotGroup().printComponent(g2d);
+//  g2d.translate(0,entry.getBasePlotGroup().getHeight());
+
+    // one line per entry
+    if(onelineDisplay.isSelected())
+    {
+      entry.getOneLinePerEntryDisplay().paintComponent(g2d);
+      g2d.translate(0,entry.getOneLinePerEntryDisplay().getHeight());
+    }
+
+    // feature display
+    if(featDisplay.isSelected())
+    {
+      entry.getFeatureDisplay().paintComponent(g2d);
+      g2d.translate(0,entry.getFeatureDisplay().getHeight());
+    }
+
+    // base display
+    if(baseDisplay.isSelected())
+    {
+      entry.getBaseDisplay().paintComponent(g2d);
+      g2d.translate(0,entry.getBaseDisplay().getHeight());
+    }
+
+    // feature list
+    if(featListDisplay.isSelected())
+      entry.getFeatureList().paintComponent(g2d);
+  }
+
+
+  private void setImageSize()
+  {
+    height = 0;
+    width  = entry.getFeatureDisplay().getDisplayWidth();
+    if(selectDisplay.isSelected())
+      height += entry.getSelectionInfoDisplay().getHeight();
+
+    if(groupsDisplay.isSelected())
+      height += entry.getEntryGroupDisplay().getHeight();
+
+    if(plotsDisplay.isSelected())
+      height += entry.getBasePlotGroup().getHeight();
+
+    if(onelineDisplay.isSelected())
+      height += entry.getOneLinePerEntryDisplay().getHeight();
+
+    if(baseDisplay.isSelected())
+      height += entry.getBaseDisplay().getHeight();
+
+    if(featDisplay.isSelected())
+      height += entry.getFeatureDisplay().getHeight();
+
+    if(featListDisplay.isSelected())
+      height += entry.getFeatureList().getHeight();
+    setPreferredSize(new Dimension(width,height));
+  }
+
+  /**
+  *
+  * Display a print preview page
+  *
+  */
+  protected void printPreview()
+  {
+    final JFrame f = new JFrame("Print Preview");
+    JPanel jpane   = (JPanel)f.getContentPane();
+
+    JScrollPane scrollPane = new JScrollPane(this);
+
+    jpane.setLayout(new BorderLayout());
+    jpane.add(scrollPane,BorderLayout.CENTER);
+    
+    final Dimension dScreen = f.getToolkit().getScreenSize();
+    Dimension d = new Dimension((int)(3*dScreen.getWidth()/4),
+                                (int)(dScreen.getHeight()/2));
+    f.setSize(d);
+    setImageSize();
+
+    JMenuBar menuBar = new JMenuBar();
+    JMenu filemenu = new JMenu("File");
+    menuBar.add(filemenu);
+
+// print png/jpeg
+    JMenuItem printImage = new JMenuItem("Print Image Files (png/jpeg)...");
+    printImage.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        print();
+      }
+    });
+    filemenu.add(printImage);
+
+// close
+    filemenu.add(new JSeparator());
+    JMenuItem menuClose = new JMenuItem("Close");
+    menuClose.setAccelerator(KeyStroke.getKeyStroke(
+              KeyEvent.VK_E, ActionEvent.CTRL_MASK));
+
+    filemenu.add(menuClose);
+    menuClose.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        f.dispose();
+      }
+    });
+
+    JMenu optionsmenu = new JMenu("Options");
+    menuBar.add(optionsmenu);
+
+// draw selection info
+    JCheckBoxMenuItem showSelection = new JCheckBoxMenuItem("Show Selection Header",
+                                                            selectDisplay.isSelected());
+    showSelection.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        selectDisplay.setSelected(!selectDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showSelection);
+
+// draw entry groups
+    JCheckBoxMenuItem showEntryGroups = new JCheckBoxMenuItem("Show Entries Loaded",
+                                                            groupsDisplay.isSelected());
+    showEntryGroups.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        groupsDisplay.setSelected(!groupsDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showEntryGroups);
+
+// draw graphs
+    JCheckBoxMenuItem showPlots = new JCheckBoxMenuItem("Show Graphs",
+                                                         plotsDisplay.isSelected());
+    showPlots.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        plotsDisplay.setSelected(!plotsDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showPlots);
+
+// draw one line 
+    JCheckBoxMenuItem showOneLine = new JCheckBoxMenuItem("Show One Line Display",
+                                                          onelineDisplay.isSelected());
+    showOneLine.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        onelineDisplay.setSelected(!onelineDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showOneLine);
+
+// draw features
+    JCheckBoxMenuItem showFeatures = new JCheckBoxMenuItem("Show Feature Display",
+                                                            featDisplay.isSelected());
+    showFeatures.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        featDisplay.setSelected(!featDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showFeatures);
+
+// draw base display
+    JCheckBoxMenuItem showBases = new JCheckBoxMenuItem("Show Bases Display",
+                                                         baseDisplay.isSelected());
+    showBases.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        baseDisplay.setSelected(!baseDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showBases);
+
+// draw feature list
+    JCheckBoxMenuItem showFeatureList = new JCheckBoxMenuItem("Show Feature List",
+                                                               featListDisplay.isSelected());
+    showFeatureList.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        featListDisplay.setSelected(!featListDisplay.isSelected());
+        repaint();
+      }
+    });
+    optionsmenu.add(showFeatureList);
+
+    f.setJMenuBar(menuBar);
+    f.setVisible(true);
+  }
+
+  /**
+  *
+  * Print to a jpeg or png file
+  *
+  */
+  public void print()
+  {
+    // file chooser
+    String cwd = System.getProperty("user.dir");
+    JFileChooser fc = new JFileChooser(cwd);
+    File fselect = new File(cwd+
+                            System.getProperty("file.separator")+
+                            "artemis.png");
+    fc.setSelectedFile(fselect);
+     
+    // file name prefix
+    Box YBox = Box.createVerticalBox();
+    JLabel labFormat = new JLabel("Select Format:");
+    Font font = labFormat.getFont();
+    labFormat.setFont(font.deriveFont(Font.BOLD));
+    YBox.add(labFormat);
+
+    Box bacross = Box.createHorizontalBox();
+    JComboBox formatSelect =
+       new JComboBox(javax.imageio.ImageIO.getWriterFormatNames());
+    formatSelect.setSelectedItem("png");
+
+    Dimension d = formatSelect.getPreferredSize();
+    formatSelect.setMaximumSize(d);
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(formatSelect);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(selectDisplay);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(groupsDisplay);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(plotsDisplay);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(onelineDisplay);
+    YBox.add(bacross);
+ 
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(featDisplay);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(baseDisplay);
+    YBox.add(bacross);
+
+    bacross = Box.createHorizontalBox();
+    bacross.add(Box.createHorizontalGlue());
+    bacross.add(featListDisplay);
+    YBox.add(bacross);
+    
+    // file prefix & format options
+    fc.setAccessory(YBox);
+    int n = fc.showSaveDialog(null);
+    if(n == JFileChooser.CANCEL_OPTION)
+      return;
+
+    // remove file extension
+    String fsave = fc.getSelectedFile().getAbsolutePath().toLowerCase();
+    if(fsave.endsWith(".png") ||
+       fsave.endsWith(".jpg") ||
+       fsave.endsWith(".jpeg") )
+    {
+      int ind = fsave.lastIndexOf(".");
+      fsave = fc.getSelectedFile().getAbsolutePath();
+      fsave = fsave.substring(0,ind);
+    }
+    else
+      fsave = fc.getSelectedFile().getAbsolutePath();
+
+    // image type
+    String ftype = (String)formatSelect.getSelectedItem();
+    try
+    {
+      RenderedImage rendImage = createImage();
+      writeImageToFile(rendImage, new File(fsave+"."+ftype),
+                       ftype);
+    }
+    catch(NoClassDefFoundError ex)
+    {
+      JOptionPane.showMessageDialog(this,
+            "This option requires Java 1.4 or higher.");
+    }
+  }
+
+  /**
+  *
+  *  Returns a generated image
+  *  @param pageIndex   page number
+  *  @return            image
+  *
+  */
+  private RenderedImage createImage()
+  {
+    setImageSize();
+    // Create a buffered image in which to draw
+    BufferedImage bufferedImage = new BufferedImage(
+                                  width,height,
+                                  BufferedImage.TYPE_INT_RGB);
+    // Create a graphics contents on the buffered image
+    Graphics2D g2d = bufferedImage.createGraphics();
+    paintComponent(g2d);
+
+    return bufferedImage;
+  }
+
+
+  /**
+  *
+  * Write out the image
+  * @param image        image
+  * @param file         file to write image to
+  * @param type         type of image
+  *
+  */
+  private void writeImageToFile(RenderedImage image,
+                               File file, String type)
+  {
+    try
+    {
+      javax.imageio.ImageIO.write(image,type,file);
+    }
+    catch ( IOException e )
+    {
+      System.out.println("Java 1.4+ is required");
+      e.printStackTrace();
+    }
+  }
+
+}