From a3b4ec9805c4cee4c2dbe2a4c98913ee9c189c6b Mon Sep 17 00:00:00 2001 From: Charles Ofoegbu Date: Wed, 12 Nov 2014 17:54:32 +0000 Subject: [PATCH] Added support for SVG Export --- .gitignore | 2 +- lib/jfreesvg-2.1.jar | Bin 0 -> 49768 bytes src/MCview/PDBViewer.java | 75 +++++++++++++++---- src/jalview/gui/AlignFrame.java | 50 +++++++++++++ src/jalview/gui/AlignmentPanel.java | 71 ++++++++++++------ src/jalview/gui/AppJmol.java | 95 ++++++++++++++++++------ src/jalview/gui/Desktop.java | 7 +- src/jalview/gui/PCAPanel.java | 65 ++++++++++++----- src/jalview/jbgui/GAlignFrame.java | 19 +++++ src/jalview/util/ImageMaker.java | 137 +++++++++++++++++++++++++++-------- 10 files changed, 411 insertions(+), 110 deletions(-) create mode 100644 lib/jfreesvg-2.1.jar diff --git a/.gitignore b/.gitignore index 9841761..7b4e5bc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ /dist /classes .externalToolBuilders/Jalview Release indices [Builder].launch -/.DS_Store +.DS_Store /.com.apple.timemachine.supported diff --git a/lib/jfreesvg-2.1.jar b/lib/jfreesvg-2.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..91d453cd2afb0050156d231aff53a95053d5f2b9 GIT binary patch literal 49768 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 literal 0 HcmV?d00001 diff --git a/src/MCview/PDBViewer.java b/src/MCview/PDBViewer.java index a297892..d3535c0 100755 --- a/src/MCview/PDBViewer.java +++ b/src/MCview/PDBViewer.java @@ -20,18 +20,50 @@ */ package MCview; -import java.io.*; - -import java.awt.event.*; -import javax.swing.*; - -import jalview.datamodel.*; -import jalview.gui.*; -import jalview.io.*; -import jalview.schemes.*; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.gui.AlignmentPanel; +import jalview.gui.Desktop; +import jalview.gui.OOMWarning; +import jalview.gui.UserDefinedColours; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.UserColourScheme; +import jalview.schemes.ZappoColourScheme; import jalview.util.MessageManager; import jalview.ws.ebi.EBIFetchClient; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.PrintWriter; + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JInternalFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.SwingUtilities; + public class PDBViewer extends JInternalFrame implements Runnable { @@ -123,7 +155,9 @@ public class PDBViewer extends JInternalFrame implements Runnable .getAbsolutePath()); if (pdbentry.getFile() != null) + { pdbcanvas.init(pdbentry, seq, chains, ap, protocol); + } } catch (Exception ex) { pdbcanvas.errorMessage = "Error retrieving file: " + pdbentry.getId(); @@ -466,7 +500,7 @@ public class PDBViewer extends JInternalFrame implements Runnable */ public void eps_actionPerformed(ActionEvent e) { - makePDBImage(jalview.util.ImageMaker.EPS); + makePDBImage(jalview.util.ImageMaker.TYPE.EPS); } /** @@ -477,27 +511,36 @@ public class PDBViewer extends JInternalFrame implements Runnable */ public void png_actionPerformed(ActionEvent e) { - makePDBImage(jalview.util.ImageMaker.PNG); + makePDBImage(jalview.util.ImageMaker.TYPE.PNG); } - void makePDBImage(int type) + void makePDBImage(jalview.util.ImageMaker.TYPE type) { int width = pdbcanvas.getWidth(); int height = pdbcanvas.getHeight(); jalview.util.ImageMaker im; - if (type == jalview.util.ImageMaker.PNG) + if (type == jalview.util.ImageMaker.TYPE.PNG) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.PNG, "Make PNG image from view", width, height, null, null); } - else + else if (type == jalview.util.ImageMaker.TYPE.EPS) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.EPS, "Make EPS file from view", width, height, null, this.getTitle()); } + else + { + + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.SVG, "Make SVG file from PCA", + width, height, null, this.getTitle()); + } if (im.getGraphics() != null) { diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index d9c0c6a..8b47302 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -377,7 +377,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt .getKeyCode() <= KeyEvent.VK_NUMPAD9)) && Character.isDigit(evt.getKeyChar())) + { alignPanel.seqPanel.numberPressed(evt.getKeyChar()); + } switch (evt.getKeyCode()) { @@ -389,32 +391,48 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, case KeyEvent.VK_DOWN: if (evt.isAltDown() || !viewport.cursorMode) + { moveSelectedSequences(false); + } if (viewport.cursorMode) + { alignPanel.seqPanel.moveCursor(0, 1); + } break; case KeyEvent.VK_UP: if (evt.isAltDown() || !viewport.cursorMode) + { moveSelectedSequences(true); + } if (viewport.cursorMode) + { alignPanel.seqPanel.moveCursor(0, -1); + } break; case KeyEvent.VK_LEFT: if (evt.isAltDown() || !viewport.cursorMode) + { slideSequences(false, alignPanel.seqPanel.getKeyboardNo1()); + } else + { alignPanel.seqPanel.moveCursor(-1, 0); + } break; case KeyEvent.VK_RIGHT: if (evt.isAltDown() || !viewport.cursorMode) + { slideSequences(true, alignPanel.seqPanel.getKeyboardNo1()); + } else + { alignPanel.seqPanel.moveCursor(1, 0); + } break; case KeyEvent.VK_SPACE: @@ -551,14 +569,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { case KeyEvent.VK_LEFT: if (evt.isAltDown() || !viewport.cursorMode) + { viewport.firePropertyChange("alignment", null, viewport .getAlignment().getSequences()); + } break; case KeyEvent.VK_RIGHT: if (evt.isAltDown() || !viewport.cursorMode) + { viewport.firePropertyChange("alignment", null, viewport .getAlignment().getSequences()); + } break; } } @@ -1236,6 +1258,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, alignPanel.makeEPS(f); } + public void createSVG(File f) + { + alignPanel.makeSVG(f); + } @Override public void pageSetup_actionPerformed(ActionEvent e) { @@ -1458,7 +1484,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, protected void undoMenuItem_actionPerformed(ActionEvent e) { if (viewport.historyList.empty()) + { return; + } CommandI command = (CommandI) viewport.historyList.pop(); viewport.redoList.push(command); command.undoCommand(getViewAlignments()); @@ -1611,37 +1639,53 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, for (int i = 0; i < viewport.getAlignment().getHeight(); i++) { if (!sg.contains(viewport.getAlignment().getSequenceAt(i))) + { invertGroup.add(viewport.getAlignment().getSequenceAt(i)); + } } SequenceI[] seqs1 = sg.toArray(new SequenceI[0]); SequenceI[] seqs2 = new SequenceI[invertGroup.size()]; for (int i = 0; i < invertGroup.size(); i++) + { seqs2[i] = (SequenceI) invertGroup.elementAt(i); + } SlideSequencesCommand ssc; if (right) + { ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size, viewport.getGapCharacter()); + } else + { ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size, viewport.getGapCharacter()); + } int groupAdjustment = 0; if (ssc.getGapsInsertedBegin() && right) { if (viewport.cursorMode) + { alignPanel.seqPanel.moveCursor(size, 0); + } else + { groupAdjustment = size; + } } else if (!ssc.getGapsInsertedBegin() && !right) { if (viewport.cursorMode) + { alignPanel.seqPanel.moveCursor(-size, 0); + } else + { groupAdjustment = -size; + } } if (groupAdjustment != 0) @@ -1662,7 +1706,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } if (!appendHistoryItem) + { addHistoryItem(ssc); + } repaint(); } @@ -1997,7 +2043,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { AlignmentAnnotation sann[] = sequences[i].getAnnotation(); if (sann == null) + { continue; + } for (int avnum = 0; avnum < alview.length; avnum++) { if (alview[avnum] != alignment) @@ -4643,7 +4691,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, if (ds.getSequences() == null || !ds.getSequences().contains( sprods[s].getDatasetSequence())) + { ds.addSequence(sprods[s].getDatasetSequence()); + } sprods[s].updatePDBIds(); } Alignment al = new Alignment(sprods); diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index cdac5b4..d2670f4 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -20,22 +20,38 @@ */ package jalview.gui; -import java.beans.*; -import java.io.*; - -import java.awt.*; -import java.awt.event.*; -import java.awt.print.*; -import javax.swing.*; - import jalview.api.AlignmentViewPanel; import jalview.bin.Cache; -import jalview.datamodel.*; -import jalview.jbgui.*; -import jalview.schemes.*; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.jbgui.GAlignmentPanel; +import jalview.schemes.ResidueProperties; import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; + +import javax.swing.SwingUtilities; + /** * DOCUMENT ME! * @@ -179,7 +195,7 @@ public class AlignmentPanel extends GAlignmentPanel implements int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300); int maxwidth = Math.max(20, - Math.min(afwidth - 200, (int) 2 * afwidth / 3)); + Math.min(afwidth - 200, 2 * afwidth / 3)); return calculateIdWidth(maxwidth); } @@ -841,7 +857,7 @@ public class AlignmentPanel extends GAlignmentPanel implements // / How many sequences and residues can we fit on a printable page? int totalRes = (pwidth - idWidth) / av.getCharWidth(); - int totalSeq = (int) ((pheight - scaleHeight) / av.getCharHeight()) - 1; + int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1; int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1; @@ -954,10 +970,10 @@ public class AlignmentPanel extends GAlignmentPanel implements int offset = -alabels.scrollOffset; pg.translate(0, offset); pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3); - alabels.drawComponent((Graphics2D) pg, idWidth); + alabels.drawComponent(pg, idWidth); pg.translate(idWidth + 3, 0); annotationPanel.renderer.drawComponent(annotationPanel, av, - (Graphics2D) pg, -1, startRes, endRes + 1); + pg, -1, startRes, endRes + 1); pg.translate(0, -offset); } @@ -1113,14 +1129,17 @@ public class AlignmentPanel extends GAlignmentPanel implements return idwidth.intValue() + 4; } - void makeAlignmentImage(int type, File file) + void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file) { long progress = System.currentTimeMillis(); boolean headless = (System.getProperty("java.awt.headless") != null && System .getProperty("java.awt.headless").equals("true")); if (alignFrame != null && !headless) { - alignFrame.setProgressBar(MessageManager.formatMessage("status.saving_file", new String[]{(type == jalview.util.ImageMaker.PNG ? MessageManager.getString("label.png_image") : MessageManager.getString("label.eps_file"))}), progress); + alignFrame.setProgressBar(MessageManager.formatMessage( + "status.saving_file", + new String[] + { type.getLabel() }), progress); } try { @@ -1164,16 +1183,22 @@ public class AlignmentPanel extends GAlignmentPanel implements jalview.util.ImageMaker im; final String imageAction, imageTitle; - if (type == jalview.util.ImageMaker.PNG) + if (type == jalview.util.ImageMaker.TYPE.PNG) { imageAction = "Create PNG image from alignment"; imageTitle = null; } - else + else if (type == jalview.util.ImageMaker.TYPE.EPS) { imageAction = "Create EPS file from alignment"; imageTitle = alignFrame.getTitle(); } + else + { + imageAction = "Create SVG file from alignment"; + imageTitle = alignFrame.getTitle(); + } + im = new jalview.util.ImageMaker(this, type, imageAction, width, height, file, imageTitle); if (av.getWrapAlignment()) @@ -1217,7 +1242,7 @@ public class AlignmentPanel extends GAlignmentPanel implements */ public void makeEPS(File epsFile) { - makeAlignmentImage(jalview.util.ImageMaker.EPS, epsFile); + makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile); } /** @@ -1225,9 +1250,13 @@ public class AlignmentPanel extends GAlignmentPanel implements */ public void makePNG(File pngFile) { - makeAlignmentImage(jalview.util.ImageMaker.PNG, pngFile); + makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile); } + public void makeSVG(File svgFile) + { + makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile); + } public void makePNGImageMap(File imgMapFile, String imageName) { // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 998db4b..5d4b910 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -20,28 +20,64 @@ */ package jalview.gui; -import java.util.*; -import java.awt.*; - -import javax.swing.*; -import javax.swing.event.*; - -import java.awt.event.*; -import java.io.*; - -import jalview.jbgui.GStructureViewer; -import jalview.api.SequenceStructureBinding; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; -import jalview.datamodel.*; -import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; import jalview.ext.jmol.JalviewJmolBinding; -import jalview.io.*; -import jalview.schemes.*; +import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.io.AppletFormatAdapter; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.jbgui.GStructureViewer; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.PurinePyrimidineColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.ZappoColourScheme; import jalview.util.MessageManager; import jalview.util.Platform; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Vector; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JInternalFrame; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + public class AppJmol extends GStructureViewer implements Runnable, ViewSetProvider, JalviewStructureDisplayI @@ -70,6 +106,7 @@ public class AppJmol extends GStructureViewer implements Runnable, * @param bounds * @deprecated defaults to AppJmol(String[] files, ... , viewid); */ + @Deprecated public AppJmol(String file, String id, SequenceI[] seq, AlignmentPanel ap, String loadStatus, Rectangle bounds) { @@ -79,6 +116,7 @@ public class AppJmol extends GStructureViewer implements Runnable, /** * @deprecated */ + @Deprecated public AppJmol(String file, String id, SequenceI[] seq, AlignmentPanel ap, String loadStatus, Rectangle bounds, String viewid) @@ -643,7 +681,9 @@ public class AppJmol extends GStructureViewer implements Runnable, for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) + { ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true); + } } centerViewer(); allChainsSelected = false; @@ -660,7 +700,9 @@ public class AppJmol extends GStructureViewer implements Runnable, public void itemStateChanged(ItemEvent evt) { if (!allChainsSelected) + { centerViewer(); + } } }); @@ -953,7 +995,7 @@ public class AppJmol extends GStructureViewer implements Runnable, */ public void eps_actionPerformed(ActionEvent e) { - makePDBImage(jalview.util.ImageMaker.EPS); + makePDBImage(jalview.util.ImageMaker.TYPE.EPS); } /** @@ -964,27 +1006,36 @@ public class AppJmol extends GStructureViewer implements Runnable, */ public void png_actionPerformed(ActionEvent e) { - makePDBImage(jalview.util.ImageMaker.PNG); + makePDBImage(jalview.util.ImageMaker.TYPE.PNG); } - void makePDBImage(int type) + void makePDBImage(jalview.util.ImageMaker.TYPE type) { int width = getWidth(); int height = getHeight(); jalview.util.ImageMaker im; - if (type == jalview.util.ImageMaker.PNG) + if (type == jalview.util.ImageMaker.TYPE.PNG) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.PNG, "Make PNG image from view", width, height, null, null); } - else + else if (type == jalview.util.ImageMaker.TYPE.EPS) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.EPS, "Make EPS file from view", width, height, null, this.getTitle()); } + else + { + + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.SVG, "Make SVG file from PCA", + width, height, null, this.getTitle()); + } if (im.getGraphics() != null) { diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index 63f0caa..faffd89 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -2152,7 +2152,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements if (showMemoryUsage && g != null && df != null) { if (percentUsage < 20) + { g.setColor(Color.red); + } FontMetrics fm = g.getFontMetrics(); if (fm != null) { @@ -2762,7 +2764,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements { invalidate(); File of; - ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.EPS, "View of Desktop", getWidth(), getHeight(), of=new File("Jalview_snapshot"+System.currentTimeMillis()+".eps"), "View of desktop"); + ImageMaker im = new jalview.util.ImageMaker(this, ImageMaker.TYPE.EPS, + "View of Desktop", getWidth(), getHeight(), of = new File( + "Jalview_snapshot" + System.currentTimeMillis() + + ".eps"), "View of desktop"); try { paintAll(im.getGraphics()); im.writeImage(); diff --git a/src/jalview/gui/PCAPanel.java b/src/jalview/gui/PCAPanel.java index 3483cc4..d2d6a98 100644 --- a/src/jalview/gui/PCAPanel.java +++ b/src/jalview/gui/PCAPanel.java @@ -20,19 +20,39 @@ */ package jalview.gui; -import java.util.*; -import java.awt.*; -import java.awt.event.*; -import java.awt.print.*; - -import javax.swing.*; - -import jalview.datamodel.*; -import jalview.jbgui.*; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.SeqCigar; +import jalview.datamodel.SequenceI; +import jalview.jbgui.GPCAPanel; import jalview.schemes.ResidueProperties; import jalview.util.MessageManager; import jalview.viewmodel.PCAModel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.util.Hashtable; + +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JRadioButtonMenuItem; + /** * DOCUMENT ME! * @@ -135,9 +155,9 @@ public class PCAPanel extends GPCAPanel implements Runnable, @Override public void actionPerformed(ActionEvent e) { - if (!pcaModel.getScore_matrix().equals((String) sm)) + if (!pcaModel.getScore_matrix().equals(sm)) { - pcaModel.setScore_matrix((String) sm); + pcaModel.setScore_matrix(sm); Thread worker = new Thread(us); worker.start(); } @@ -445,7 +465,7 @@ public class PCAPanel extends GPCAPanel implements Runnable, */ public void eps_actionPerformed(ActionEvent e) { - makePCAImage(jalview.util.ImageMaker.EPS); + makePCAImage(jalview.util.ImageMaker.TYPE.EPS); } /** @@ -456,27 +476,36 @@ public class PCAPanel extends GPCAPanel implements Runnable, */ public void png_actionPerformed(ActionEvent e) { - makePCAImage(jalview.util.ImageMaker.PNG); + makePCAImage(jalview.util.ImageMaker.TYPE.PNG); } - void makePCAImage(int type) + void makePCAImage(jalview.util.ImageMaker.TYPE type) { int width = rc.getWidth(); int height = rc.getHeight(); jalview.util.ImageMaker im; - if (type == jalview.util.ImageMaker.PNG) + if (type == jalview.util.ImageMaker.TYPE.PNG) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.PNG, "Make PNG image from PCA", width, height, null, null); } - else + else if (type == jalview.util.ImageMaker.TYPE.EPS) { - im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS, + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.EPS, "Make EPS file from PCA", width, height, null, this.getTitle()); } + else + { + im = new jalview.util.ImageMaker(this, + jalview.util.ImageMaker.TYPE.SVG, "Make SVG file from PCA", + width, height, null, this.getTitle()); + + } if (im.getGraphics() != null) { diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index afb0dc1..5146128 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -210,6 +210,8 @@ public class GAlignFrame extends JInternalFrame JMenuItem createPNG = new JMenuItem(); + JMenuItem createSVG = new JMenuItem(); + protected JMenuItem font = new JMenuItem(); public JCheckBoxMenuItem seqLimits = new JCheckBoxMenuItem(); @@ -1488,6 +1490,7 @@ public class GAlignFrame extends JInternalFrame createPNG.setActionCommand(MessageManager .getString("label.save_png_image")); createPNG.setText("PNG"); + font.setText(MessageManager.getString("action.font")); font.addActionListener(new java.awt.event.ActionListener() { @@ -1518,6 +1521,17 @@ public class GAlignFrame extends JInternalFrame createEPS(null); } }); + + createSVG.setText("SVG"); + createSVG.addActionListener(new java.awt.event.ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + createSVG(null); + } + }); + LoadtreeMenuItem.setActionCommand(MessageManager .getString("label.load_tree_for_sequence_set")); LoadtreeMenuItem.setText(MessageManager @@ -2225,6 +2239,7 @@ public class GAlignFrame extends JInternalFrame jMenu2.add(htmlMenuItem); jMenu2.add(epsFile); jMenu2.add(createPNG); + jMenu2.add(createSVG); addSequenceMenu.add(addFromFile); addSequenceMenu.add(addFromText); addSequenceMenu.add(addFromURL); @@ -2708,6 +2723,10 @@ public class GAlignFrame extends JInternalFrame { } + public void createSVG(java.io.File f) + { + + } protected void LoadtreeMenuItem_actionPerformed(ActionEvent e) { diff --git a/src/jalview/util/ImageMaker.java b/src/jalview/util/ImageMaker.java index c93f8e8..1953a60 100755 --- a/src/jalview/util/ImageMaker.java +++ b/src/jalview/util/ImageMaker.java @@ -20,41 +20,91 @@ */ package jalview.util; -import java.io.*; -import javax.imageio.*; +import jalview.gui.EPSOptions; +import jalview.io.JalviewFileChooser; -import java.awt.*; -import java.awt.image.*; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; -import org.jibble.epsgraphics.*; -import jalview.gui.*; -import jalview.io.*; +import javax.imageio.ImageIO; + +import org.jfree.graphics2d.svg.SVGGraphics2D; +import org.jibble.epsgraphics.EpsGraphics2D; public class ImageMaker { - public static final int EPS = 0; - - public static final int PNG = 1; - - int type = -1; + // public static final int EPS = 0; + // + // public static final int PNG = 1; + // + // public static final int SVG = 2; + // + // int type = -1; EpsGraphics2D pg; + SVGGraphics2D g2; + Graphics graphics; FileOutputStream out; BufferedImage bi; - public ImageMaker(Component parent, int type, String title, int width, - int height, File file, String EPStitle) + TYPE type; + + public enum TYPE + { + EPS("EPS", MessageManager.getString("label.eps_file"), getEPSChooser()), PNG( + "PNG", MessageManager.getString("label.png_image"), + getPNGChooser()), SVG("SVG", "SVG", getSVGChooser()); + + private JalviewFileChooser chooser; + + private String name; + + private String label; + + TYPE(String name, String label, JalviewFileChooser chooser) + { + this.name = name; + this.label = label; + this.chooser = chooser; + } + + public String getName() + { + return name; + } + + public JalviewFileChooser getChooser() + { + return chooser; + } + + public String getLabel() + { + return label; + } + + } + + + public ImageMaker(Component parent, TYPE type, String title, int width, + int height, File file, String fileTitle) { this.type = type; if (file == null) { JalviewFileChooser chooser; - chooser = type == EPS ? getEPSChooser() : getPNGChooser(); + // chooser = type == EPS ? getEPSChooser() : getPNGChooser(); + chooser = type.getChooser(); chooser.setFileView(new jalview.io.JalviewFileView()); chooser.setDialogTitle(title); @@ -76,19 +126,23 @@ public class ImageMaker try { out = new FileOutputStream(file); - - if (type == EPS) + if (type == TYPE.SVG) + { + setupSVG(width, height, fileTitle); + } + else if (type == TYPE.EPS) { - setupEPS(width, height, EPStitle); + setupEPS(width, height, fileTitle); } - else + else if (type == TYPE.PNG) { setupPNG(width, height); } + } catch (Exception ex) { System.out.println("Error creating " - + (type == EPS ? "EPS" : "PNG") + " file."); + + type.getName() + " file."); } } } @@ -98,14 +152,7 @@ public class ImageMaker return graphics; } - void setupPNG(int width, int height) - { - bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - graphics = bi.getGraphics(); - Graphics2D ig2 = (Graphics2D) graphics; - ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - } + public void writeImage() { @@ -117,6 +164,11 @@ public class ImageMaker pg.flush(); pg.close(); break; + case SVG: + String svg = ((SVGGraphics2D) getGraphics()).getSVGDocument(); + out.write(svg.getBytes()); + out.close(); + break; case PNG: ImageIO.write(bi, "png", out); out.close(); @@ -158,7 +210,7 @@ public class ImageMaker try { pg = new EpsGraphics2D(title, out, 0, 0, width, height); - Graphics2D ig2 = (Graphics2D) pg; + Graphics2D ig2 = pg; ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); @@ -170,7 +222,22 @@ public class ImageMaker } } - JalviewFileChooser getPNGChooser() + void setupPNG(int width, int height) + { + bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + graphics = bi.getGraphics(); + Graphics2D ig2 = (Graphics2D) graphics; + ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + } + + void setupSVG(int width, int height, String title) + { + g2 = new SVGGraphics2D(width, height); + graphics = g2; + } + + static JalviewFileChooser getPNGChooser() { return new jalview.io.JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] @@ -178,11 +245,19 @@ public class ImageMaker { "Portable network graphics" }, "Portable network graphics"); } - JalviewFileChooser getEPSChooser() + static JalviewFileChooser getEPSChooser() { return new jalview.io.JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] { "eps" }, new String[] { "Encapsulated Postscript" }, "Encapsulated Postscript"); } + + static JalviewFileChooser getSVGChooser() + { + return new jalview.io.JalviewFileChooser( + jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] + { "svg" }, new String[] + { "Scalable Vector Graphics" }, "Scalable Vector Graphics"); + } } -- 1.7.10.2