[med-svn] [figtree] 02/08: Imported Upstream version 1.4.3+dfsg
Fabian Klötzl
kloetzl-guest at moszumanska.debian.org
Fri Jul 14 12:20:54 UTC 2017
This is an automated email from the git hooks/post-receive script.
kloetzl-guest pushed a commit to branch master
in repository figtree.
commit 5918ea4d167053cde08211f72f9136d370edfd5a
Author: Fabian Klötzl <fabian at kloetzl.info>
Date: Fri Jul 14 12:54:23 2017 +0200
Imported Upstream version 1.4.3+dfsg
---
.gitignore | 9 +
README.md | 4 +
build.xml | 64 ++-
lib/libquaqua64.dylib | Bin 0 -> 90576 bytes
release/common/README.txt | 50 +-
src/figtree/application/FigTreeApplication.java | 63 +--
src/figtree/application/FigTreeFrame.java | 134 ++---
src/figtree/application/FigTreePDF.java | 205 --------
src/figtree/application/FigTreePanel.java | 40 +-
src/figtree/application/JSONTreeExporter.java | 3 +-
src/figtree/panel/FigTreePanel.java | 7 +-
src/figtree/panel/LabelPainterController.java | 17 +-
src/figtree/panel/SimpleLabelPainter.java | 544 ++++++++++-----------
src/figtree/panel/TreeAppearanceController.java | 35 +-
src/figtree/panel/TreesController.java | 124 +++--
src/figtree/treeviewer/DefaultTreeViewer.java | 23 +
src/figtree/treeviewer/ScaleAxis.java | 4 +
src/figtree/treeviewer/TimeScale.java | 13 +-
src/figtree/treeviewer/TreePane.java | 332 ++++++++-----
src/figtree/treeviewer/TreePaneRollOver.java | 31 +-
.../treeviewer/decorators/ContinuousScale.java | 67 ++-
src/figtree/treeviewer/painters/LegendPainter.java | 5 +
.../treeviewer/painters/NodeBarController.java | 2 +-
.../treeviewer/painters/NodeShapeController.java | 132 ++++-
.../treeviewer/painters/NodeShapePainter.java | 34 +-
.../treeviewer/painters/ScaleAxisPainter.java | 76 +--
.../painters/ScaleAxisPainterController.java | 4 +-
.../treeviewer/painters/ScaleGridPainter.java | 4 +-
.../treeviewer/treelayouts/AbstractTreeLayout.java | 9 -
.../treeviewer/treelayouts/PolarTreeLayout.java | 3 -
.../treelayouts/RectilinearTreeLayout.java | 6 -
src/figtree/treeviewer/treelayouts/TreeLayout.java | 5 -
32 files changed, 1116 insertions(+), 933 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e9825d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+
+*.class
+build/*
+classes/*
+dist/*
+out/*
+FigTree*
+tests/*
+examples/*
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0b6c937
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+_FigTree_
+
+FigTree is designed as a graphical viewer of phylogenetic trees and as a program for producing publication-ready figures. As with most of my programs, it was written for my own needs so may not be as polished and feature-complete as a commercial program. In particular it is designed to display summarized and annotated trees produced by BEAST.
+
diff --git a/build.xml b/build.xml
index a3ae8db..636060e 100755
--- a/build.xml
+++ b/build.xml
@@ -12,6 +12,7 @@
<property name="lib" location="lib"/>
<property name="dist" location="dist"/>
+ <property name="packaging_tools" value="packaging_tools" />
<property environment="env"/>
@@ -60,17 +61,27 @@
</manifest>
</jar>
+ <jar jarfile="${dist}/figtreepanel.jar">
+ <fileset dir="${build}"
+ includes="figtree/panel/**/*.class,figtree/treeviewer/**/*.class,**/*.properties,**/*.png,**/*.gif"
+ />
+
+ <manifest>
+ <attribute name="Built-By" value="${user.name}"/>
+ </manifest>
+ </jar>
+
<jar jarfile="${dist}/figtree-pdf.jar">
- <zipgroupfileset dir="${lib}" includes="jebl.jar"/>
- <zipgroupfileset dir="${lib}" includes="jam.jar"/>
- <zipgroupfileset dir="${lib}" includes="iText.jar"/>
- <fileset dir="${build}" includes="**/*.class,**/*.properties,**/*.png,**/*.gif"/>
+ <fileset dir="${build}"
+ includes="figtree/panel/**/*.class,figtree/treeviewer/**/*.class,**/*.properties,**/*.png,**/*.gif"
+ />
+
<manifest>
<attribute name="Built-By" value="${user.name}"/>
- <attribute name="Main-Class" value="figtree.application.FigTreePDF"/>
</manifest>
</jar>
+
<war destfile="${dist}/figtree.war"
webxml="WebRoot/WEB-INF/web.xml">
<fileset dir="WebRoot"/>
@@ -91,7 +102,8 @@
</target>
- <property name="version" value="1.4.2" />
+ <property name="version" value="1.4.3" />
+ <property name="version_number" value="1.4.3" />
<property name="release_dir" value="release" />
<property name="name" value="FigTree" />
@@ -101,7 +113,6 @@
<property name="Linux_dir" value="${release_dir}/Linux" />
<property name="Windows_dir" value="${release_dir}/Windows" />
- <property name="Mac_package_dir_SL" value="${Mac_dir}/${name} v${version}" />
<property name="Mac_package_dir" value="${Mac_dir}/${name} v${version}" />
<property name="Linux_package_dir" value="${Linux_dir}/${name}_v${version}" />
<property name="Windows_package_dir" value="${Windows_dir}/${name} v${version}" />
@@ -121,9 +132,11 @@
classpath="${launch4j.dir}/launch4j.jar :${launch4j.dir}/lib/xstream.jar" />
<copy file="${dist}/figtree.jar" todir="${Windows_package_dir}/lib"/>
+ <!--
<copy todir="${Windows_package_dir}/lib">
<fileset dir="${Windows_dir}/lib"/>
</copy>
+ -->
<copy todir="${Windows_package_dir}">
<fileset dir="${common_dir}/"/>
</copy>
@@ -131,9 +144,9 @@
<launch4j configFile="${Windows_dir}/FigTree_launch4j.xml"
jar="${dist}/figtree.jar"
outfile="${Windows_package_dir}/${name} v${version}.exe"
- fileVersion="${version}.0"
+ fileVersion="${version_number}.0"
txtFileVersion="${version}"
- productVersion="${version}.0"
+ productVersion="${version_number}.0"
txtProductVersion="${version}"
/>
@@ -156,9 +169,11 @@
<copy file="${Linux_dir}/icons/figtree.png" todir="${Linux_package_dir}/images"/>
<copy file="${dist}/figtree.jar" todir="${Linux_package_dir}/lib"/>
+ <!--
<copy todir="${Linux_package_dir}/lib">
<fileset dir="${Linux_dir}/lib"/>
</copy>
+ -->
<copy todir="${Linux_package_dir}">
<fileset dir="${common_dir}/"/>
</copy>
@@ -170,33 +185,36 @@
<echo message="Linux/Unix version release is finished." />
</target>
- <target name="mac_sl_release"
- description="release Mac Snow Leopard version of FigTree">
- <delete dir="${Mac_package_dir_SL}" />
+ <target name="mac_release"
+ description="release Mac version of FigTree">
+ <delete dir="${Mac_package_dir}" />
<!-- Create the release directory -->
- <mkdir dir="${Mac_package_dir_SL}" />
+ <mkdir dir="${Mac_package_dir}" />
- <copy file="${dist}/figtree.jar" todir="${Mac_package_dir_SL}/lib"/>
- <copy file="${dist}/figtree-pdf.jar" todir="${Mac_package_dir_SL}/QuickLook Plugin/FigTreeQuickLookPlugin.qlgenerator/Contents/Resources"/>
- <copy todir="${Mac_package_dir_SL}">
+ <copy file="${dist}/figtree.jar" todir="${Mac_package_dir}/lib"/>
+ <copy file="${dist}/figtree-pdf.jar" todir="${Mac_package_dir}/QuickLook Plugin/FigTreeQuickLookPlugin.qlgenerator/Contents/Resources"/>
+ <copy todir="${Mac_package_dir}">
<fileset dir="${common_dir}/"/>
</copy>
- <copy todir="${Mac_package_dir_SL}/QuickLook Plugin">
+ <copy todir="${Mac_package_dir}/QuickLook Plugin">
<fileset dir="${Mac_dir}/QuickLook Plugin"/>
</copy>
<taskdef name="jarbundler" classname="net.sourceforge.jarbundler.JarBundler"/>
<!-- create a jar bundle for the mac -->
- <jarbundler dir="${Mac_package_dir_SL}"
+ <jarbundler dir="${Mac_package_dir}"
name="${name} v${version}"
mainclass="figtree.application.FigTreeApplication"
icon="${Mac_dir}/icons/FigTree.icns"
+ stubfile="${packaging_tools}/mac/universalJavaApplicationStub"
+ useJavaXKey="true"
jvmversion="1.6+"
vmoptions="-Xmx1024M"
arguments=""
- version="${version} SL"
- infostring="${name} v${version} SL, Copyright 2006-2014, Andrew Rambaut"
+ version="${version}"
+ build="1"
+ copyright="${name} v${version}, Copyright 2006-2015, Andrew Rambaut"
bundleid="figtree" >
<javaproperty name="apple.laf.useScreenMenuBar" value="true"/>
<jarfileset dir="${dist}">
@@ -215,13 +233,15 @@
</jarbundler>
<!-- remove code signing -->
+ <!--
<exec executable="/usr/bin/codesign">
<arg value="-s"/>
<arg value="-"/>
- <arg value="--force"/>
+ <arg value="- -force"/> remove space from between minus signs
<arg value="${Mac_dir}/${name} v${version}/${name} v${version}.app"/>
</exec>
-
+ -->
+
<echo message="Building disk image." />
<!-- create disk image -->
diff --git a/lib/libquaqua64.dylib b/lib/libquaqua64.dylib
new file mode 100644
index 0000000..4bd3c39
Binary files /dev/null and b/lib/libquaqua64.dylib differ
diff --git a/release/common/README.txt b/release/common/README.txt
index 9dce2a7..b3e9d69 100644
--- a/release/common/README.txt
+++ b/release/common/README.txt
@@ -1,4 +1,4 @@
- FigTree v1.4 2006-2012
+ FigTree v1.4.3 2006-2016
Andrew Rambaut
Institute of Evolutionary Biology
@@ -7,7 +7,7 @@
UNIX/Linux/Mac OS X (command-line) version README
-Last updated: a.rambaut at ed.ac.uk - 8th October 2012
+Last updated: a.rambaut at ed.ac.uk - 4th October 2016
Contents:
1) INTRODUCTION
@@ -27,6 +27,52 @@ FigTree is designed as a graphical viewer of phylogenetic trees and as a program
___________________________________________________________________________
2) VERSION HISTORY
+v1.4.3 Released 4th October 2016
+
+New features:
+ Node shape option can now show shapes for internal or external nodes or both.
+ Copying selected taxon labels when these are selected, subtree when branches are selected.
+ Selecting 'reverse axis' should automatically reverse the Time Scale scale factor. Previously the user needed to set this to -1.0.
+ When searching for text, scrolls to show highlighted tip.
+
+Bugs fixed:
+ Issue 102: Large SVG files from figtree are broken
+ Issue 95: Changing the origin value for the Scale Axis does not work
+ Issue 94: The trait legend overlaps the tree.
+ Issue 93: Command-line PDF/SVG export options not working
+ Issue 92: Reading a file with a mix of integer and real node labels causes exception.
+ Issue 90: Export picture cuts the top of the higest tip label
+ Issue 79: Export of .SVG produces corrupt files
+
+v1.4.2 Released 9th July 2014
+
+New features:
+ New -url command line option allows reading of trees from URLs in pipelines.
+
+Bugs fixed:
+ Issue 76: Scale axis should only show as many decimal places as necessary.
+ Issue 75: Export PNG & JPEG produce blank images.
+ Issue 64: Putting node bars on translates the tree to the right (now really fixed, I think).
+
+v1.4.1 Released 14th June 2014
+
+New features:
+ Copy selected subtrees to clipboard as NEXUS format.
+
+ New graphics export options (PDF, SVG, PNG & JPEG).
+
+ Control panel now scrolls and can be resized.
+
+Bugs fixed:
+ Issue 23: Find bar opens slowly with big trees.
+ Issue 28: Filtering should work on currently display labels.
+ Issue 53: Option Tip Labels: "Colour By" does not render Names in colour.
+ Issue 57: Midpoint rooting not working correctly.
+ Issue 59: Clear Highlighting/Cartoon etc doesn't seem to work on individual branches.
+ Issue 62: When all clades are 'collapsed', the top triangle is clipped.
+ Issue 64: Putting node bars on translates the tree to the right.
+ Issue 69: Import annotation causes crash.
+
v1.4 Released 8th October 2012.
New Features:
diff --git a/src/figtree/application/FigTreeApplication.java b/src/figtree/application/FigTreeApplication.java
index 495267c..6e9684e 100755
--- a/src/figtree/application/FigTreeApplication.java
+++ b/src/figtree/application/FigTreeApplication.java
@@ -30,6 +30,11 @@
package figtree.application;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.pdf.PdfContentByte;
+import com.itextpdf.text.pdf.PdfTemplate;
+import com.itextpdf.text.pdf.PdfWriter;
import figtree.application.preferences.*;
import figtree.treeviewer.ExtendedTreeViewer;
import jam.framework.*;
@@ -52,6 +57,9 @@ import javax.imageio.ImageIO;
import javax.swing.*;
import ch.randelshofer.quaqua.QuaquaManager;
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.w3c.dom.DOMImplementation;
/**
* Application class for FigTree including main() method for invoking it.
@@ -68,8 +76,8 @@ import ch.randelshofer.quaqua.QuaquaManager;
*/
public class FigTreeApplication extends MultiDocApplication {
- public static final String VERSION = "1.4.2";
- public static final String DATES = "2006-2014";
+ public static final String VERSION = "1.4.3";
+ public static final String DATES = "2006-2016";
public static FigTreeApplication application;
@@ -164,34 +172,10 @@ public class FigTreeApplication extends MultiDocApplication {
GraphicFormat format = null;
if (graphicFormat.equals("PDF")) {
- if (graphicFileName != null) {
- System.out.println("Creating PDF graphic: " + graphicFileName);
- }
format = GraphicFormat.PDF;
-// } else if (graphicFormat.equals("PS")) {
-// if (graphicFileName != null) {
-// System.out.println("Creating PS graphic: " + graphicFileName);
-// }
-// g = new PSGraphics2D(stream, new Dimension(width, height));
-// } else if (graphicFormat.equals("EMF")) {
-// if (graphicFileName != null) {
-// System.out.println("Creating EMF graphic: " + graphicFileName);
-// }
-// g = new EMFGraphics2D(stream, new Dimension(width, height));
-// } else if (graphicFormat.equals("SVG")) {
-// if (graphicFileName != null) {
-// System.out.println("Creating SVG graphic: " + graphicFileName);
-// }
-// g = new SVGGraphics2D(stream, new Dimension(width, height));
-// } else if (graphicFormat.equals("SWF")) {
-// if (graphicFileName != null) {
-// System.out.println("Creating SWF graphic: " + graphicFileName);
-// }
-// g = new SWFGraphics2D(stream, new Dimension(width, height));
+ } else if (graphicFormat.equals("SVG")) {
+ format = GraphicFormat.SVG;
} else if (graphicFormat.equals("GIF")) {
- if (graphicFileName != null) {
- System.out.println("Creating GIF graphic: " + graphicFileName);
- }
format = GraphicFormat.GIF;
} else if (graphicFormat.equals("PNG")) {
format = GraphicFormat.PNG;
@@ -201,17 +185,18 @@ public class FigTreeApplication extends MultiDocApplication {
throw new RuntimeException("Unknown graphic format");
}
- JComponent comp = treeViewer.getContentPane();
- BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- Graphics g = bi.createGraphics();
- comp.paint(g);
- g.dispose();
- ImageIO.write(bi, format.getName(), stream);
+ if (graphicFileName != null) {
+ System.out.println("Creating " + graphicFormat + " graphic: " + graphicFileName);
+ }
+
+ FigTreeFrame.exportGraphics(format, treeViewer.getContentPane(), stream);
} catch(ImportException ie) {
- throw new RuntimeException("Error writing graphic file: " + ie);
+ throw new RuntimeException("Error writing graphic file: " + ie.getMessage());
} catch(IOException ioe) {
- throw new RuntimeException("Error writing graphic file: " + ioe);
+ throw new RuntimeException("Error writing graphic file: " + ioe.getMessage());
+ } catch (DocumentException de) {
+ throw new RuntimeException("Error writing graphic file: " + de.getMessage());
}
}
@@ -264,10 +249,10 @@ public class FigTreeApplication extends MultiDocApplication {
new Arguments.Option[] {
new Arguments.StringOption("graphic", new String[] {
"PDF",
- // "SVG",
+ "SVG",
// "SWF", "PS", "EMF",
"PNG",
- "GIF",
+ // "GIF",
"JPEG"
}, false, "produce a graphic with the given format"),
new Arguments.IntegerOption("width", "the width of the graphic in pixels"),
@@ -405,7 +390,7 @@ public class FigTreeApplication extends MultiDocApplication {
icon = new ImageIcon(url);
}
- final String nameString = "FigTree " + VERSION;
+ final String nameString = "FigTree";
String titleString = "<html>" +
"<div style=\"font-family:'Helvetica Neue', Helvetica, Arial, 'Lucida Grande',sans-serif\">" +
"<p style=\"font-weight: 100; font-size: 36px\">FigTree</p>" +
diff --git a/src/figtree/application/FigTreeFrame.java b/src/figtree/application/FigTreeFrame.java
index e96d370..0c4b3a7 100755
--- a/src/figtree/application/FigTreeFrame.java
+++ b/src/figtree/application/FigTreeFrame.java
@@ -29,6 +29,7 @@ import com.itextpdf.text.pdf.PdfWriter;
import figtree.treeviewer.decorators.DiscreteColourDecorator;
import figtree.treeviewer.decorators.HSBDiscreteColourDecorator;
import figtree.treeviewer.painters.StatesPainter;
+import jebl.evolution.align.Output;
import jebl.evolution.alignments.Alignment;
import jebl.evolution.alignments.BasicAlignment;
import jebl.evolution.graphs.Node;
@@ -52,6 +53,7 @@ import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Element;
import javax.imageio.ImageIO;
import javax.swing.*;
@@ -288,7 +290,7 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
public void actionPerformed(ActionEvent e){
if (treeViewer.isRootingOn() && treeViewer.getRootingType() == TreePane.RootingType.USER_ROOTING) {
JOptionPane.showMessageDialog(FigTreeFrame.this, "Cannot switch trees when user rooting option is on.\n" +
- "Turn this option off to switch trees",
+ "Turn this option off to switch trees",
"Unable to switch trees",
JOptionPane.ERROR_MESSAGE);
@@ -308,7 +310,7 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
public void actionPerformed(ActionEvent e){
if (treeViewer.isRootingOn() && treeViewer.getRootingType() == TreePane.RootingType.USER_ROOTING) {
JOptionPane.showMessageDialog(FigTreeFrame.this, "Cannot switch trees when user rooting option is on.\n" +
- "Turn this option off to switch trees",
+ "Turn this option off to switch trees",
"Unable to switch trees",
JOptionPane.ERROR_MESSAGE);
@@ -1216,27 +1218,16 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
File file = new File(dialog.getDirectory(), dialog.getFile());
try {
- JComponent comp = treeViewer.getContentPane();
- switch (format) {
-
- case PNG:
- case GIF:
- case BMP:
- case JPEG:
- exportGraphicsFile(format, comp, file);
- break;
- case EPS:
- throw new UnsupportedOperationException("EPS not handled");
- case SVG:
- exportSVGFile(comp, file);
- break;
- case PDF:
- exportPDFFile(comp, file);
- break;
- default:
- throw new UnsupportedOperationException("Format not handled: " + format);
+ OutputStream stream = new FileOutputStream(file);
- }
+ exportGraphics(format, treeViewer.getContentPane(), stream);
+
+ stream.flush();
+ stream.close();
+ } catch(DocumentException de) {
+ JOptionPane.showMessageDialog(this, "Error writing PDF file: " + de,
+ "Export PDF Error",
+ JOptionPane.ERROR_MESSAGE);
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this, "Error writing tree file: " + ioe.getMessage(),
"Export Error",
@@ -1247,7 +1238,30 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
}
- private final void exportGraphicsFile(GraphicFormat format, JComponent component, File file) throws IOException {
+ public final static void exportGraphics(GraphicFormat format, JComponent comp, OutputStream stream) throws IOException, DocumentException {
+ switch (format) {
+
+ case PNG:
+ case GIF:
+ case BMP:
+ case JPEG:
+ exportGraphicsFile(format, comp, stream);
+ break;
+ case EPS:
+ throw new UnsupportedOperationException("EPS not handled");
+ case SVG:
+ exportSVGFile(comp, stream);
+ break;
+ case PDF:
+ exportPDFFile(comp, stream);
+ break;
+ default:
+ throw new UnsupportedOperationException("Format not handled: " + format);
+
+ }
+
+ }
+ private final static void exportGraphicsFile(GraphicFormat format, JComponent component, OutputStream stream) throws IOException {
int imageType = BufferedImage.TYPE_INT_RGB;
if (format == GraphicFormat.PNG) {
@@ -1263,10 +1277,10 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
}
component.paint(g);
g.dispose();
- ImageIO.write(bi, format.getName(), file);
+ ImageIO.write(bi, format.getName(), stream);
}
- private final void exportSVGFile(JComponent component, File file) throws IOException {
+ private final static void exportSVGFile(JComponent component, OutputStream stream) throws IOException {
// Get a DOMImplementation and create an XML document
DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
org.w3c.dom.Document document = domImpl.createDocument(null, "svg", null);
@@ -1275,50 +1289,46 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
component.paint(svgGenerator);
+ Element svgRoot = svgGenerator.getRoot();
+ Rectangle2D bounds = component.getBounds();
+ String viewBox = "0 0 " + bounds.getWidth() + " " + bounds.getHeight();
+ svgRoot.setAttributeNS(null, svgGenerator.SVG_VIEW_BOX_ATTRIBUTE, viewBox);
+ svgRoot.setAttributeNS(null, svgGenerator.SVG_WIDTH_ATTRIBUTE, Double.toString(bounds.getWidth()));
+ svgRoot.setAttributeNS(null, svgGenerator.SVG_HEIGHT_ATTRIBUTE, Double.toString(bounds.getHeight()));
// Write svg file
- OutputStream outputStream = new FileOutputStream(file);
- Writer out = new OutputStreamWriter(outputStream, "UTF-8");
- svgGenerator.stream(out, true /* use css */);
- outputStream.flush();
- outputStream.close();
+ Writer out = new OutputStreamWriter(stream, "UTF-8");
+ svgGenerator.stream(svgRoot, out, true /* use css */, false /* escaped */);
}
- public final void exportPDFFile(JComponent component, File file) {
- Rectangle2D bounds = treeViewer.getContentPane().getBounds();
+ public final static void exportPDFFile(JComponent component, OutputStream stream) throws DocumentException {
+ Rectangle2D bounds = component.getBounds();
Document document = new Document(new com.itextpdf
.text.Rectangle((float)bounds.getWidth(), (float)bounds.getHeight()));
- try {
- // step 2
- PdfWriter writer;
- writer = PdfWriter.getInstance(document, new FileOutputStream(file));
- // step 3
- document.open();
- // step 4
- PdfContentByte cb = writer.getDirectContent();
- PdfTemplate tp = cb.createTemplate((float)bounds.getWidth(), (float)bounds.getHeight());
- Graphics2D g2d = tp.createGraphics((float)bounds.getWidth(), (float)bounds.getHeight(), new DefaultFontMapper());
- component.print(g2d);
- g2d.dispose();
- cb.addTemplate(tp, 0, 0);
- }
- catch(DocumentException de) {
- JOptionPane.showMessageDialog(this, "Error writing PDF file: " + de,
- "Export PDF Error",
- JOptionPane.ERROR_MESSAGE);
- }
- catch (FileNotFoundException e) {
- JOptionPane.showMessageDialog(this, "Error writing PDF file: " + e,
- "Export PDF Error",
- JOptionPane.ERROR_MESSAGE);
- }
+ // step 2
+ PdfWriter writer;
+ writer = PdfWriter.getInstance(document, stream);
+ // step 3
+ document.open();
+ // step 4
+ PdfContentByte cb = writer.getDirectContent();
+ PdfTemplate tp = cb.createTemplate((float)bounds.getWidth(), (float)bounds.getHeight());
+ Graphics2D g2d = tp.createGraphics((float)bounds.getWidth(), (float)bounds.getHeight(), new DefaultFontMapper());
+ component.print(g2d);
+ g2d.dispose();
+ cb.addTemplate(tp, 0, 0);
+
document.close();
}
public void doCopy() {
StringWriter writer = new StringWriter();
try {
- writeTreeFile(writer, ExportTreeDialog.Format.NEXUS, true, false, false, true, true);
+ if (treeViewer.getSelectionMode() == TreePaneSelector.SelectionMode.TAXA) {
+ writeTaxa(writer);
+ } else {
+ writeTreeFile(writer, ExportTreeDialog.Format.NEXUS, true, false, false, true, true);
+ }
} catch (IOException e) {
e.printStackTrace();
}
@@ -1382,6 +1392,14 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
treeViewer.selectAll();
}
+ protected void writeTaxa(Writer writer) throws IOException {
+ PrintWriter printWriter = new PrintWriter(writer);
+ for (Taxon taxon : treeViewer.getSelectedTaxa()) {
+ printWriter.println(taxon.getName());
+ }
+ writer.close();
+ }
+
protected void writeTreeFile(Writer writer, ExportTreeDialog.Format format,
boolean writeAllTrees,
boolean writeAsDisplayed,
@@ -1852,4 +1870,4 @@ public class FigTreeFrame extends DocumentFrame implements FigTreeFileMenuHandle
private AnnotationDialog annotationDialog = null;
private AnnotationDialog copyAnnotationDialog = null;
private SelectAnnotationDialog selectAnnotationDialog = null;
-}
\ No newline at end of file
+}
diff --git a/src/figtree/application/FigTreePDF.java b/src/figtree/application/FigTreePDF.java
deleted file mode 100755
index dc9ff76..0000000
--- a/src/figtree/application/FigTreePDF.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * FigTreePDF.java
- *
- * Copyright (C) 2006-2014 Andrew Rambaut
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/**
- * TracerApp.java
- *
- * Title: Tracer
- * Description: An application for analysing MCMC trace files.
- * @author Andrew Rambaut
- * @author Alexei Drummond
- * @version $Id: FigTreeApplication.java,v 1.15 2007/09/10 14:52:02 rambaut Exp $
- */
-
-package figtree.application;
-
-import com.itextpdf.text.Document;
-import com.itextpdf.text.pdf.PdfContentByte;
-import com.itextpdf.text.pdf.PdfTemplate;
-import com.itextpdf.text.pdf.PdfWriter;
-import figtree.treeviewer.ExtendedTreeViewer;
-import jam.controlpalettes.BasicControlPalette;
-import jam.controlpalettes.ControlPalette;
-
-import java.io.*;
-import java.util.*;
-import java.util.List;
-import java.awt.*;
-
-import jebl.evolution.io.ImportException;
-import jebl.evolution.io.NewickImporter;
-import jebl.evolution.trees.Tree;
-
-/**
- * Commandline main() to generate PDF graphics from FigTree trees.
- *
- * @author Andrew Rambaut
- * @version $Id$
- *
- * $HeadURL$
- *
- * $LastChangedBy$
- * $LastChangedDate$
- * $LastChangedRevision$
- */
-public class FigTreePDF {
-
- public static final String VERSION = "1.4.1";
- public static final String DATES = "2006-2014";
-
- static public void createGraphic(int width, int height, String treeFileName, String graphicFileName) {
-
- try {
- BufferedReader bufferedReader = new BufferedReader(new FileReader(treeFileName));
- String line = bufferedReader.readLine();
- while (line != null && line.length() == 0) {
- line = bufferedReader.readLine();
- }
-
- bufferedReader.close();
-
- boolean isNexus = (line != null && line.toUpperCase().contains("#NEXUS"));
-
- Reader reader = new FileReader(treeFileName);
-
- Map<String, Object> settings = new HashMap<String, Object>();
-
- ExtendedTreeViewer treeViewer = new ExtendedTreeViewer();
- ControlPalette controlPalette = new BasicControlPalette(200, BasicControlPalette.DisplayMode.ONLY_ONE_OPEN);
- FigTreePanel figTreePanel = new FigTreePanel(null, treeViewer, controlPalette);
-
- // First of all, fully populate the settings map so that
- // all the settings have defaults
- controlPalette.getSettings(settings);
-
- List<Tree> trees = new ArrayList<Tree>();
-
- if (isNexus) {
- FigTreeNexusImporter importer = new FigTreeNexusImporter(reader);
- trees.add(importer.importNextTree());
-
- // Try to find a figtree block and if found, parse the settings
- while (true) {
- try {
- importer.findNextBlock();
- if (importer.getNextBlockName().equalsIgnoreCase("FIGTREE")) {
- importer.parseFigTreeBlock(settings);
- }
- } catch (EOFException ex) {
- break;
- }
- }
- } else {
- NewickImporter importer = new NewickImporter(reader, true);
- trees.add(importer.importNextTree());
- }
-
- if (trees.size() == 0) {
- throw new ImportException("This file contained no trees.");
- }
-
- treeViewer.setTrees(trees);
-
- controlPalette.setSettings(settings);
-
- treeViewer.getContentPane().setSize(width, height);
-
- OutputStream stream;
- if (graphicFileName != null) {
- stream = new FileOutputStream(graphicFileName);
- } else {
- stream = System.out;
- }
-
- Document document = new Document();
- document.setPageSize(new com.itextpdf.text.Rectangle(width, height));
- try {
- PdfWriter writer = PdfWriter.getInstance(document, stream);
- document.open();
- PdfContentByte cb = writer.getDirectContent();
- PdfTemplate tp = cb.createTemplate(width, height);
- Graphics2D g2 = tp.createGraphics(width, height);
- tp.setWidth(width);
- tp.setHeight(height);
- treeViewer.getContentPane().print(g2);
- g2.dispose();
- tp.sanityCheck(); // all the g2 content is written to tp, not cb
- cb.addTemplate(tp, 0, 0);
- cb.sanityCheck();
- } catch (Exception e) {
- System.err.println(e.getMessage());
- }
- document.close();
-
- } catch(ImportException ie) {
- throw new RuntimeException("Error writing graphic file: " + ie);
- } catch(IOException ioe) {
- throw new RuntimeException("Error writing graphic file: " + ioe);
- }
-
- }
-
- // Main entry point
- static public void main(String[] args) {
-
- Arguments arguments = new Arguments(
- new Arguments.Option[] {
- new Arguments.IntegerOption("width", "the width of the graphic in pixels"),
- new Arguments.IntegerOption("height", "the height of the graphic in pixels")
- });
-
- try {
- arguments.parseArguments(args);
- } catch (Arguments.ArgumentException ae) {
- System.out.println();
- System.out.println(ae.getMessage());
- System.out.println();
- System.exit(1);
- }
-
-
- int width = 800;
- int height = 600;
-
- if (arguments.hasOption("width")) {
- width = arguments.getIntegerOption("width");
- }
-
- if (arguments.hasOption("height")) {
- height = arguments.getIntegerOption("height");
- }
-
- // command line version...
- String[] args2 = arguments.getLeftoverArguments();
-
- if (args2.length == 0) {
- // no tree file specified
- System.exit(0);
- } else if (args2.length == 1) {
- // no graphic file specified - write to stdout
- createGraphic(width, height, args2[0], (args2.length > 1 ? args2[1] : null));
- System.exit(0);
- } else {
- createGraphic(width, height, args2[0], (args2.length > 1 ? args2[1] : null));
- System.exit(0);
- }
- }
-}
-
diff --git a/src/figtree/application/FigTreePanel.java b/src/figtree/application/FigTreePanel.java
index fa1a5aa..c04a05c 100755
--- a/src/figtree/application/FigTreePanel.java
+++ b/src/figtree/application/FigTreePanel.java
@@ -48,6 +48,8 @@ public class FigTreePanel extends JPanel {
public final static int CONTROL_PALETTE_WIDTH = 200;
+ private final static boolean SEPARATE_NODE_SHAPE_PANELS = true;
+
public FigTreePanel(JFrame frame, final ExtendedTreeViewer treeViewer, ControlPalette controlPalette) {
this.treeViewer = treeViewer;
@@ -80,12 +82,30 @@ public class FigTreePanel extends JPanel {
controlPalette.addController(new LabelPainterController("Tip Labels", "tipLabels", tipLabelPainter, frame, attributeColourController, treeViewer));
treeViewer.setTipLabelPainter(tipLabelPainter);
+ // Create a node shape painter and its controller
+ if (SEPARATE_NODE_SHAPE_PANELS) {
+ final NodeShapePainter tipNodeShapePainter = new NodeShapePainter();
+ tipNodeShapePainter.setVisible(false);
+ controlPalette.addController(new NodeShapeController("Tip Shapes", NodeShapeController.NodeType.EXTERNAL, tipNodeShapePainter, attributeColourController, treeViewer));
+ treeViewer.setTipShapePainter(tipNodeShapePainter);
+ }
// Create a node label painter and its controller
final BasicLabelPainter nodeLabelPainter = new BasicLabelPainter(BasicLabelPainter.PainterIntent.NODE);
nodeLabelPainter.setVisible(false);
controlPalette.addController(new LabelPainterController("Node Labels", "nodeLabels", nodeLabelPainter, frame, attributeColourController, treeViewer));
treeViewer.setNodeLabelPainter(nodeLabelPainter);
+ // Create a node shape painter and its controller
+ final NodeShapePainter nodeShapePainter = new NodeShapePainter();
+ nodeShapePainter.setVisible(false);
+ controlPalette.addController(new NodeShapeController("Node Shapes",
+ (SEPARATE_NODE_SHAPE_PANELS ? NodeShapeController.NodeType.INTERNAL : NodeShapeController.NodeType.BOTH),
+ nodeShapePainter, attributeColourController, treeViewer));
+ if (!SEPARATE_NODE_SHAPE_PANELS) {
+ treeViewer.setTipShapePainter(nodeShapePainter);
+ }
+ treeViewer.setNodeShapePainter(nodeShapePainter);
+
// Create a node bar painter and its controller
final NodeBarPainter nodeBarPainter = new NodeBarPainter();
nodeBarPainter.setForeground(new Color(24, 32, 228, 128));
@@ -93,12 +113,6 @@ public class FigTreePanel extends JPanel {
controlPalette.addController(new NodeBarController("Node Bars", nodeBarPainter, treeViewer));
treeViewer.setNodeBarPainter(nodeBarPainter);
- // Create a node shape painter and its controller
- final NodeShapePainter nodeShapePainter = new NodeShapePainter();
- nodeShapePainter.setVisible(false);
- controlPalette.addController(new NodeShapeController("Node Shapes", nodeShapePainter, attributeColourController, treeViewer));
- treeViewer.setNodeShapePainter(nodeShapePainter);
-
// Create a branch label painter and its controller
final BasicLabelPainter branchLabelPainter = new BasicLabelPainter(BasicLabelPainter.PainterIntent.BRANCH);
branchLabelPainter.setVisible(false);
@@ -193,17 +207,17 @@ public class FigTreePanel extends JPanel {
if (utilityPanel == null) {
return;
}
- slideOpenPanel.showUtilityPanel(utilityPanel);
+ slideOpenPanel.showUtilityPanel(utilityPanel);
}
- public void hideUtilityPanel() {
- slideOpenPanel.hideUtilityPanel();
- }
+ public void hideUtilityPanel() {
+ slideOpenPanel.hideUtilityPanel();
+ }
- public JPanel getUtilityPanel() {
- return slideOpenPanel.getUtilityPanel();
- }
+ public JPanel getUtilityPanel() {
+ return slideOpenPanel.getUtilityPanel();
+ }
public void toggleMidpointRoot() {
treesController.toggleMidpointRoot();
diff --git a/src/figtree/application/JSONTreeExporter.java b/src/figtree/application/JSONTreeExporter.java
index 5f9f080..5b8c560 100755
--- a/src/figtree/application/JSONTreeExporter.java
+++ b/src/figtree/application/JSONTreeExporter.java
@@ -56,7 +56,8 @@ import java.util.*;
public class JSONTreeExporter implements TreeExporter {
public static final String treeNameAttributeKey = "name";
- public final static Set<String> ATTRIBUTE_NAMES = new TreeSet<String>(Arrays.asList(new String[] { "location", "host", "Hx", "Nx", "posterior" }));
+ public final static Set<String> ATTRIBUTE_NAMES = new TreeSet<String>(Arrays.asList(new String[] {
+ "location", "host", "Hx", "Nx", "posterior", "country", "region" }));
public final static String ORIGIN = "2013.34520547945";
public JSONTreeExporter(Writer writer) {
diff --git a/src/figtree/panel/FigTreePanel.java b/src/figtree/panel/FigTreePanel.java
index 7ae88ce..aa381e9 100755
--- a/src/figtree/panel/FigTreePanel.java
+++ b/src/figtree/panel/FigTreePanel.java
@@ -121,7 +121,8 @@ public class FigTreePanel extends JPanel {
treeViewer,
"tipLabels", tipLabelPainter,
"nodeLabels", nodeLabelPainter,
- "branchLabels", branchLabelPainter));
+ "branchLabels", branchLabelPainter,
+ true, true));
controlPalette1.addController(new LabelPainterController(
"tipLabels", tipLabelPainter,
@@ -139,7 +140,7 @@ public class FigTreePanel extends JPanel {
"tipLabels", tipLabelPainter,
"nodeLabels", nodeLabelPainter,
"branchLabels", branchLabelPainter,
- true));
+ true, false));
controlPalette1.addController(new LabelPainterController(
"tipLabels", tipLabelPainter,
@@ -160,7 +161,7 @@ public class FigTreePanel extends JPanel {
"tipLabels", tipLabelPainter,
"nodeLabels", nodeLabelPainter,
"branchLabels", branchLabelPainter,
- true));
+ true, false));
controlPalette2.addController(new TreeColouringController(treeViewer, "Clustering:"));
add(controlPalette2.getPanel(), BorderLayout.NORTH);
diff --git a/src/figtree/panel/LabelPainterController.java b/src/figtree/panel/LabelPainterController.java
index ff79687..29b0e91 100755
--- a/src/figtree/panel/LabelPainterController.java
+++ b/src/figtree/panel/LabelPainterController.java
@@ -22,6 +22,7 @@ package figtree.panel;
import figtree.treeviewer.TreeViewer;
import figtree.treeviewer.painters.AttributeComboHelper;
+import figtree.treeviewer.painters.AttributeComboHelperListener;
import jam.controlpalettes.AbstractController;
import jam.panels.OptionsPanel;
@@ -31,7 +32,6 @@ import java.awt.event.ItemListener;
import java.util.Map;
import figtree.treeviewer.painters.LabelPainter;
-import sun.jvm.hotspot.tools.FinalizerInfo;
/**
* @author Andrew Rambaut
@@ -48,11 +48,11 @@ public class LabelPainterController extends AbstractController {
private static final String DISPLAY_ATTRIBUTE_KEY = "displayAttribute";
public LabelPainterController(String tipKey,
- final LabelPainter tipLabelPainter,
+ final SimpleLabelPainter tipLabelPainter,
String nodeKey,
- final LabelPainter nodeLabelPainter,
+ final SimpleLabelPainter nodeLabelPainter,
String branchKey,
- final LabelPainter branchLabelPainter,
+ final SimpleLabelPainter branchLabelPainter,
final TreeViewer treeViewer) {
this.tipKey = tipKey;
@@ -68,17 +68,20 @@ public class LabelPainterController extends AbstractController {
}
- private JComboBox setupComboBox(String title, final LabelPainter labelPainter, final TreeViewer treeViewer) {
+ private JComboBox setupComboBox(String title, final SimpleLabelPainter labelPainter, final TreeViewer treeViewer) {
// String[] attributes = labelPainter.getAttributes();
final JComboBox displayAttributeCombo = new JComboBox();
displayAttributeCombo.addItem("None");
- new AttributeComboHelper(displayAttributeCombo, treeViewer, "None");
+ for (String attribute : labelPainter.getAttributes()) {
+ displayAttributeCombo.addItem(attribute);
+ }
+ new AttributeComboHelper(displayAttributeCombo, treeViewer, "None", labelPainter.getIntent());
optionsPanel.addComponentWithLabel(title, displayAttributeCombo);
displayAttributeCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
String attribute = (String)displayAttributeCombo.getSelectedItem();
- if (attribute.equals("none")) {
+ if (attribute == null || attribute.equalsIgnoreCase("none")) {
labelPainter.setVisible(false);
} else {
labelPainter.setDisplayAttribute(attribute);
diff --git a/src/figtree/panel/SimpleLabelPainter.java b/src/figtree/panel/SimpleLabelPainter.java
index 172f775..101562a 100755
--- a/src/figtree/panel/SimpleLabelPainter.java
+++ b/src/figtree/panel/SimpleLabelPainter.java
@@ -50,298 +50,296 @@ import java.util.List;
*/
public class SimpleLabelPainter extends LabelPainter<Node> {
- public static final String TAXON_NAMES = "Taxon names";
- public static final String NODE_AGES = "Node ages";
- public static final String BRANCH_LENGTHS = "Branch lengths";
+ public static final String NAMES = "Names";
+ public static final String NODE_AGES = "Node ages";
+ public static final String BRANCH_LENGTHS = "Branch lengths";
- public SimpleLabelPainter(PainterIntent intent) {
+ public SimpleLabelPainter(PainterIntent intent) {
super(intent);
- setupAttributes(null);
-
- if (this.displayAttribute == null) {
- this.displayAttribute = attributes[0];
- } else {
- this.displayAttribute = "";
- }
-
- }
-
- public void setupAttributes(Collection<? extends Tree> trees) {
-
- List<String> attributeNames = new ArrayList<String>();
- switch( intent ) {
- case TIP: {
- attributeNames.add(TAXON_NAMES);
- attributeNames.add(NODE_AGES);
- attributeNames.add(BRANCH_LENGTHS);
- break;
- }
- case NODE: {
- attributeNames.add(NODE_AGES);
- attributeNames.add(BRANCH_LENGTHS);
- break;
- }
- case BRANCH: {
- attributeNames.add(BRANCH_LENGTHS);
- attributeNames.add(NODE_AGES);
- break;
- }
- }
-
- if (trees != null) {
- for (Tree tree : trees) {
- Set<String> nodeAttributes = new TreeSet<String>();
- if (intent == PainterIntent.TIP) {
- for (Node node : tree.getExternalNodes()) {
- nodeAttributes.addAll(node.getAttributeNames());
- }
- } else if (intent == PainterIntent.NODE) {
- for (Node node : tree.getInternalNodes()) {
- nodeAttributes.addAll(node.getAttributeNames());
- }
- } else {
- for (Node node : tree.getNodes()) {
- nodeAttributes.addAll(node.getAttributeNames());
- }
- }
- for (String attributeName : nodeAttributes) {
- if (!attributeName.startsWith("!")) {
- attributeNames.add(attributeName);
- }
- }
- }
- }
-
- this.attributes = new String[attributeNames.size()];
- attributeNames.toArray(this.attributes);
-
- firePainterSettingsChanged();
- }
-
- public void setTreePane(TreePane treePane) {
- this.treePane = treePane;
- }
-
- public Decorator getBorderDecorator() {
- return borderDecorator;
- }
-
- public void setBorderDecorator(Decorator borderDecorator) {
- this.borderDecorator = borderDecorator;
- }
-
- public Decorator getTextDecorator() {
- return textDecorator;
- }
-
- public void setTextDecorator(Decorator textDecorator) {
- this.textDecorator = textDecorator;
- }
+ setupAttributes(null);
+
+ if (this.displayAttribute == null) {
+ this.displayAttribute = attributes[0];
+ } else {
+ this.displayAttribute = "";
+ }
+
+ }
+
+ public void setupAttributes(Collection<? extends Tree> trees) {
+
+ List<String> attributeNames = new ArrayList<String>();
+ switch (getIntent()) {
+ case TIP: {
+ attributeNames.add(NAMES);
+ attributeNames.add(NODE_AGES);
+ attributeNames.add(BRANCH_LENGTHS);
+ break;
+ }
+ case NODE: {
+ attributeNames.add(NODE_AGES);
+ attributeNames.add(BRANCH_LENGTHS);
+ break;
+ }
+ case BRANCH: {
+ attributeNames.add(BRANCH_LENGTHS);
+ attributeNames.add(NODE_AGES);
+ break;
+ }
+ }
+
+ if (trees != null) {
+ for (Tree tree : trees) {
+ Set<String> nodeAttributes = new TreeSet<String>();
+ if (getIntent() == PainterIntent.TIP) {
+ for (Node node : tree.getExternalNodes()) {
+ nodeAttributes.addAll(node.getAttributeNames());
+ }
+ } else if (getIntent() == PainterIntent.NODE) {
+ for (Node node : tree.getInternalNodes()) {
+ nodeAttributes.addAll(node.getAttributeNames());
+ }
+ } else {
+ for (Node node : tree.getNodes()) {
+ nodeAttributes.addAll(node.getAttributeNames());
+ }
+ }
+ for (String attributeName : nodeAttributes) {
+ if (!attributeName.startsWith("!")) {
+ attributeNames.add(attributeName);
+ }
+ }
+ }
+ }
+
+ this.attributes = new String[attributeNames.size()];
+ attributeNames.toArray(this.attributes);
+
+ firePainterSettingsChanged();
+ }
+
+ public void setTreePane(TreePane treePane) {
+ this.treePane = treePane;
+ }
+
+ public Decorator getBorderDecorator() {
+ return borderDecorator;
+ }
+
+ public void setBorderDecorator(Decorator borderDecorator) {
+ this.borderDecorator = borderDecorator;
+ }
+
+ public Decorator getTextDecorator() {
+ return textDecorator;
+ }
+
+ public void setTextDecorator(Decorator textDecorator) {
+ this.textDecorator = textDecorator;
+ }
public Set<Attributable> getAttributableItems() {
return null;
}
public Tree getTree() {
- return treePane.getTree();
- }
-
- protected String getLabel(Tree tree, Node node) {
- if (displayAttribute.equalsIgnoreCase(TAXON_NAMES)) {
- Taxon taxon = tree.getTaxon(node);
- if (taxon != null) {
- if (textDecorator != null) {
- textDecorator.setItem(taxon);
- }
- return taxon.getName();
- } else {
- String name = (String)node.getAttribute("name");
- if (name != null) {
- return name;
- }
- return "unlabelled";
- }
- }
-
- if ( tree instanceof RootedTree) {
- final RootedTree rtree = (RootedTree) tree;
-
- if (textDecorator != null) {
- textDecorator.setItem(node);
- }
-
- if (displayAttribute.equalsIgnoreCase(NODE_AGES) ) {
- return getNumberFormat().format(rtree.getHeight(node));
- } else if (displayAttribute.equalsIgnoreCase(BRANCH_LENGTHS) ) {
- return getNumberFormat().format(rtree.getLength(node));
- }
- }
-
- return formatValue(node.getAttribute(displayAttribute));
- }
-
- private String formatValue(Object value) {
- if (value != null) {
- if (value instanceof Double) {
- return getNumberFormat().format(value);
- } else if (value instanceof Object[]) {
- Object[] values = (Object[])value;
-
- if (values.length == 0) return null;
- if (values.length == 1) return formatValue(values[0]);
-
- StringBuilder builder = new StringBuilder("[");
- builder.append(formatValue(values[0]));
- for (int i = 1; i < values.length; i++) {
- builder.append(",");
- builder.append(formatValue(values[i]));
- }
- builder.append("]");
- return builder.toString();
- }
- return value.toString();
- }
- return null;
- }
-
- public Rectangle2D calibrate(Graphics2D g2, Node item) {
- Tree tree = treePane.getTree();
-
- String label = getLabel(tree, item);
-
- final Font oldFont = g2.getFont();
- if (textDecorator != null) {
- g2.setFont(textDecorator.getFont(getFont()));
- } else {
- g2.setFont(getFont());
- }
-
- FontMetrics fm = g2.getFontMetrics();
- preferredHeight = fm.getHeight();
- preferredWidth = 0;
-
- if (label != null) {
- Rectangle2D rect = fm.getStringBounds(label, g2);
- preferredWidth = rect.getWidth();
- }
-
- yOffset = (float)fm.getAscent();
-
- g2.setFont(oldFont);
-
- return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
- }
-
- public double getPreferredWidth() {
- return preferredWidth;
- }
-
- public double getPreferredHeight() {
- return preferredHeight;
- }
-
- public double getHeightBound() {
- return preferredHeight + yOffset;
- }
-
- public void paint(Graphics2D g2, Node item, Justification justification, Rectangle2D bounds) {
- Tree tree = treePane.getTree();
-
- if (TreePane.DEBUG_OUTLINE) {
- g2.setPaint(Color.red);
- g2.draw(bounds);
- }
-
- String label = getLabel(tree, item);
-
- Font oldFont = g2.getFont();
-
- Paint backgroundPaint = getBackground();
- Paint borderPaint = getBorderPaint();
- Stroke borderStroke = getBorderStroke();
-
- if (borderDecorator != null) {
- backgroundPaint = borderDecorator.getPaint(backgroundPaint);
- borderPaint = borderDecorator.getPaint(borderPaint);
- borderStroke = borderDecorator.getStroke(borderStroke);
- }
-
- if (backgroundPaint != null) {
- g2.setPaint(backgroundPaint);
- g2.fill(bounds);
- }
-
- if (borderPaint != null && borderStroke != null) {
- g2.setPaint(borderPaint);
- g2.setStroke(borderStroke);
- g2.draw(bounds);
- }
-
- if (textDecorator != null) {
- g2.setPaint(textDecorator.getPaint(getForeground()));
- g2.setFont(textDecorator.getFont(getFont()));
- } else {
- g2.setPaint(getForeground());
- g2.setFont(getFont());
- }
-
- if (label != null) {
-
- Rectangle2D rect = null;
- if (justification == Justification.CENTER || justification == Justification.RIGHT)
- rect = g2.getFontMetrics().getStringBounds(label, g2);
-
- float xOffset;
- float y = yOffset + (float) bounds.getY();
- switch (justification) {
- case CENTER:
- xOffset = (float)(-rect.getWidth()/2.0);
- y = yOffset + (float) rect.getY();
+ return treePane.getTree();
+ }
+
+ protected String getLabel(Tree tree, Node node) {
+ if (displayAttribute.equalsIgnoreCase(NAMES)) {
+ Taxon taxon = tree.getTaxon(node);
+ if (taxon != null) {
+ if (textDecorator != null) {
+ textDecorator.setItem(taxon);
+ }
+ return taxon.getName();
+ } else {
+ String name = (String)node.getAttribute("name");
+ if (name != null) {
+ return name;
+ }
+ return "unlabelled";
+ }
+ }
+
+ if ( tree instanceof RootedTree) {
+ final RootedTree rtree = (RootedTree) tree;
+
+ if (textDecorator != null) {
+ textDecorator.setItem(node);
+ }
+
+ if (displayAttribute.equalsIgnoreCase(NODE_AGES) ) {
+ return getNumberFormat().format(rtree.getHeight(node));
+ } else if (displayAttribute.equalsIgnoreCase(BRANCH_LENGTHS) ) {
+ return getNumberFormat().format(rtree.getLength(node));
+ }
+ }
+
+ return formatValue(node.getAttribute(displayAttribute));
+ }
+
+ private String formatValue(Object value) {
+ if (value != null) {
+ if (value instanceof Double) {
+ return getNumberFormat().format(value);
+ } else if (value instanceof Object[]) {
+ Object[] values = (Object[])value;
+
+ if (values.length == 0) return null;
+ if (values.length == 1) return formatValue(values[0]);
+
+ StringBuilder builder = new StringBuilder("[");
+ builder.append(formatValue(values[0]));
+ for (int i = 1; i < values.length; i++) {
+ builder.append(",");
+ builder.append(formatValue(values[i]));
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+ return value.toString();
+ }
+ return null;
+ }
+
+ public Rectangle2D calibrate(Graphics2D g2, Node item) {
+ Tree tree = treePane.getTree();
+
+ String label = getLabel(tree, item);
+
+ final Font oldFont = g2.getFont();
+ if (textDecorator != null) {
+ g2.setFont(textDecorator.getFont(getFont()));
+ } else {
+ g2.setFont(getFont());
+ }
+
+ FontMetrics fm = g2.getFontMetrics();
+ preferredHeight = fm.getHeight();
+ preferredWidth = 0;
+
+ if (label != null) {
+ Rectangle2D rect = fm.getStringBounds(label, g2);
+ preferredWidth = rect.getWidth();
+ }
+
+ yOffset = (float)fm.getAscent();
+
+ g2.setFont(oldFont);
+
+ return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
+ }
+
+ public double getPreferredWidth() {
+ return preferredWidth;
+ }
+
+ public double getPreferredHeight() {
+ return preferredHeight;
+ }
+
+ public double getHeightBound() {
+ return preferredHeight + yOffset;
+ }
+
+ public void paint(Graphics2D g2, Node item, Justification justification, Rectangle2D bounds) {
+ Tree tree = treePane.getTree();
+
+ if (TreePane.DEBUG_OUTLINE) {
+ g2.setPaint(Color.red);
+ g2.draw(bounds);
+ }
+
+ String label = getLabel(tree, item);
+
+ Font oldFont = g2.getFont();
+
+ Paint backgroundPaint = getBackground();
+ Paint borderPaint = getBorderPaint();
+ Stroke borderStroke = getBorderStroke();
+
+ if (borderDecorator != null) {
+ backgroundPaint = borderDecorator.getPaint(backgroundPaint);
+ borderPaint = borderDecorator.getPaint(borderPaint);
+ borderStroke = borderDecorator.getStroke(borderStroke);
+ }
+
+ if (backgroundPaint != null) {
+ g2.setPaint(backgroundPaint);
+ g2.fill(bounds);
+ }
+
+ if (borderPaint != null && borderStroke != null) {
+ g2.setPaint(borderPaint);
+ g2.setStroke(borderStroke);
+ g2.draw(bounds);
+ }
+
+ if (textDecorator != null) {
+ g2.setPaint(textDecorator.getPaint(getForeground()));
+ g2.setFont(textDecorator.getFont(getFont()));
+ } else {
+ g2.setPaint(getForeground());
+ g2.setFont(getFont());
+ }
+
+ if (label != null) {
+
+ Rectangle2D rect = null;
+ if (justification == Justification.CENTER || justification == Justification.RIGHT)
+ rect = g2.getFontMetrics().getStringBounds(label, g2);
+
+ float xOffset;
+ float y = yOffset + (float) bounds.getY();
+ switch (justification) {
+ case CENTER:
+ xOffset = (float)(-rect.getWidth()/2.0);
+ y = yOffset + (float) rect.getY();
//xOffset = (float) (bounds.getX() + (bounds.getWidth() - rect.getWidth()) / 2.0);
- break;
- case FLUSH:
- case LEFT:
- xOffset = (float) bounds.getX();
- break;
- case RIGHT:
- xOffset = (float) (bounds.getX() + bounds.getWidth() - rect.getWidth());
- break;
- default:
- throw new IllegalArgumentException("Unrecognized alignment enum option");
- }
-
- g2.drawString(label, xOffset, y);
- }
-
- g2.setFont(oldFont);
- }
-
- public String[] getAttributes() {
- return attributes;
- }
+ break;
+ case FLUSH:
+ case LEFT:
+ xOffset = (float) bounds.getX();
+ break;
+ case RIGHT:
+ xOffset = (float) (bounds.getX() + bounds.getWidth() - rect.getWidth());
+ break;
+ default:
+ throw new IllegalArgumentException("Unrecognized alignment enum option");
+ }
+
+ g2.drawString(label, xOffset, y);
+ }
+
+ g2.setFont(oldFont);
+ }
+
+ public String[] getAttributes() {
+ return attributes;
+ }
public String getDisplayAttribute() {
return displayAttribute;
}
public void setDisplayAttribute(String displayAttribute) {
- this.displayAttribute = displayAttribute;
- firePainterChanged();
- }
-
- private PainterIntent intent;
+ this.displayAttribute = displayAttribute;
+ firePainterChanged();
+ }
- private double preferredWidth;
- private double preferredHeight;
- private float yOffset;
+ private double preferredWidth;
+ private double preferredHeight;
+ private float yOffset;
- protected String displayAttribute;
- protected String[] attributes;
+ protected String displayAttribute;
+ protected String[] attributes;
- protected TreePane treePane;
+ protected TreePane treePane;
- private Decorator textDecorator = null;
- private Decorator borderDecorator = null;
+ private Decorator textDecorator = null;
+ private Decorator borderDecorator = null;
}
\ No newline at end of file
diff --git a/src/figtree/panel/TreeAppearanceController.java b/src/figtree/panel/TreeAppearanceController.java
index 38f279c..7f40564 100755
--- a/src/figtree/panel/TreeAppearanceController.java
+++ b/src/figtree/panel/TreeAppearanceController.java
@@ -20,6 +20,7 @@
package figtree.panel;
+import jebl.evolution.trees.SortedRootedTree;
import jebl.evolution.trees.Tree;
import jebl.evolution.graphs.Node;
import figtree.treeviewer.TreeViewer;
@@ -94,7 +95,7 @@ public class TreeAppearanceController extends AbstractController {
final LabelPainter nodeLabelPainter,
String branchKey,
final LabelPainter branchLabelPainter) {
- this(treeViewer, tipKey, tipLabelPainter, nodeKey, nodeLabelPainter, branchKey, branchLabelPainter, true);
+ this(treeViewer, tipKey, tipLabelPainter, nodeKey, nodeLabelPainter, branchKey, branchLabelPainter, true, false);
}
public TreeAppearanceController(final TreeViewer treeViewer,
@@ -104,7 +105,8 @@ public class TreeAppearanceController extends AbstractController {
final LabelPainter nodeLabelPainter,
String branchKey,
final LabelPainter branchLabelPainter,
- boolean hideColouring) {
+ boolean hideColouring,
+ boolean ordering) {
this.treeViewer = treeViewer;
this.hideColouring = hideColouring;
@@ -247,7 +249,30 @@ public class TreeAppearanceController extends AbstractController {
}
});
}
- }
+
+ if (ordering) {
+ orderCombo = new JComboBox(new String[]{"Off",
+ SortedRootedTree.BranchOrdering.INCREASING_NODE_DENSITY.toString(),
+ SortedRootedTree.BranchOrdering.DECREASING_NODE_DENSITY.toString()});
+ orderCombo.setOpaque(false);
+ orderCombo.setSelectedItem(treeViewer.isOrderBranchesOn() ?
+ treeViewer.getBranchOrdering().ordinal() + 1 : 0);
+ orderCombo.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent itemEvent) {
+ if (orderCombo.getSelectedIndex() == 0) {
+ treeViewer.setOrderBranchesOn(false);
+ } else {
+ treeViewer.setOrderBranchesOn(true);
+ treeViewer.setBranchOrdering(SortedRootedTree.BranchOrdering.values()[orderCombo.getSelectedIndex() - 1]);
+ }
+ }
+ });
+
+ optionsPanel.addComponentWithLabel("Order:", orderCombo);
+ } else {
+ orderCombo = null;
+ }
+ }
private void setupAttributes(Collection<? extends Tree> trees) {
Object selected = branchColourAttributeCombo.getSelectedItem();
@@ -361,7 +386,9 @@ public class TreeAppearanceController extends AbstractController {
private final JSpinner fontSizeSpinner;
private final JSpinner digitsSpinner;
- private final TreeViewer treeViewer;
+ private final JComboBox orderCombo;
+
+ private final TreeViewer treeViewer;
private final String tipKey;
private final String nodeKey;
diff --git a/src/figtree/panel/TreesController.java b/src/figtree/panel/TreesController.java
index f64491d..0577cf8 100755
--- a/src/figtree/panel/TreesController.java
+++ b/src/figtree/panel/TreesController.java
@@ -60,69 +60,87 @@ public class TreesController extends AbstractController {
public TreesController(final TreeViewer treeViewer) {
+ this(treeViewer, true, true, true);
+ }
+ public TreesController(final TreeViewer treeViewer,
+ final boolean rooting,
+ final boolean ordering,
+ final boolean transforming) {
this.treeViewer = treeViewer;
titleLabel = new JLabel(CONTROLLER_TITLE);
optionsPanel = new OptionsPanel();
- rootingCheck = new JCheckBox("Midpoint root");
- rootingCheck.setOpaque(false);
- optionsPanel.addComponent(rootingCheck);
-
- rootingCheck.setSelected(treeViewer.isRootingOn());
-
- rootingCheck.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent actionEvent) {
- if (rootingCheck.isSelected()) {
- treeViewer.setRootingOn(true);
- treeViewer.setRootingType(TreePane.RootingType.MID_POINT);
- } else {
- treeViewer.setRootingOn(false);
- treeViewer.setRootingType(TreePane.RootingType.USER_ROOTING);
+ if (rooting) {
+ rootingCheck = new JCheckBox("Midpoint root");
+ rootingCheck.setOpaque(false);
+ optionsPanel.addComponent(rootingCheck);
+
+ rootingCheck.setSelected(treeViewer.isRootingOn());
+
+ rootingCheck.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent actionEvent) {
+ if (rootingCheck.isSelected()) {
+ treeViewer.setRootingOn(true);
+ treeViewer.setRootingType(TreePane.RootingType.MID_POINT);
+ } else {
+ treeViewer.setRootingOn(false);
+ treeViewer.setRootingType(TreePane.RootingType.USER_ROOTING);
+ }
+
}
+ });
+ } else {
+ rootingCheck = null;
+ }
- }
- });
-
- orderCombo = new JComboBox(new String[] {"Off",
- SortedRootedTree.BranchOrdering.INCREASING_NODE_DENSITY.toString(),
- SortedRootedTree.BranchOrdering.DECREASING_NODE_DENSITY.toString()});
- orderCombo.setOpaque(false);
- orderCombo.setSelectedItem(treeViewer.isOrderBranchesOn() ?
- treeViewer.getBranchOrdering().ordinal() + 1 : 0);
- orderCombo.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent itemEvent) {
- if (orderCombo.getSelectedIndex() == 0) {
- treeViewer.setOrderBranchesOn(false);
- } else {
- treeViewer.setOrderBranchesOn(true);
- treeViewer.setBranchOrdering(SortedRootedTree.BranchOrdering.values()[orderCombo.getSelectedIndex() - 1]);
+ if (ordering) {
+ orderCombo = new JComboBox(new String[]{"Off",
+ SortedRootedTree.BranchOrdering.INCREASING_NODE_DENSITY.toString(),
+ SortedRootedTree.BranchOrdering.DECREASING_NODE_DENSITY.toString()});
+ orderCombo.setOpaque(false);
+ orderCombo.setSelectedItem(treeViewer.isOrderBranchesOn() ?
+ treeViewer.getBranchOrdering().ordinal() + 1 : 0);
+ orderCombo.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent itemEvent) {
+ if (orderCombo.getSelectedIndex() == 0) {
+ treeViewer.setOrderBranchesOn(false);
+ } else {
+ treeViewer.setOrderBranchesOn(true);
+ treeViewer.setBranchOrdering(SortedRootedTree.BranchOrdering.values()[orderCombo.getSelectedIndex() - 1]);
+ }
}
- }
- });
-
- optionsPanel.addComponentWithLabel("Order:", orderCombo);
-
- transformCombo = new JComboBox(new String[] {"Off",
- TransformedRootedTree.Transform.CLADOGRAM.toString(),
- TransformedRootedTree.Transform.PROPORTIONAL.toString(),
- TransformedRootedTree.Transform.EQUAL_LENGTHS.toString()});
- transformCombo.setOpaque(false);
- transformCombo.setSelectedItem(treeViewer.isOrderBranchesOn() ?
- treeViewer.getBranchTransform().ordinal() + 1 : 0);
- transformCombo.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent itemEvent) {
- if (transformCombo.getSelectedIndex() == 0) {
- treeViewer.setTransformBranchesOn(false);
- } else {
- treeViewer.setTransformBranchesOn(true);
- treeViewer.setBranchTransform(TransformedRootedTree.Transform.values()[transformCombo.getSelectedIndex() - 1]);
+ });
+
+ optionsPanel.addComponentWithLabel("Order:", orderCombo);
+ } else {
+ orderCombo = null;
+ }
+
+ if (transforming) {
+ transformCombo = new JComboBox(new String[]{"Off",
+ TransformedRootedTree.Transform.CLADOGRAM.toString(),
+ TransformedRootedTree.Transform.PROPORTIONAL.toString(),
+ TransformedRootedTree.Transform.EQUAL_LENGTHS.toString()});
+ transformCombo.setOpaque(false);
+ transformCombo.setSelectedItem(treeViewer.isOrderBranchesOn() ?
+ treeViewer.getBranchTransform().ordinal() + 1 : 0);
+ transformCombo.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent itemEvent) {
+ if (transformCombo.getSelectedIndex() == 0) {
+ treeViewer.setTransformBranchesOn(false);
+ } else {
+ treeViewer.setTransformBranchesOn(true);
+ treeViewer.setBranchTransform(TransformedRootedTree.Transform.values()[transformCombo.getSelectedIndex() - 1]);
+ }
}
- }
- });
- optionsPanel.addComponentWithLabel("Transform:", transformCombo);
+ });
+ optionsPanel.addComponentWithLabel("Transform:", transformCombo);
+ } else {
+ transformCombo = null;
+ }
}
public JComponent getTitleComponent() {
diff --git a/src/figtree/treeviewer/DefaultTreeViewer.java b/src/figtree/treeviewer/DefaultTreeViewer.java
index 1163014..0da8c6b 100755
--- a/src/figtree/treeviewer/DefaultTreeViewer.java
+++ b/src/figtree/treeviewer/DefaultTreeViewer.java
@@ -274,6 +274,10 @@ public class DefaultTreeViewer extends TreeViewer {
return treePane.getSelectedTips();
}
+ public Set<Taxon> getSelectedTaxa() {
+ return treePane.getSelectedTaxa();
+ }
+
/**
* Select taxa with a search string matching the currently displayed attribute
* @param searchType
@@ -288,6 +292,8 @@ public class DefaultTreeViewer extends TreeViewer {
}
selectTaxa(attributeName, searchType, searchString, caseSensitive);
+
+ scrollToSelectedTips();
}
public void selectTaxa(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive) {
@@ -504,6 +510,14 @@ public class DefaultTreeViewer extends TreeViewer {
return false;
}
+ public void scrollToSelectedTips() {
+ Set<Node> selectedTips = treePane.getSelectedTips();
+ if (selectedTips.size() > 0) {
+ Point point = treePane.getLocationOfTip(selectedTips.iterator().next());
+ treePane.scrollPointToVisible(point);
+ }
+ }
+
public void cartoonSelectedNodes() {
treePane.cartoonSelectedNodes();
fireTreeSettingsChanged();
@@ -591,6 +605,11 @@ public class DefaultTreeViewer extends TreeViewer {
treePane.removeTreeSelectionListener(treeSelectionListener);
}
+ public TreePaneSelector.SelectionMode getSelectionMode() {
+ return treePaneSelector.getSelectionMode();
+ }
+
+
public void setSelectionMode(TreePaneSelector.SelectionMode selectionMode) {
TreePaneSelector.SelectionMode oldSelectionMode = treePaneSelector.getSelectionMode();
@@ -629,6 +648,10 @@ public class DefaultTreeViewer extends TreeViewer {
// nodeBarPainter.setupAttributes(trees);
}
+ public void setTipShapePainter(NodeShapePainter tipShapePainter) {
+ treePane.setTipShapePainter(tipShapePainter);
+ }
+
public void setNodeShapePainter(NodeShapePainter nodeShapePainter) {
treePane.setNodeShapePainter(nodeShapePainter);
}
diff --git a/src/figtree/treeviewer/ScaleAxis.java b/src/figtree/treeviewer/ScaleAxis.java
index eb93945..ef53440 100755
--- a/src/figtree/treeviewer/ScaleAxis.java
+++ b/src/figtree/treeviewer/ScaleAxis.java
@@ -666,6 +666,10 @@ public class ScaleAxis {
if (!isCalibrated)
calibrate();
+ if (minorTick <= 0) {
+ return 0;
+ }
+
if (majorTickIndex == majorTickCount-1)
return (int)((maxAxis-maxTick)/minorTick);
else if (majorTickIndex==-1)
diff --git a/src/figtree/treeviewer/TimeScale.java b/src/figtree/treeviewer/TimeScale.java
index 8816713..6f5642f 100755
--- a/src/figtree/treeviewer/TimeScale.java
+++ b/src/figtree/treeviewer/TimeScale.java
@@ -34,7 +34,9 @@ import jebl.evolution.trees.RootedTree;
*/
public class TimeScale {
- public TimeScale(double rootAge) {
+ private boolean isReversed = false;
+
+ public TimeScale(double rootAge) {
this.rootAge = rootAge;
this.scaleFactor = Double.NaN;
this.offsetAge = 0.0;
@@ -50,7 +52,7 @@ public class TimeScale {
if (Double.isNaN(scaleFactor)) {
return rootAge / tree.getHeight(tree.getRootNode());
}
- return scaleFactor;
+ return scaleFactor * (isReversed ? -1.0 : 1.0);
}
public double getAge(double height, RootedTree tree) {
@@ -71,7 +73,12 @@ public class TimeScale {
return (time / getScaleFactor(tree));
}
- private final double rootAge;
+ public void setReversed(boolean isReversed) {
+ this.isReversed = isReversed;
+ }
+
+ private final double rootAge;
private final double offsetAge;
private final double scaleFactor;
+
}
diff --git a/src/figtree/treeviewer/TreePane.java b/src/figtree/treeviewer/TreePane.java
index 5724c86..aae47a7 100755
--- a/src/figtree/treeviewer/TreePane.java
+++ b/src/figtree/treeviewer/TreePane.java
@@ -33,7 +33,6 @@ import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.print.*;
-import java.io.IOException;
import java.util.*;
import java.util.List;
@@ -48,6 +47,8 @@ import java.util.List;
* $LastChangedRevision$
*/
public class TreePane extends JComponent implements PainterListener, Printable {
+ public final static boolean DEBUG_OUTLINE = false;
+
public enum RootingType {
USER_ROOTING("User Selection"),
MID_POINT("Midpoint");
@@ -63,8 +64,6 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
- public final static boolean DEBUG_OUTLINE = false;
-
public final String CARTOON_ATTRIBUTE_NAME = "!cartoon";
public final String COLLAPSE_ATTRIBUTE_NAME = "!collapse";
public final String HILIGHT_ATTRIBUTE_NAME = "!hilight";
@@ -91,12 +90,16 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
+ private void recalibrate() {
+ calibrated = false;
+ }
+
private void setupTree() {
tree = constructTransformedTree(originalTree);
recalculateCollapsedNodes();
- calibrated = false;
+ recalibrate();
invalidate();
repaint();
}
@@ -152,11 +155,11 @@ public class TreePane extends JComponent implements PainterListener, Printable {
treeLayout.addTreeLayoutListener(new TreeLayoutListener() {
public void treeLayoutChanged() {
- calibrated = false;
+ recalibrate();
repaint();
}
});
- calibrated = false;
+ recalibrate();
invalidate();
repaint();
}
@@ -167,7 +170,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setTimeScale(TimeScale timeScale) {
this.timeScale = timeScale;
- calibrated = false;
+ this.timeScale.setReversed(isAxisReversed());
+ recalibrate();
repaint();
}
@@ -233,7 +237,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
node.setAttribute("!rotate", rotate);
- calibrated = false;
+ recalibrate();
invalidate();
repaint();
}
@@ -247,7 +251,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
node.removeAttribute("!rotate");
}
- calibrated = false;
+ recalibrate();
invalidate();
repaint();
}
@@ -300,14 +304,19 @@ public class TreePane extends JComponent implements PainterListener, Printable {
*/
public double scaleOnAxis(double value) {
double height = timeScale.getHeight(value, tree);
- if (treeLayout.isAxisReversed()) {
- return treeBounds.getX() + treeBounds.getWidth() - (height * treeScale);
+ if (isAxisReversed()) {
+ return (treeBounds.getX() + treeBounds.getWidth()) - (height * treeScale);
} else {
return treeBounds.getX() + (height * treeScale);
}
}
public Shape getAxisLine(double value) {
+ if (isAxisReversed()) {
+ value = maxTreeHeight - value;
+ } else {
+ value -= rootHeightOffset;
+ }
double height = timeScale.getHeight(value, tree);
Shape line = treeLayout.getAxisLine(height);
if (line != null) {
@@ -327,16 +336,21 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setAxisOrigin(double axisOrigin) {
this.axisOrigin = axisOrigin;
- calibrated = false;
+ recalibrate();
repaint();
}
public void setAxisReversed(final boolean isAxisReversed) {
- treeLayout.setAxisReversed(isAxisReversed);
- calibrated = false;
+ this.isAxisReversed = isAxisReversed;
+ this.timeScale.setReversed(isAxisReversed());
+ recalibrate();
repaint();
}
+ public boolean isAxisReversed() {
+ return isAxisReversed;
+ }
+
private void setupScaleAxis() {
double minValue = timeScale.getAge(0.0, tree);
double maxValue = timeScale.getAge(maxTreeHeight, tree);
@@ -357,7 +371,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setRootAge(double rootAge) {
double rootLength = timeScale.getHeight(rootAge, tree) - tree.getHeight(tree.getRootNode());
treeLayout.setRootLength(rootLength);
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -376,28 +390,28 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setTickSpacing(double userMajorTickSpacing, double userMinorTickSpacing) {
scaleAxis.setManualAxis(userMajorTickSpacing, userMinorTickSpacing);
- calibrated = false;
+ recalibrate();
repaint();
}
public void setAutomaticScale() {
scaleAxis.setAutomatic();
- calibrated = false;
+ recalibrate();
repaint();
}
public void painterChanged() {
- calibrated = false;
+ recalibrate();
repaint();
}
public void painterSettingsChanged() {
- calibrated = false;
+ recalibrate();
repaint();
}
public void attributesChanged() {
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -496,7 +510,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setShowingTipCallouts(boolean showingTipCallouts) {
this.showingTipCallouts = showingTipCallouts;
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -720,7 +734,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Object[] values = new Object[] { tipCount, height };
node.setAttribute(CARTOON_ATTRIBUTE_NAME, values);
}
- calibrated = false;
+ recalibrate();
repaint();
} else {
for (Node child : tree.getChildren(node)) {
@@ -746,7 +760,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Object[] values = new Object[] { tipName, height };
node.setAttribute(COLLAPSE_ATTRIBUTE_NAME, values);
}
- calibrated = false;
+ recalibrate();
repaint();
} else {
for (Node child : tree.getChildren(node)) {
@@ -769,7 +783,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Object[] values = new Object[] { tipCount, height, color };
node.setAttribute(HILIGHT_ATTRIBUTE_NAME, values);
- calibrated = false;
+ recalibrate();
repaint();
} else {
for (Node child : tree.getChildren(node)) {
@@ -806,7 +820,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Object[] values = new Object[] { tipCount, height, oldValues[2] };
node.setAttribute(HILIGHT_ATTRIBUTE_NAME, values);
}
- calibrated = false;
+ recalibrate();
repaint();
} else {
for (Node child : tree.getChildren(node)) {
@@ -828,7 +842,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
node.removeAttribute(CARTOON_ATTRIBUTE_NAME);
}
}
- calibrated = false;
+ recalibrate();
repaint();
}
}
@@ -846,7 +860,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (node.getAttribute(CARTOON_ATTRIBUTE_NAME) != null) {
node.removeAttribute(CARTOON_ATTRIBUTE_NAME);
}
- calibrated = false;
+ recalibrate();
repaint();
} else {
for (Node child : tree.getChildren(node)) {
@@ -865,7 +879,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
node.removeAttribute(HILIGHT_ATTRIBUTE_NAME);
}
}
- calibrated = false;
+ recalibrate();
repaint();
}
}
@@ -876,7 +890,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (selectedNodes.size() == 0 || selectedNodes.contains(node)) {
if (node.getAttribute(HILIGHT_ATTRIBUTE_NAME) != null) {
node.removeAttribute(HILIGHT_ATTRIBUTE_NAME);
- calibrated = false;
+ recalibrate();
repaint();
}
}
@@ -977,7 +991,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.tipLabelPainter != null) {
this.tipLabelPainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -994,7 +1008,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.nodeLabelPainter != null) {
this.nodeLabelPainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1011,7 +1025,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.branchLabelPainter != null) {
this.branchLabelPainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1028,7 +1042,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.nodeBarPainter != null) {
this.nodeBarPainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1036,6 +1050,22 @@ public class TreePane extends JComponent implements PainterListener, Printable {
return nodeBarPainter;
}
+ public void setTipShapePainter(NodeShapePainter tipShapePainter) {
+ tipShapePainter.setTreePane(this);
+ if (this.tipShapePainter != null) {
+ this.tipShapePainter.removePainterListener(this);
+ }
+ this.tipShapePainter = tipShapePainter;
+ if (this.tipShapePainter != null) {
+ this.tipShapePainter.addPainterListener(this);
+ }
+ recalibrate();
+ repaint();
+ }
+
+ public NodeShapePainter getTipShapePainter() {
+ return tipShapePainter;
+ }
public void setNodeShapePainter(NodeShapePainter nodeShapePainter) {
nodeShapePainter.setTreePane(this);
@@ -1046,7 +1076,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.nodeShapePainter != null) {
this.nodeShapePainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1062,7 +1092,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
scalePainters.add(scalePainter);
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1073,7 +1103,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
scalePainters.remove(scalePainter);
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1086,7 +1116,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (this.scaleGridPainter != null) {
this.scaleGridPainter.addPainterListener(this);
}
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1096,7 +1126,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
this.legendPainter = legendPainter;
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1110,7 +1140,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void setLabelSpacing(float labelSpacing) {
this.labelXOffset = labelSpacing;
- calibrated = false;
+ recalibrate();
repaint();
}
@@ -1121,7 +1151,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
super.setPreferredSize(dimension);
}
- calibrated = false;
+ recalibrate();
}
public double getHeightAt(Graphics2D graphics2D, Point2D point) {
@@ -1135,6 +1165,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public Node getNodeAt(Graphics2D g2, Point point) {
Rectangle rect = new Rectangle(point.x - 1, point.y - 1, 3, 3);
+ rect.translate(-insets.left, -insets.top);
for (Node node : tree.getExternalNodes()) {
Shape taxonLabelBound = tipLabelBounds.get(node);
@@ -1192,6 +1223,14 @@ public class TreePane extends JComponent implements PainterListener, Printable {
return selectedTips;
}
+ public Set<Taxon> getSelectedTaxa() {
+ Set<Taxon> selectedTaxa = new LinkedHashSet<Taxon>();
+ for (Node node : getSelectedTips()) {
+ selectedTaxa.add(tree.getTaxon(node));
+ }
+ return selectedTaxa;
+ }
+
public RootedTree getSelectedSubtree() {
if (selectedNodes.size() == 0 && selectedTips.size() == 0) {
// nothing selected so return the whole tree
@@ -1277,6 +1316,14 @@ public class TreePane extends JComponent implements PainterListener, Printable {
this.rulerHeight = rulerHeight;
}
+ public Point getLocationOfTip(Node tip) {
+ if (tip == null) {
+ return new Point(0,0);
+ }
+ Shape path = transform.createTransformedShape(treeLayoutCache.getTipLabelPath(tip));
+ return path.getBounds().getLocation();
+ }
+
public void scrollPointToVisible(Point point) {
scrollRectToVisible(new Rectangle(point.x, point.y, 0, 0));
}
@@ -1317,13 +1364,15 @@ public class TreePane extends JComponent implements PainterListener, Printable {
public void paint(Graphics graphics) {
if (tree == null) return;
- graphics.setColor(Color.white);
- Rectangle r = graphics.getClipBounds();
- if (r != null) {
- graphics.fillRect(r.x, r.y, r.width, r.height);
- }
-
+// graphics.setColor(Color.white);
+// Rectangle r = graphics.getClipBounds();
+// if (r != null) {
+// graphics.fillRect(r.x, r.y, r.width, r.height);
+// }
+//
final Graphics2D g2 = (Graphics2D) graphics;
+ g2.translate(insets.left, insets.top);
+
if (!calibrated) {
calibrate(g2, getWidth(), getHeight());
}
@@ -1402,13 +1451,13 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Graphics2D g2 = (Graphics2D) graphics;
g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
- calibrated = false;
+ recalibrate();
setDoubleBuffered(false);
drawTree(g2, pageFormat.getImageableWidth(), pageFormat.getImageableHeight());
setDoubleBuffered(true);
- calibrated = false;
+ recalibrate();
return PAGE_EXISTS;
}
@@ -1445,6 +1494,14 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
+ if (scaleGridPainter != null && scaleGridPainter.isVisible()) {
+ Rectangle2D gridBounds = new Rectangle2D.Double(
+ treeBounds.getX(), 0.0,
+ treeBounds.getWidth(), treeBounds.getHeight());
+ scaleGridPainter.paint(g2, this, null, gridBounds);
+ }
+
+
// Paint backgrounds
if (nodeBackgroundDecorator != null) {
for (Node node : treeLayoutCache.getNodeAreaMap().keySet() ) {
@@ -1457,7 +1514,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
g2.setPaint(background);
g2.fill(transNodePath);
-// Experimental outlining - requires order of drawing to be pre-order
+// Experimental outlining - requires order of drawing to be pre-order
// g2.setStroke(new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
// g2.draw(transNodePath);
}
@@ -1496,15 +1553,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
- if (scaleGridPainter != null && scaleGridPainter.isVisible()) {
- Rectangle2D gridBounds = new Rectangle2D.Double(
- treeBounds.getX(), 0.0,
- treeBounds.getWidth(), totalScaleBounds.getY());
- scaleGridPainter.paint(g2, this, null, gridBounds);
- }
-
if (DEBUG_OUTLINE) {
- g2.setPaint(Color.red);
+ g2.setPaint(Color.blue);
g2.draw(treeBounds);
}
@@ -1627,6 +1677,14 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
+ if (tipShapePainter != null && tipShapePainter.isVisible()) {
+ for (Node node : tipPoints.keySet()) {
+ Point2D point = tipPoints.get(node);
+ point = transform.transform(point, null);
+ tipShapePainter.paint(g2, node, point, nodeShapeTransforms.get(node));
+ }
+ }
+
// Paint tip labels
if (tipLabelPainter != null && tipLabelPainter.isVisible()) {
@@ -1637,8 +1695,9 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Painter.Justification tipLabelJustification = tipLabelJustifications.get(node);
g2.transform(tipLabelTransform);
+ double labelWidth = tipLabelWidths.get(node);
tipLabelPainter.paint(g2, node, tipLabelJustification,
- new Rectangle2D.Double(0.0, 0.0, tipLabelWidth, tipLabelPainter.getPreferredHeight()));
+ new Rectangle2D.Double(0.0, 0.0, labelWidth, tipLabelPainter.getPreferredHeight()));
g2.setTransform(oldTransform);
@@ -1681,10 +1740,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
final double preferredWidth = branchLabelPainter.getPreferredWidth();
final double preferredHeight = branchLabelPainter.getPreferredHeight();
- //Line2D labelPath = treeLayout.getBranchLabelPath(node);
-
branchLabelPainter.paint(g2, node, Painter.Justification.CENTER,
- //new Rectangle2D.Double(-preferredWidth/2, -preferredHeight, preferredWidth, preferredHeight));
new Rectangle2D.Double(0, 0, preferredWidth, preferredHeight));
g2.setTransform(oldTransform);
@@ -1702,6 +1758,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
treeLayout.layout(tree, treeLayoutCache);
maxTreeHeight = tree.getHeight(tree.getRootNode()) + treeLayout.getRootLength();
+ rootHeightOffset = 0.0;
+
// First of all get the bounds for the unscaled tree
treeBounds = null;
@@ -1755,6 +1813,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// bounds on node bars
if (!isTransformBranchesOn() && nodeBarPainter != null && nodeBarPainter.isVisible()) {
nodeBars.clear();
+
// Iterate though the nodes
for (Node node : tree.getInternalNodes()) {
@@ -1764,24 +1823,29 @@ public class TreePane extends JComponent implements PainterListener, Printable {
nodeBars.put(node, nodeBarPainter.getNodeBar());
}
}
+
if (nodeBarPainter.getMaxHeight() > maxTreeHeight) {
+ rootHeightOffset = Math.max(nodeBarPainter.getMaxHeight() - maxTreeHeight, 0.0);
maxTreeHeight = nodeBarPainter.getMaxHeight();
}
}
+
// totalTreeBounds includes all the stuff which is not in a tree scale (like labels and shapes) but in
// screen pixel scale. This is added to the treeBounds to make space round the edge.
// add the tree bounds
- final Rectangle2D totalTreeBounds = treeBounds.getBounds2D(); // (YH) same as (Rectangle2D) treeBounds.clone();
+ final Rectangle2D totalTreeBounds = treeBounds.getBounds2D();
+// final Rectangle2D totalTreeBounds = new Rectangle2D.Double(0.0, 0.0,treeBounds.getWidth(),treeBounds.getHeight());
+
+ tipLabelWidths.clear();
if (tipLabelPainter != null && tipLabelPainter.isVisible()) {
- tipLabelWidth = 0.0;
- final double tipLabelHeight = tipLabelPainter.getPreferredHeight();
+// calculateMaxTipLabelWidth(g2, tree.getRootNode());
// put this in a recursive function to allow for collapsed node labels
- calibrateTipLabels(g2, tree.getRootNode(), tipLabelHeight, totalTreeBounds);
+ calibrateTipLabels(g2, tree.getRootNode(), totalTreeBounds);
}
if (nodeLabelPainter != null && nodeLabelPainter.isVisible()) {
@@ -1824,10 +1888,24 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
// bounds on nodeShapes
+ if (tipShapePainter != null && tipShapePainter.isVisible()) {
+ tipPoints.clear();
+ // Iterate though the external nodes
+ for (Node node : tree.getExternalNodes()) {
+
+ Rectangle2D shapeBounds = tipShapePainter.calibrate(g2, node);
+ if (shapeBounds != null) {
+ totalTreeBounds.add(shapeBounds);
+
+ // just at the centroid in here as the actual shape will be reconstructed when drawing
+ tipPoints.put(node, new Point2D.Double(shapeBounds.getCenterX(), shapeBounds.getCenterY()));
+ }
+ }
+ }
if (nodeShapePainter != null && nodeShapePainter.isVisible()) {
nodePoints.clear();
- // Iterate though the nodes
- for (Node node : tree.getNodes()) {
+ // Iterate though the internal nodes
+ for (Node node : tree.getInternalNodes()) {
Rectangle2D shapeBounds = nodeShapePainter.calibrate(g2, node);
if (shapeBounds != null) {
@@ -1842,37 +1920,28 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// Now rescale the scale axis
setupScaleAxis();
- totalScaleBounds = new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0);
+ bottomPanelBounds = new Rectangle2D.Double();
double y = totalTreeBounds.getHeight();
for (ScalePainter scalePainter : scalePainters) {
if (scalePainter.isVisible()) {
scalePainter.calibrate(g2, this);
Rectangle2D sb = new Rectangle2D.Double(
- totalTreeBounds.getX(), y,
- totalTreeBounds.getWidth(), scalePainter.getPreferredHeight());
+ treeBounds.getX(), y,
+ treeBounds.getWidth(), scalePainter.getPreferredHeight());
y += sb.getHeight();
- totalScaleBounds.add(sb);
+ bottomPanelBounds.add(sb);
scaleBounds.put(scalePainter, sb);
}
}
- totalTreeBounds.add(totalScaleBounds);
+ leftPanelBounds = new Rectangle2D.Double();
if (legendPainter != null && legendPainter.isVisible()) {
legendPainter.calibrate(g2, this);
final double w2 = legendPainter.getPreferredWidth();
- legendBounds = new Rectangle2D.Double(-w2, 0, w2, treeBounds.getHeight());
- totalTreeBounds.add(legendBounds);
+ legendBounds = new Rectangle2D.Double(0.0, 0.0, w2, height);
+ leftPanelBounds.add(legendBounds);
}
-// // translate treeBounds to the inset within totalTreeBounds
-// treeBounds.setRect(-totalTreeBounds.getX(), -totalTreeBounds.getY(), treeBounds.getWidth(), treeBounds.getHeight());
-//
-// // translate totalTreeBounds so it is at 0, 0
-// totalTreeBounds.setRect(0, 0,
-// totalTreeBounds.getWidth(),
-// totalTreeBounds.getHeight());
-
-
final double availableW = width - insets.left - insets.right;
final double availableH = height - insets.top - insets.bottom;
@@ -1913,8 +1982,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// Get the amount of canvas that is going to be taken up by the tree -
// The rest is taken up by taxon labels which don't scale
- final double w = availableW - xDiff;
- final double h = availableH - yDiff;
+ final double w = availableW - xDiff - leftPanelBounds.getWidth() - rightPanelBounds.getWidth();
+ final double h = availableH - yDiff - topPanelBounds.getHeight() - bottomPanelBounds.getHeight();
double xScale;
double yScale;
@@ -1948,9 +2017,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
yScale = h / treeBounds.getHeight();
// and set the origin in the top left corner
- xOffset = - treeBounds.getX() * xScale;
- yOffset = - treeBounds.getY() * yScale;
-
+ xOffset = -treeBounds.getX() * xScale + (treeBounds.getX() - totalTreeBounds.getX());
+ yOffset = -treeBounds.getY() * yScale + (treeBounds.getY() - totalTreeBounds.getY());
treeScale = xScale;
}
@@ -1958,7 +2026,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// Create the overall transform
transform = new AffineTransform();
- transform.translate(xOffset + insets.left, yOffset + insets.top);
+ transform.translate(xOffset + leftPanelBounds.getWidth(), yOffset + topPanelBounds.getHeight());
transform.scale(xScale, yScale);
// Get the bounds for the newly scaled tree
@@ -1993,6 +2061,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
Rectangle2D shapeBounds = nodeBarPainter.calibrate(g2, node);
if (shapeBounds != null) {
+ shapeBounds = transform.createTransformedShape(shapeBounds).getBounds2D();
treeBounds.add(shapeBounds);
nodeBars.put(node, nodeBarPainter.getNodeBar());
}
@@ -2006,15 +2075,17 @@ public class TreePane extends JComponent implements PainterListener, Printable {
if (tipLabelPainter != null && tipLabelPainter.isVisible()) {
final double labelHeight = tipLabelPainter.getPreferredHeight();
- Rectangle2D labelBounds = new Rectangle2D.Double(0.0, 0.0, tipLabelWidth, labelHeight);
// Iterate though the external nodes with tip labels
for (Node node : treeLayoutCache.getTipLabelPathMap().keySet()) {
// Get the line that represents the path for the tip label
Line2D tipPath = treeLayoutCache.getTipLabelPath(node);
+ final double labelWidth = tipLabelWidths.get(node);
+ Rectangle2D labelBounds = new Rectangle2D.Double(0.0, 0.0, labelWidth, labelHeight);
+
// Work out how it is rotated and create a transform that matches that
- AffineTransform taxonTransform = calculateTransform(transform, tipPath, tipLabelWidth, labelHeight, true);
+ AffineTransform taxonTransform = calculateTransform(transform, tipPath, labelWidth, labelHeight, true);
// Store the transformed bounds in the map for use when selecting
tipLabelBounds.put(node, taxonTransform.createTransformedShape(labelBounds));
@@ -2102,8 +2173,8 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
+ nodeShapeTransforms.clear();
if (nodeShapePainter != null && nodeShapePainter.isVisible()) {
- nodeShapeTransforms.clear();
// Iterate though the nodes
for (Node node : nodePoints.keySet()) {
Line2D shapePath = getTreeLayoutCache().getNodeShapePath(node);
@@ -2112,8 +2183,18 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
}
+ if (tipShapePainter != null && tipShapePainter.isVisible()) {
+ // Iterate though the nodes
+ for (Node node : tipPoints.keySet()) {
+ Line2D shapePath = getTreeLayoutCache().getNodeShapePath(node);
+ if (shapePath != null) {
+ nodeShapeTransforms.put(node, calculateTransform(transform, shapePath));
+ }
+ }
+ }
+
- y = height;
+ y = availableH;
for (ScalePainter scalePainter : scalePainters) {
if (scalePainter.isVisible()) {
scalePainter.calibrate(g2, this);
@@ -2121,22 +2202,25 @@ public class TreePane extends JComponent implements PainterListener, Printable {
}
}
- totalScaleBounds = new Rectangle2D.Double(0, y, treeBounds.getWidth(), 0.0);
+ bottomPanelBounds = new Rectangle2D.Double(0, y, treeBounds.getWidth(), 0.0);
for (ScalePainter scalePainter : scalePainters) {
if (scalePainter.isVisible()) {
scalePainter.calibrate(g2, this);
final double h1 = scalePainter.getPreferredHeight();
Rectangle2D sb = new Rectangle2D.Double(treeBounds.getX(), y, treeBounds.getWidth(), h1);
y += h1;
- totalScaleBounds.add(sb);
+ bottomPanelBounds.add(sb);
scaleBounds.put(scalePainter, sb);
}
}
+ leftPanelBounds = new Rectangle2D.Double(0, 0, 0.0, 0.0);
if (legendPainter != null && legendPainter.isVisible()) {
legendPainter.calibrate(g2, this);
final double w2 = legendPainter.getPreferredWidth();
- legendBounds = new Rectangle2D.Double(0, 0, w2, treeBounds.getHeight());
+ legendBounds = new Rectangle2D.Double(0.0, 0.0, w2, availableH);
+ leftPanelBounds.add(legendBounds);
+
}
calloutPaths.clear();
@@ -2145,34 +2229,49 @@ public class TreePane extends JComponent implements PainterListener, Printable {
calibrated = true;
}
- private void calibrateTipLabels(final Graphics2D g2, final Node node, final double tipLabelHeight, final Rectangle2D totalTreeBounds) {
+// private void calculateMaxTipLabelWidth(final Graphics2D g2, final Node node) {
+//
+// if (tree.isExternal(node) || node.getAttribute(COLLAPSE_ATTRIBUTE_NAME) != null) {
+// tipLabelPainter.calibrate(g2, node);
+// double labelWidth = tipLabelPainter.getPreferredWidth();
+// tipLabelWidths.put(node, labelWidth);
+// maxTipLabelWidth = Math.max(maxTipLabelWidth, labelWidth);
+// } else {
+// for (Node child : tree.getChildren(node)) {
+// calculateMaxTipLabelWidth(g2, child);
+// }
+// }
+// }
+
+ private void calibrateTipLabels(final Graphics2D g2, final Node node, final Rectangle2D totalTreeBounds) {
if (tree.isExternal(node) || node.getAttribute(COLLAPSE_ATTRIBUTE_NAME) != null) {
tipLabelPainter.calibrate(g2, node);
- double width = tipLabelPainter.getPreferredWidth();
- tipLabelWidth = Math.max(tipLabelWidth, width);
+ double labelWidth = tipLabelPainter.getPreferredWidth();
+ double labelHeight = tipLabelPainter.getPreferredHeight();
- Rectangle2D labelBounds = new Rectangle2D.Double(0.0, 0.0, width, tipLabelHeight);
+ tipLabelWidths.put(node, labelWidth);
+ Rectangle2D labelBounds = new Rectangle2D.Double(0.0, 0.0, labelWidth, labelHeight);
// Get the line that represents the path for the taxon label
Line2D taxonPath = treeLayoutCache.getTipLabelPath(node);
if (taxonPath != null) {
// Work out how it is rotated and create a transform that matches that
- AffineTransform taxonTransform = calculateTransform(null, taxonPath, tipLabelWidth, tipLabelHeight, true);
+ AffineTransform taxonTransform = calculateTransform(null, taxonPath, labelWidth, labelHeight, true);
// and add the translated bounds to the overall bounds
totalTreeBounds.add(taxonTransform.createTransformedShape(labelBounds).getBounds2D());
}
} else {
for (Node child : tree.getChildren(node)) {
- calibrateTipLabels(g2, child, tipLabelHeight, totalTreeBounds);
+ calibrateTipLabels(g2, child, totalTreeBounds);
}
}
}
private AffineTransform calculateTransform(AffineTransform globalTransform, Line2D line,
- double width, double height, boolean just) {
+ double width, double height, boolean justify) {
final Point2D origin = line.getP1();
if (globalTransform != null) {
globalTransform.transform(origin, origin);
@@ -2193,7 +2292,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// to shift it by the entire width of the string.
final double ty = origin.getY() - (height / 2.0);
double tx = origin.getX();
- if( just) {
+ if (justify) {
if (line.getX2() > line.getX1()) {
tx += labelXOffset;
} else {
@@ -2227,22 +2326,22 @@ public class TreePane extends JComponent implements PainterListener, Printable {
// Overridden methods to recalibrate tree when bounds change
public void setBounds(int x, int y, int width, int height) {
- calibrated = false;
+ recalibrate();
super.setBounds(x, y, width, height);
}
public void setBounds(Rectangle rectangle) {
- calibrated = false;
+ recalibrate();
super.setBounds(rectangle);
}
public void setSize(Dimension dimension) {
- calibrated = false;
+ recalibrate();
super.setSize(dimension);
}
public void setSize(int width, int height) {
- calibrated = false;
+ recalibrate();
super.setSize(width, height);
}
@@ -2265,16 +2364,18 @@ public class TreePane extends JComponent implements PainterListener, Printable {
private Rectangle2D treeBounds = new Rectangle2D.Double();
private double treeScale;
private double maxTreeHeight;
+ private double rootHeightOffset;
private ScaleAxis scaleAxis = new ScaleAxis(ScaleAxis.AT_DATA, ScaleAxis.AT_DATA);
private double axisOrigin = 0.0;
private TimeScale timeScale = new TimeScale(1.0, 0.0);
+ private boolean isAxisReversed = false;
//private Insets insets = new Insets(0, 0, 0, 0);
private Insets insets = new Insets(6, 6, 6, 6);
private Set<Node> selectedNodes = new HashSet<Node>();
- private Set<Node> selectedTips = new HashSet<Node>();
+ private Set<Node> selectedTips = new LinkedHashSet<Node>();
private double rulerHeight = -1.0;
private Rectangle2D dragRectangle = null;
@@ -2291,18 +2392,18 @@ public class TreePane extends JComponent implements PainterListener, Printable {
private Decorator nodeBackgroundDecorator = null;
- private float labelXOffset = 5.0F;
+ private float labelXOffset = 10.0F;
private LabelPainter<Node> tipLabelPainter = null;
- private double tipLabelWidth;
+ //private double maxTipLabelWidth;
private LabelPainter<Node> nodeLabelPainter = null;
private LabelPainter<Node> branchLabelPainter = null;
private NodeBarPainter nodeBarPainter = null;
private NodeShapePainter nodeShapePainter = null;
+ private NodeShapePainter tipShapePainter = null;
private List<ScalePainter> scalePainters = new ArrayList<ScalePainter>();
- private Rectangle2D totalScaleBounds = null;
private Map<ScalePainter, Rectangle2D> scaleBounds = new HashMap<ScalePainter, Rectangle2D>();
private ScaleGridPainter scaleGridPainter = null;
@@ -2310,6 +2411,11 @@ public class TreePane extends JComponent implements PainterListener, Printable {
private LegendPainter legendPainter = null;
private Rectangle2D legendBounds = new Rectangle2D.Double();
+ private Rectangle2D topPanelBounds = new Rectangle2D.Double();
+ private Rectangle2D leftPanelBounds = new Rectangle2D.Double();
+ private Rectangle2D bottomPanelBounds = new Rectangle2D.Double();
+ private Rectangle2D rightPanelBounds = new Rectangle2D.Double();
+
private BasicStroke branchLineStroke = new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
private BasicStroke calloutStroke = new BasicStroke(0.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[]{0.5f, 2.0f}, 0.0f);
@@ -2325,6 +2431,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
private Map<Node, AffineTransform> tipLabelTransforms = new HashMap<Node, AffineTransform>();
private Map<Node, Shape> tipLabelBounds = new HashMap<Node, Shape>();
+ private Map<Node, Double> tipLabelWidths = new HashMap<Node, Double>();
private Map<Node, Painter.Justification> tipLabelJustifications = new HashMap<Node, Painter.Justification>();
private Map<Node, AffineTransform> nodeLabelTransforms = new HashMap<Node, AffineTransform>();
@@ -2336,6 +2443,7 @@ public class TreePane extends JComponent implements PainterListener, Printable {
private Map<Node, Painter.Justification> branchLabelJustifications = new HashMap<Node, Painter.Justification>();
private Map<Node, Shape> nodeBars = new HashMap<Node, Shape>();
+ private Map<Node, Point2D> tipPoints = new HashMap<Node, Point2D>();
private Map<Node, Point2D> nodePoints = new HashMap<Node, Point2D>();
private Map<Node, AffineTransform> nodeShapeTransforms = new HashMap<Node, AffineTransform>();
diff --git a/src/figtree/treeviewer/TreePaneRollOver.java b/src/figtree/treeviewer/TreePaneRollOver.java
index 4f11036..d11d704 100755
--- a/src/figtree/treeviewer/TreePaneRollOver.java
+++ b/src/figtree/treeviewer/TreePaneRollOver.java
@@ -46,8 +46,7 @@ public class TreePaneRollOver extends StatusProvider.Helper implements MouseMoti
public TreePaneRollOver(TreePane treePane) {
this.treePane = treePane;
treePane.addMouseMotionListener(this);
-
- }
+ }
public void mouseEntered(MouseEvent mouseEvent) {
}
@@ -60,25 +59,29 @@ public class TreePaneRollOver extends StatusProvider.Helper implements MouseMoti
if (tree != null) {
Node node = treePane.getNodeAt((Graphics2D) treePane.getGraphics(), mouseEvent.getPoint());
if (node != null) {
- StringBuilder sb = new StringBuilder();
- if (!tree.isExternal(node)) {
- int n = RootedTreeUtils.getTipCount(tree, node);
- sb.append("Subtree: ").append(n).append(" tips");
- } else {
- sb.append("Tip: \"").append(tree.getTaxon(node).toString()).append("\"");
- }
- sb.append(" [height = ").append(formatter.getFormattedValue(tree.getHeight(node)));
- sb.append(", length = ").append(formatter.getFormattedValue(tree.getLength(node)));
- sb.append("]");
- fireStatusChanged(StatusPanel.NORMAL, sb.toString());
+ fireStatusChanged(StatusPanel.NORMAL, getNodeText(tree, node));
} else {
- fireStatusChanged(StatusPanel.NORMAL, " ");
+ fireStatusChanged(StatusPanel.NORMAL, getNodeText(tree, tree.getRootNode()));
}
} else {
fireStatusChanged(StatusPanel.NORMAL, " ");
}
}
+ private String getNodeText(RootedTree tree, Node node) {
+ StringBuilder sb = new StringBuilder();
+ if (!tree.isExternal(node)) {
+ int n = RootedTreeUtils.getTipCount(tree, node);
+ sb.append(tree.isRoot(node) ? "Tree: " : "Subtree: ").append(n).append(" tips");
+ } else {
+ sb.append("Tip: \"").append(tree.getTaxon(node).toString()).append("\"");
+ }
+ sb.append(" [height = ").append(formatter.getFormattedValue(tree.getHeight(node)));
+ sb.append(", length = ").append(formatter.getFormattedValue(tree.getLength(node)));
+ sb.append("]");
+ return sb.toString();
+ }
+
public void mouseDragged(MouseEvent mouseEvent) {
}
diff --git a/src/figtree/treeviewer/decorators/ContinuousScale.java b/src/figtree/treeviewer/decorators/ContinuousScale.java
index 20e91b8..abade31 100755
--- a/src/figtree/treeviewer/decorators/ContinuousScale.java
+++ b/src/figtree/treeviewer/decorators/ContinuousScale.java
@@ -43,7 +43,7 @@ public class ContinuousScale {
*/
public ContinuousScale(String settings) {
if (settings.startsWith("{")) {
- settings = settings.substring(1, settings.length());
+ settings = settings.substring(1, settings.length());
}
if (settings.endsWith("}")) {
settings = settings.substring(0, settings.length() - 1);
@@ -88,47 +88,46 @@ public class ContinuousScale {
// First collect the set of all attribute values
Set<Object> values = new TreeSet<Object>();
- for (Attributable item : items) {
- Object value = item.getAttribute(attributeName);
- if (value != null) {
- values.add(value);
- }
- }
boolean isNumber = true;
// Find the range of numbers
- for (Object value : values) {
- double realValue = -1.0;
-
- if (value instanceof Boolean) {
- realValue = ((Boolean)value ? 1 : 0);
- } else if (value instanceof Number) {
- realValue = ((Number)value).doubleValue();
- } else if (value instanceof String) {
- // it is a string but it could still code for
- // a boolean, integer or real
- if (value.toString().equalsIgnoreCase("true")) {
- realValue = 1;
- } else if (value.toString().equalsIgnoreCase("false")) {
- realValue = 0;
- } else {
- try {
- realValue = Double.parseDouble(value.toString());
- } catch(NumberFormatException nfe) {
- isNumber = false;
+ for (Attributable item : items) {
+ Object value = item.getAttribute(attributeName);
+ if (value != null) {
+
+ double realValue = -1.0;
+
+ if (value instanceof Boolean) {
+ realValue = ((Boolean)value ? 1 : 0);
+ } else if (value instanceof Number) {
+ realValue = ((Number)value).doubleValue();
+ } else if (value instanceof String) {
+ // it is a string but it could still code for
+ // a boolean, integer or real
+ if (value.toString().equalsIgnoreCase("true")) {
+ realValue = 1;
+ } else if (value.toString().equalsIgnoreCase("false")) {
+ realValue = 0;
+ } else {
+ try {
+ realValue = Double.parseDouble(value.toString());
+ } catch(NumberFormatException nfe) {
+ isNumber = false;
+ }
}
}
- }
- if (isNumber) {
- if (realValue < minValue) {
- minValue = realValue;
- }
- if (realValue > maxValue) {
- maxValue = realValue;
- }
+ if (isNumber) {
+ if (realValue < minValue) {
+ minValue = realValue;
+ }
+ if (realValue > maxValue) {
+ maxValue = realValue;
+ }
+ }
+ values.add(realValue);
}
}
diff --git a/src/figtree/treeviewer/painters/LegendPainter.java b/src/figtree/treeviewer/painters/LegendPainter.java
index b96aacf..8e2b822 100755
--- a/src/figtree/treeviewer/painters/LegendPainter.java
+++ b/src/figtree/treeviewer/painters/LegendPainter.java
@@ -122,6 +122,11 @@ public class LegendPainter extends LabelPainter<TreePane> implements ScalePainte
}
String attribute = colourDecorator.getAttributeName();
+ if (TreePane.DEBUG_OUTLINE) {
+ g2.setPaint(Color.red);
+ g2.draw(bounds);
+ }
+
Font oldFont = g2.getFont();
Paint oldPaint = g2.getPaint();
Stroke oldStroke = g2.getStroke();
diff --git a/src/figtree/treeviewer/painters/NodeBarController.java b/src/figtree/treeviewer/painters/NodeBarController.java
index ff47690..12e27a5 100755
--- a/src/figtree/treeviewer/painters/NodeBarController.java
+++ b/src/figtree/treeviewer/painters/NodeBarController.java
@@ -50,7 +50,7 @@ import jebl.util.Attributable;
*/
public class NodeBarController extends AbstractController {
- private static Preferences PREFS = Preferences.userNodeForPackage(NodeBarController.class);
+ private static Preferences PREFS = Preferences.userNodeForPackage(TreeViewer.class);
private static final String NODE_BARS_KEY = "nodeBars";
public static final String DISPLAY_ATTRIBUTE_KEY = "displayAttribute";
diff --git a/src/figtree/treeviewer/painters/NodeShapeController.java b/src/figtree/treeviewer/painters/NodeShapeController.java
index c86fbbc..7b8103a 100755
--- a/src/figtree/treeviewer/painters/NodeShapeController.java
+++ b/src/figtree/treeviewer/painters/NodeShapeController.java
@@ -24,12 +24,12 @@ import figtree.treeviewer.AttributeColourController;
import figtree.treeviewer.TreeViewer;
import figtree.treeviewer.decorators.Decorator;
import jam.controlpalettes.AbstractController;
-import jam.controlpalettes.ControllerListener;
import jam.panels.OptionsPanel;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map;
@@ -49,8 +49,14 @@ import figtree.treeviewer.ControllerOptionsPanel;
*/
public class NodeShapeController extends AbstractController {
- private static Preferences PREFS = Preferences.userNodeForPackage(NodeBarController.class);
+ public enum NodeType {
+ INTERNAL, EXTERNAL, BOTH
+ }
+
+ private static Preferences PREFS = Preferences.userNodeForPackage(TreeViewer.class);
+ private static final String IS_EXTERNAL = "isExternal";
+ private static final String IS_INTERNAL = "isInternal";
private static final String NODE_SHAPE_KEY = "nodeShape";
public static final String SHAPE_TYPE_KEY = "shapeType";
public static final String SCALE_TYPE_KEY = "scaleType";
@@ -59,18 +65,19 @@ public class NodeShapeController extends AbstractController {
private static final String SHAPE_SIZE_KEY = "size";
private static final String SHAPE_MIN_SIZE_KEY = "minSize";
- public NodeShapeController(String title, final NodeShapePainter nodeShapePainter,
+ public NodeShapeController(final String title, final NodeType type, final NodeShapePainter nodeShapePainter,
final AttributeColourController colourController,
final TreeViewer treeViewer) {
this.title = title;
- this.nodeShapePainter = nodeShapePainter;
+
+ this.type = type;
final float defaultShapeSize = PREFS.getFloat(SHAPE_SIZE_KEY, (float)NodeShapePainter.MAX_SIZE);
optionsPanel = new ControllerOptionsPanel(2, 2);
titleCheckBox = new JCheckBox(getTitle());
- titleCheckBox.setSelected(this.nodeShapePainter.isVisible());
+ titleCheckBox.setSelected(nodeShapePainter.isVisible());
titleCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
@@ -79,6 +86,35 @@ public class NodeShapeController extends AbstractController {
}
});
+ final ControllerOptionsPanel nodeCheckPanel;
+ if (type == NodeType.BOTH) {
+ externalNodeCheck = new JCheckBox("external");
+ internalNodeCheck = new JCheckBox("internal");
+ ActionListener listener = new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ nodeShapePainter.setNodeType(externalNodeCheck.isSelected(), internalNodeCheck.isSelected());
+ }
+ };
+ externalNodeCheck.addActionListener(listener);
+ internalNodeCheck.addActionListener(listener);
+ nodeCheckPanel = new ControllerOptionsPanel(2, 2);
+ nodeCheckPanel.setBorder(BorderFactory.createEmptyBorder());
+ nodeCheckPanel.addSpanningComponent(externalNodeCheck);
+ nodeCheckPanel.addSpanningComponent(internalNodeCheck);
+
+ externalNodeCheck.setSelected(nodeShapePainter.isExternal());
+ internalNodeCheck.setSelected(nodeShapePainter.isInternal());
+ } else {
+ nodeCheckPanel = null;
+ externalNodeCheck = null;
+ internalNodeCheck = null;
+ if (type == NodeType.EXTERNAL) {
+ nodeShapePainter.setNodeType(true, false);
+ } else if (type == NodeType.INTERNAL) {
+ nodeShapePainter.setNodeType(false, true);
+ }
+ }
+
shapeTypeCombo = new JComboBox(NodeShapePainter.ShapeType.values());
shapeTypeCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
@@ -116,6 +152,33 @@ public class NodeShapeController extends AbstractController {
}
});
+ outlineStrokeCombo = new JComboBox(new String[] {"None", "0.25", "0.5", "1.0", "2.0", "3.0", "4.0", "5.0"});
+ outlineStrokeCombo.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ nodeShapePainter.setOutline((outlineStrokeCombo.getSelectedIndex() == 0 ? 0.0f :
+ Float.parseFloat(outlineStrokeCombo.getSelectedItem().toString())),
+ (Paint)outlinePaintCombo.getSelectedItem()
+ );
+ }
+ });
+
+ final Paint[] outlinePaints = {Color.black, Color.white};
+ outlinePaintCombo = new JComboBox(new String[] {"black", "white"});
+ outlinePaintCombo.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ nodeShapePainter.setOutline((outlineStrokeCombo.getSelectedIndex() == 0 ? 0.0f :
+ Float.parseFloat(outlineStrokeCombo.getSelectedItem().toString())),
+ outlinePaints[outlinePaintCombo.getSelectedIndex()]
+ );
+ }
+ });
+
+ final JLabel label8;
+ if (type == NodeType.BOTH) {
+ label8 = optionsPanel.addComponentWithLabel("Show:", nodeCheckPanel);
+ } else {
+ label8 = null;
+ }
final JLabel label1 = optionsPanel.addComponentWithLabel("Shape:", shapeTypeCombo);
final JLabel label2 = optionsPanel.addComponentWithLabel("Max size:", shapeSizeSpinner);
@@ -126,6 +189,9 @@ public class NodeShapeController extends AbstractController {
final JLabel label6 = optionsPanel.addComponentWithLabel("Colour by:", colourAttributeCombo);
final JLabel label7 = optionsPanel.addComponentWithLabel("Setup:", setupColourButton);
+ final JLabel label9 = optionsPanel.addComponentWithLabel("Outline width:", outlineStrokeCombo);
+ final JLabel label10 = optionsPanel.addComponentWithLabel("Outline colour:", outlinePaintCombo);
+
new AttributeComboHelper(colourAttributeCombo, treeViewer, "User selection").addListener(new AttributeComboHelperListener() {
@Override
public void attributeComboChanged() {
@@ -162,6 +228,11 @@ public class NodeShapeController extends AbstractController {
addComponent(label1);
addComponent(shapeTypeCombo);
+ if (type == NodeType.BOTH) {
+ addComponent(label8);
+ addComponent(externalNodeCheck);
+ addComponent(internalNodeCheck);
+ }
addComponent(label2);
addComponent(shapeSizeSpinner);
addComponent(label3);
@@ -174,6 +245,10 @@ public class NodeShapeController extends AbstractController {
addComponent(colourAttributeCombo);
addComponent(label7);
addComponent(setupColourButton);
+ addComponent(label9);
+ addComponent(outlineStrokeCombo);
+ addComponent(label10);
+ addComponent(outlinePaintCombo);
enableComponents(titleCheckBox.isSelected());
titleCheckBox.addChangeListener(new ChangeListener() {
@@ -206,40 +281,55 @@ public class NodeShapeController extends AbstractController {
}
public void setSettings(Map<String,Object> settings) {
- titleCheckBox.setSelected((Boolean)settings.get(NODE_SHAPE_KEY + "." + IS_SHOWN));
-
- shapeTypeCombo.setSelectedItem((NodeShapePainter.ShapeType.valueOf(settings.get(NODE_SHAPE_KEY + "." + SHAPE_TYPE_KEY).toString().toUpperCase())));
- scaleTypeCombo.setSelectedItem((NodeShapePainter.ScaleType.valueOf(settings.get(NODE_SHAPE_KEY + "." + SCALE_TYPE_KEY).toString().toUpperCase())));
- colourAttributeCombo.setSelectedItem((String) settings.get(NODE_SHAPE_KEY + "." + COLOUR_ATTRIBUTE_KEY));
- sizeAttributeCombo.setSelectedItem((String) settings.get(NODE_SHAPE_KEY + "." + SIZE_ATTRIBUTE_KEY));
- shapeSizeSpinner.setValue((Double)settings.get(NODE_SHAPE_KEY + "." + SHAPE_SIZE_KEY));
- shapeMinSizeSpinner.setValue((Double) settings.get(NODE_SHAPE_KEY + "." + SHAPE_MIN_SIZE_KEY));
+ String key = NODE_SHAPE_KEY + (type == NodeType.INTERNAL ? "Internal" : (type == NodeType.EXTERNAL ? "External" : ""));
+
+ titleCheckBox.setSelected((Boolean)settings.get(key + "." + IS_SHOWN));
+
+ if (type == NodeType.BOTH) {
+ externalNodeCheck.setSelected((Boolean) settings.get(key + "." + IS_EXTERNAL));
+ internalNodeCheck.setSelected((Boolean) settings.get(key + "." + IS_INTERNAL));
+ }
+ shapeTypeCombo.setSelectedItem((NodeShapePainter.ShapeType.valueOf(settings.get(key + "." + SHAPE_TYPE_KEY).toString().toUpperCase())));
+ scaleTypeCombo.setSelectedItem((NodeShapePainter.ScaleType.valueOf(settings.get(key + "." + SCALE_TYPE_KEY).toString().toUpperCase())));
+ colourAttributeCombo.setSelectedItem((String) settings.get(key + "." + COLOUR_ATTRIBUTE_KEY));
+ sizeAttributeCombo.setSelectedItem((String) settings.get(key + "." + SIZE_ATTRIBUTE_KEY));
+ shapeSizeSpinner.setValue((Double)settings.get(key + "." + SHAPE_SIZE_KEY));
+ shapeMinSizeSpinner.setValue((Double) settings.get(key + "." + SHAPE_MIN_SIZE_KEY));
}
public void getSettings(Map<String, Object> settings) {
- settings.put(NODE_SHAPE_KEY + "." + IS_SHOWN, titleCheckBox.isSelected());
- settings.put(NODE_SHAPE_KEY + "." + SHAPE_TYPE_KEY, shapeTypeCombo.getSelectedItem());
- settings.put(NODE_SHAPE_KEY + "." + SCALE_TYPE_KEY, scaleTypeCombo.getSelectedItem());
- settings.put(NODE_SHAPE_KEY + "." + COLOUR_ATTRIBUTE_KEY, colourAttributeCombo.getSelectedItem());
- settings.put(NODE_SHAPE_KEY + "." + SIZE_ATTRIBUTE_KEY, sizeAttributeCombo.getSelectedItem());
- settings.put(NODE_SHAPE_KEY + "." + SHAPE_SIZE_KEY, shapeSizeSpinner.getValue());
- settings.put(NODE_SHAPE_KEY + "." + SHAPE_MIN_SIZE_KEY, shapeMinSizeSpinner.getValue());
+ String key = NODE_SHAPE_KEY + (type == NodeType.INTERNAL ? "Internal" : (type == NodeType.EXTERNAL ? "External" : ""));
+ settings.put(key + "." + IS_SHOWN, titleCheckBox.isSelected());
+ if (type == NodeType.BOTH) {
+ settings.put(key + "." + IS_EXTERNAL, externalNodeCheck.isSelected());
+ settings.put(key + "." + IS_INTERNAL, internalNodeCheck.isSelected());
+ }
+ settings.put(key + "." + SHAPE_TYPE_KEY, shapeTypeCombo.getSelectedItem());
+ settings.put(key + "." + SCALE_TYPE_KEY, scaleTypeCombo.getSelectedItem());
+ settings.put(key + "." + COLOUR_ATTRIBUTE_KEY, colourAttributeCombo.getSelectedItem());
+ settings.put(key + "." + SIZE_ATTRIBUTE_KEY, sizeAttributeCombo.getSelectedItem());
+ settings.put(key + "." + SHAPE_SIZE_KEY, shapeSizeSpinner.getValue());
+ settings.put(key + "." + SHAPE_MIN_SIZE_KEY, shapeMinSizeSpinner.getValue());
}
private final JCheckBox titleCheckBox;
private final OptionsPanel optionsPanel;
+ private final JCheckBox externalNodeCheck;
+ private final JCheckBox internalNodeCheck;
private final JComboBox shapeTypeCombo;
private final JComboBox scaleTypeCombo;
private final JComboBox sizeAttributeCombo;
private final JComboBox colourAttributeCombo;
private final JSpinner shapeSizeSpinner;
private final JSpinner shapeMinSizeSpinner;
+ private final JComboBox outlineStrokeCombo;
+ private final JComboBox outlinePaintCombo;
public String getTitle() {
return title;
}
private final String title;
- private final NodeShapePainter nodeShapePainter;
+ private final NodeType type;
}
diff --git a/src/figtree/treeviewer/painters/NodeShapePainter.java b/src/figtree/treeviewer/painters/NodeShapePainter.java
index 05e724f..0baf3bf 100755
--- a/src/figtree/treeviewer/painters/NodeShapePainter.java
+++ b/src/figtree/treeviewer/painters/NodeShapePainter.java
@@ -117,6 +117,20 @@ public class NodeShapePainter extends NodePainter {
firePainterChanged();
}
+ public void setNodeType(boolean external, boolean internal) {
+ this.external = external;
+ this.internal = internal;
+ firePainterChanged();
+ }
+
+ public boolean isExternal() {
+ return external;
+ }
+
+ public boolean isInternal() {
+ return internal;
+ }
+
public double getPreferredWidth() {
return 1.0;
}
@@ -147,9 +161,11 @@ public class NodeShapePainter extends NodePainter {
g2.setPaint(paint);
g2.fill(nodeShape);
- g2.setPaint(Color.black);
- g2.setStroke(new BasicStroke(0.5F));
- g2.draw(nodeShape);
+ if (outlineStroke > 0.0F) {
+ g2.setPaint(outlinePaint);
+ g2.setStroke(new BasicStroke(outlineStroke));
+ g2.draw(nodeShape);
+ }
}
/**
@@ -184,6 +200,12 @@ public class NodeShapePainter extends NodePainter {
firePainterChanged();
}
+ public void setOutline(final float outlineStroke, final Paint outlinePaint) {
+ this.outlineStroke = outlineStroke;
+ this.outlinePaint = outlinePaint;
+ firePainterChanged();
+ }
+
private Shape createNodeShape(Node node, double x, double y) {
double size = maxSize;
@@ -247,8 +269,14 @@ public class NodeShapePainter extends NodePainter {
private ScaleType scaleType = ScaleType.WIDTH;
private String sizeAttribute = null;
+ private boolean external = true;
+ private boolean internal = true;
+
private Decorator colourDecorator = null;
private ContinuousScale sizeScale = null;
+ private float outlineStroke = 0.5f;
+ private Paint outlinePaint = Color.black;
+
private TreePane treePane;
}
diff --git a/src/figtree/treeviewer/painters/ScaleAxisPainter.java b/src/figtree/treeviewer/painters/ScaleAxisPainter.java
index d2f05a0..fed070a 100755
--- a/src/figtree/treeviewer/painters/ScaleAxisPainter.java
+++ b/src/figtree/treeviewer/painters/ScaleAxisPainter.java
@@ -192,55 +192,55 @@ public class ScaleAxisPainter extends LabelPainter<TreePane> implements ScalePai
protected void paintAxis(Graphics2D g2, Rectangle2D axisBounds)
{
- ScaleAxis axis = treePane.getScaleAxis();
+ ScaleAxis axis = treePane.getScaleAxis();
- g2.setPaint(getForeground());
- g2.setStroke(getScaleBarStroke());
+ g2.setPaint(getForeground());
+ g2.setStroke(getScaleBarStroke());
- double minX = treePane.scaleOnAxis(axis.getMinAxis());
- double maxX = treePane.scaleOnAxis(axis.getMaxAxis());
+ double minX = treePane.scaleOnAxis(axis.getMinAxis());
+ double maxX = treePane.scaleOnAxis(axis.getMaxAxis());
- Line2D line = new Line2D.Double(minX, axisBounds.getMinY(), maxX, axisBounds.getMinY());
- g2.draw(line);
+ Line2D line = new Line2D.Double(minX, axisBounds.getY() + topMargin, maxX, axisBounds.getY() + topMargin);
+ g2.draw(line);
- int n1 = axis.getMajorTickCount();
- int n2, i, j;
+ int n1 = axis.getMajorTickCount();
+ int n2, i, j;
- n2 = axis.getMinorTickCount(-1);
- if (axis.getLabelFirst()) { // Draw first minor tick as a major one (with a label)
+ n2 = axis.getMinorTickCount(-1);
+ if (axis.getLabelFirst()) { // Draw first minor tick as a major one (with a label)
- paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, -1));
+ paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, -1));
- for (j = 1; j < n2; j++) {
- paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
- }
- } else {
+ for (j = 1; j < n2; j++) {
+ paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
+ }
+ } else {
- for (j = 0; j < n2; j++) {
- paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
- }
- }
+ for (j = 0; j < n2; j++) {
+ paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
+ }
+ }
- for (i = 0; i < n1; i++) {
+ for (i = 0; i < n1; i++) {
- paintMajorTick(g2, axisBounds, axis, axis.getMajorTickValue(i));
- n2 = axis.getMinorTickCount(i);
+ paintMajorTick(g2, axisBounds, axis, axis.getMajorTickValue(i));
+ n2 = axis.getMinorTickCount(i);
- if (i == (n1-1) && axis.getLabelLast()) { // Draw last minor tick as a major one
+ if (i == (n1-1) && axis.getLabelLast()) { // Draw last minor tick as a major one
- paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, i));
+ paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, i));
- for (j = 1; j < n2; j++) {
- paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
- }
- } else {
+ for (j = 1; j < n2; j++) {
+ paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
+ }
+ } else {
- for (j = 0; j < n2; j++) {
- paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
- }
- }
- }
- }
+ for (j = 0; j < n2; j++) {
+ paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
+ }
+ }
+ }
+ }
protected void paintMajorTick(Graphics2D g2, Rectangle2D axisBounds, ScaleAxis axis, double value)
{
@@ -251,12 +251,12 @@ public class ScaleAxisPainter extends LabelPainter<TreePane> implements ScalePai
String label = getNumberFormat().format(value);
double pos = treePane.scaleOnAxis(value);
- Line2D line = new Line2D.Double(pos, axisBounds.getMinY(), pos, axisBounds.getMinY() + majorTickSize);
+ Line2D line = new Line2D.Double(pos, axisBounds.getMinY() + topMargin, pos, axisBounds.getMinY() + majorTickSize + topMargin);
g2.draw(line);
g2.setPaint(getForeground());
double width = g2.getFontMetrics().stringWidth(label);
- g2.drawString(label, (float)(pos - (width / 2)), (float)(axisBounds.getMinY() + tickLabelOffset));
+ g2.drawString(label, (float)(pos - (width / 2)), (float)(axisBounds.getMinY() + tickLabelOffset + topMargin));
}
protected void paintMinorTick(Graphics2D g2, Rectangle2D axisBounds, double value)
@@ -267,7 +267,7 @@ public class ScaleAxisPainter extends LabelPainter<TreePane> implements ScalePai
double pos = treePane.scaleOnAxis(value);
- Line2D line = new Line2D.Double(pos, axisBounds.getMinY(), pos, axisBounds.getMinY() + minorTickSize);
+ Line2D line = new Line2D.Double(pos, axisBounds.getMinY() + topMargin, pos, axisBounds.getMinY() + minorTickSize + topMargin);
g2.draw(line);
}
diff --git a/src/figtree/treeviewer/painters/ScaleAxisPainterController.java b/src/figtree/treeviewer/painters/ScaleAxisPainterController.java
index c3bd7de..60c36ab 100755
--- a/src/figtree/treeviewer/painters/ScaleAxisPainterController.java
+++ b/src/figtree/treeviewer/painters/ScaleAxisPainterController.java
@@ -314,7 +314,7 @@ public class ScaleAxisPainterController extends AbstractController {
titleCheckBox.setSelected((Boolean)settings.get(SCALE_AXIS_KEY + "." + IS_SHOWN));
reverseAxisCheck.setSelected((Boolean)settings.get(SCALE_AXIS_KEY + "." + REVERSE_AXIS_KEY));
showGridCheck.setSelected((Boolean)settings.get(SCALE_AXIS_KEY + "." + SHOW_GRID_KEY));
-// minorTicksText.setValue((Double)settings.get(SCALE_AXIS_KEY + "." + MINOR_TICKS_KEY));
+ minorTicksText.setValue((Double)settings.get(SCALE_AXIS_KEY + "." + MINOR_TICKS_KEY));
majorTicksText.setValue((Double)settings.get(SCALE_AXIS_KEY + "." + MAJOR_TICKS_KEY));
originText.setValue((Double)settings.get(SCALE_AXIS_KEY + "." + ORIGIN_KEY));
autoScaleCheck.setSelected((Boolean)settings.get(SCALE_AXIS_KEY + "." + AUTOMATIC_SCALE_KEY));
@@ -329,7 +329,7 @@ public class ScaleAxisPainterController extends AbstractController {
settings.put(SCALE_AXIS_KEY + "." + REVERSE_AXIS_KEY, reverseAxisCheck.isSelected());
settings.put(SCALE_AXIS_KEY + "." + SHOW_GRID_KEY, showGridCheck.isSelected());
settings.put(SCALE_AXIS_KEY + "." + AUTOMATIC_SCALE_KEY, autoScaleCheck.isSelected());
-// settings.put(SCALE_AXIS_KEY + "." + MINOR_TICKS_KEY, minorTicksText.getValue());
+ settings.put(SCALE_AXIS_KEY + "." + MINOR_TICKS_KEY, minorTicksText.getValue());
settings.put(SCALE_AXIS_KEY + "." + MAJOR_TICKS_KEY, majorTicksText.getValue());
settings.put(SCALE_AXIS_KEY + "." + ORIGIN_KEY, originText.getValue());
settings.put(SCALE_AXIS_KEY + "." + FONT_SIZE_KEY, fontSizeSpinner.getValue());
diff --git a/src/figtree/treeviewer/painters/ScaleGridPainter.java b/src/figtree/treeviewer/painters/ScaleGridPainter.java
index 7236b45..8a65b58 100755
--- a/src/figtree/treeviewer/painters/ScaleGridPainter.java
+++ b/src/figtree/treeviewer/painters/ScaleGridPainter.java
@@ -57,7 +57,7 @@ public class ScaleGridPainter extends LabelPainter<TreePane> implements ScalePai
preferredWidth = treePane.getTreeBounds().getWidth();
preferredHeight = treePane.getTreeBounds().getHeight();
- return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
+ return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
}
public void paint(Graphics2D g2, TreePane treePane, Justification justification, Rectangle2D bounds) {
@@ -66,7 +66,7 @@ public class ScaleGridPainter extends LabelPainter<TreePane> implements ScalePai
Stroke oldStroke = g2.getStroke();
if (TreePane.DEBUG_OUTLINE) {
- g2.setPaint(Color.red);
+ g2.setPaint(Color.blue);
g2.draw(bounds);
}
diff --git a/src/figtree/treeviewer/treelayouts/AbstractTreeLayout.java b/src/figtree/treeviewer/treelayouts/AbstractTreeLayout.java
index 3ff5057..225a115 100755
--- a/src/figtree/treeviewer/treelayouts/AbstractTreeLayout.java
+++ b/src/figtree/treeviewer/treelayouts/AbstractTreeLayout.java
@@ -35,15 +35,6 @@ import java.util.Set;
*/
public abstract class AbstractTreeLayout implements TreeLayout {
private double rootLength = 0.0;
- private boolean isAxisReversed;
-
- public boolean isAxisReversed() {
- return isAxisReversed;
- }
-
- public void setAxisReversed(final boolean axisReversed) {
- isAxisReversed = axisReversed;
- }
public double getRootLength() {
return rootLength;
diff --git a/src/figtree/treeviewer/treelayouts/PolarTreeLayout.java b/src/figtree/treeviewer/treelayouts/PolarTreeLayout.java
index 1cadcd3..3ae9350 100755
--- a/src/figtree/treeviewer/treelayouts/PolarTreeLayout.java
+++ b/src/figtree/treeviewer/treelayouts/PolarTreeLayout.java
@@ -93,9 +93,6 @@ public class PolarTreeLayout extends AbstractTreeLayout {
public Shape getAxisLine(double height) {
double x = height;
- if (isAxisReversed()) {
- x = maxXPosition - x;
- }
return new Ellipse2D.Double(-x, -x, x * 2.0, x * 2.0);
}
diff --git a/src/figtree/treeviewer/treelayouts/RectilinearTreeLayout.java b/src/figtree/treeviewer/treelayouts/RectilinearTreeLayout.java
index 21a6b27..47be98e 100755
--- a/src/figtree/treeviewer/treelayouts/RectilinearTreeLayout.java
+++ b/src/figtree/treeviewer/treelayouts/RectilinearTreeLayout.java
@@ -85,9 +85,6 @@ public class RectilinearTreeLayout extends AbstractTreeLayout {
public Shape getAxisLine(double height) {
double x = height;
- if (isAxisReversed()) {
- x = maxXPosition - x;
- }
double y1 = 0.0;
double y2 = 1.0;
return new Line2D.Double(x, y1, x, y2);
@@ -95,9 +92,6 @@ public class RectilinearTreeLayout extends AbstractTreeLayout {
public Shape getHeightArea(double height1, double height2) {
double x = height1;
- if (isAxisReversed()) {
- x = maxXPosition - x;
- }
double y = 0.0;
double w = Math.abs(height2 - height1);
double h = 1.0;
diff --git a/src/figtree/treeviewer/treelayouts/TreeLayout.java b/src/figtree/treeviewer/treelayouts/TreeLayout.java
index 1b62e6d..8cac641 100755
--- a/src/figtree/treeviewer/treelayouts/TreeLayout.java
+++ b/src/figtree/treeviewer/treelayouts/TreeLayout.java
@@ -82,11 +82,6 @@ public interface TreeLayout {
void setRootLength(double rootLength);
- boolean isAxisReversed();
-
- void setAxisReversed(final boolean axisReversed);
-
-
/**
* Return whether this layout is showing a branch colouring
* @return showing colouring?
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/figtree.git
More information about the debian-med-commit
mailing list