imported Vamsas bindings and alpha vamsas client code from VamJalview cvs branch...
authorjprocter <Jim Procter>
Mon, 9 Oct 2006 16:13:13 +0000 (16:13 +0000)
committerjprocter <Jim Procter>
Mon, 9 Oct 2006 16:13:13 +0000 (16:13 +0000)
lib/vamsas-client.jar [new file with mode: 0644]
src/jalview/analysis/NJTree.java
src/jalview/bin/Cache.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/Desktop.java
src/jalview/gui/TreePanel.java
src/jalview/gui/VamsasClient.java [new file with mode: 0755]
src/jalview/io/VamsasDatastore.java [new file with mode: 0755]
src/jalview/jbgui/GDesktop.java

diff --git a/lib/vamsas-client.jar b/lib/vamsas-client.jar
new file mode 100644 (file)
index 0000000..24a4d00
Binary files /dev/null and b/lib/vamsas-client.jar differ
index a58b6f7..1ab9c02 100755 (executable)
-/*\r
-* Jalview - A Sequence Alignment Editor and Viewer\r
-* Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
-*\r
-* This program is free software; you can redistribute it and/or\r
-* modify it under the terms of the GNU General Public License\r
-* as published by the Free Software Foundation; either version 2\r
-* of the License, or (at your option) any later version.\r
-*\r
-* This program is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with this program; if not, write to the Free Software\r
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
-*/\r
-package jalview.analysis;\r
-\r
-import jalview.datamodel.*;\r
-\r
-import jalview.io.NewickFile;\r
-\r
-import jalview.schemes.ResidueProperties;\r
-\r
-import jalview.util.*;\r
-\r
-import java.util.*;\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class NJTree\r
-{\r
-    Vector cluster;\r
-    SequenceI[] sequence;\r
-\r
-    //SequenceData is a string representation of what the user\r
-    //sees. The display may contain hidden columns.\r
-    public AlignmentView seqData=null;\r
-\r
-    int[] done;\r
-    int noseqs;\r
-    int noClus;\r
-    float[][] distance;\r
-    int mini;\r
-    int minj;\r
-    float ri;\r
-    float rj;\r
-    Vector groups = new Vector();\r
-    SequenceNode maxdist;\r
-    SequenceNode top;\r
-    float maxDistValue;\r
-    float maxheight;\r
-    int ycount;\r
-    Vector node;\r
-    String type;\r
-    String pwtype;\r
-    Object found = null;\r
-    Object leaves = null;\r
-\r
-    boolean hasDistances = true; // normal case for jalview trees\r
-    boolean hasBootstrap = false; // normal case for jalview trees\r
-\r
-    private boolean hasRootDistance = true;\r
-\r
-    /**\r
-     * Create a new NJTree object with leaves associated with sequences in seqs,\r
-     * and original alignment data represented by Cigar strings.\r
-     * @param seqs SequenceI[]\r
-     * @param odata Cigar[]\r
-     * @param treefile NewickFile\r
-     */\r
-    public NJTree(SequenceI[] seqs, AlignmentView odata, NewickFile treefile) {\r
-      this(seqs, treefile);\r
-      if (odata!=null)\r
-        seqData = odata;\r
-      /*\r
-      sequenceString = new String[odata.length];\r
-      char gapChar = jalview.util.Comparison.GapChars.charAt(0);\r
-      for (int i = 0; i < odata.length; i++)\r
-      {\r
-        SequenceI oseq_aligned = odata[i].getSeq(gapChar);\r
-          sequenceString[i] = oseq_aligned.getSequence();\r
-      } */\r
-    }\r
-\r
-    /**\r
-     * Creates a new NJTree object from a tree from an external source\r
-     *\r
-     * @param seqs SequenceI which should be associated with leafs of treefile\r
-     * @param treefile A parsed tree\r
-     */\r
-    public NJTree(SequenceI[] seqs,  NewickFile treefile)\r
-    {\r
-        this.sequence = seqs;\r
-        top = treefile.getTree();\r
-\r
-        /**\r
-         * There is no dependent alignment to be recovered from an\r
-         * imported tree.\r
-         *\r
-        if (sequenceString == null)\r
-        {\r
-          sequenceString = new String[seqs.length];\r
-          for (int i = 0; i < seqs.length; i++)\r
-          {\r
-            sequenceString[i] = seqs[i].getSequence();\r
-          }\r
-        }\r
-        */\r
-\r
-        hasDistances = treefile.HasDistances();\r
-        hasBootstrap = treefile.HasBootstrap();\r
-        hasRootDistance = treefile.HasRootDistance();\r
-\r
-        maxheight = findHeight(top);\r
-\r
-        SequenceIdMatcher algnIds = new SequenceIdMatcher(seqs);\r
-\r
-        Vector leaves = new Vector();\r
-        findLeaves(top, leaves);\r
-\r
-        int i = 0;\r
-        int namesleft = seqs.length;\r
-\r
-        SequenceNode j;\r
-        SequenceI nam;\r
-        String realnam;\r
-\r
-        while (i < leaves.size())\r
-        {\r
-            j = (SequenceNode) leaves.elementAt(i++);\r
-            realnam = j.getName();\r
-            nam = null;\r
-\r
-            if (namesleft > -1)\r
-            {\r
-                nam = algnIds.findIdMatch(realnam);\r
-            }\r
-\r
-            if (nam != null)\r
-            {\r
-                j.setElement(nam);\r
-                namesleft--;\r
-            }\r
-            else\r
-            {\r
-                j.setElement(new Sequence(realnam, "THISISAPLACEHLDER"));\r
-                j.setPlaceholder(true);\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Creates a new NJTree object.\r
-     *\r
-     * @param sequence DOCUMENT ME!\r
-     * @param type DOCUMENT ME!\r
-     * @param pwtype DOCUMENT ME!\r
-     * @param start DOCUMENT ME!\r
-     * @param end DOCUMENT ME!\r
-     */\r
-    public NJTree(SequenceI[] sequence,\r
-                  AlignmentView seqData,\r
-                  String type,\r
-                  String pwtype,\r
-                  int start, int end)\r
-    {\r
-        this.sequence = sequence;\r
-        this.node = new Vector();\r
-        this.type = type;\r
-        this.pwtype = pwtype;\r
-        if (seqData!=null) {\r
-          this.seqData = seqData;\r
-        } else {\r
-          SeqCigar[] seqs = new SeqCigar[sequence.length];\r
-          for(int i=0; i<sequence.length; i++)\r
-            {\r
-              seqs[i] = new SeqCigar(sequence[i], start, end);\r
-            }\r
-            CigarArray sdata = new CigarArray(seqs);\r
-            sdata.addOperation(CigarArray.M, end-start+1);\r
-            this.seqData = new AlignmentView(sdata);\r
-        }\r
-\r
-        if (!(type.equals("NJ")))\r
-        {\r
-            type = "AV";\r
-        }\r
-\r
-        if (!(pwtype.equals("PID")))\r
-        {\r
-            type = "BL";\r
-        }\r
-\r
-        int i = 0;\r
-\r
-        done = new int[sequence.length];\r
-\r
-        while ((i < sequence.length) && (sequence[i] != null))\r
-        {\r
-            done[i] = 0;\r
-            i++;\r
-        }\r
-\r
-        noseqs = i++;\r
-\r
-        distance = findDistances(this.seqData.getSequenceStrings(Comparison.GapChars.charAt(0)));\r
-\r
-        makeLeaves();\r
-\r
-        noClus = cluster.size();\r
-\r
-        cluster();\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public String toString()\r
-    {\r
-        jalview.io.NewickFile fout = new jalview.io.NewickFile(getTopNode());\r
-\r
-        return fout.print(false, true); // distances only\r
-    }\r
-\r
-    /**\r
-     *\r
-     * used when the alignment associated to a tree has changed.\r
-     *\r
-     * @param alignment Vector\r
-     */\r
-    public void UpdatePlaceHolders(Vector alignment)\r
-    {\r
-        Vector leaves = new Vector();\r
-        findLeaves(top, leaves);\r
-\r
-        int sz = leaves.size();\r
-        SequenceIdMatcher seqmatcher = null;\r
-        int i = 0;\r
-\r
-        while (i < sz)\r
-        {\r
-            SequenceNode leaf = (SequenceNode) leaves.elementAt(i++);\r
-\r
-            if (alignment.contains(leaf.element()))\r
-            {\r
-                leaf.setPlaceholder(false);\r
-            }\r
-            else\r
-            {\r
-                if (seqmatcher == null)\r
-                {\r
-                    // Only create this the first time we need it\r
-                    SequenceI[] seqs = new SequenceI[alignment.size()];\r
-\r
-                    for (int j = 0; j < seqs.length; j++)\r
-                        seqs[j] = (SequenceI) alignment.elementAt(j);\r
-\r
-                    seqmatcher = new SequenceIdMatcher(seqs);\r
-                }\r
-\r
-                SequenceI nam = seqmatcher.findIdMatch(leaf.getName());\r
-\r
-                if (nam != null)\r
-                {\r
-                    leaf.setPlaceholder(false);\r
-                    leaf.setElement(nam);\r
-                }\r
-                else\r
-                {\r
-                    leaf.setPlaceholder(true);\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     */\r
-    public void cluster()\r
-    {\r
-        while (noClus > 2)\r
-        {\r
-            if (type.equals("NJ"))\r
-            {\r
-                findMinNJDistance();\r
-            }\r
-            else\r
-            {\r
-                findMinDistance();\r
-            }\r
-\r
-            Cluster c = joinClusters(mini, minj);\r
-\r
-            done[minj] = 1;\r
-\r
-            cluster.setElementAt(null, minj);\r
-            cluster.setElementAt(c, mini);\r
-\r
-            noClus--;\r
-        }\r
-\r
-        boolean onefound = false;\r
-\r
-        int one = -1;\r
-        int two = -1;\r
-\r
-        for (int i = 0; i < noseqs; i++)\r
-        {\r
-            if (done[i] != 1)\r
-            {\r
-                if (onefound == false)\r
-                {\r
-                    two = i;\r
-                    onefound = true;\r
-                }\r
-                else\r
-                {\r
-                    one = i;\r
-                }\r
-            }\r
-        }\r
-\r
-        joinClusters(one, two);\r
-        top = (SequenceNode) (node.elementAt(one));\r
-\r
-        reCount(top);\r
-        findHeight(top);\r
-        findMaxDist(top);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param i DOCUMENT ME!\r
-     * @param j DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Cluster joinClusters(int i, int j)\r
-    {\r
-        float dist = distance[i][j];\r
-\r
-        int noi = ((Cluster) cluster.elementAt(i)).value.length;\r
-        int noj = ((Cluster) cluster.elementAt(j)).value.length;\r
-\r
-        int[] value = new int[noi + noj];\r
-\r
-        for (int ii = 0; ii < noi; ii++)\r
-        {\r
-            value[ii] = ((Cluster) cluster.elementAt(i)).value[ii];\r
-        }\r
-\r
-        for (int ii = noi; ii < (noi + noj); ii++)\r
-        {\r
-            value[ii] = ((Cluster) cluster.elementAt(j)).value[ii - noi];\r
-        }\r
-\r
-        Cluster c = new Cluster(value);\r
-\r
-        ri = findr(i, j);\r
-        rj = findr(j, i);\r
-\r
-        if (type.equals("NJ"))\r
-        {\r
-            findClusterNJDistance(i, j);\r
-        }\r
-        else\r
-        {\r
-            findClusterDistance(i, j);\r
-        }\r
-\r
-        SequenceNode sn = new SequenceNode();\r
-\r
-        sn.setLeft((SequenceNode) (node.elementAt(i)));\r
-        sn.setRight((SequenceNode) (node.elementAt(j)));\r
-\r
-        SequenceNode tmpi = (SequenceNode) (node.elementAt(i));\r
-        SequenceNode tmpj = (SequenceNode) (node.elementAt(j));\r
-\r
-        if (type.equals("NJ"))\r
-        {\r
-            findNewNJDistances(tmpi, tmpj, dist);\r
-        }\r
-        else\r
-        {\r
-            findNewDistances(tmpi, tmpj, dist);\r
-        }\r
-\r
-        tmpi.setParent(sn);\r
-        tmpj.setParent(sn);\r
-\r
-        node.setElementAt(sn, i);\r
-\r
-        return c;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param tmpi DOCUMENT ME!\r
-     * @param tmpj DOCUMENT ME!\r
-     * @param dist DOCUMENT ME!\r
-     */\r
-    public void findNewNJDistances(SequenceNode tmpi, SequenceNode tmpj,\r
-        float dist)\r
-    {\r
-\r
-        tmpi.dist = ((dist + ri) - rj) / 2;\r
-        tmpj.dist = (dist - tmpi.dist);\r
-\r
-        if (tmpi.dist < 0)\r
-        {\r
-            tmpi.dist = 0;\r
-        }\r
-\r
-        if (tmpj.dist < 0)\r
-        {\r
-            tmpj.dist = 0;\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param tmpi DOCUMENT ME!\r
-     * @param tmpj DOCUMENT ME!\r
-     * @param dist DOCUMENT ME!\r
-     */\r
-    public void findNewDistances(SequenceNode tmpi, SequenceNode tmpj,\r
-        float dist)\r
-    {\r
-        float ih = 0;\r
-        float jh = 0;\r
-\r
-        SequenceNode sni = tmpi;\r
-        SequenceNode snj = tmpj;\r
-\r
-        while (sni != null)\r
-        {\r
-            ih = ih + sni.dist;\r
-            sni = (SequenceNode) sni.left();\r
-        }\r
-\r
-        while (snj != null)\r
-        {\r
-            jh = jh + snj.dist;\r
-            snj = (SequenceNode) snj.left();\r
-        }\r
-\r
-        tmpi.dist = ((dist / 2) - ih);\r
-        tmpj.dist = ((dist / 2) - jh);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param i DOCUMENT ME!\r
-     * @param j DOCUMENT ME!\r
-     */\r
-    public void findClusterDistance(int i, int j)\r
-    {\r
-        int noi = ((Cluster) cluster.elementAt(i)).value.length;\r
-        int noj = ((Cluster) cluster.elementAt(j)).value.length;\r
-\r
-        // New distances from cluster to others\r
-        float[] newdist = new float[noseqs];\r
-\r
-        for (int l = 0; l < noseqs; l++)\r
-        {\r
-            if ((l != i) && (l != j))\r
-            {\r
-                newdist[l] = ((distance[i][l] * noi) + (distance[j][l] * noj)) / (noi +\r
-                    noj);\r
-            }\r
-            else\r
-            {\r
-                newdist[l] = 0;\r
-            }\r
-        }\r
-\r
-        for (int ii = 0; ii < noseqs; ii++)\r
-        {\r
-            distance[i][ii] = newdist[ii];\r
-            distance[ii][i] = newdist[ii];\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param i DOCUMENT ME!\r
-     * @param j DOCUMENT ME!\r
-     */\r
-    public void findClusterNJDistance(int i, int j)\r
-    {\r
-\r
-        // New distances from cluster to others\r
-        float[] newdist = new float[noseqs];\r
-\r
-        for (int l = 0; l < noseqs; l++)\r
-        {\r
-            if ((l != i) && (l != j))\r
-            {\r
-                newdist[l] = ((distance[i][l] + distance[j][l]) -\r
-                    distance[i][j]) / 2;\r
-            }\r
-            else\r
-            {\r
-                newdist[l] = 0;\r
-            }\r
-        }\r
-\r
-        for (int ii = 0; ii < noseqs; ii++)\r
-        {\r
-            distance[i][ii] = newdist[ii];\r
-            distance[ii][i] = newdist[ii];\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param i DOCUMENT ME!\r
-     * @param j DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float findr(int i, int j)\r
-    {\r
-        float tmp = 1;\r
-\r
-        for (int k = 0; k < noseqs; k++)\r
-        {\r
-            if ((k != i) && (k != j) && (done[k] != 1))\r
-            {\r
-                tmp = tmp + distance[i][k];\r
-            }\r
-        }\r
-\r
-        if (noClus > 2)\r
-        {\r
-            tmp = tmp / (noClus - 2);\r
-        }\r
-\r
-        return tmp;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float findMinNJDistance()\r
-    {\r
-        float min = 100000;\r
-\r
-        for (int i = 0; i < (noseqs - 1); i++)\r
-        {\r
-            for (int j = i + 1; j < noseqs; j++)\r
-            {\r
-                if ((done[i] != 1) && (done[j] != 1))\r
-                {\r
-                    float tmp = distance[i][j] - (findr(i, j) + findr(j, i));\r
-\r
-                    if (tmp < min)\r
-                    {\r
-                        mini = i;\r
-                        minj = j;\r
-\r
-                        min = tmp;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return min;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float findMinDistance()\r
-    {\r
-        float min = 100000;\r
-\r
-        for (int i = 0; i < (noseqs - 1); i++)\r
-        {\r
-            for (int j = i + 1; j < noseqs; j++)\r
-            {\r
-                if ((done[i] != 1) && (done[j] != 1))\r
-                {\r
-                    if (distance[i][j] < min)\r
-                    {\r
-                        mini = i;\r
-                        minj = j;\r
-\r
-                        min = distance[i][j];\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return min;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float[][] findDistances(String[] sequenceString)\r
-    {\r
-        float[][] distance = new float[noseqs][noseqs];\r
-\r
-        if (pwtype.equals("PID"))\r
-        {\r
-            for (int i = 0; i < (noseqs - 1); i++)\r
-            {\r
-                for (int j = i; j < noseqs; j++)\r
-                {\r
-                    if (j == i)\r
-                    {\r
-                        distance[i][i] = 0;\r
-                    }\r
-                    else\r
-                    {\r
-                        distance[i][j] = 100 -\r
-                             Comparison.PID(sequenceString[i], sequenceString[j]);\r
-\r
-                        distance[j][i] = distance[i][j];\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        else if (pwtype.equals("BL"))\r
-        {\r
-            int maxscore = 0;\r
-            int end = sequenceString[0].length();\r
-            for (int i = 0; i < (noseqs - 1); i++)\r
-            {\r
-                for (int j = i; j < noseqs; j++)\r
-                {\r
-                    int score = 0;\r
-\r
-                    for (int k = 0; k < end; k++)\r
-                    {\r
-                        try\r
-                        {\r
-                            score += ResidueProperties.getBLOSUM62(\r
-                              sequenceString[i].substring(k, k + 1),\r
-                              sequenceString[j].substring(k, k + 1));\r
-                        }\r
-                        catch (Exception ex)\r
-                        {\r
-                            System.err.println("err creating BLOSUM62 tree");\r
-                            ex.printStackTrace();\r
-                        }\r
-                    }\r
-\r
-                    distance[i][j] = (float) score;\r
-\r
-                    if (score > maxscore)\r
-                    {\r
-                        maxscore = score;\r
-                    }\r
-                }\r
-            }\r
-\r
-            for (int i = 0; i < (noseqs - 1); i++)\r
-            {\r
-                for (int j = i; j < noseqs; j++)\r
-                {\r
-                    distance[i][j] = (float) maxscore - distance[i][j];\r
-                    distance[j][i] = distance[i][j];\r
-                }\r
-            }\r
-        }\r
-      /*  else if (pwtype.equals("SW"))\r
-        {\r
-            float max = -1;\r
-\r
-            for (int i = 0; i < (noseqs - 1); i++)\r
-            {\r
-                for (int j = i; j < noseqs; j++)\r
-                {\r
-                    AlignSeq as = new AlignSeq(sequence[i], sequence[j], "pep");\r
-                    as.calcScoreMatrix();\r
-                    as.traceAlignment();\r
-                    as.printAlignment(System.out);\r
-                    distance[i][j] = (float) as.maxscore;\r
-\r
-                    if (max < distance[i][j])\r
-                    {\r
-                        max = distance[i][j];\r
-                    }\r
-                }\r
-            }\r
-\r
-            for (int i = 0; i < (noseqs - 1); i++)\r
-            {\r
-                for (int j = i; j < noseqs; j++)\r
-                {\r
-                    distance[i][j] = max - distance[i][j];\r
-                    distance[j][i] = distance[i][j];\r
-                }\r
-            }\r
-        }/*/\r
-\r
-        return distance;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     */\r
-    public void makeLeaves()\r
-    {\r
-        cluster = new Vector();\r
-\r
-        for (int i = 0; i < noseqs; i++)\r
-        {\r
-            SequenceNode sn = new SequenceNode();\r
-\r
-            sn.setElement(sequence[i]);\r
-            sn.setName(sequence[i].getName());\r
-            node.addElement(sn);\r
-\r
-            int[] value = new int[1];\r
-            value[0] = i;\r
-\r
-            Cluster c = new Cluster(value);\r
-            cluster.addElement(c);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     * @param leaves DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Vector findLeaves(SequenceNode node, Vector leaves)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return leaves;\r
-        }\r
-\r
-        if ((node.left() == null) && (node.right() == null))\r
-        {\r
-            leaves.addElement(node);\r
-\r
-            return leaves;\r
-        }\r
-        else\r
-        {\r
-            findLeaves((SequenceNode) node.left(), leaves);\r
-            findLeaves((SequenceNode) node.right(), leaves);\r
-        }\r
-\r
-        return leaves;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     * @param count DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Object findLeaf(SequenceNode node, int count)\r
-    {\r
-        found = _findLeaf(node, count);\r
-\r
-        return found;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     * @param count DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Object _findLeaf(SequenceNode node, int count)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return null;\r
-        }\r
-\r
-        if (node.ycount == count)\r
-        {\r
-            found = node.element();\r
-\r
-            return found;\r
-        }\r
-        else\r
-        {\r
-            _findLeaf((SequenceNode) node.left(), count);\r
-            _findLeaf((SequenceNode) node.right(), count);\r
-        }\r
-\r
-        return found;\r
-    }\r
-\r
-    /**\r
-     * printNode is mainly for debugging purposes.\r
-     *\r
-     * @param node SequenceNode\r
-     */\r
-    public void printNode(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if ((node.left() == null) && (node.right() == null))\r
-        {\r
-            System.out.println("Leaf = " +\r
-                ((SequenceI) node.element()).getName());\r
-            System.out.println("Dist " + ((SequenceNode) node).dist);\r
-            System.out.println("Boot " + node.getBootstrap());\r
-        }\r
-        else\r
-        {\r
-            System.out.println("Dist " + ((SequenceNode) node).dist);\r
-            printNode((SequenceNode) node.left());\r
-            printNode((SequenceNode) node.right());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     */\r
-    public void findMaxDist(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if ((node.left() == null) && (node.right() == null))\r
-        {\r
-            float dist = ((SequenceNode) node).dist;\r
-\r
-            if (dist > maxDistValue)\r
-            {\r
-                maxdist = (SequenceNode) node;\r
-                maxDistValue = dist;\r
-            }\r
-        }\r
-        else\r
-        {\r
-            findMaxDist((SequenceNode) node.left());\r
-            findMaxDist((SequenceNode) node.right());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Vector getGroups()\r
-    {\r
-        return groups;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float getMaxHeight()\r
-    {\r
-        return maxheight;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     * @param threshold DOCUMENT ME!\r
-     */\r
-    public void groupNodes(SequenceNode node, float threshold)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if ((node.height / maxheight) > threshold)\r
-        {\r
-            groups.addElement(node);\r
-        }\r
-        else\r
-        {\r
-            groupNodes((SequenceNode) node.left(), threshold);\r
-            groupNodes((SequenceNode) node.right(), threshold);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public float findHeight(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return maxheight;\r
-        }\r
-\r
-        if ((node.left() == null) && (node.right() == null))\r
-        {\r
-            node.height = ((SequenceNode) node.parent()).height + node.dist;\r
-\r
-            if (node.height > maxheight)\r
-            {\r
-                return node.height;\r
-            }\r
-            else\r
-            {\r
-                return maxheight;\r
-            }\r
-        }\r
-        else\r
-        {\r
-            if (node.parent() != null)\r
-            {\r
-                node.height = ((SequenceNode) node.parent()).height +\r
-                    node.dist;\r
-            }\r
-            else\r
-            {\r
-                maxheight = 0;\r
-                node.height = (float) 0.0;\r
-            }\r
-\r
-            maxheight = findHeight((SequenceNode) (node.left()));\r
-            maxheight = findHeight((SequenceNode) (node.right()));\r
-        }\r
-\r
-        return maxheight;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public SequenceNode reRoot()\r
-    {\r
-        if (maxdist != null)\r
-        {\r
-            ycount = 0;\r
-\r
-            float tmpdist = maxdist.dist;\r
-\r
-            // New top\r
-            SequenceNode sn = new SequenceNode();\r
-            sn.setParent(null);\r
-\r
-            // New right hand of top\r
-            SequenceNode snr = (SequenceNode) maxdist.parent();\r
-            changeDirection(snr, maxdist);\r
-            System.out.println("Printing reversed tree");\r
-            printN(snr);\r
-            snr.dist = tmpdist / 2;\r
-            maxdist.dist = tmpdist / 2;\r
-\r
-            snr.setParent(sn);\r
-            maxdist.setParent(sn);\r
-\r
-            sn.setRight(snr);\r
-            sn.setLeft(maxdist);\r
-\r
-            top = sn;\r
-\r
-            ycount = 0;\r
-            reCount(top);\r
-            findHeight(top);\r
-        }\r
-\r
-        return top;\r
-    }\r
-    /**\r
-     *\r
-     * @return true if original sequence data can be recovered\r
-     */\r
-    public boolean hasOriginalSequenceData() {\r
-      return seqData!=null;\r
-    }\r
-    /**\r
-     * Returns original alignment data used for calculation - or null where\r
-     * not available.\r
-     *\r
-     * @return null or cut'n'pasteable alignment\r
-     */\r
-    public String printOriginalSequenceData(char gapChar)\r
-    {\r
-      if (seqData==null)\r
-        return null;\r
-\r
-      StringBuffer sb = new StringBuffer();\r
-      String[] seqdatas = seqData.getSequenceStrings(gapChar);\r
-      for(int i=0; i<seqdatas.length; i++)\r
-      {\r
-        sb.append(new jalview.util.Format("%-" + 15 + "s").form(\r
-            sequence[i].getName()));\r
-        sb.append(" "+seqdatas[i]+"\n");\r
-      }\r
-      return sb.toString();\r
-    }\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     */\r
-    public void printN(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if ((node.left() != null) && (node.right() != null))\r
-        {\r
-            printN((SequenceNode) node.left());\r
-            printN((SequenceNode) node.right());\r
-        }\r
-        else\r
-        {\r
-            System.out.println(" name = " +\r
-                ((SequenceI) node.element()).getName());\r
-        }\r
-\r
-        System.out.println(" dist = " + ((SequenceNode) node).dist + " " +\r
-            ((SequenceNode) node).count + " " + ((SequenceNode) node).height);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     */\r
-    public void reCount(SequenceNode node)\r
-    {\r
-        ycount = 0;\r
-        _reCount(node);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     */\r
-    public void _reCount(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if ((node.left() != null) && (node.right() != null))\r
-        {\r
-            _reCount((SequenceNode) node.left());\r
-            _reCount((SequenceNode) node.right());\r
-\r
-            SequenceNode l = (SequenceNode) node.left();\r
-            SequenceNode r = (SequenceNode) node.right();\r
-\r
-            ((SequenceNode) node).count = l.count + r.count;\r
-            ((SequenceNode) node).ycount = (l.ycount + r.ycount) / 2;\r
-        }\r
-        else\r
-        {\r
-            ((SequenceNode) node).count = 1;\r
-            ((SequenceNode) node).ycount = ycount++;\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     */\r
-    public void swapNodes(SequenceNode node)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        SequenceNode tmp = (SequenceNode) node.left();\r
-\r
-        node.setLeft(node.right());\r
-        node.setRight(tmp);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param node DOCUMENT ME!\r
-     * @param dir DOCUMENT ME!\r
-     */\r
-    public void changeDirection(SequenceNode node, SequenceNode dir)\r
-    {\r
-        if (node == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        if (node.parent() != top)\r
-        {\r
-            changeDirection((SequenceNode) node.parent(), node);\r
-\r
-            SequenceNode tmp = (SequenceNode) node.parent();\r
-\r
-            if (dir == node.left())\r
-            {\r
-                node.setParent(dir);\r
-                node.setLeft(tmp);\r
-            }\r
-            else if (dir == node.right())\r
-            {\r
-                node.setParent(dir);\r
-                node.setRight(tmp);\r
-            }\r
-        }\r
-        else\r
-        {\r
-            if (dir == node.left())\r
-            {\r
-                node.setParent(node.left());\r
-\r
-                if (top.left() == node)\r
-                {\r
-                    node.setRight(top.right());\r
-                }\r
-                else\r
-                {\r
-                    node.setRight(top.left());\r
-                }\r
-            }\r
-            else\r
-            {\r
-                node.setParent(node.right());\r
-\r
-                if (top.left() == node)\r
-                {\r
-                    node.setLeft(top.right());\r
-                }\r
-                else\r
-                {\r
-                    node.setLeft(top.left());\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public SequenceNode getMaxDist()\r
-    {\r
-        return maxdist;\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public SequenceNode getTopNode()\r
-    {\r
-        return top;\r
-    }\r
-    /**\r
-     *\r
-     * @return true if tree has real distances\r
-     */\r
-    public boolean isHasDistances() {\r
-      return hasDistances;\r
-    }\r
-\r
-    /**\r
-     *\r
-     * @return true if tree has real bootstrap values\r
-     */\r
-    public boolean isHasBootstrap() {\r
-      return hasBootstrap;\r
-    }\r
-\r
-  public boolean isHasRootDistance()\r
-  {\r
-    return hasRootDistance;\r
-  }\r
-\r
-}\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-class Cluster\r
-{\r
-    int[] value;\r
-\r
-    /**\r
-     * Creates a new Cluster object.\r
-     *\r
-     * @param value DOCUMENT ME!\r
-     */\r
-    public Cluster(int[] value)\r
-    {\r
-        this.value = value;\r
-    }\r
-}\r
-\r
+/*
+* Jalview - A Sequence Alignment Editor and Viewer
+* Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+*
+* 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
+*/
+package jalview.analysis;
+
+import jalview.datamodel.*;
+
+import jalview.io.NewickFile;
+
+import jalview.schemes.ResidueProperties;
+
+import jalview.util.*;
+
+import java.util.*;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class NJTree
+{
+    Vector cluster;
+    SequenceI[] sequence;
+
+    //SequenceData is a string representation of what the user
+    //sees. The display may contain hidden columns.
+    public AlignmentView seqData=null;
+
+    int[] done;
+    int noseqs;
+    int noClus;
+    float[][] distance;
+    int mini;
+    int minj;
+    float ri;
+    float rj;
+    Vector groups = new Vector();
+    SequenceNode maxdist;
+    SequenceNode top;
+    float maxDistValue;
+    float maxheight;
+    int ycount;
+    Vector node;
+    String type;
+    String pwtype;
+    Object found = null;
+    Object leaves = null;
+
+    boolean hasDistances = true; // normal case for jalview trees
+    boolean hasBootstrap = false; // normal case for jalview trees
+
+    private boolean hasRootDistance = true;
+
+    /**
+     * Create a new NJTree object with leaves associated with sequences in seqs,
+     * and original alignment data represented by Cigar strings.
+     * @param seqs SequenceI[]
+     * @param odata Cigar[]
+     * @param treefile NewickFile
+     */
+    public NJTree(SequenceI[] seqs, AlignmentView odata, NewickFile treefile) {
+      this(seqs, treefile);
+      if (odata!=null)
+        seqData = odata;
+      /*
+      sequenceString = new String[odata.length];
+      char gapChar = jalview.util.Comparison.GapChars.charAt(0);
+      for (int i = 0; i < odata.length; i++)
+      {
+        SequenceI oseq_aligned = odata[i].getSeq(gapChar);
+          sequenceString[i] = oseq_aligned.getSequence();
+      } */
+    }
+
+    /**
+     * Creates a new NJTree object from a tree from an external source
+     *
+     * @param seqs SequenceI which should be associated with leafs of treefile
+     * @param treefile A parsed tree
+     */
+    public NJTree(SequenceI[] seqs,  NewickFile treefile)
+    {
+        this.sequence = seqs;
+        top = treefile.getTree();
+
+        /**
+         * There is no dependent alignment to be recovered from an
+         * imported tree.
+         *
+        if (sequenceString == null)
+        {
+          sequenceString = new String[seqs.length];
+          for (int i = 0; i < seqs.length; i++)
+          {
+            sequenceString[i] = seqs[i].getSequence();
+          }
+        }
+        */
+
+        hasDistances = treefile.HasDistances();
+        hasBootstrap = treefile.HasBootstrap();
+        hasRootDistance = treefile.HasRootDistance();
+
+        maxheight = findHeight(top);
+
+        SequenceIdMatcher algnIds = new SequenceIdMatcher(seqs);
+
+        Vector leaves = new Vector();
+        findLeaves(top, leaves);
+
+        int i = 0;
+        int namesleft = seqs.length;
+
+        SequenceNode j;
+        SequenceI nam;
+        String realnam;
+
+        while (i < leaves.size())
+        {
+            j = (SequenceNode) leaves.elementAt(i++);
+            realnam = j.getName();
+            nam = null;
+
+            if (namesleft > -1)
+            {
+                nam = algnIds.findIdMatch(realnam);
+            }
+
+            if (nam != null)
+            {
+                j.setElement(nam);
+                namesleft--;
+            }
+            else
+            {
+                j.setElement(new Sequence(realnam, "THISISAPLACEHLDER"));
+                j.setPlaceholder(true);
+            }
+        }
+    }
+
+    /**
+     * Creates a new NJTree object.
+     *
+     * @param sequence DOCUMENT ME!
+     * @param type DOCUMENT ME!
+     * @param pwtype DOCUMENT ME!
+     * @param start DOCUMENT ME!
+     * @param end DOCUMENT ME!
+     */
+    public NJTree(SequenceI[] sequence,
+                  AlignmentView seqData,
+                  String type,
+                  String pwtype,
+                  int start, int end)
+    {
+        this.sequence = sequence;
+        this.node = new Vector();
+        this.type = type;
+        this.pwtype = pwtype;
+        if (seqData!=null) {
+          this.seqData = seqData;
+        } else {
+          SeqCigar[] seqs = new SeqCigar[sequence.length];
+          for(int i=0; i<sequence.length; i++)
+            {
+              seqs[i] = new SeqCigar(sequence[i], start, end);
+            }
+            CigarArray sdata = new CigarArray(seqs);
+            sdata.addOperation(CigarArray.M, end-start+1);
+            this.seqData = new AlignmentView(sdata, start);
+        }
+
+        if (!(type.equals("NJ")))
+        {
+            type = "AV";
+        }
+
+        if (!(pwtype.equals("PID")))
+        {
+            type = "BL";
+        }
+
+        int i = 0;
+
+        done = new int[sequence.length];
+
+        while ((i < sequence.length) && (sequence[i] != null))
+        {
+            done[i] = 0;
+            i++;
+        }
+
+        noseqs = i++;
+
+        distance = findDistances(this.seqData.getSequenceStrings(Comparison.GapChars.charAt(0)));
+
+        makeLeaves();
+
+        noClus = cluster.size();
+
+        cluster();
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public String toString()
+    {
+        jalview.io.NewickFile fout = new jalview.io.NewickFile(getTopNode());
+
+        return fout.print(false, true); // distances only
+    }
+
+    /**
+     *
+     * used when the alignment associated to a tree has changed.
+     *
+     * @param alignment Vector
+     */
+    public void UpdatePlaceHolders(Vector alignment)
+    {
+        Vector leaves = new Vector();
+        findLeaves(top, leaves);
+
+        int sz = leaves.size();
+        SequenceIdMatcher seqmatcher = null;
+        int i = 0;
+
+        while (i < sz)
+        {
+            SequenceNode leaf = (SequenceNode) leaves.elementAt(i++);
+
+            if (alignment.contains(leaf.element()))
+            {
+                leaf.setPlaceholder(false);
+            }
+            else
+            {
+                if (seqmatcher == null)
+                {
+                    // Only create this the first time we need it
+                    SequenceI[] seqs = new SequenceI[alignment.size()];
+
+                    for (int j = 0; j < seqs.length; j++)
+                        seqs[j] = (SequenceI) alignment.elementAt(j);
+
+                    seqmatcher = new SequenceIdMatcher(seqs);
+                }
+
+                SequenceI nam = seqmatcher.findIdMatch(leaf.getName());
+
+                if (nam != null)
+                {
+                    leaf.setPlaceholder(false);
+                    leaf.setElement(nam);
+                }
+                else
+                {
+                    leaf.setPlaceholder(true);
+                }
+            }
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     */
+    public void cluster()
+    {
+        while (noClus > 2)
+        {
+            if (type.equals("NJ"))
+            {
+                findMinNJDistance();
+            }
+            else
+            {
+                findMinDistance();
+            }
+
+            Cluster c = joinClusters(mini, minj);
+
+            done[minj] = 1;
+
+            cluster.setElementAt(null, minj);
+            cluster.setElementAt(c, mini);
+
+            noClus--;
+        }
+
+        boolean onefound = false;
+
+        int one = -1;
+        int two = -1;
+
+        for (int i = 0; i < noseqs; i++)
+        {
+            if (done[i] != 1)
+            {
+                if (onefound == false)
+                {
+                    two = i;
+                    onefound = true;
+                }
+                else
+                {
+                    one = i;
+                }
+            }
+        }
+
+        joinClusters(one, two);
+        top = (SequenceNode) (node.elementAt(one));
+
+        reCount(top);
+        findHeight(top);
+        findMaxDist(top);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param i DOCUMENT ME!
+     * @param j DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public Cluster joinClusters(int i, int j)
+    {
+        float dist = distance[i][j];
+
+        int noi = ((Cluster) cluster.elementAt(i)).value.length;
+        int noj = ((Cluster) cluster.elementAt(j)).value.length;
+
+        int[] value = new int[noi + noj];
+
+        for (int ii = 0; ii < noi; ii++)
+        {
+            value[ii] = ((Cluster) cluster.elementAt(i)).value[ii];
+        }
+
+        for (int ii = noi; ii < (noi + noj); ii++)
+        {
+            value[ii] = ((Cluster) cluster.elementAt(j)).value[ii - noi];
+        }
+
+        Cluster c = new Cluster(value);
+
+        ri = findr(i, j);
+        rj = findr(j, i);
+
+        if (type.equals("NJ"))
+        {
+            findClusterNJDistance(i, j);
+        }
+        else
+        {
+            findClusterDistance(i, j);
+        }
+
+        SequenceNode sn = new SequenceNode();
+
+        sn.setLeft((SequenceNode) (node.elementAt(i)));
+        sn.setRight((SequenceNode) (node.elementAt(j)));
+
+        SequenceNode tmpi = (SequenceNode) (node.elementAt(i));
+        SequenceNode tmpj = (SequenceNode) (node.elementAt(j));
+
+        if (type.equals("NJ"))
+        {
+            findNewNJDistances(tmpi, tmpj, dist);
+        }
+        else
+        {
+            findNewDistances(tmpi, tmpj, dist);
+        }
+
+        tmpi.setParent(sn);
+        tmpj.setParent(sn);
+
+        node.setElementAt(sn, i);
+
+        return c;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param tmpi DOCUMENT ME!
+     * @param tmpj DOCUMENT ME!
+     * @param dist DOCUMENT ME!
+     */
+    public void findNewNJDistances(SequenceNode tmpi, SequenceNode tmpj,
+        float dist)
+    {
+
+        tmpi.dist = ((dist + ri) - rj) / 2;
+        tmpj.dist = (dist - tmpi.dist);
+
+        if (tmpi.dist < 0)
+        {
+            tmpi.dist = 0;
+        }
+
+        if (tmpj.dist < 0)
+        {
+            tmpj.dist = 0;
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param tmpi DOCUMENT ME!
+     * @param tmpj DOCUMENT ME!
+     * @param dist DOCUMENT ME!
+     */
+    public void findNewDistances(SequenceNode tmpi, SequenceNode tmpj,
+        float dist)
+    {
+        float ih = 0;
+        float jh = 0;
+
+        SequenceNode sni = tmpi;
+        SequenceNode snj = tmpj;
+
+        while (sni != null)
+        {
+            ih = ih + sni.dist;
+            sni = (SequenceNode) sni.left();
+        }
+
+        while (snj != null)
+        {
+            jh = jh + snj.dist;
+            snj = (SequenceNode) snj.left();
+        }
+
+        tmpi.dist = ((dist / 2) - ih);
+        tmpj.dist = ((dist / 2) - jh);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param i DOCUMENT ME!
+     * @param j DOCUMENT ME!
+     */
+    public void findClusterDistance(int i, int j)
+    {
+        int noi = ((Cluster) cluster.elementAt(i)).value.length;
+        int noj = ((Cluster) cluster.elementAt(j)).value.length;
+
+        // New distances from cluster to others
+        float[] newdist = new float[noseqs];
+
+        for (int l = 0; l < noseqs; l++)
+        {
+            if ((l != i) && (l != j))
+            {
+                newdist[l] = ((distance[i][l] * noi) + (distance[j][l] * noj)) / (noi +
+                    noj);
+            }
+            else
+            {
+                newdist[l] = 0;
+            }
+        }
+
+        for (int ii = 0; ii < noseqs; ii++)
+        {
+            distance[i][ii] = newdist[ii];
+            distance[ii][i] = newdist[ii];
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param i DOCUMENT ME!
+     * @param j DOCUMENT ME!
+     */
+    public void findClusterNJDistance(int i, int j)
+    {
+
+        // New distances from cluster to others
+        float[] newdist = new float[noseqs];
+
+        for (int l = 0; l < noseqs; l++)
+        {
+            if ((l != i) && (l != j))
+            {
+                newdist[l] = ((distance[i][l] + distance[j][l]) -
+                    distance[i][j]) / 2;
+            }
+            else
+            {
+                newdist[l] = 0;
+            }
+        }
+
+        for (int ii = 0; ii < noseqs; ii++)
+        {
+            distance[i][ii] = newdist[ii];
+            distance[ii][i] = newdist[ii];
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param i DOCUMENT ME!
+     * @param j DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float findr(int i, int j)
+    {
+        float tmp = 1;
+
+        for (int k = 0; k < noseqs; k++)
+        {
+            if ((k != i) && (k != j) && (done[k] != 1))
+            {
+                tmp = tmp + distance[i][k];
+            }
+        }
+
+        if (noClus > 2)
+        {
+            tmp = tmp / (noClus - 2);
+        }
+
+        return tmp;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float findMinNJDistance()
+    {
+        float min = 100000;
+
+        for (int i = 0; i < (noseqs - 1); i++)
+        {
+            for (int j = i + 1; j < noseqs; j++)
+            {
+                if ((done[i] != 1) && (done[j] != 1))
+                {
+                    float tmp = distance[i][j] - (findr(i, j) + findr(j, i));
+
+                    if (tmp < min)
+                    {
+                        mini = i;
+                        minj = j;
+
+                        min = tmp;
+                    }
+                }
+            }
+        }
+
+        return min;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float findMinDistance()
+    {
+        float min = 100000;
+
+        for (int i = 0; i < (noseqs - 1); i++)
+        {
+            for (int j = i + 1; j < noseqs; j++)
+            {
+                if ((done[i] != 1) && (done[j] != 1))
+                {
+                    if (distance[i][j] < min)
+                    {
+                        mini = i;
+                        minj = j;
+
+                        min = distance[i][j];
+                    }
+                }
+            }
+        }
+
+        return min;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float[][] findDistances(String[] sequenceString)
+    {
+        float[][] distance = new float[noseqs][noseqs];
+
+        if (pwtype.equals("PID"))
+        {
+            for (int i = 0; i < (noseqs - 1); i++)
+            {
+                for (int j = i; j < noseqs; j++)
+                {
+                    if (j == i)
+                    {
+                        distance[i][i] = 0;
+                    }
+                    else
+                    {
+                        distance[i][j] = 100 -
+                             Comparison.PID(sequenceString[i], sequenceString[j]);
+
+                        distance[j][i] = distance[i][j];
+                    }
+                }
+            }
+        }
+        else if (pwtype.equals("BL"))
+        {
+            int maxscore = 0;
+            int end = sequenceString[0].length();
+            for (int i = 0; i < (noseqs - 1); i++)
+            {
+                for (int j = i; j < noseqs; j++)
+                {
+                    int score = 0;
+
+                    for (int k = 0; k < end; k++)
+                    {
+                        try
+                        {
+                            score += ResidueProperties.getBLOSUM62(
+                              sequenceString[i].substring(k, k + 1),
+                              sequenceString[j].substring(k, k + 1));
+                        }
+                        catch (Exception ex)
+                        {
+                            System.err.println("err creating BLOSUM62 tree");
+                            ex.printStackTrace();
+                        }
+                    }
+
+                    distance[i][j] = (float) score;
+
+                    if (score > maxscore)
+                    {
+                        maxscore = score;
+                    }
+                }
+            }
+
+            for (int i = 0; i < (noseqs - 1); i++)
+            {
+                for (int j = i; j < noseqs; j++)
+                {
+                    distance[i][j] = (float) maxscore - distance[i][j];
+                    distance[j][i] = distance[i][j];
+                }
+            }
+        }
+      /*  else if (pwtype.equals("SW"))
+        {
+            float max = -1;
+
+            for (int i = 0; i < (noseqs - 1); i++)
+            {
+                for (int j = i; j < noseqs; j++)
+                {
+                    AlignSeq as = new AlignSeq(sequence[i], sequence[j], "pep");
+                    as.calcScoreMatrix();
+                    as.traceAlignment();
+                    as.printAlignment(System.out);
+                    distance[i][j] = (float) as.maxscore;
+
+                    if (max < distance[i][j])
+                    {
+                        max = distance[i][j];
+                    }
+                }
+            }
+
+            for (int i = 0; i < (noseqs - 1); i++)
+            {
+                for (int j = i; j < noseqs; j++)
+                {
+                    distance[i][j] = max - distance[i][j];
+                    distance[j][i] = distance[i][j];
+                }
+            }
+        }/*/
+
+        return distance;
+    }
+
+    /**
+     * DOCUMENT ME!
+     */
+    public void makeLeaves()
+    {
+        cluster = new Vector();
+
+        for (int i = 0; i < noseqs; i++)
+        {
+            SequenceNode sn = new SequenceNode();
+
+            sn.setElement(sequence[i]);
+            sn.setName(sequence[i].getName());
+            node.addElement(sn);
+
+            int[] value = new int[1];
+            value[0] = i;
+
+            Cluster c = new Cluster(value);
+            cluster.addElement(c);
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     * @param leaves DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public Vector findLeaves(SequenceNode node, Vector leaves)
+    {
+        if (node == null)
+        {
+            return leaves;
+        }
+
+        if ((node.left() == null) && (node.right() == null))
+        {
+            leaves.addElement(node);
+
+            return leaves;
+        }
+        else
+        {
+            findLeaves((SequenceNode) node.left(), leaves);
+            findLeaves((SequenceNode) node.right(), leaves);
+        }
+
+        return leaves;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     * @param count DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public Object findLeaf(SequenceNode node, int count)
+    {
+        found = _findLeaf(node, count);
+
+        return found;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     * @param count DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public Object _findLeaf(SequenceNode node, int count)
+    {
+        if (node == null)
+        {
+            return null;
+        }
+
+        if (node.ycount == count)
+        {
+            found = node.element();
+
+            return found;
+        }
+        else
+        {
+            _findLeaf((SequenceNode) node.left(), count);
+            _findLeaf((SequenceNode) node.right(), count);
+        }
+
+        return found;
+    }
+
+    /**
+     * printNode is mainly for debugging purposes.
+     *
+     * @param node SequenceNode
+     */
+    public void printNode(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if ((node.left() == null) && (node.right() == null))
+        {
+            System.out.println("Leaf = " +
+                ((SequenceI) node.element()).getName());
+            System.out.println("Dist " + ((SequenceNode) node).dist);
+            System.out.println("Boot " + node.getBootstrap());
+        }
+        else
+        {
+            System.out.println("Dist " + ((SequenceNode) node).dist);
+            printNode((SequenceNode) node.left());
+            printNode((SequenceNode) node.right());
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     */
+    public void findMaxDist(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if ((node.left() == null) && (node.right() == null))
+        {
+            float dist = ((SequenceNode) node).dist;
+
+            if (dist > maxDistValue)
+            {
+                maxdist = (SequenceNode) node;
+                maxDistValue = dist;
+            }
+        }
+        else
+        {
+            findMaxDist((SequenceNode) node.left());
+            findMaxDist((SequenceNode) node.right());
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public Vector getGroups()
+    {
+        return groups;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float getMaxHeight()
+    {
+        return maxheight;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     * @param threshold DOCUMENT ME!
+     */
+    public void groupNodes(SequenceNode node, float threshold)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if ((node.height / maxheight) > threshold)
+        {
+            groups.addElement(node);
+        }
+        else
+        {
+            groupNodes((SequenceNode) node.left(), threshold);
+            groupNodes((SequenceNode) node.right(), threshold);
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public float findHeight(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return maxheight;
+        }
+
+        if ((node.left() == null) && (node.right() == null))
+        {
+            node.height = ((SequenceNode) node.parent()).height + node.dist;
+
+            if (node.height > maxheight)
+            {
+                return node.height;
+            }
+            else
+            {
+                return maxheight;
+            }
+        }
+        else
+        {
+            if (node.parent() != null)
+            {
+                node.height = ((SequenceNode) node.parent()).height +
+                    node.dist;
+            }
+            else
+            {
+                maxheight = 0;
+                node.height = (float) 0.0;
+            }
+
+            maxheight = findHeight((SequenceNode) (node.left()));
+            maxheight = findHeight((SequenceNode) (node.right()));
+        }
+
+        return maxheight;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public SequenceNode reRoot()
+    {
+        if (maxdist != null)
+        {
+            ycount = 0;
+
+            float tmpdist = maxdist.dist;
+
+            // New top
+            SequenceNode sn = new SequenceNode();
+            sn.setParent(null);
+
+            // New right hand of top
+            SequenceNode snr = (SequenceNode) maxdist.parent();
+            changeDirection(snr, maxdist);
+            System.out.println("Printing reversed tree");
+            printN(snr);
+            snr.dist = tmpdist / 2;
+            maxdist.dist = tmpdist / 2;
+
+            snr.setParent(sn);
+            maxdist.setParent(sn);
+
+            sn.setRight(snr);
+            sn.setLeft(maxdist);
+
+            top = sn;
+
+            ycount = 0;
+            reCount(top);
+            findHeight(top);
+        }
+
+        return top;
+    }
+    /**
+     *
+     * @return true if original sequence data can be recovered
+     */
+    public boolean hasOriginalSequenceData() {
+      return seqData!=null;
+    }
+    /**
+     * Returns original alignment data used for calculation - or null where
+     * not available.
+     *
+     * @return null or cut'n'pasteable alignment
+     */
+    public String printOriginalSequenceData(char gapChar)
+    {
+      if (seqData==null)
+        return null;
+
+      StringBuffer sb = new StringBuffer();
+      String[] seqdatas = seqData.getSequenceStrings(gapChar);
+      for(int i=0; i<seqdatas.length; i++)
+      {
+        sb.append(new jalview.util.Format("%-" + 15 + "s").form(
+            sequence[i].getName()));
+        sb.append(" "+seqdatas[i]+"\n");
+      }
+      return sb.toString();
+    }
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     */
+    public void printN(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if ((node.left() != null) && (node.right() != null))
+        {
+            printN((SequenceNode) node.left());
+            printN((SequenceNode) node.right());
+        }
+        else
+        {
+            System.out.println(" name = " +
+                ((SequenceI) node.element()).getName());
+        }
+
+        System.out.println(" dist = " + ((SequenceNode) node).dist + " " +
+            ((SequenceNode) node).count + " " + ((SequenceNode) node).height);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     */
+    public void reCount(SequenceNode node)
+    {
+        ycount = 0;
+        _reCount(node);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     */
+    public void _reCount(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if ((node.left() != null) && (node.right() != null))
+        {
+            _reCount((SequenceNode) node.left());
+            _reCount((SequenceNode) node.right());
+
+            SequenceNode l = (SequenceNode) node.left();
+            SequenceNode r = (SequenceNode) node.right();
+
+            ((SequenceNode) node).count = l.count + r.count;
+            ((SequenceNode) node).ycount = (l.ycount + r.ycount) / 2;
+        }
+        else
+        {
+            ((SequenceNode) node).count = 1;
+            ((SequenceNode) node).ycount = ycount++;
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     */
+    public void swapNodes(SequenceNode node)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        SequenceNode tmp = (SequenceNode) node.left();
+
+        node.setLeft(node.right());
+        node.setRight(tmp);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param node DOCUMENT ME!
+     * @param dir DOCUMENT ME!
+     */
+    public void changeDirection(SequenceNode node, SequenceNode dir)
+    {
+        if (node == null)
+        {
+            return;
+        }
+
+        if (node.parent() != top)
+        {
+            changeDirection((SequenceNode) node.parent(), node);
+
+            SequenceNode tmp = (SequenceNode) node.parent();
+
+            if (dir == node.left())
+            {
+                node.setParent(dir);
+                node.setLeft(tmp);
+            }
+            else if (dir == node.right())
+            {
+                node.setParent(dir);
+                node.setRight(tmp);
+            }
+        }
+        else
+        {
+            if (dir == node.left())
+            {
+                node.setParent(node.left());
+
+                if (top.left() == node)
+                {
+                    node.setRight(top.right());
+                }
+                else
+                {
+                    node.setRight(top.left());
+                }
+            }
+            else
+            {
+                node.setParent(node.right());
+
+                if (top.left() == node)
+                {
+                    node.setLeft(top.right());
+                }
+                else
+                {
+                    node.setLeft(top.left());
+                }
+            }
+        }
+    }
+
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public SequenceNode getMaxDist()
+    {
+        return maxdist;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public SequenceNode getTopNode()
+    {
+        return top;
+    }
+    /**
+     *
+     * @return true if tree has real distances
+     */
+    public boolean isHasDistances() {
+      return hasDistances;
+    }
+
+    /**
+     *
+     * @return true if tree has real bootstrap values
+     */
+    public boolean isHasBootstrap() {
+      return hasBootstrap;
+    }
+
+  public boolean isHasRootDistance()
+  {
+    return hasRootDistance;
+  }
+
+}
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+class Cluster
+{
+    int[] value;
+
+    /**
+     * Creates a new Cluster object.
+     *
+     * @param value DOCUMENT ME!
+     */
+    public Cluster(int[] value)
+    {
+        this.value = value;
+    }
+}
+
index 6f468ae..1050a56 100755 (executable)
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-package jalview.bin;\r
-\r
-import java.io.*;\r
-\r
-import java.util.*;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.apache.log4j.SimpleLayout;\r
-import org.apache.log4j.Level;\r
-import org.apache.log4j.ConsoleAppender;\r
-\r
-\r
-/**\r
- * Stores and retrieves Jalview Application Properties\r
- * <br><br>Current properties include:\r
- * <br>logs.Axis.Level - one of the stringified Levels for log4j controlling the logging level for axis (used for web services)\r
- * <br>logs.Castor.Level - one of the stringified Levels for log4j controlling the logging level for castor (used for serialization)\r
- * <br>logs.Jalview.Level - Cache.log stringified level.\r
- * <br>DISCOVERY_START - Boolean - controls if discovery services are queried on startup\r
- * <br>DISCOVERY_URLS - comma separated list of Discovery Service endpoints.\r
- * <br>SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_Y=285,SCREEN_X=371,SHOW_FULLSCREEN\r
- * FONT_NAME,FONT_SIZE,FONT_STYLE,GAP_SYMBOL,LAST_DIRECTORY,USER_DEFINED_COLOUR\r
- * SHOW_FULL_ID,SHOW_IDENTITY,SHOW_QUALITY,SHOW_ANNOTATIONS,SHOW_CONSERVATION,\r
- * DEFAULT_COLOUR,DEFAULT_FILE_FORMAT,STARTUP_FILE,SHOW_STARTUP_FILE\r
-\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class Cache\r
-{\r
-  /**\r
-   * Initialises the Apache Axis logger\r
-   */\r
-  public static Logger log;\r
-\r
-    /** Jalview Properties */\r
-    public static Properties applicationProperties = new Properties();\r
-\r
-    /** Default file is  ~/.jalview_properties */\r
-    static String propertiesFile;\r
-\r
-    public static void initLogger()\r
-    {\r
-      try\r
-      {\r
-        Logger laxis = Logger.getLogger("org.apache.axis");\r
-        Logger lcastor = Logger.getLogger("org.exolab.castor");\r
-        jalview.bin.Cache.log = Logger.getLogger("jalview.bin.Jalview");\r
-\r
-        laxis.setLevel(Level.toLevel(Cache.getDefault("logs.Axis.Level",\r
-            Level.INFO.toString())));\r
-        lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",\r
-            Level.INFO.toString())));\r
-        jalview.bin.Cache.log.setLevel(Level.toLevel(Cache.getDefault(\r
-            "logs.Jalview.level",\r
-            Level.INFO.toString())));\r
-        ConsoleAppender ap = new ConsoleAppender(new SimpleLayout(),\r
-                                                 "System.err");\r
-        ap.setName("JalviewLogger");\r
-\r
-        laxis.addAppender(ap);\r
-        lcastor.addAppender(ap);\r
-        jalview.bin.Cache.log.addAppender(ap);\r
-        // Tell the user that debug is enabled\r
-        jalview.bin.Cache.log.debug("Jalview Debugging Output Follows.");\r
-      }\r
-      catch (Exception ex)\r
-      {\r
-      System.err.println("Problems initializing the log4j system\n");\r
-      }\r
-    }\r
-\r
-\r
-    /** Called when Jalview is started */\r
-    public static void loadProperties(String propsFile)\r
-    {\r
-        propertiesFile = propsFile;\r
-        if (propsFile == null)\r
-        {\r
-          propertiesFile = System.getProperty("user.home") + "/.jalview_properties";\r
-        }\r
-\r
-        try\r
-        {\r
-            FileInputStream fis = new FileInputStream(propertiesFile);\r
-            applicationProperties.load(fis);\r
-            applicationProperties.remove("LATEST_VERSION");\r
-            applicationProperties.remove("VERSION");\r
-            fis.close();\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-          System.out.println("Error reading properties file: "+ex);\r
-        }\r
-\r
-      if(getDefault("USE_PROXY", false))\r
-      {\r
-          System.out.println("Using proxyServer: "+getDefault("PROXY_SERVER", null)+\r
-                           " proxyPort: "+getDefault("PROXY_PORT", null));\r
-          System.setProperty("http.proxyHost", getDefault("PROXY_SERVER", null));\r
-          System.setProperty("http.proxyPort", getDefault("PROXY_PORT", null));\r
-      }\r
-\r
-        // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar\r
-        // MUST FOLLOW READING OF LOCAL PROPERTIES FILE AS THE\r
-        // VERSION MAY HAVE CHANGED SINCE LAST USING JALVIEW\r
-         try\r
-         {\r
-             String buildDetails = "jar:"\r
-                 .concat(\r
-                 Cache.class.getProtectionDomain().getCodeSource().getLocation().toString()\r
-                 .concat("!/.build_properties")\r
-                 );\r
-\r
-             java.net.URL localJarFileURL = new java.net.URL(buildDetails);\r
-\r
-            InputStream in = localJarFileURL.openStream();\r
-            applicationProperties.load(in);\r
-            in.close();\r
-         }\r
-         catch (Exception ex)\r
-         {\r
-           System.out.println("Error reading build details: "+ex);\r
-           applicationProperties.remove("VERSION");\r
-        }\r
-\r
-        String jnlpVersion = System.getProperty("jalview.version");\r
-        String codeVersion = getProperty("VERSION");\r
-\r
-\r
-        if(codeVersion==null)\r
-        {\r
-          // THIS SHOULD ONLY BE THE CASE WHEN TESTING!!\r
-          codeVersion = "Test";\r
-          jnlpVersion = "Test";\r
-        }\r
-\r
-\r
-        System.out.println("Jalview Version: "+codeVersion);\r
-\r
-\r
-        // jnlpVersion will be null if we're using InstallAnywhere\r
-        // Dont do this check if running in headless mode\r
-        if(jnlpVersion==null && (\r
-                System.getProperty("java.awt.headless")==null\r
-             || System.getProperty("java.awt.headless").equals("false")))\r
-        {\r
-\r
-          class VersionChecker\r
-              extends Thread\r
-          {\r
-            public void run()\r
-            {\r
-              String jnlpVersion = null;\r
-              try\r
-              {\r
-                java.net.URL url = new java.net.URL(\r
-                    "http://www.jalview.org/webstart/jalview.jnlp");\r
-                BufferedReader in = new BufferedReader(new InputStreamReader(url.\r
-                    openStream()));\r
-                String line = null;\r
-                while ( (line = in.readLine()) != null)\r
-                {\r
-                  if (line.indexOf("jalview.version") == -1)\r
-                    continue;\r
-\r
-                  line = line.substring(line.indexOf("value=") + 7);\r
-                  line = line.substring(0, line.lastIndexOf("\""));\r
-                  jnlpVersion = line;\r
-                  break;\r
-                }\r
-              }\r
-              catch (Exception ex)\r
-              {\r
-                System.out.println(ex);\r
-                jnlpVersion = getProperty("VERSION");\r
-              }\r
-\r
-              setProperty("LATEST_VERSION", jnlpVersion);\r
-            }\r
-          }\r
-\r
-          VersionChecker vc = new VersionChecker();\r
-          vc.start();\r
-        }\r
-        else\r
-        {\r
-          if(jnlpVersion!=null)\r
-            setProperty("LATEST_VERSION", jnlpVersion);\r
-          else\r
-          applicationProperties.remove("LATEST_VERSION");\r
-        }\r
-\r
-        setProperty("VERSION", codeVersion);\r
-\r
-        //LOAD USERDEFINED COLOURS\r
-        jalview.gui.UserDefinedColours.initUserColourSchemes( getProperty("USER_DEFINED_COLOURS"));\r
-        jalview.io.PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER", false);\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * Gets Jalview application property of given key. Returns null\r
-     * if key not found\r
-     *\r
-     * @param key Name of property\r
-     *\r
-     * @return Property value\r
-     */\r
-    public static String getProperty(String key)\r
-    {\r
-        return applicationProperties.getProperty(key);\r
-    }\r
-\r
-\r
-    /** These methods are used when checking if the saved preference\r
-     * is different to the default setting\r
-     */\r
-\r
-    public static boolean getDefault(String property, boolean def)\r
-    {\r
-      String string = getProperty(property);\r
-      if (string != null)\r
-      {\r
-        def = Boolean.valueOf(string).booleanValue();\r
-      }\r
-\r
-      return def;\r
-    }\r
-\r
-    /** These methods are used when checking if the saved preference\r
-    * is different to the default setting\r
-    */\r
-    public static String getDefault(String property, String def)\r
-    {\r
-      String string = getProperty(property);\r
-      if (string != null)\r
-      {\r
-        return string;\r
-      }\r
-\r
-      return def;\r
-    }\r
-\r
-\r
-    /**\r
-     * Stores property in the file "HOME_DIR/.jalview_properties"\r
-     *\r
-     * @param key Name of object\r
-     * @param obj String value of property\r
-     *\r
-     * @return String value of property\r
-     */\r
-    public static String setProperty(String key, String obj)\r
-    {\r
-        try\r
-        {\r
-            FileOutputStream out = new FileOutputStream(propertiesFile);\r
-            applicationProperties.setProperty(key, obj);\r
-            applicationProperties.store(out, "---JalviewX Properties File---");\r
-            out.close();\r
-        }\r
-        catch (Exception ex)\r
-        {   System.out.println("Error setting property: "+key+" "+obj+"\n"+ex);   }\r
-        return obj;\r
-    }\r
-\r
-    public static void saveProperties()\r
-    {\r
-        try\r
-        {\r
-            FileOutputStream out = new FileOutputStream(propertiesFile);\r
-            applicationProperties.store(out, "---JalviewX Properties File---");\r
-            out.close();\r
-        }\r
-        catch (Exception ex)\r
-        {  System.out.println("Error saving properties: "+ex);  }\r
-    }\r
-}\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * 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
+ */
+package jalview.bin;
+
+import java.io.*;
+
+import java.util.*;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.SimpleLayout;
+import org.apache.log4j.Level;
+import org.apache.log4j.ConsoleAppender;
+
+
+/**
+ * Stores and retrieves Jalview Application Properties
+ * <br><br>Current properties include:
+ * <br>logs.Axis.Level - one of the stringified Levels for log4j controlling the logging level for axis (used for web services)
+ * <br>logs.Castor.Level - one of the stringified Levels for log4j controlling the logging level for castor (used for serialization)
+ * <br>logs.Jalview.Level - Cache.log stringified level.
+ * <br>DISCOVERY_START - Boolean - controls if discovery services are queried on startup
+ * <br>DISCOVERY_URLS - comma separated list of Discovery Service endpoints.
+ * <br>SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_Y=285,SCREEN_X=371,SHOW_FULLSCREEN
+ * FONT_NAME,FONT_SIZE,FONT_STYLE,GAP_SYMBOL,LAST_DIRECTORY,USER_DEFINED_COLOUR
+ * SHOW_FULL_ID,SHOW_IDENTITY,SHOW_QUALITY,SHOW_ANNOTATIONS,SHOW_CONSERVATION,
+ * DEFAULT_COLOUR,DEFAULT_FILE_FORMAT,STARTUP_FILE,SHOW_STARTUP_FILE
+
+ * @author $author$
+ * @version $Revision$
+ */
+public class Cache
+{
+  /**
+   * Initialises the Apache Axis logger
+   */
+  public static Logger log;
+
+    /** Jalview Properties */
+    public static Properties applicationProperties = new Properties();
+
+    /** Default file is  ~/.jalview_properties */
+    static String propertiesFile;
+
+    public static void initLogger()
+    {
+      try
+      {
+        Logger laxis = Logger.getLogger("org.apache.axis");
+        Logger lcastor = Logger.getLogger("org.exolab.castor");
+        jalview.bin.Cache.log = Logger.getLogger("jalview.bin.Jalview");
+
+        laxis.setLevel(Level.toLevel(Cache.getDefault("logs.Axis.Level",
+            Level.INFO.toString())));
+        lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",
+            Level.INFO.toString())));
+        jalview.bin.Cache.log.setLevel(Level.toLevel(Cache.getDefault(
+            "logs.Jalview.level",
+            Level.INFO.toString())));
+        ConsoleAppender ap = new ConsoleAppender(new SimpleLayout(),
+                                                 "System.err");
+        ap.setName("JalviewLogger");
+
+        laxis.addAppender(ap);
+        lcastor.addAppender(ap);
+        jalview.bin.Cache.log.addAppender(ap);
+        // Tell the user that debug is enabled
+        jalview.bin.Cache.log.debug("Jalview Debugging Output Follows.");
+      }
+      catch (Exception ex)
+      {
+      System.err.println("Problems initializing the log4j system\n");
+      }
+    }
+
+
+    /** Called when Jalview is started */
+    public static void loadProperties(String propsFile)
+    {
+        propertiesFile = propsFile;
+        if (propsFile == null)
+        {
+          propertiesFile = System.getProperty("user.home") + "/.jalview_properties";
+        }
+
+        try
+        {
+            FileInputStream fis = new FileInputStream(propertiesFile);
+            applicationProperties.load(fis);
+            applicationProperties.remove("LATEST_VERSION");
+            applicationProperties.remove("VERSION");
+            fis.close();
+        }
+        catch (Exception ex)
+        {
+          System.out.println("Error reading properties file: "+ex);
+        }
+
+      if(getDefault("USE_PROXY", false))
+      {
+          System.out.println("Using proxyServer: "+getDefault("PROXY_SERVER", null)+
+                           " proxyPort: "+getDefault("PROXY_PORT", null));
+          System.setProperty("http.proxyHost", getDefault("PROXY_SERVER", null));
+          System.setProperty("http.proxyPort", getDefault("PROXY_PORT", null));
+      }
+
+        // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar
+        // MUST FOLLOW READING OF LOCAL PROPERTIES FILE AS THE
+        // VERSION MAY HAVE CHANGED SINCE LAST USING JALVIEW
+         try
+         {
+             String buildDetails = "jar:"
+                 .concat(
+                 Cache.class.getProtectionDomain().getCodeSource().getLocation().toString()
+                 .concat("!/.build_properties")
+                 );
+
+             java.net.URL localJarFileURL = new java.net.URL(buildDetails);
+
+            InputStream in = localJarFileURL.openStream();
+            applicationProperties.load(in);
+            in.close();
+         }
+         catch (Exception ex)
+         {
+           System.out.println("Error reading build details: "+ex);
+           applicationProperties.remove("VERSION");
+        }
+
+        String jnlpVersion = System.getProperty("jalview.version");
+        String codeVersion = getProperty("VERSION");
+
+
+        if(codeVersion==null)
+        {
+          // THIS SHOULD ONLY BE THE CASE WHEN TESTING!!
+          codeVersion = "Test";
+          jnlpVersion = "Test";
+        }
+
+
+        System.out.println("Jalview Version: "+codeVersion);
+
+
+        // jnlpVersion will be null if we're using InstallAnywhere
+        // Dont do this check if running in headless mode
+        if(jnlpVersion==null && (
+                System.getProperty("java.awt.headless")==null
+             || System.getProperty("java.awt.headless").equals("false")))
+        {
+
+          class VersionChecker
+              extends Thread
+          {
+            public void run()
+            {
+              String jnlpVersion = null;
+              try
+              {
+                java.net.URL url = new java.net.URL(
+                    "http://www.jalview.org/webstart/jalview.jnlp");
+                BufferedReader in = new BufferedReader(new InputStreamReader(url.
+                    openStream()));
+                String line = null;
+                while ( (line = in.readLine()) != null)
+                {
+                  if (line.indexOf("jalview.version") == -1)
+                    continue;
+
+                  line = line.substring(line.indexOf("value=") + 7);
+                  line = line.substring(0, line.lastIndexOf("\""));
+                  jnlpVersion = line;
+                  break;
+                }
+              }
+              catch (Exception ex)
+              {
+                System.out.println(ex);
+                jnlpVersion = getProperty("VERSION");
+              }
+
+              setProperty("LATEST_VERSION", jnlpVersion);
+            }
+          }
+
+          VersionChecker vc = new VersionChecker();
+          vc.start();
+        }
+        else
+        {
+          if(jnlpVersion!=null)
+            setProperty("LATEST_VERSION", jnlpVersion);
+          else
+          applicationProperties.remove("LATEST_VERSION");
+        }
+
+        setProperty("VERSION", codeVersion);
+
+        //LOAD USERDEFINED COLOURS
+        jalview.gui.UserDefinedColours.initUserColourSchemes( getProperty("USER_DEFINED_COLOURS"));
+        jalview.io.PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER", false);
+    }
+
+
+
+    /**
+     * Gets Jalview application property of given key. Returns null
+     * if key not found
+     *
+     * @param key Name of property
+     *
+     * @return Property value
+     */
+    public static String getProperty(String key)
+    {
+        return applicationProperties.getProperty(key);
+    }
+
+
+    /** These methods are used when checking if the saved preference
+     * is different to the default setting
+     */
+
+    public static boolean getDefault(String property, boolean def)
+    {
+      String string = getProperty(property);
+      if (string != null)
+      {
+        def = Boolean.valueOf(string).booleanValue();
+      }
+
+      return def;
+    }
+
+    /** These methods are used when checking if the saved preference
+    * is different to the default setting
+    */
+    public static String getDefault(String property, String def)
+    {
+      String string = getProperty(property);
+      if (string != null)
+      {
+        return string;
+      }
+
+      return def;
+    }
+
+
+    /**
+     * Stores property in the file "HOME_DIR/.jalview_properties"
+     *
+     * @param key Name of object
+     * @param obj String value of property
+     *
+     * @return String value of property
+     */
+    public static String setProperty(String key, String obj)
+    {
+        try
+        {
+            FileOutputStream out = new FileOutputStream(propertiesFile);
+            applicationProperties.setProperty(key, obj);
+            applicationProperties.store(out, "---JalviewX Properties File---");
+            out.close();
+        }
+        catch (Exception ex)
+        {   System.out.println("Error setting property: "+key+" "+obj+"\n"+ex);   }
+        return obj;
+    }
+
+    public static void saveProperties()
+    {
+        try
+        {
+            FileOutputStream out = new FileOutputStream(propertiesFile);
+            applicationProperties.store(out, "---JalviewX Properties File---");
+            out.close();
+        }
+        catch (Exception ex)
+        {  System.out.println("Error saving properties: "+ex);  }
+    }
+    /**
+     * internal vamsas class discovery state
+     */
+    private static int vamsasJarsArePresent=-1;
+    /**
+     * Searches for vamsas client classes on class path.
+     * @return true if vamsas client is present on classpath
+     */
+    public static boolean vamsasJarsPresent() {
+      if (vamsasJarsArePresent==-1) {
+        try {
+          if (jalview.jbgui.GDesktop.class.getClassLoader().loadClass("org.vamsas.client.VorbaId")!=null) {
+            jalview.bin.Cache.log.debug("Found Vamsas Classes (org.vamsas.client.VorbaId can be loaded)");
+            vamsasJarsArePresent=1;
+          }
+        } catch (Exception e) {
+          vamsasJarsArePresent=0;
+          jalview.bin.Cache.log.debug("Vamsas Classes are not present");
+        }
+      }
+      return (vamsasJarsArePresent>0);
+    }
+
+}
index f7c8840..77f1e41 100755 (executable)
@@ -2747,16 +2747,26 @@ public class AlignFrame
   {
     return ShowNewickTree(nf,title,600,500,4,5);
   }
+  public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input)
+  {
+    return ShowNewickTree(nf,title, input, 600,500,4,5);
+  }
+  public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y) {
+    return ShowNewickTree(nf, title, null, w, h, x, y);
+  }
   /**
-   * DOCUMENT ME!
+   * Add a treeviewer for the tree extracted from a newick file object to the current alignment view 
    *
-   * @param nf DOCUMENT ME!
-   * @param title DOCUMENT ME!
-   *
-   * @return DOCUMENT ME!
+   * @param nf the tree
+   * @param title tree viewer title
+   * @param input Associated alignment input data (or null)
+   * @param w width
+   * @param h height
+   * @param x position
+   * @param y position
+   * @return TreePanel handle
    */
-  public TreePanel ShowNewickTree(NewickFile nf, String title, int w,int h,int x, int y)
-  {
+  public TreePanel ShowNewickTree(NewickFile nf, String title, AlignmentView input, int w,int h,int x, int y) {
     TreePanel tp = null;
 
     try
@@ -2768,7 +2778,7 @@ public class AlignFrame
         tp = new TreePanel(alignPanel,
                            "FromFile",
                            title,
-                           nf);
+                           nf, input);
 
         tp.setSize(w,h);
 
index 163e297..eb62972 100755 (executable)
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-package jalview.gui;\r
-\r
-import jalview.io.*;\r
-\r
-import java.awt.*;\r
-import java.awt.datatransfer.*;\r
-import java.awt.dnd.*;\r
-import java.awt.event.*;\r
-import java.util.*;\r
-\r
-import javax.swing.*;\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class Desktop extends jalview.jbgui.GDesktop\r
-    implements DropTargetListener, ClipboardOwner\r
-{\r
-    /** DOCUMENT ME!! */\r
-    public static Desktop instance;\r
-    public static JDesktopPane desktop;\r
-    static int openFrameCount = 0;\r
-    static final int xOffset = 30;\r
-    static final int yOffset = 30;\r
-    public static jalview.ws.Discoverer discoverer;\r
-\r
-    public static Object [] jalviewClipboard;\r
-\r
-    static int fileLoadingCount= 0;\r
-\r
-    /**\r
-     * Creates a new Desktop object.\r
-     */\r
-    public Desktop()\r
-    {\r
-        instance = this;\r
-\r
-        Image image = null;\r
-\r
-        try\r
-        {\r
-            java.net.URL url = getClass().getResource("/images/logo.gif");\r
-\r
-            if (url != null)\r
-            {\r
-                image = java.awt.Toolkit.getDefaultToolkit().createImage(url);\r
-\r
-                MediaTracker mt = new MediaTracker(this);\r
-                mt.addImage(image, 0);\r
-                mt.waitForID(0);\r
-                setIconImage(image);\r
-            }\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-        }\r
-\r
-        setTitle("Jalview "+jalview.bin.Cache.getProperty("VERSION"));\r
-        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
-        desktop = new JDesktopPane();\r
-        desktop.setBackground(Color.white);\r
-        getContentPane().setLayout(new BorderLayout());\r
-        getContentPane().add(desktop, BorderLayout.CENTER);\r
-        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);\r
-\r
-        // This line prevents Windows Look&Feel resizing all new windows to maximum\r
-        // if previous window was maximised\r
-        desktop.setDesktopManager(new DefaultDesktopManager());\r
-\r
-        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();\r
-        String x = jalview.bin.Cache.getProperty("SCREEN_X");\r
-        String y = jalview.bin.Cache.getProperty("SCREEN_Y");\r
-        String width = jalview.bin.Cache.getProperty("SCREEN_WIDTH");\r
-        String height = jalview.bin.Cache.getProperty("SCREEN_HEIGHT");\r
-\r
-        if ((x != null) && (y != null) && (width != null) && (height != null))\r
-        {\r
-            setBounds(Integer.parseInt(x), Integer.parseInt(y),\r
-                Integer.parseInt(width), Integer.parseInt(height));\r
-        }\r
-        else\r
-        {\r
-            setBounds((int) (screenSize.width - 900) / 2,\r
-                (int) (screenSize.height - 650) / 2, 900, 650);\r
-        }\r
-\r
-        this.addWindowListener(new WindowAdapter()\r
-            {\r
-                public void windowClosing(WindowEvent evt)\r
-                {\r
-                    quit();\r
-                }\r
-            });\r
-\r
-        this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));\r
-\r
-        /////////Add a splashscreen on startup\r
-        /////////Add a splashscreen on startup\r
-        JInternalFrame frame = new JInternalFrame();\r
-\r
-        SplashScreen splash = new SplashScreen(frame, image);\r
-        frame.setContentPane(splash);\r
-        frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
-        frame.setLocation((int) ((getWidth() - 750) / 2),\r
-            (int) ((getHeight() - 160) / 2));\r
-\r
-        addInternalFrame(frame, "", 750, 160, false);\r
-\r
-        discoverer=new jalview.ws.Discoverer(); // Only gets started if gui is displayed.\r
-\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param frame DOCUMENT ME!\r
-     * @param title DOCUMENT ME!\r
-     * @param w DOCUMENT ME!\r
-     * @param h DOCUMENT ME!\r
-     */\r
-    public static synchronized void addInternalFrame(final JInternalFrame frame,\r
-        String title, int w, int h)\r
-    {\r
-        addInternalFrame(frame, title, w, h, true);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param frame DOCUMENT ME!\r
-     * @param title DOCUMENT ME!\r
-     * @param w DOCUMENT ME!\r
-     * @param h DOCUMENT ME!\r
-     * @param resizable DOCUMENT ME!\r
-     */\r
-    public static synchronized void addInternalFrame(final JInternalFrame frame,\r
-        String title, int w, int h, boolean resizable)\r
-    {\r
-\r
-      frame.setTitle(title);\r
-      if(frame.getWidth()<1 || frame.getHeight()<1)\r
-      {\r
-        frame.setSize(w, h);\r
-      }\r
-      // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN\r
-      // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN\r
-      // IF JALVIEW IS RUNNING HEADLESS\r
-      /////////////////////////////////////////////////\r
-      if (System.getProperty("java.awt.headless") != null\r
-          && System.getProperty("java.awt.headless").equals("true"))\r
-      {\r
-        return;\r
-      }\r
-\r
-\r
-        openFrameCount++;\r
-\r
-        frame.setVisible(true);\r
-        frame.setClosable(true);\r
-        frame.setResizable(resizable);\r
-        frame.setMaximizable(resizable);\r
-        frame.setIconifiable(resizable);\r
-        frame.setFrameIcon(null);\r
-\r
-        if (frame.getX()<1 && frame.getY()<1)\r
-       {\r
-         frame.setLocation(xOffset * openFrameCount, yOffset * ((openFrameCount-1)%10)+yOffset);\r
-       }\r
-\r
-        final JMenuItem menuItem = new JMenuItem(title);\r
-        frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
-            {\r
-              public void internalFrameActivated(javax.swing.event.\r
-                                                 InternalFrameEvent evt)\r
-              {\r
-                JInternalFrame itf = desktop.getSelectedFrame();\r
-                if (itf != null)\r
-                  itf.requestFocus();\r
-\r
-              }\r
-\r
-                public void internalFrameClosed(\r
-                    javax.swing.event.InternalFrameEvent evt)\r
-                {\r
-                    openFrameCount--;\r
-                    windowMenu.remove(menuItem);\r
-                    JInternalFrame itf = desktop.getSelectedFrame();\r
-                       if (itf != null)\r
-                        itf.requestFocus();\r
-                }\r
-                ;\r
-            });\r
-\r
-        menuItem.addActionListener(new ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    try\r
-                    {\r
-                        frame.setSelected(true);\r
-                        frame.setIcon(false);\r
-                    }\r
-                    catch (java.beans.PropertyVetoException ex)\r
-                    {\r
-\r
-                    }\r
-                }\r
-            });\r
-\r
-        windowMenu.add(menuItem);\r
-\r
-        desktop.add(frame);\r
-        frame.toFront();\r
-        try{\r
-          frame.setSelected(true);\r
-          frame.requestFocus();\r
-        }catch(java.beans.PropertyVetoException ve)\r
-        {}\r
-    }\r
-\r
-    public void lostOwnership(Clipboard clipboard, Transferable contents)\r
-    {\r
-      Desktop.jalviewClipboard = null;\r
-    }\r
-\r
-    public void dragEnter(DropTargetDragEvent evt)\r
-    {}\r
-\r
-    public void dragExit(DropTargetEvent evt)\r
-    {}\r
-\r
-    public void dragOver(DropTargetDragEvent evt)\r
-    {}\r
-\r
-    public void dropActionChanged(DropTargetDragEvent evt)\r
-    {}\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param evt DOCUMENT ME!\r
-     */\r
-    public void drop(DropTargetDropEvent evt)\r
-    {\r
-        Transferable t = evt.getTransferable();\r
-        java.util.List files = null;\r
-\r
-        try\r
-        {\r
-          DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");\r
-          if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))\r
-          {\r
-            //Works on Windows and MacOSX\r
-            evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);\r
-            files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);\r
-          }\r
-          else if (t.isDataFlavorSupported(uriListFlavor))\r
-          {\r
-            // This is used by Unix drag system\r
-            evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);\r
-            String data = (String) t.getTransferData(uriListFlavor);\r
-            files = new java.util.ArrayList(1);\r
-            for (java.util.StringTokenizer st = new java.util.StringTokenizer(\r
-                data,\r
-                "\r\n");\r
-                 st.hasMoreTokens(); )\r
-            {\r
-              String s = st.nextToken();\r
-              if (s.startsWith("#"))\r
-              {\r
-                // the line is a comment (as per the RFC 2483)\r
-                continue;\r
-              }\r
-\r
-              java.net.URI uri = new java.net.URI(s);\r
-              java.io.File file = new java.io.File(uri);\r
-              files.add(file);\r
-            }\r
-          }\r
-        }\r
-        catch (Exception e)\r
-        {\r
-          e.printStackTrace();\r
-        }\r
-\r
-        if (files != null)\r
-        {\r
-          try\r
-          {\r
-            for (int i = 0; i < files.size(); i++)\r
-            {\r
-              String file = files.get(i).toString();\r
-              String protocol = FormatAdapter.FILE;\r
-              String format = null;\r
-\r
-              if (file.endsWith(".jar"))\r
-              {\r
-                format = "Jalview";\r
-\r
-              }\r
-              else\r
-              {\r
-                format = new IdentifyFile().Identify(file,\r
-                                                          protocol);\r
-              }\r
-\r
-\r
-              new FileLoader().LoadFile(file, protocol, format);\r
-\r
-            }\r
-          }\r
-          catch (Exception ex)\r
-          {\r
-            ex.printStackTrace();\r
-          }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)\r
-    {\r
-        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                    "LAST_DIRECTORY"),\r
-                new String[]\r
-                {\r
-                    "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc",\r
-                    "jar"\r
-                },\r
-                new String[]\r
-                {\r
-                    "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"\r
-                }, jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));\r
-\r
-        chooser.setFileView(new JalviewFileView());\r
-        chooser.setDialogTitle("Open local file");\r
-        chooser.setToolTipText("Open");\r
-\r
-        int value = chooser.showOpenDialog(this);\r
-\r
-        if (value == JalviewFileChooser.APPROVE_OPTION)\r
-        {\r
-            String choice = chooser.getSelectedFile().getPath();\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
-                chooser.getSelectedFile().getParent());\r
-\r
-            String format = null;\r
-            if (chooser.getSelectedFormat().equals("Jalview"))\r
-            {\r
-                format = "Jalview";\r
-            }\r
-            else\r
-            {\r
-                format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);\r
-            }\r
-\r
-            if (viewport != null)\r
-              new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE, format);\r
-            else\r
-              new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);\r
-        }\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void inputURLMenuItem_actionPerformed(AlignViewport viewport)\r
-    {\r
-      // This construct allows us to have a wider textfield\r
-      // for viewing\r
-      JLabel label = new JLabel("Enter URL of Input File");\r
-      final JComboBox history = new JComboBox();\r
-\r
-      JPanel panel = new JPanel(new GridLayout(2,1));\r
-      panel.add(label);\r
-      panel.add(history);\r
-      history.setPreferredSize(new Dimension(400,20));\r
-      history.setEditable(true);\r
-      history.addItem("http://www.");\r
-\r
-      String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");\r
-\r
-      StringTokenizer st;\r
-\r
-      if (historyItems != null)\r
-      {\r
-        st = new StringTokenizer(historyItems, "\t");\r
-\r
-        while (st.hasMoreTokens())\r
-        {\r
-          history.addItem(st.nextElement());\r
-        }\r
-      }\r
-\r
-       int reply = JOptionPane.showInternalConfirmDialog(desktop,\r
-          panel, "Input Alignment From URL",\r
-          JOptionPane.OK_CANCEL_OPTION );\r
-\r
-\r
-        if (reply != JOptionPane.OK_OPTION )\r
-        {\r
-            return;\r
-        }\r
-\r
-        String url = history.getSelectedItem().toString();\r
-\r
-        if (url.toLowerCase().endsWith(".jar"))\r
-        {\r
-          if (viewport != null)\r
-            new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, "Jalview");\r
-          else\r
-            new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");\r
-        }\r
-        else\r
-        {\r
-          String format = new IdentifyFile().Identify(url, FormatAdapter.URL);\r
-\r
-          if (format.equals("URL NOT FOUND"))\r
-          {\r
-            JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
-                                                  "Couldn't locate " + url,\r
-                                                  "URL not found",\r
-                                                  JOptionPane.WARNING_MESSAGE);\r
-\r
-            return;\r
-          }\r
-\r
-          if (viewport != null)\r
-            new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);\r
-          else\r
-            new FileLoader().LoadFile(url, FormatAdapter.URL, format);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)\r
-    {\r
-        CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
-        cap.setForInput(viewport);\r
-        Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);\r
-    }\r
-\r
-    /*\r
-     * Exit the program\r
-     */\r
-    public void quit()\r
-    {\r
-        jalview.bin.Cache.setProperty("SCREEN_X", getBounds().x + "");\r
-        jalview.bin.Cache.setProperty("SCREEN_Y", getBounds().y + "");\r
-        jalview.bin.Cache.setProperty("SCREEN_WIDTH", getWidth() + "");\r
-        jalview.bin.Cache.setProperty("SCREEN_HEIGHT", getHeight() + "");\r
-        System.exit(0);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void aboutMenuItem_actionPerformed(ActionEvent e)\r
-    {\r
-      StringBuffer message = new StringBuffer("JalView version " +\r
-                                              jalview.bin.Cache.getProperty(\r
-          "VERSION") +\r
-                                              "; last updated: " +\r
-                                              jalview.bin.\r
-                                              Cache.getDefault("BUILD_DATE", "unknown"));\r
-\r
-      if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(\r
-          jalview.bin.Cache.getProperty("VERSION")))\r
-      {\r
-        message.append("\n\n!! Jalview version "\r
-                       + jalview.bin.Cache.getProperty("LATEST_VERSION")\r
-                       + " is available for download from http://www.jalview.org !!\n");\r
-\r
-      }\r
-\r
-      message.append( "\nAuthors:  Michele Clamp, James Cuff, Steve Searle, Andrew Waterhouse, Jim Procter & Geoff Barton." +\r
-            "\nCurrent development managed by Andrew Waterhouse; Barton Group, University of Dundee." +\r
-            "\nFor all issues relating to Jalview, email help@jalview.org" +\r
-            "\n\nIf  you use JalView, please cite:" +\r
-            "\n\"Clamp, M., Cuff, J., Searle, S. M. and Barton, G. J. (2004), The Jalview Java Alignment Editor\"" +\r
-            "\nBioinformatics,  2004 20;426-7.");\r
-\r
-        JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
-\r
-           message.toString(), "About Jalview",\r
-            JOptionPane.INFORMATION_MESSAGE);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void documentationMenuItem_actionPerformed(ActionEvent e)\r
-    {\r
-        try\r
-        {\r
-            ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();\r
-            java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");\r
-            javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);\r
-\r
-            javax.help.HelpBroker hb = hs.createHelpBroker();\r
-            hb.setCurrentID("home");\r
-            hb.setDisplayed(true);\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-            ex.printStackTrace();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void preferences_actionPerformed(ActionEvent e)\r
-    {\r
-        new Preferences();\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void saveState_actionPerformed(ActionEvent e)\r
-    {\r
-        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                    "LAST_DIRECTORY"), new String[] { "jar" },\r
-                new String[] { "Jalview Project" }, "Jalview Project");\r
-\r
-        chooser.setFileView(new JalviewFileView());\r
-        chooser.setDialogTitle("Save State");\r
-\r
-        int value = chooser.showSaveDialog(this);\r
-\r
-        if (value == JalviewFileChooser.APPROVE_OPTION)\r
-        {\r
-            java.io.File choice = chooser.getSelectedFile();\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());\r
-            new Jalview2XML().SaveState(choice);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void loadState_actionPerformed(ActionEvent e)\r
-    {\r
-        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                    "LAST_DIRECTORY"), new String[] { "jar" },\r
-                new String[] { "Jalview Project" }, "Jalview Project");\r
-        chooser.setFileView(new JalviewFileView());\r
-        chooser.setDialogTitle("Restore state");\r
-\r
-        int value = chooser.showOpenDialog(this);\r
-\r
-        if (value == JalviewFileChooser.APPROVE_OPTION)\r
-        {\r
-            String choice = chooser.getSelectedFile().getAbsolutePath();\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
-                chooser.getSelectedFile().getParent());\r
-            new Jalview2XML().LoadJalviewAlign(choice);\r
-        }\r
-    }\r
-\r
-  /*  public void vamsasLoad_actionPerformed(ActionEvent e)\r
-    {\r
-      JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
-          getProperty("LAST_DIRECTORY"));\r
-\r
-      chooser.setFileView(new JalviewFileView());\r
-      chooser.setDialogTitle("Load Vamsas file");\r
-      chooser.setToolTipText("Import");\r
-\r
-      int value = chooser.showOpenDialog(this);\r
-\r
-      if (value == JalviewFileChooser.APPROVE_OPTION)\r
-      {\r
-        jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(null);\r
-        vs.load(\r
-            chooser.getSelectedFile().getAbsolutePath()\r
-            );\r
-      }\r
-\r
-    }*/\r
-\r
-\r
-    public void inputSequence_actionPerformed(ActionEvent e)\r
-    {\r
-      new SequenceFetcher(null);\r
-    }\r
-\r
-    JPanel progressPanel;\r
-\r
-    public void startLoading(final String fileName)\r
-    {\r
-      if (fileLoadingCount == 0)\r
-      {\r
-        progressPanel = new JPanel(new BorderLayout());\r
-        JProgressBar progressBar = new JProgressBar();\r
-        progressBar.setIndeterminate(true);\r
-\r
-        progressPanel.add(new JLabel("Loading File: " + fileName + "   "),\r
-                          BorderLayout.WEST);\r
-\r
-        progressPanel.add(progressBar, BorderLayout.CENTER);\r
-\r
-        instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);\r
-      }\r
-      fileLoadingCount++;\r
-      validate();\r
-    }\r
-\r
-    public void stopLoading()\r
-    {\r
-      fileLoadingCount--;\r
-      if (fileLoadingCount < 1)\r
-      {\r
-        if(progressPanel!=null)\r
-        {\r
-          this.getContentPane().remove(progressPanel);\r
-          progressPanel = null;\r
-        }\r
-        fileLoadingCount = 0;\r
-      }\r
-      validate();\r
-    }\r
-\r
-    public static int getViewCount(String viewId)\r
-    {\r
-      int count = 0;\r
-      JInternalFrame[] frames = Desktop.desktop.getAllFrames();\r
-      for (int t = 0; t < frames.length; t++)\r
-      {\r
-        if (frames[t] instanceof AlignFrame)\r
-        {\r
-          AlignFrame af = (AlignFrame) frames[t];\r
-          for(int a=0; a<af.alignPanels.size(); a++)\r
-          {\r
-            if(viewId.equals(\r
-                ((AlignmentPanel)af.alignPanels.elementAt(a)).av.getSequenceSetId() )\r
-                )\r
-            count ++;\r
-          }\r
-        }\r
-      }\r
-\r
-      return count;\r
-    }\r
-\r
-    public void explodeViews(AlignFrame af)\r
-    {\r
-      int size = af.alignPanels.size();\r
-      if(size<2)\r
-        return;\r
-      af.closeMenuItem_actionPerformed(null);\r
-\r
-      for(int i=0; i<size; i++)\r
-      {\r
-        AlignmentPanel ap = (AlignmentPanel)af.alignPanels.elementAt(i);\r
-        AlignFrame newaf = new AlignFrame(ap);\r
-        if(ap.av.explodedPosition!=null)\r
-          newaf.setBounds(ap.av.explodedPosition);\r
-\r
-        ap.av.gatherViewsHere = false;\r
-\r
-        PaintRefresher.Register(ap.seqPanel.seqCanvas, ap.av.getSequenceSetId());\r
-        PaintRefresher.Register(ap.idPanel.idCanvas, ap.av.getSequenceSetId());\r
-        PaintRefresher.Register(ap, ap.av.getSequenceSetId());\r
-\r
-\r
-        newaf.viewport = ap.av;\r
-        addInternalFrame(newaf, af.getTitle(),\r
-                         AlignFrame.DEFAULT_WIDTH,\r
-                         AlignFrame.DEFAULT_HEIGHT);\r
-      }\r
-\r
-    }\r
-\r
-    public void gatherViews(AlignFrame source)\r
-    {\r
-      source.viewport.gatherViewsHere = true;\r
-      source.viewport.explodedPosition = source.getBounds();\r
-      JInternalFrame[] frames = Desktop.desktop.getAllFrames();\r
-      String viewId = source.viewport.sequenceSetID;\r
-\r
-      for (int t = 0; t < frames.length; t++)\r
-      {\r
-        if (frames[t] instanceof AlignFrame && frames[t] != source)\r
-        {\r
-          AlignFrame af = (AlignFrame) frames[t];\r
-          boolean gatherThis = false;\r
-          for (int a = 0; a < af.alignPanels.size(); a++)\r
-          {\r
-            AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);\r
-            if (viewId.equals(ap.av.getSequenceSetId()))\r
-            {\r
-              gatherThis = true;\r
-              ap.av.gatherViewsHere = false;\r
-              ap.av.explodedPosition = af.getBounds();\r
-              source.addAlignmentPanel(ap);\r
-            }\r
-          }\r
-          if (gatherThis)\r
-            af.closeMenuItem_actionPerformed(null);\r
-        }\r
-      }\r
-\r
-    }\r
-\r
-\r
-}\r
-\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * 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
+ */
+package jalview.gui;
+
+import jalview.io.*;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class Desktop extends jalview.jbgui.GDesktop
+    implements DropTargetListener, ClipboardOwner
+{
+    /** DOCUMENT ME!! */
+    public static Desktop instance;
+    public static JDesktopPane desktop;
+    static int openFrameCount = 0;
+    static final int xOffset = 30;
+    static final int yOffset = 30;
+    public static jalview.ws.Discoverer discoverer;
+
+    public static Object [] jalviewClipboard;
+
+    static int fileLoadingCount= 0;
+
+    /**
+     * Creates a new Desktop object.
+     */
+    public Desktop()
+    {
+        instance = this;
+        doVamsasClientCheck();
+        Image image = null;
+
+        try
+        {
+            java.net.URL url = getClass().getResource("/images/logo.gif");
+
+            if (url != null)
+            {
+                image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
+
+                MediaTracker mt = new MediaTracker(this);
+                mt.addImage(image, 0);
+                mt.waitForID(0);
+                setIconImage(image);
+            }
+        }
+        catch (Exception ex)
+        {
+        }
+
+        setTitle("Jalview "+jalview.bin.Cache.getProperty("VERSION"));
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        desktop = new JDesktopPane();
+        desktop.setBackground(Color.white);
+        getContentPane().setLayout(new BorderLayout());
+        getContentPane().add(desktop, BorderLayout.CENTER);
+        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
+
+        // This line prevents Windows Look&Feel resizing all new windows to maximum
+        // if previous window was maximised
+        desktop.setDesktopManager(new DefaultDesktopManager());
+
+        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        String x = jalview.bin.Cache.getProperty("SCREEN_X");
+        String y = jalview.bin.Cache.getProperty("SCREEN_Y");
+        String width = jalview.bin.Cache.getProperty("SCREEN_WIDTH");
+        String height = jalview.bin.Cache.getProperty("SCREEN_HEIGHT");
+
+        if ((x != null) && (y != null) && (width != null) && (height != null))
+        {
+            setBounds(Integer.parseInt(x), Integer.parseInt(y),
+                Integer.parseInt(width), Integer.parseInt(height));
+        }
+        else
+        {
+            setBounds((int) (screenSize.width - 900) / 2,
+                (int) (screenSize.height - 650) / 2, 900, 650);
+        }
+
+        this.addWindowListener(new WindowAdapter()
+            {
+                public void windowClosing(WindowEvent evt)
+                {
+                    quit();
+                }
+            });
+
+        this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
+
+        /////////Add a splashscreen on startup
+        /////////Add a splashscreen on startup
+        JInternalFrame frame = new JInternalFrame();
+
+        SplashScreen splash = new SplashScreen(frame, image);
+        frame.setContentPane(splash);
+        frame.setLayer(JLayeredPane.PALETTE_LAYER);
+        frame.setLocation((int) ((getWidth() - 750) / 2),
+            (int) ((getHeight() - 160) / 2));
+
+        addInternalFrame(frame, "", 750, 160, false);
+
+        discoverer=new jalview.ws.Discoverer(); // Only gets started if gui is displayed.
+    }
+
+    private void doVamsasClientCheck() {
+      if (jalview.bin.Cache.vamsasJarsPresent()) {
+        VamsasMenu.setVisible(true);
+        vamsasLoad.setVisible(true);
+      }
+      
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param frame DOCUMENT ME!
+     * @param title DOCUMENT ME!
+     * @param w DOCUMENT ME!
+     * @param h DOCUMENT ME!
+     */
+    public static synchronized void addInternalFrame(final JInternalFrame frame,
+        String title, int w, int h)
+    {
+        addInternalFrame(frame, title, w, h, true);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param frame DOCUMENT ME!
+     * @param title DOCUMENT ME!
+     * @param w DOCUMENT ME!
+     * @param h DOCUMENT ME!
+     * @param resizable DOCUMENT ME!
+     */
+    public static synchronized void addInternalFrame(final JInternalFrame frame,
+        String title, int w, int h, boolean resizable)
+    {
+
+      frame.setTitle(title);
+      if(frame.getWidth()<1 || frame.getHeight()<1)
+      {
+        frame.setSize(w, h);
+      }
+      // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
+      // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
+      // IF JALVIEW IS RUNNING HEADLESS
+      /////////////////////////////////////////////////
+      if (System.getProperty("java.awt.headless") != null
+          && System.getProperty("java.awt.headless").equals("true"))
+      {
+        return;
+      }
+
+
+        openFrameCount++;
+
+        frame.setVisible(true);
+        frame.setClosable(true);
+        frame.setResizable(resizable);
+        frame.setMaximizable(resizable);
+        frame.setIconifiable(resizable);
+        frame.setFrameIcon(null);
+
+        if (frame.getX()<1 && frame.getY()<1)
+       {
+         frame.setLocation(xOffset * openFrameCount, yOffset * ((openFrameCount-1)%10)+yOffset);
+       }
+
+        final JMenuItem menuItem = new JMenuItem(title);
+        frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
+            {
+              public void internalFrameActivated(javax.swing.event.
+                                                 InternalFrameEvent evt)
+              {
+                JInternalFrame itf = desktop.getSelectedFrame();
+                if (itf != null)
+                  itf.requestFocus();
+
+              }
+
+                public void internalFrameClosed(
+                    javax.swing.event.InternalFrameEvent evt)
+                {
+                    openFrameCount--;
+                    windowMenu.remove(menuItem);
+                    JInternalFrame itf = desktop.getSelectedFrame();
+                       if (itf != null)
+                        itf.requestFocus();
+                }
+                ;
+            });
+
+        menuItem.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    try
+                    {
+                        frame.setSelected(true);
+                        frame.setIcon(false);
+                    }
+                    catch (java.beans.PropertyVetoException ex)
+                    {
+
+                    }
+                }
+            });
+
+        windowMenu.add(menuItem);
+
+        desktop.add(frame);
+        frame.toFront();
+        try{
+          frame.setSelected(true);
+          frame.requestFocus();
+        }catch(java.beans.PropertyVetoException ve)
+        {}
+    }
+
+    public void lostOwnership(Clipboard clipboard, Transferable contents)
+    {
+      Desktop.jalviewClipboard = null;
+    }
+
+    public void dragEnter(DropTargetDragEvent evt)
+    {}
+
+    public void dragExit(DropTargetEvent evt)
+    {}
+
+    public void dragOver(DropTargetDragEvent evt)
+    {}
+
+    public void dropActionChanged(DropTargetDragEvent evt)
+    {}
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param evt DOCUMENT ME!
+     */
+    public void drop(DropTargetDropEvent evt)
+    {
+        Transferable t = evt.getTransferable();
+        java.util.List files = null;
+
+        try
+        {
+          DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
+          if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
+          {
+            //Works on Windows and MacOSX
+            evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+            files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
+          }
+          else if (t.isDataFlavorSupported(uriListFlavor))
+          {
+            // This is used by Unix drag system
+            evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+            String data = (String) t.getTransferData(uriListFlavor);
+            files = new java.util.ArrayList(1);
+            for (java.util.StringTokenizer st = new java.util.StringTokenizer(
+                data,
+                "\r\n");
+                 st.hasMoreTokens(); )
+            {
+              String s = st.nextToken();
+              if (s.startsWith("#"))
+              {
+                // the line is a comment (as per the RFC 2483)
+                continue;
+              }
+
+              java.net.URI uri = new java.net.URI(s);
+              java.io.File file = new java.io.File(uri);
+              files.add(file);
+            }
+          }
+        }
+        catch (Exception e)
+        {
+          e.printStackTrace();
+        }
+
+        if (files != null)
+        {
+          try
+          {
+            for (int i = 0; i < files.size(); i++)
+            {
+              String file = files.get(i).toString();
+              String protocol = FormatAdapter.FILE;
+              String format = null;
+
+              if (file.endsWith(".jar"))
+              {
+                format = "Jalview";
+
+              }
+              else
+              {
+                format = new IdentifyFile().Identify(file,
+                                                          protocol);
+              }
+
+
+              new FileLoader().LoadFile(file, protocol, format);
+
+            }
+          }
+          catch (Exception ex)
+          {
+            ex.printStackTrace();
+          }
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
+    {
+        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                    "LAST_DIRECTORY"),
+                new String[]
+                {
+                    "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc",
+                    "jar"
+                },
+                new String[]
+                {
+                    "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview"
+                }, jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
+
+        chooser.setFileView(new JalviewFileView());
+        chooser.setDialogTitle("Open local file");
+        chooser.setToolTipText("Open");
+
+        int value = chooser.showOpenDialog(this);
+
+        if (value == JalviewFileChooser.APPROVE_OPTION)
+        {
+            String choice = chooser.getSelectedFile().getPath();
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                chooser.getSelectedFile().getParent());
+
+            String format = null;
+            if (chooser.getSelectedFormat().equals("Jalview"))
+            {
+                format = "Jalview";
+            }
+            else
+            {
+                format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
+            }
+
+            if (viewport != null)
+              new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE, format);
+            else
+              new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
+        }
+    }
+
+
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
+    {
+      // This construct allows us to have a wider textfield
+      // for viewing
+      JLabel label = new JLabel("Enter URL of Input File");
+      final JComboBox history = new JComboBox();
+
+      JPanel panel = new JPanel(new GridLayout(2,1));
+      panel.add(label);
+      panel.add(history);
+      history.setPreferredSize(new Dimension(400,20));
+      history.setEditable(true);
+      history.addItem("http://www.");
+
+      String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
+
+      StringTokenizer st;
+
+      if (historyItems != null)
+      {
+        st = new StringTokenizer(historyItems, "\t");
+
+        while (st.hasMoreTokens())
+        {
+          history.addItem(st.nextElement());
+        }
+      }
+
+       int reply = JOptionPane.showInternalConfirmDialog(desktop,
+          panel, "Input Alignment From URL",
+          JOptionPane.OK_CANCEL_OPTION );
+
+
+        if (reply != JOptionPane.OK_OPTION )
+        {
+            return;
+        }
+
+        String url = history.getSelectedItem().toString();
+
+        if (url.toLowerCase().endsWith(".jar"))
+        {
+          if (viewport != null)
+            new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, "Jalview");
+          else
+            new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
+        }
+        else
+        {
+          String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
+
+          if (format.equals("URL NOT FOUND"))
+          {
+            JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                                                  "Couldn't locate " + url,
+                                                  "URL not found",
+                                                  JOptionPane.WARNING_MESSAGE);
+
+            return;
+          }
+
+          if (viewport != null)
+            new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
+          else
+            new FileLoader().LoadFile(url, FormatAdapter.URL, format);
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
+    {
+        CutAndPasteTransfer cap = new CutAndPasteTransfer();
+        cap.setForInput(viewport);
+        Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
+    }
+
+    /*
+     * Exit the program
+     */
+    public void quit()
+    {
+        jalview.bin.Cache.setProperty("SCREEN_X", getBounds().x + "");
+        jalview.bin.Cache.setProperty("SCREEN_Y", getBounds().y + "");
+        jalview.bin.Cache.setProperty("SCREEN_WIDTH", getWidth() + "");
+        jalview.bin.Cache.setProperty("SCREEN_HEIGHT", getHeight() + "");
+        System.exit(0);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void aboutMenuItem_actionPerformed(ActionEvent e)
+    {
+      StringBuffer message = new StringBuffer("JalView version " +
+                                              jalview.bin.Cache.getProperty(
+          "VERSION") +
+                                              "; last updated: " +
+                                              jalview.bin.
+                                              Cache.getDefault("BUILD_DATE", "unknown"));
+
+      if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
+          jalview.bin.Cache.getProperty("VERSION")))
+      {
+        message.append("\n\n!! Jalview version "
+                       + jalview.bin.Cache.getProperty("LATEST_VERSION")
+                       + " is available for download from http://www.jalview.org !!\n");
+
+      }
+
+      message.append( "\nAuthors:  Michele Clamp, James Cuff, Steve Searle, Andrew Waterhouse, Jim Procter & Geoff Barton." +
+            "\nCurrent development managed by Andrew Waterhouse; Barton Group, University of Dundee." +
+            "\nFor all issues relating to Jalview, email help@jalview.org" +
+            "\n\nIf  you use JalView, please cite:" +
+            "\n\"Clamp, M., Cuff, J., Searle, S. M. and Barton, G. J. (2004), The Jalview Java Alignment Editor\"" +
+            "\nBioinformatics,  2004 20;426-7.");
+
+        JOptionPane.showInternalMessageDialog(Desktop.desktop,
+
+           message.toString(), "About Jalview",
+            JOptionPane.INFORMATION_MESSAGE);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void documentationMenuItem_actionPerformed(ActionEvent e)
+    {
+        try
+        {
+            ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
+            java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
+            javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
+
+            javax.help.HelpBroker hb = hs.createHelpBroker();
+            hb.setCurrentID("home");
+            hb.setDisplayed(true);
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void preferences_actionPerformed(ActionEvent e)
+    {
+        new Preferences();
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void saveState_actionPerformed(ActionEvent e)
+    {
+        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                    "LAST_DIRECTORY"), new String[] { "jar" },
+                new String[] { "Jalview Project" }, "Jalview Project");
+
+        chooser.setFileView(new JalviewFileView());
+        chooser.setDialogTitle("Save State");
+
+        int value = chooser.showSaveDialog(this);
+
+        if (value == JalviewFileChooser.APPROVE_OPTION)
+        {
+            java.io.File choice = chooser.getSelectedFile();
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
+            new Jalview2XML().SaveState(choice);
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void loadState_actionPerformed(ActionEvent e)
+    {
+        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                    "LAST_DIRECTORY"), new String[] { "jar" },
+                new String[] { "Jalview Project" }, "Jalview Project");
+        chooser.setFileView(new JalviewFileView());
+        chooser.setDialogTitle("Restore state");
+
+        int value = chooser.showOpenDialog(this);
+
+        if (value == JalviewFileChooser.APPROVE_OPTION)
+        {
+            String choice = chooser.getSelectedFile().getAbsolutePath();
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                chooser.getSelectedFile().getParent());
+            new Jalview2XML().LoadJalviewAlign(choice);
+        }
+    }
+
+  /*  public void vamsasLoad_actionPerformed(ActionEvent e)
+    {
+      JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
+          getProperty("LAST_DIRECTORY"));
+
+      chooser.setFileView(new JalviewFileView());
+      chooser.setDialogTitle("Load Vamsas file");
+      chooser.setToolTipText("Import");
+
+      int value = chooser.showOpenDialog(this);
+
+      if (value == JalviewFileChooser.APPROVE_OPTION)
+      {
+        jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(null);
+        vs.load(
+            chooser.getSelectedFile().getAbsolutePath()
+            );
+      }
+
+    }*/
+
+
+    public void inputSequence_actionPerformed(ActionEvent e)
+    {
+      new SequenceFetcher(null);
+    }
+
+    JPanel progressPanel;
+
+    public void startLoading(final String fileName)
+    {
+      if (fileLoadingCount == 0)
+      {
+        progressPanel = new JPanel(new BorderLayout());
+        JProgressBar progressBar = new JProgressBar();
+        progressBar.setIndeterminate(true);
+
+        progressPanel.add(new JLabel("Loading File: " + fileName + "   "),
+                          BorderLayout.WEST);
+
+        progressPanel.add(progressBar, BorderLayout.CENTER);
+
+        instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
+      }
+      fileLoadingCount++;
+      validate();
+    }
+
+    public void stopLoading()
+    {
+      fileLoadingCount--;
+      if (fileLoadingCount < 1)
+      {
+        if(progressPanel!=null)
+        {
+          this.getContentPane().remove(progressPanel);
+          progressPanel = null;
+        }
+        fileLoadingCount = 0;
+      }
+      validate();
+    }
+
+    public static int getViewCount(String viewId)
+    {
+      int count = 0;
+      JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+      for (int t = 0; t < frames.length; t++)
+      {
+        if (frames[t] instanceof AlignFrame)
+        {
+          AlignFrame af = (AlignFrame) frames[t];
+          for(int a=0; a<af.alignPanels.size(); a++)
+          {
+            if(viewId.equals(
+                ((AlignmentPanel)af.alignPanels.elementAt(a)).av.getSequenceSetId() )
+                )
+            count ++;
+          }
+        }
+      }
+
+      return count;
+    }
+
+    public void explodeViews(AlignFrame af)
+    {
+      int size = af.alignPanels.size();
+      if(size<2)
+        return;
+      af.closeMenuItem_actionPerformed(null);
+
+      for(int i=0; i<size; i++)
+      {
+        AlignmentPanel ap = (AlignmentPanel)af.alignPanels.elementAt(i);
+        AlignFrame newaf = new AlignFrame(ap);
+        if(ap.av.explodedPosition!=null)
+          newaf.setBounds(ap.av.explodedPosition);
+
+        ap.av.gatherViewsHere = false;
+
+        PaintRefresher.Register(ap.seqPanel.seqCanvas, ap.av.getSequenceSetId());
+        PaintRefresher.Register(ap.idPanel.idCanvas, ap.av.getSequenceSetId());
+        PaintRefresher.Register(ap, ap.av.getSequenceSetId());
+
+
+        newaf.viewport = ap.av;
+        addInternalFrame(newaf, af.getTitle(),
+                         AlignFrame.DEFAULT_WIDTH,
+                         AlignFrame.DEFAULT_HEIGHT);
+      }
+
+    }
+
+    public void gatherViews(AlignFrame source)
+    {
+      source.viewport.gatherViewsHere = true;
+      source.viewport.explodedPosition = source.getBounds();
+      JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+      String viewId = source.viewport.sequenceSetID;
+
+      for (int t = 0; t < frames.length; t++)
+      {
+        if (frames[t] instanceof AlignFrame && frames[t] != source)
+        {
+          AlignFrame af = (AlignFrame) frames[t];
+          boolean gatherThis = false;
+          for (int a = 0; a < af.alignPanels.size(); a++)
+          {
+            AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
+            if (viewId.equals(ap.av.getSequenceSetId()))
+            {
+              gatherThis = true;
+              ap.av.gatherViewsHere = false;
+              ap.av.explodedPosition = af.getBounds();
+              source.addAlignmentPanel(ap);
+            }
+          }
+          if (gatherThis)
+            af.closeMenuItem_actionPerformed(null);
+        }
+      }
+
+    }
+
+    jalview.gui.VamsasClient v_client=null;
+    public void vamsasLoad_actionPerformed(ActionEvent e)
+    {
+      if (v_client==null) {
+        // Start a session.
+        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
+            getProperty("LAST_DIRECTORY"));
+
+        chooser.setFileView(new JalviewFileView());
+        chooser.setDialogTitle("Load Vamsas file");
+        chooser.setToolTipText("Import");
+
+        int value = chooser.showOpenDialog(this);
+
+        if (value == JalviewFileChooser.APPROVE_OPTION)
+        {
+          v_client = new jalview.gui.VamsasClient(this,
+              chooser.getSelectedFile());
+          this.vamsasLoad.setText("Session Update");
+          this.vamsasStop.setVisible(true);
+          v_client.initial_update();
+          v_client.startWatcher();
+        }
+      } else {
+        // store current data in session.
+        v_client.push_update();
+      }
+    }
+    public void vamsasStop_actionPerformed(ActionEvent e) {
+      if (v_client!=null) {
+        v_client.end_session();
+        v_client=null;
+        this.vamsasStop.setVisible(false);
+        this.vamsasLoad.setText("Start Vamsas Session...");
+      }
+    }
+    /**
+     * hide vamsas user gui bits when a vamsas document event is being handled.
+     * @param b true to hide gui, false to reveal gui
+     */
+    public void setVamsasUpdate(boolean b) {
+      jalview.bin.Cache.log.debug("Setting gui for Vamsas update "+(b ? "in progress" : "finished"));
+      vamsasLoad.setVisible(!b); 
+      vamsasStop.setVisible(!b);
+      
+    }
+}
+
index 06f8269..dc2b820 100755 (executable)
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-package jalview.gui;\r
-\r
-import jalview.analysis.*;\r
-\r
-import jalview.datamodel.*;\r
-\r
-import jalview.io.*;\r
-\r
-import jalview.jbgui.*;\r
-\r
-import org.jibble.epsgraphics.*;\r
-\r
-import java.awt.*;\r
-import java.awt.event.*;\r
-import java.awt.image.*;\r
-\r
-import java.io.*;\r
-\r
-import java.util.*;\r
-\r
-import javax.imageio.*;\r
-\r
-import java.beans.PropertyChangeEvent;\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class TreePanel extends GTreePanel\r
-{\r
-    String type;\r
-    String pwtype;\r
-    TreeCanvas treeCanvas;\r
-    NJTree tree;\r
-    AlignViewport av;\r
-\r
-    /**\r
-     * Creates a new TreePanel object.\r
-     *\r
-     * @param av DOCUMENT ME!\r
-     * @param seqVector DOCUMENT ME!\r
-     * @param type DOCUMENT ME!\r
-     * @param pwtype DOCUMENT ME!\r
-     * @param s DOCUMENT ME!\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public TreePanel(AlignmentPanel ap, String type, String pwtype)\r
-    {\r
-      super();\r
-      initTreePanel(ap, type, pwtype, null);\r
-\r
-      // We know this tree has distances. JBPNote TODO: prolly should add this as a userdefined default\r
-      // showDistances(true);\r
-    }\r
-\r
-    /**\r
-     * Creates a new TreePanel object.\r
-     *\r
-     * @param av DOCUMENT ME!\r
-     * @param seqVector DOCUMENT ME!\r
-     * @param newtree DOCUMENT ME!\r
-     * @param type DOCUMENT ME!\r
-     * @param pwtype DOCUMENT ME!\r
-     */\r
-    public TreePanel(AlignmentPanel ap,\r
-                     String type,\r
-                     String pwtype,\r
-                     NewickFile newtree)\r
-    {\r
-      super();\r
-      initTreePanel(ap, type, pwtype, newtree);\r
-    }\r
-\r
-    public AlignmentI getAlignment()\r
-    {\r
-      return treeCanvas.av.getAlignment();\r
-    }\r
-\r
-\r
-    void initTreePanel(AlignmentPanel ap, String type,  String pwtype,\r
-                       NewickFile newTree)\r
-    {\r
-\r
-      av = ap.av;\r
-      this.type = type;\r
-      this.pwtype = pwtype;\r
-\r
-      treeCanvas = new TreeCanvas(ap, scrollPane);\r
-      scrollPane.setViewportView(treeCanvas);\r
-\r
-      av.addPropertyChangeListener(new java.beans.PropertyChangeListener()\r
-      {\r
-        public void propertyChange(PropertyChangeEvent evt)\r
-        {\r
-          if (evt.getPropertyName().equals("alignment"))\r
-          {\r
-            if(tree==null)\r
-              System.out.println("tree is null");\r
-            if(evt.getNewValue()==null)\r
-              System.out.println("new value is null");\r
-\r
-            tree.UpdatePlaceHolders( (Vector) evt.getNewValue());\r
-\r
-            repaint();\r
-          }\r
-        }\r
-      });\r
-\r
-      this.av = av;\r
-\r
-\r
-      TreeLoader tl = new TreeLoader(newTree);\r
-      tl.start();\r
-\r
-    }\r
-\r
-    class TreeLoader extends Thread\r
-    {\r
-      NewickFile newtree;\r
-      jalview.datamodel.AlignmentView odata=null;\r
-      public TreeLoader(NewickFile newtree)\r
-      {\r
-        this.newtree = newtree;\r
-        if (newtree != null)\r
-        {\r
-          // Must be outside run(), as Jalview2XML tries to\r
-          // update distance/bootstrap visibility at the same time\r
-          showBootstrap(newtree.HasBootstrap());\r
-          showDistances(newtree.HasDistances());\r
-        }\r
-      }\r
-\r
-      public void run()\r
-      {\r
-\r
-        if(newtree!=null)\r
-        {\r
-          if (odata==null) {\r
-            tree = new NJTree(av.alignment.getSequencesArray(),\r
-                              newtree);\r
-          } else {\r
-            tree = new NJTree(av.alignment.getSequencesArray(), odata, newtree);\r
-          }\r
-          if (!tree.hasOriginalSequenceData())\r
-            allowOriginalSeqData(false);\r
-        }\r
-        else\r
-        {\r
-          int start, end;\r
-          SequenceI [] seqs;\r
-          AlignmentView seqStrings = av.getAlignmentView(av.getSelectionGroup()!=null);\r
-          if(av.getSelectionGroup()==null)\r
-          {\r
-            start = 0;\r
-            end = av.alignment.getWidth();\r
-            seqs = av.alignment.getSequencesArray();\r
-          }\r
-          else\r
-          {\r
-            start = av.getSelectionGroup().getStartRes();\r
-            end = av.getSelectionGroup().getEndRes()+1;\r
-            seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);\r
-          }\r
-\r
-          tree = new NJTree(seqs, seqStrings, type, pwtype, start, end);\r
-          showDistances(true);\r
-        }\r
-\r
-\r
-        tree.reCount(tree.getTopNode());\r
-        tree.findHeight(tree.getTopNode());\r
-        treeCanvas.setTree(tree);\r
-        treeCanvas.repaint();\r
-        av.setCurrentTree(tree);\r
-\r
-      }\r
-    }\r
-\r
-    public void showDistances(boolean b)\r
-    {\r
-      treeCanvas.setShowDistances(b);\r
-      distanceMenu.setSelected(b);\r
-    }\r
-\r
-    public void showBootstrap(boolean b)\r
-    {\r
-      treeCanvas.setShowBootstrap(b);\r
-      bootstrapMenu.setSelected(b);\r
-    }\r
-\r
-    public void showPlaceholders(boolean b)\r
-    {\r
-      placeholdersMenu.setState(b);\r
-      treeCanvas.setMarkPlaceholders(b);\r
-    }\r
-\r
-    private void allowOriginalSeqData(boolean b) {\r
-      originalSeqData.setVisible(b);\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public NJTree getTree()\r
-    {\r
-        return tree;\r
-    }\r
-\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void textbox_actionPerformed(ActionEvent e)\r
-    {\r
-        CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
-\r
-        StringBuffer buffer = new StringBuffer();\r
-\r
-        if (type.equals("AV"))\r
-        {\r
-            buffer.append("Average distance tree using ");\r
-        }\r
-        else\r
-        {\r
-            buffer.append("Neighbour joining tree using ");\r
-        }\r
-\r
-        if (pwtype.equals("BL"))\r
-        {\r
-            buffer.append("BLOSUM62");\r
-        }\r
-        else\r
-        {\r
-            buffer.append("PID");\r
-        }\r
-\r
-        Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);\r
-\r
-        jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
-        cap.setText(fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance()));\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void saveAsNewick_actionPerformed(ActionEvent e)\r
-    {\r
-        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                    "LAST_DIRECTORY"));\r
-        chooser.setFileView(new JalviewFileView());\r
-        chooser.setDialogTitle("Save tree as newick file");\r
-        chooser.setToolTipText("Save");\r
-\r
-        int value = chooser.showSaveDialog(null);\r
-\r
-        if (value == JalviewFileChooser.APPROVE_OPTION)\r
-        {\r
-            String choice = chooser.getSelectedFile().getPath();\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
-                chooser.getSelectedFile().getParent());\r
-\r
-            try\r
-            {\r
-                jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
-                String output = fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance());\r
-                java.io.PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(\r
-                            choice));\r
-                out.println(output);\r
-                out.close();\r
-            }\r
-            catch (Exception ex)\r
-            {\r
-                ex.printStackTrace();\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void printMenu_actionPerformed(ActionEvent e)\r
-    {\r
-        //Putting in a thread avoids Swing painting problems\r
-        treeCanvas.startPrinting();\r
-    }\r
-\r
-\r
-    public void originalSeqData_actionPerformed(ActionEvent e)\r
-    {\r
-      if (!tree.hasOriginalSequenceData())\r
-      {\r
-        jalview.bin.Cache.log.info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");\r
-        return;\r
-      }\r
-      // decide if av alignment is sufficiently different to original data to warrant a new window to be created\r
-      // create new alignmnt window with hidden regions (unhiding hidden regions yields unaligned seqs)\r
-      // or create a selection box around columns in alignment view\r
-      // test Alignment(SeqCigar[])\r
-      Object[] alAndColsel = tree.seqData.getAlignmentAndColumnSelection(av.\r
-          getGapCharacter());\r
-\r
-\r
-      if (alAndColsel != null && alAndColsel[0]!=null)\r
-       {\r
-         // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);\r
-\r
-         Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);\r
-         Alignment dataset = av.getAlignment().getDataset();\r
-         if (dataset != null)\r
-         {\r
-           al.setDataset(dataset);\r
-         }\r
-\r
-         if (true)\r
-         {\r
-           // make a new frame!\r
-           AlignFrame af = new AlignFrame(al, (ColumnSelection) alAndColsel[1],\r
-                                           AlignFrame.DEFAULT_WIDTH,\r
-                                           AlignFrame.DEFAULT_HEIGHT\r
-);\r
-\r
-           //>>>This is a fix for the moment, until a better solution is found!!<<<\r
-           // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());\r
-\r
-       //           af.addSortByOrderMenuItem(ServiceName + " Ordering",\r
-       //                                     msaorder);\r
-\r
-           Desktop.addInternalFrame(af, "Original Data for " + this.title,\r
-                                    AlignFrame.DEFAULT_WIDTH,\r
-                                    AlignFrame.DEFAULT_HEIGHT);\r
-         }\r
-       }\r
-    }\r
-\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void fitToWindow_actionPerformed(ActionEvent e)\r
-    {\r
-        treeCanvas.fitToWindow = fitToWindow.isSelected();\r
-        repaint();\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void font_actionPerformed(ActionEvent e)\r
-    {\r
-        if (treeCanvas == null)\r
-        {\r
-            return;\r
-        }\r
-\r
-        new FontChooser(this);\r
-    }\r
-\r
-    public Font getTreeFont()\r
-    {\r
-        return treeCanvas.font;\r
-    }\r
-\r
-    public void setTreeFont(Font font)\r
-    {\r
-      if(treeCanvas!=null)\r
-      treeCanvas.setFont(font);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void distanceMenu_actionPerformed(ActionEvent e)\r
-    {\r
-        treeCanvas.setShowDistances(distanceMenu.isSelected());\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void bootstrapMenu_actionPerformed(ActionEvent e)\r
-    {\r
-        treeCanvas.setShowBootstrap(bootstrapMenu.isSelected());\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void placeholdersMenu_actionPerformed(ActionEvent e)\r
-    {\r
-        treeCanvas.setMarkPlaceholders(placeholdersMenu.isSelected());\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void epsTree_actionPerformed(ActionEvent e)\r
-    {\r
-      boolean accurateText = true;\r
-\r
-      String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",\r
-          "Prompt each time");\r
-\r
-    // If we need to prompt, and if the GUI is visible then\r
-    // Prompt for EPS rendering style\r
-      if (renderStyle.equalsIgnoreCase("Prompt each time")\r
-          && !\r
-          (System.getProperty("java.awt.headless") != null\r
-           && System.getProperty("java.awt.headless").equals("true")))\r
-      {\r
-        EPSOptions eps = new EPSOptions();\r
-        renderStyle = eps.getValue();\r
-\r
-        if (renderStyle==null || eps.cancelled)\r
-          return;\r
-\r
-\r
-      }\r
-\r
-      if (renderStyle.equalsIgnoreCase("text"))\r
-      {\r
-        accurateText = false;\r
-      }\r
-\r
-        int width = treeCanvas.getWidth();\r
-        int height = treeCanvas.getHeight();\r
-\r
-        try\r
-        {\r
-            jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                        "LAST_DIRECTORY"), new String[] { "eps" },\r
-                    new String[] { "Encapsulated Postscript" },\r
-                    "Encapsulated Postscript");\r
-            chooser.setFileView(new jalview.io.JalviewFileView());\r
-            chooser.setDialogTitle("Create EPS file from tree");\r
-            chooser.setToolTipText("Save");\r
-\r
-            int value = chooser.showSaveDialog(this);\r
-\r
-            if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
-            {\r
-                return;\r
-            }\r
-\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
-                                          chooser.getSelectedFile().getParent());\r
-\r
-            FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
-            EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,\r
-                                                 height);\r
-\r
-            pg.setAccurateTextMode(accurateText);\r
-\r
-            treeCanvas.draw(pg, width, height);\r
-\r
-            pg.flush();\r
-            pg.close();\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-            ex.printStackTrace();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void pngTree_actionPerformed(ActionEvent e)\r
-    {\r
-        int width = treeCanvas.getWidth();\r
-        int height = treeCanvas.getHeight();\r
-\r
-        try\r
-        {\r
-            jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                        "LAST_DIRECTORY"), new String[] { "png" },\r
-                    new String[] { "Portable network graphics" },\r
-                    "Portable network graphics");\r
-\r
-            chooser.setFileView(new jalview.io.JalviewFileView());\r
-            chooser.setDialogTitle("Create PNG image from tree");\r
-            chooser.setToolTipText("Save");\r
-\r
-            int value = chooser.showSaveDialog(this);\r
-\r
-            if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
-            {\r
-                return;\r
-            }\r
-\r
-            jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
-                chooser.getSelectedFile().getParent());\r
-\r
-            FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
-\r
-            BufferedImage bi = new BufferedImage(width, height,\r
-                    BufferedImage.TYPE_INT_RGB);\r
-            Graphics png = bi.getGraphics();\r
-\r
-            treeCanvas.draw(png, width, height);\r
-\r
-            ImageIO.write(bi, "png", out);\r
-            out.close();\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-            ex.printStackTrace();\r
-        }\r
-    }\r
-}\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * 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
+ */
+package jalview.gui;
+
+import jalview.analysis.*;
+
+import jalview.datamodel.*;
+
+import jalview.io.*;
+
+import jalview.jbgui.*;
+
+import org.jibble.epsgraphics.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+
+import java.io.*;
+
+import java.util.*;
+
+import javax.imageio.*;
+
+import java.beans.PropertyChangeEvent;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class TreePanel extends GTreePanel
+{
+    String type;
+    String pwtype;
+    TreeCanvas treeCanvas;
+    NJTree tree;
+    AlignViewport av;
+
+    /**
+     * Creates a new TreePanel object.
+     *
+     * @param av DOCUMENT ME!
+     * @param seqVector DOCUMENT ME!
+     * @param type DOCUMENT ME!
+     * @param pwtype DOCUMENT ME!
+     * @param s DOCUMENT ME!
+     * @param e DOCUMENT ME!
+     */
+    public TreePanel(AlignmentPanel ap, String type, String pwtype)
+    {
+      super();
+      initTreePanel(ap, type, pwtype, null, null);
+
+      // We know this tree has distances. JBPNote TODO: prolly should add this as a userdefined default
+      // showDistances(true);
+    }
+
+    /**
+     * Creates a new TreePanel object.
+     *
+     * @param av DOCUMENT ME!
+     * @param seqVector DOCUMENT ME!
+     * @param newtree DOCUMENT ME!
+     * @param type DOCUMENT ME!
+     * @param pwtype DOCUMENT ME!
+     */
+    public TreePanel(AlignmentPanel ap,
+                     String type,
+                     String pwtype,
+                     NewickFile newtree)
+    {
+      super();
+      initTreePanel(ap, type, pwtype, newtree, null);
+    }
+    
+    public TreePanel(AlignmentPanel av,
+        String type,
+        String pwtype,
+        NewickFile newtree, AlignmentView inputData) {
+     super();
+     initTreePanel(av,type,pwtype,newtree,inputData);
+    }
+
+    public AlignmentI getAlignment()
+    {
+      return treeCanvas.av.getAlignment();
+    }
+    public AlignViewport getViewPort() {
+      return treeCanvas.av;
+    }
+
+    void initTreePanel(AlignmentPanel ap, String type,  String pwtype,
+                       NewickFile newTree, AlignmentView inputData)
+    {
+
+      av = ap.av;
+      this.type = type;
+      this.pwtype = pwtype;
+
+      treeCanvas = new TreeCanvas(ap, scrollPane);
+      scrollPane.setViewportView(treeCanvas);
+
+      av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
+      {
+        public void propertyChange(PropertyChangeEvent evt)
+        {
+          if (evt.getPropertyName().equals("alignment"))
+          {
+            if(tree==null)
+              System.out.println("tree is null");
+            if(evt.getNewValue()==null)
+              System.out.println("new value is null");
+
+            tree.UpdatePlaceHolders( (Vector) evt.getNewValue());
+
+            repaint();
+          }
+        }
+      });
+
+      this.av = av;
+
+
+      TreeLoader tl = new TreeLoader(newTree);
+      if (inputData!=null) {
+        tl.odata=inputData;
+      }
+      tl.start();
+
+    }
+
+    class TreeLoader extends Thread
+    {
+      NewickFile newtree;
+      jalview.datamodel.AlignmentView odata=null;
+      public TreeLoader(NewickFile newtree)
+      {
+        this.newtree = newtree;
+        if (newtree != null)
+        {
+          // Must be outside run(), as Jalview2XML tries to
+          // update distance/bootstrap visibility at the same time
+          showBootstrap(newtree.HasBootstrap());
+          showDistances(newtree.HasDistances());
+        }
+      }
+
+      public void run()
+      {
+
+        if(newtree!=null)
+        {
+          if (odata==null) {
+            tree = new NJTree(av.alignment.getSequencesArray(),
+                              newtree);
+          } else {
+            tree = new NJTree(av.alignment.getSequencesArray(), odata, newtree);
+          }
+          if (!tree.hasOriginalSequenceData())
+            allowOriginalSeqData(false);
+        }
+        else
+        {
+          int start, end;
+          SequenceI [] seqs;
+          AlignmentView seqStrings = av.getAlignmentView(av.getSelectionGroup()!=null);
+          if(av.getSelectionGroup()==null)
+          {
+            start = 0;
+            end = av.alignment.getWidth();
+            seqs = av.alignment.getSequencesArray();
+          }
+          else
+          {
+            start = av.getSelectionGroup().getStartRes();
+            end = av.getSelectionGroup().getEndRes()+1;
+            seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);
+          }
+
+          tree = new NJTree(seqs, seqStrings, type, pwtype, start, end);
+          showDistances(true);
+        }
+
+
+        tree.reCount(tree.getTopNode());
+        tree.findHeight(tree.getTopNode());
+        treeCanvas.setTree(tree);
+        treeCanvas.repaint();
+        av.setCurrentTree(tree);
+
+      }
+    }
+
+    public void showDistances(boolean b)
+    {
+      treeCanvas.setShowDistances(b);
+      distanceMenu.setSelected(b);
+    }
+
+    public void showBootstrap(boolean b)
+    {
+      treeCanvas.setShowBootstrap(b);
+      bootstrapMenu.setSelected(b);
+    }
+
+    public void showPlaceholders(boolean b)
+    {
+      placeholdersMenu.setState(b);
+      treeCanvas.setMarkPlaceholders(b);
+    }
+
+    private void allowOriginalSeqData(boolean b) {
+      originalSeqData.setVisible(b);
+    }
+
+
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public NJTree getTree()
+    {
+        return tree;
+    }
+
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void textbox_actionPerformed(ActionEvent e)
+    {
+        CutAndPasteTransfer cap = new CutAndPasteTransfer();
+
+        StringBuffer buffer = new StringBuffer();
+
+        if (type.equals("AV"))
+        {
+            buffer.append("Average distance tree using ");
+        }
+        else
+        {
+            buffer.append("Neighbour joining tree using ");
+        }
+
+        if (pwtype.equals("BL"))
+        {
+            buffer.append("BLOSUM62");
+        }
+        else
+        {
+            buffer.append("PID");
+        }
+
+        Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);
+
+        jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());
+        cap.setText(fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance()));
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void saveAsNewick_actionPerformed(ActionEvent e)
+    {
+        JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                    "LAST_DIRECTORY"));
+        chooser.setFileView(new JalviewFileView());
+        chooser.setDialogTitle("Save tree as newick file");
+        chooser.setToolTipText("Save");
+
+        int value = chooser.showSaveDialog(null);
+
+        if (value == JalviewFileChooser.APPROVE_OPTION)
+        {
+            String choice = chooser.getSelectedFile().getPath();
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                chooser.getSelectedFile().getParent());
+
+            try
+            {
+                jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());
+                String output = fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance());
+                java.io.PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
+                            choice));
+                out.println(output);
+                out.close();
+            }
+            catch (Exception ex)
+            {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void printMenu_actionPerformed(ActionEvent e)
+    {
+        //Putting in a thread avoids Swing painting problems
+        treeCanvas.startPrinting();
+    }
+
+
+    public void originalSeqData_actionPerformed(ActionEvent e)
+    {
+      if (!tree.hasOriginalSequenceData())
+      {
+        jalview.bin.Cache.log.info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
+        return;
+      }
+      // decide if av alignment is sufficiently different to original data to warrant a new window to be created
+      // create new alignmnt window with hidden regions (unhiding hidden regions yields unaligned seqs)
+      // or create a selection box around columns in alignment view
+      // test Alignment(SeqCigar[])
+      Object[] alAndColsel = tree.seqData.getAlignmentAndColumnSelection(av.
+          getGapCharacter());
+
+
+      if (alAndColsel != null && alAndColsel[0]!=null)
+       {
+         // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
+
+         Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
+         Alignment dataset = av.getAlignment().getDataset();
+         if (dataset != null)
+         {
+           al.setDataset(dataset);
+         }
+
+         if (true)
+         {
+           // make a new frame!
+           AlignFrame af = new AlignFrame(al, (ColumnSelection) alAndColsel[1],
+                                           AlignFrame.DEFAULT_WIDTH,
+                                           AlignFrame.DEFAULT_HEIGHT
+);
+
+           //>>>This is a fix for the moment, until a better solution is found!!<<<
+           // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
+
+       //           af.addSortByOrderMenuItem(ServiceName + " Ordering",
+       //                                     msaorder);
+
+           Desktop.addInternalFrame(af, "Original Data for " + this.title,
+                                    AlignFrame.DEFAULT_WIDTH,
+                                    AlignFrame.DEFAULT_HEIGHT);
+         }
+       }
+    }
+
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void fitToWindow_actionPerformed(ActionEvent e)
+    {
+        treeCanvas.fitToWindow = fitToWindow.isSelected();
+        repaint();
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void font_actionPerformed(ActionEvent e)
+    {
+        if (treeCanvas == null)
+        {
+            return;
+        }
+
+        new FontChooser(this);
+    }
+
+    public Font getTreeFont()
+    {
+        return treeCanvas.font;
+    }
+
+    public void setTreeFont(Font font)
+    {
+      if(treeCanvas!=null)
+      treeCanvas.setFont(font);
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void distanceMenu_actionPerformed(ActionEvent e)
+    {
+        treeCanvas.setShowDistances(distanceMenu.isSelected());
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void bootstrapMenu_actionPerformed(ActionEvent e)
+    {
+        treeCanvas.setShowBootstrap(bootstrapMenu.isSelected());
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void placeholdersMenu_actionPerformed(ActionEvent e)
+    {
+        treeCanvas.setMarkPlaceholders(placeholdersMenu.isSelected());
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void epsTree_actionPerformed(ActionEvent e)
+    {
+      boolean accurateText = true;
+
+      String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
+          "Prompt each time");
+
+    // If we need to prompt, and if the GUI is visible then
+    // Prompt for EPS rendering style
+      if (renderStyle.equalsIgnoreCase("Prompt each time")
+          && !
+          (System.getProperty("java.awt.headless") != null
+           && System.getProperty("java.awt.headless").equals("true")))
+      {
+        EPSOptions eps = new EPSOptions();
+        renderStyle = eps.getValue();
+
+        if (renderStyle==null || eps.cancelled)
+          return;
+
+
+      }
+
+      if (renderStyle.equalsIgnoreCase("text"))
+      {
+        accurateText = false;
+      }
+
+        int width = treeCanvas.getWidth();
+        int height = treeCanvas.getHeight();
+
+        try
+        {
+            jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(
+                        "LAST_DIRECTORY"), new String[] { "eps" },
+                    new String[] { "Encapsulated Postscript" },
+                    "Encapsulated Postscript");
+            chooser.setFileView(new jalview.io.JalviewFileView());
+            chooser.setDialogTitle("Create EPS file from tree");
+            chooser.setToolTipText("Save");
+
+            int value = chooser.showSaveDialog(this);
+
+            if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)
+            {
+                return;
+            }
+
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                                          chooser.getSelectedFile().getParent());
+
+            FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
+            EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
+                                                 height);
+
+            pg.setAccurateTextMode(accurateText);
+
+            treeCanvas.draw(pg, width, height);
+
+            pg.flush();
+            pg.close();
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void pngTree_actionPerformed(ActionEvent e)
+    {
+        int width = treeCanvas.getWidth();
+        int height = treeCanvas.getHeight();
+
+        try
+        {
+            jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(
+                        "LAST_DIRECTORY"), new String[] { "png" },
+                    new String[] { "Portable network graphics" },
+                    "Portable network graphics");
+
+            chooser.setFileView(new jalview.io.JalviewFileView());
+            chooser.setDialogTitle("Create PNG image from tree");
+            chooser.setToolTipText("Save");
+
+            int value = chooser.showSaveDialog(this);
+
+            if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)
+            {
+                return;
+            }
+
+            jalview.bin.Cache.setProperty("LAST_DIRECTORY",
+                chooser.getSelectedFile().getParent());
+
+            FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
+
+            BufferedImage bi = new BufferedImage(width, height,
+                    BufferedImage.TYPE_INT_RGB);
+            Graphics png = bi.getGraphics();
+
+            treeCanvas.draw(png, width, height);
+
+            ImageIO.write(bi, "png", out);
+            out.close();
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+}
diff --git a/src/jalview/gui/VamsasClient.java b/src/jalview/gui/VamsasClient.java
new file mode 100755 (executable)
index 0000000..d943374
--- /dev/null
@@ -0,0 +1,231 @@
+/**
+ * 
+ */
+package jalview.gui;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Vector;
+import java.util.jar.JarOutputStream;
+
+import javax.swing.JInternalFrame;
+
+import jalview.bin.Cache;
+import jalview.io.VamsasDatastore;
+
+import org.vamsas.client.UserHandle;
+import org.vamsas.client.simpleclient.FileWatcher;
+import org.vamsas.client.simpleclient.VamsasArchive;
+import org.vamsas.client.simpleclient.VamsasFile;
+import org.vamsas.objects.core.Entry;
+import org.vamsas.objects.core.VamsasDocument;
+import org.vamsas.test.simpleclient.ArchiveClient;
+import org.vamsas.test.simpleclient.ClientDoc;
+
+/**
+ * @author jimp
+ *
+ */
+public class VamsasClient extends ArchiveClient {
+       // Cache.preferences for vamsas client session arena
+       // preferences for check for default session at startup.
+       // user and organisation stuff.
+       public VamsasClient(Desktop jdesktop,
+                       File sessionPath) {
+               super(System.getProperty("user.name"),System.getProperty("host.name"), "jalview","2.7",
+                               sessionPath);
+       }
+       public void initial_update() {
+               Cache.log.info("Jalview loading the Vamsas Session.");
+               // load in the vamsas archive for the first time
+               ClientDoc cdoc = this.getUpdateable();
+               updateJalview(cdoc);
+    JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+    if (frames == null)
+    {
+        return;
+    }
+
+    try
+    { 
+      //REVERSE ORDER
+        for (int i = frames.length - 1; i > -1; i--)
+        {
+            if (frames[i] instanceof AlignFrame)
+            {
+              AlignFrame af = (AlignFrame) frames[i];
+              af.alignmentChanged();
+            }
+        }
+    } catch (Exception e) {
+      Cache.log.warn("Exception whilst refreshing jalview windows after a vamsas document update.", e);
+    }
+    doUpdate(cdoc);
+    cdoc.closeDoc();
+  }
+       /**
+        * this will close all windows currently in Jalview.
+        *
+        
+       protected void closeWindows() {
+               JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+        if (frames == null)
+        {
+            return;
+        }
+
+        try
+        {      
+            for (int i = frames.length - 1; i > -1; i--) {
+               frames[i].dispose();    
+            }
+        } catch (Exception e) {
+               Cache.log.error("Whilst closing windows",e);
+        }
+               
+       }
+  
+       public void get_update(VamsasArchive doc) {
+               // Close windows - load update.
+               Cache.log.info("Jalview updating from Vamsas Session.");
+       }
+  */
+  VamsasClientWatcher watcher=null;
+       public void push_update() {
+         watchForChange=false;
+    try {
+      Thread.sleep(WATCH_SLEEP); 
+    } catch (Exception e) {
+      
+    };
+    ClientDoc cdoc = getUpdateable();
+    updateVamsasDocument(cdoc);
+    doUpdate(cdoc);
+    cdoc.closeDoc();
+    cdoc=null;
+    watchForChange=true;
+    if (watcher!=null) {
+      Thread wthread = new Thread() {
+        public void run() {
+          watcher.run();          
+        }
+      };
+      wthread.start();
+      
+    }
+               // collect all uncached alignments and put them into the vamsas dataset.
+               // store them.
+               Cache.log.info("Jalview updating the Vamsas Session.");
+       }
+       public void end_session() {
+         //   stop any update/watcher thread.
+    watchForChange=false; // this makes any watch(long) loops return. 
+    // we should also wait arount for this.WATCH_SLEEP to really make sure the watcher thread has stopped. 
+    try {
+      Thread.sleep(WATCH_SLEEP); 
+    } catch (Exception e) {
+      
+    };
+    Cache.log.info("Jalview disconnecting from the Vamsas Session.");
+       }
+       public void updateJalview(ClientDoc cdoc) {
+               ensureJvVamsas();
+    VamsasDatastore vds = new VamsasDatastore(cdoc, vobj2jv, jv2vobj, baseProvEntry());
+    vds.updateToJalview();
+       }
+       private void ensureJvVamsas() {
+    if (jv2vobj==null) {
+      jv2vobj = new IdentityHashMap();
+      vobj2jv = new Hashtable();
+    }
+       }
+       /**
+        * jalview object binding to VorbaIds
+        */
+       IdentityHashMap jv2vobj = null;
+       Hashtable vobj2jv = null;
+       public void updateVamsasDocument(ClientDoc doc) {
+         ensureJvVamsas();
+    VamsasDatastore vds = new VamsasDatastore(doc, vobj2jv, jv2vobj, baseProvEntry());
+    // wander through frames 
+               JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+        if (frames == null)
+        {
+            return;
+        }
+
+        try
+        {      
+               //REVERSE ORDER
+            for (int i = frames.length - 1; i > -1; i--)
+            {
+                if (frames[i] instanceof AlignFrame)
+                {
+                       AlignFrame af = (AlignFrame) frames[i];
+                       
+                       // update alignment and root from frame.
+                       vds.storeVAMSAS(af.getViewport(), af.getTitle());
+                }
+            }
+        }
+        catch (Exception e) {
+               Cache.log.error("Vamsas Document store exception",e);
+        }
+       }
+       private Entry baseProvEntry() {
+    org.vamsas.objects.core.Entry pentry = new org.vamsas.objects.core.Entry();
+    pentry.setUser(this.getProvenanceUser());
+    pentry.setApp(this.getClientHandle().getClientName());
+    pentry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));
+    pentry.setAction("created");
+    return pentry;
+       }
+  protected class VamsasClientWatcher extends Thread implements Runnable {
+               /* (non-Javadoc)
+                * @see java.lang.Thread#run()
+                */
+               VamsasClient client=null;
+               VamsasClientWatcher(VamsasClient client) {
+                       this.client = client;
+               }
+    boolean running=false;
+               public void run() {
+                 running=true;
+                       while (client.watchForChange) {
+                         ClientDoc docio = client.watch(0);
+                         if (docio!=null) {
+          client.disableGui(true);
+          Cache.log.debug("Updating jalview from changed vamsas document.");
+                           client.updateJalview(docio);
+          Cache.log.debug("Finished updating from document change.");
+          docio.closeDoc();
+          docio=null;
+          client.disableGui(false);
+                         }
+      }
+      running=false;
+      
+               }
+               
+       }
+  public void disableGui(boolean b) {
+      Desktop.instance.setVamsasUpdate(b);    
+  }
+  public void startWatcher() {
+    if (watcher==null)
+      watcher=new VamsasClientWatcher(this);
+    Thread thr = new Thread() {
+      public void run() {
+        watcher.start();
+      }
+    };
+    thr.start();
+  }
+}
diff --git a/src/jalview/io/VamsasDatastore.java b/src/jalview/io/VamsasDatastore.java
new file mode 100755 (executable)
index 0000000..395a251
--- /dev/null
@@ -0,0 +1,1552 @@
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
+ */\r
+\r
+package jalview.io;\r
+\r
+import org.vamsas.client.Vobject;\r
+import org.vamsas.client.VorbaId;\r
+import org.vamsas.objects.core.*;\r
+import org.vamsas.objects.utils.DocumentStuff;\r
+import org.vamsas.test.simpleclient.ClientDoc;\r
+\r
+import jalview.bin.Cache;\r
+import jalview.datamodel.AlignmentAnnotation;\r
+import jalview.datamodel.AlignmentI;\r
+import jalview.datamodel.AlignmentView;\r
+import jalview.datamodel.DBRefEntry;\r
+import jalview.datamodel.SequenceFeature;\r
+import jalview.datamodel.SequenceI;\r
+import jalview.gui.*;\r
+\r
+import java.io.*;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Hashtable;\r
+import java.util.IdentityHashMap;\r
+import java.util.Vector;\r
+import java.util.jar.*;\r
+import org.exolab.castor.xml.*;\r
+import org.exolab.castor.mapping.Mapping;\r
+\r
+/*\r
+ * \r
+ * static {\r
+ * org.exolab.castor.util.LocalConfiguration.getInstance().getProperties().setProperty(\r
+ * "org.exolab.castor.serializer", "org.apache.xml.serialize.XMLSerilazizer"); }\r
+ * \r
+ */\r
+\r
+public class VamsasDatastore {\r
+  Entry provEntry = null;\r
+\r
+  // AlignViewport av;\r
+\r
+  org.exolab.castor.types.Date date = new org.exolab.castor.types.Date(\r
+      new java.util.Date());\r
+\r
+  ClientDoc cdoc;\r
+\r
+  Hashtable vobj2jv;\r
+\r
+  IdentityHashMap jv2vobj;\r
+\r
+  public VamsasDatastore(ClientDoc cdoc, Hashtable vobj2jv,\r
+      IdentityHashMap jv2vobj, Entry provEntry) {\r
+      this.cdoc = cdoc;\r
+    this.vobj2jv = vobj2jv;\r
+    this.jv2vobj = jv2vobj;\r
+    this.provEntry = provEntry;\r
+  }\r
+\r
+  /*\r
+   * public void storeJalview(String file, AlignFrame af) { try { // 1. Load the\r
+   * mapping information from the file Mapping map = new\r
+   * Mapping(getClass().getClassLoader()); java.net.URL url =\r
+   * getClass().getResource("/jalview_mapping.xml"); map.loadMapping(url); // 2.\r
+   * Unmarshal the data // Unmarshaller unmar = new Unmarshaller();\r
+   * //unmar.setIgnoreExtraElements(true); //unmar.setMapping(map); // uni =\r
+   * (UniprotFile) unmar.unmarshal(new FileReader(file)); // 3. marshal the data\r
+   * with the total price back and print the XML in the console Marshaller\r
+   * marshaller = new Marshaller( new FileWriter(file) );\r
+   * \r
+   * marshaller.setMapping(map); marshaller.marshal(af); } catch (Exception e) {\r
+   * e.printStackTrace(); } }\r
+   * \r
+   * \r
+   */\r
+  /**\r
+   * @return the Vobject bound to Jalview datamodel object\r
+   */\r
+  protected Vobject getjv2vObj(Object jvobj) {\r
+    if (jv2vobj.containsKey(jvobj))\r
+      return cdoc.getObject((VorbaId) jv2vobj.get(jvobj));\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param vobj\r
+   * @return Jalview datamodel object bound to the vamsas document object\r
+   */\r
+  protected Object getvObj2jv(org.vamsas.client.Vobject vobj) {\r
+    VorbaId id = vobj.getVorbaId();\r
+    if (id == null)\r
+    {\r
+      id = cdoc.registerObject(vobj);\r
+      Cache.log\r
+      .debug("Registering new object and returning null for getvObj2jv");\r
+      return null;\r
+    }\r
+    if (vobj2jv.containsKey(vobj.getVorbaId()))\r
+      return vobj2jv.get(vobj.getVorbaId());\r
+    return null;\r
+  }\r
+\r
+  protected void bindjvvobj(Object jvobj, org.vamsas.client.Vobject vobj) {\r
+    VorbaId id = vobj.getVorbaId();\r
+    if (id == null)\r
+    {\r
+      id = cdoc.registerObject(vobj);\r
+      if (id==null || vobj.getVorbaId()==null)\r
+        Cache.log.error("Failed to get id for "+(vobj.isRegisterable() ? "registerable" : "unregisterable") +" object "+vobj);\r
+    }\r
+    \r
+    if (vobj2jv.containsKey(vobj.getVorbaId()) && !((VorbaId)vobj2jv.get(vobj.getVorbaId())).equals(jvobj)) {\r
+      Cache.log.debug("Warning? Overwriting existing vamsas id binding for "+vobj.getVorbaId(), new Exception("Overwriting vamsas id binding."));\r
+    }\r
+    else if (jv2vobj.containsKey(jvobj) && !((VorbaId)jv2vobj.get(jvobj)).equals(vobj.getVorbaId())) \r
+    {\r
+      Cache.log.debug("Warning? Overwriting existing jalview object binding for "+jvobj, new Exception("Overwriting jalview object binding."));\r
+    }\r
+    /* Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id " +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+" already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to bindjvvobj"));\r
+    }*/\r
+    // we just update the hash's regardless!\r
+    vobj2jv.put(vobj.getVorbaId(), jvobj);\r
+    // JBPNote - better implementing a hybrid invertible hash.\r
+    jv2vobj.put(jvobj, vobj.getVorbaId());   \r
+  }\r
+\r
+  /**\r
+   * put the alignment viewed by AlignViewport into cdoc.\r
+   * \r
+   * @param av alignViewport to be stored\r
+   * @param aFtitle title for alignment\r
+   */\r
+  public void storeVAMSAS(AlignViewport av, String aFtitle) {\r
+    try\r
+    {\r
+      jalview.datamodel.AlignmentI jal = av.getAlignment();\r
+      boolean nw = false;\r
+      VAMSAS root = null; // will be resolved based on Dataset Parent.\r
+      // /////////////////////////////////////////\r
+      // SAVE THE DATASET\r
+      if (jal.getDataset() == null)\r
+      {\r
+        Cache.log.warn("Creating new dataset for an alignment.");\r
+        jal.setDataset(null);\r
+      }\r
+      DataSet dataset = (DataSet) getjv2vObj(jal.getDataset());\r
+      if (dataset == null)\r
+      {\r
+        root = cdoc.getVamsasRoots()[0]; // default vamsas root for modifying.\r
+        dataset = new DataSet();\r
+        root.addDataSet(dataset);\r
+        bindjvvobj(jal.getDataset(), dataset);\r
+        dataset.setProvenance(dummyProvenance());\r
+        dataset.getProvenance().addEntry(provEntry);\r
+        nw = true;\r
+      }\r
+      else\r
+      {\r
+        root = (VAMSAS) dataset.getV_parent();\r
+      }\r
+      // update dataset\r
+      Sequence sequence;\r
+      DbRef dbref;\r
+      // set new dataset and alignment sequences based on alignment Nucleotide\r
+      // flag.\r
+      // this *will* break when alignment contains both nucleotide and amino\r
+      // acid sequences.\r
+      String dict = jal.isNucleotide() ? org.vamsas.objects.utils.SymbolDictionary.STANDARD_NA\r
+          : org.vamsas.objects.utils.SymbolDictionary.STANDARD_AA;\r
+      for (int i = 0; i < jal.getHeight(); i++)\r
+      {\r
+        SequenceI sq = jal.getSequenceAt(i).getDatasetSequence(); // only insert\r
+        // referenced\r
+        // sequences\r
+        // to dataset.\r
+        sequence = (Sequence) getjv2vObj(sq);\r
+        if (sequence == null)\r
+        {\r
+          sequence = new Sequence();\r
+          bindjvvobj(sq, sequence);\r
+          sq.setVamsasId(sequence.getVorbaId().getId());\r
+          sequence.setSequence(sq.getSequence());\r
+          sequence.setDictionary(dict);\r
+          sequence.setName(jal.getDataset().getSequenceAt(i).getName());\r
+          sequence.setStart(jal.getDataset().getSequenceAt(i).getStart());\r
+          sequence.setEnd(jal.getDataset().getSequenceAt(i).getEnd());\r
+          dataset.addSequence(sequence);\r
+        }\r
+        else\r
+        {\r
+          // verify principal attributes. and update any new\r
+          // features/references.\r
+          System.out.println("update dataset sequence object.");\r
+        }\r
+        if (sq.getSequenceFeatures() != null)\r
+        {\r
+          int sfSize = sq.getSequenceFeatures().length;\r
+\r
+          for (int sf = 0; sf < sfSize; sf++)\r
+          {\r
+            jalview.datamodel.SequenceFeature feature = (jalview.datamodel.SequenceFeature) sq\r
+            .getSequenceFeatures()[sf];\r
+\r
+            DataSetAnnotations dsa = (DataSetAnnotations) getjv2vObj(feature);\r
+            if (dsa == null)\r
+            {\r
+              dsa = (DataSetAnnotations) getDSAnnotationFromJalview(\r
+                  new DataSetAnnotations(), feature);\r
+              if (dsa.getProvenance() == null)\r
+              {\r
+                dsa.setProvenance(new Provenance());\r
+              }\r
+              addProvenance(dsa.getProvenance(), "created"); // JBPNote - need\r
+              // to update\r
+              dsa.setSeqRef(sequence);\r
+              bindjvvobj(feature, dsa);\r
+              dataset.addDataSetAnnotations(dsa);\r
+            }\r
+            else\r
+            {\r
+              // todo: verify and update dataset annotations for sequence\r
+              System.out.println("update dataset sequence annotations.");\r
+            }\r
+          }\r
+        }\r
+\r
+        if (sq.getDBRef() != null)\r
+        {\r
+          DBRefEntry[] entries = sq.getDBRef();\r
+          jalview.datamodel.DBRefEntry dbentry;\r
+          for (int db = 0; db < entries.length; db++)\r
+          {\r
+            dbentry = entries[db];\r
+            dbref = (DbRef) getjv2vObj(dbentry);\r
+            if (dbref == null)\r
+            {\r
+              dbref = new DbRef();\r
+              bindjvvobj(dbentry, dbref);\r
+              dbref.setAccessionId(dbentry.getAccessionId());\r
+              dbref.setSource(dbentry.getSource());\r
+              dbref.setVersion(dbentry.getVersion());\r
+              /*\r
+               * TODO: Maps are not yet supported by Jalview. Map vMap = new\r
+               * Map(); vMap.set dbref.addMap(vMap);\r
+               */\r
+              sequence.addDbRef(dbref);\r
+            }\r
+            else\r
+            {\r
+              // TODO: verify and update dbrefs in vamsas document\r
+              // there will be trouble when a dataset sequence is modified to\r
+              // contain more residues than were originally referenced - we must\r
+              // then make a number of dataset sequence entries\r
+              System.out\r
+              .println("update dataset sequence database references.");\r
+            }\r
+          }\r
+\r
+        }\r
+      }\r
+      // dataset.setProvenance(getVamsasProvenance(jal.getDataset().getProvenance()));\r
+      // ////////////////////////////////////////////\r
+\r
+      // ////////////////////////////////////////////\r
+      // Save the Alignments\r
+\r
+      Alignment alignment = (Alignment) getjv2vObj(av); // this is so we can get the alignviewport back \r
+      if (alignment == null)\r
+      {\r
+        alignment = new Alignment();\r
+        bindjvvobj(av, alignment);\r
+        if (alignment.getProvenance() == null)\r
+          alignment.setProvenance(new Provenance());\r
+        addProvenance(alignment.getProvenance(), "added"); // TODO: insert some\r
+        // sensible source\r
+        // here\r
+        dataset.addAlignment(alignment);\r
+        {\r
+          Property title = new Property();\r
+          title.setName("jalview:AlTitle");\r
+          title.setType("string");\r
+          title.setContent(aFtitle);\r
+          alignment.addProperty(title);\r
+        }\r
+        alignment.setGapChar(String.valueOf(av.getGapCharacter()));\r
+        AlignmentSequence alseq = null;\r
+        for (int i = 0; i < jal.getHeight(); i++)\r
+        {\r
+          alseq = new AlignmentSequence();\r
+          // TODO: VAMSAS: translate lowercase symbols to annotation ?\r
+          alseq.setSequence(jal.getSequenceAt(i).getSequence());\r
+          alseq.setName(jal.getSequenceAt(i).getName());\r
+          alseq.setStart(jal.getSequenceAt(i).getStart());\r
+          alseq.setEnd(jal.getSequenceAt(i).getEnd());\r
+          alseq.setRefid(getjv2vObj(jal.getSequenceAt(i).getDatasetSequence()));\r
+          alignment.addAlignmentSequence(alseq);\r
+          bindjvvobj(jal.getSequenceAt(i), alseq);\r
+        }\r
+      }\r
+      else\r
+      {\r
+        // todo: verify and update mutable alignment props.\r
+        if (alignment.getModifiable())\r
+        {\r
+          System.out.println("update alignment in document.");\r
+        }\r
+        else\r
+        {\r
+          System.out\r
+          .println("update edited alignment to new alignment in document.");\r
+        }\r
+      }\r
+      // ////////////////////////////////////////////\r
+      // SAVE Alignment Sequence Features\r
+      for (int i = 0, iSize = alignment.getAlignmentSequenceCount(); i < iSize; i++)\r
+      {\r
+        AlignmentSequence valseq;\r
+        SequenceI alseq = (SequenceI) getvObj2jv(valseq = alignment\r
+            .getAlignmentSequence(i));\r
+        if (alseq != null && alseq.getSequenceFeatures() != null)\r
+        {\r
+          jalview.datamodel.SequenceFeature[] features = alseq\r
+          .getSequenceFeatures();\r
+          for (int f = 0; f < features.length; f++)\r
+          {\r
+            if (features[f] != null)\r
+            {\r
+              AlignmentSequenceAnnotation valseqf = (AlignmentSequenceAnnotation) getjv2vObj(features[i]);\r
+              if (valseqf == null)\r
+              {\r
+\r
+                valseqf = (AlignmentSequenceAnnotation) getDSAnnotationFromJalview(\r
+                    new AlignmentSequenceAnnotation(), features[i]);\r
+                if (valseqf.getProvenance() == null)\r
+                {\r
+                  valseqf.setProvenance(new Provenance());\r
+                }\r
+                addProvenance(valseqf.getProvenance(), "created"); // JBPNote -\r
+                // need to\r
+                // update\r
+                bindjvvobj(features[i], valseqf);\r
+                valseq.addAlignmentSequenceAnnotation(valseqf);\r
+              }\r
+            }\r
+\r
+          }\r
+        }\r
+      }\r
+\r
+      // ////////////////////////////////////////////\r
+      // SAVE ANNOTATIONS\r
+      if (jal.getAlignmentAnnotation() != null)\r
+      {\r
+        jalview.datamodel.AlignmentAnnotation[] aa = jal\r
+        .getAlignmentAnnotation();\r
+        java.util.HashMap AlSeqMaps = new HashMap(); // stores int maps from\r
+        // alignment columns to\r
+        // sequence positions.\r
+        for (int i = 0; i < aa.length; i++)\r
+        {\r
+          if (aa[i] == null || isJalviewOnly(aa[i]))\r
+          {\r
+            continue;\r
+          }\r
+          if (aa[i].sequenceRef != null)\r
+          {\r
+            org.vamsas.objects.core.AlignmentSequence alsref = (org.vamsas.objects.core.AlignmentSequence) getjv2vObj(aa[i].sequenceRef);\r
+            org.vamsas.objects.core.AlignmentSequenceAnnotation an = (org.vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(aa[i]);\r
+            int[] gapMap = null;\r
+            if (AlSeqMaps.containsKey(aa[i].sequenceRef))\r
+            {\r
+              gapMap = (int[]) AlSeqMaps.get(aa[i].sequenceRef);\r
+            }\r
+            else\r
+            {\r
+              gapMap = new int[aa[i].sequenceRef.getLength()];\r
+              // map from alignment position to sequence position.\r
+              int[] sgapMap = aa[i].sequenceRef.gapMap();\r
+              for (int a = 0; a < sgapMap.length; a++)\r
+                gapMap[sgapMap[a]] = a;\r
+            }\r
+            if (an == null)\r
+            {\r
+              an = new org.vamsas.objects.core.AlignmentSequenceAnnotation();\r
+              Seg vSeg = new Seg();\r
+              vSeg.setStart(1);\r
+              vSeg.setInclusive(true);\r
+              vSeg.setEnd(gapMap.length);\r
+              an.addSeg(vSeg);\r
+              an.setType("jalview:SecondaryStructurePrediction");// TODO: better fix this rough guess ;)\r
+              alsref.addAlignmentSequenceAnnotation(an);\r
+              bindjvvobj(aa[i],an);\r
+              // LATER: much of this is verbatim from the alignmentAnnotation\r
+              // method below. suggests refactoring to make rangeAnnotation the\r
+              // base class\r
+              an.setDescription(aa[i].description);\r
+              if (aa[i].graph > 0)\r
+                an.setGraph(true); // aa[i].graph);\r
+              else\r
+                an.setGraph(false);\r
+              an.setLabel(aa[i].label);\r
+              an.setProvenance(dummyProvenance()); // get provenance as user\r
+              // created, or jnet, or\r
+              // something else.\r
+              an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote -\r
+              // originally we\r
+              // were going to\r
+              // store\r
+              // graphGroup in\r
+              // the Jalview\r
+              // specific\r
+              // bits.\r
+              AnnotationElement ae;\r
+              for (int a = 0; a < aa[i].annotations.length; a++)\r
+              {\r
+                if (aa[i].annotations[a] == null)\r
+                {\r
+                  continue;\r
+                }\r
+\r
+                ae = new AnnotationElement();\r
+                ae.setDescription(aa[i].annotations[a].description);\r
+                ae.addGlyph(new Glyph());\r
+                ae.getGlyph(0)\r
+                .setContent(aa[i].annotations[a].displayCharacter); // assume\r
+                // jax-b\r
+                // takes\r
+                // care\r
+                // of\r
+                // utf8\r
+                // translation\r
+                if (aa[i].graph!=jalview.datamodel.AlignmentAnnotation.NO_GRAPH)\r
+                  ae.addValue(aa[i].annotations[a].value);\r
+                ae.setPosition(gapMap[a]+1); // position w.r.t. AlignmentSequence\r
+                // symbols\r
+                if (aa[i].annotations[a].secondaryStructure != ' ')\r
+                {\r
+                  // we only write an annotation where it really exists.\r
+                  Glyph ss = new Glyph();\r
+                  ss\r
+                  .setDict(org.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);\r
+                  ss.setContent(String\r
+                      .valueOf(aa[i].annotations[a].secondaryStructure));\r
+                  ae.addGlyph(ss);\r
+                }\r
+                an.addAnnotationElement(ae);\r
+              }\r
+            }\r
+            else\r
+            {\r
+              // update reference sequence Annotation\r
+              if (an.getModifiable())\r
+              {\r
+                // verify existing alignment sequence annotation is up to date\r
+                System.out.println("update alignment sequence annotation.");\r
+              }\r
+              else\r
+              {\r
+                // verify existing alignment sequence annotation is up to date\r
+                System.out\r
+                .println("make new alignment sequence annotation if modification has happened.");\r
+              }\r
+            }\r
+          }\r
+          else\r
+          {\r
+            // add Alignment Annotation\r
+            org.vamsas.objects.core.AlignmentAnnotation an = (org.vamsas.objects.core.AlignmentAnnotation) getjv2vObj(aa[i]);\r
+            if (an == null)\r
+            {\r
+              an = new org.vamsas.objects.core.AlignmentAnnotation();\r
+              an.setType("jalview:AnnotationRow");\r
+              an.setDescription(aa[i].description);\r
+              alignment.addAlignmentAnnotation(an);\r
+              Seg vSeg = new Seg();\r
+              vSeg.setStart(1);\r
+              vSeg.setInclusive(true);\r
+              vSeg.setEnd(jal.getWidth());\r
+              an.addSeg(vSeg);\r
+              if (aa[i].graph > 0)\r
+                an.setGraph(true); // aa[i].graph);\r
+              an.setLabel(aa[i].label);\r
+              an.setProvenance(dummyProvenance());\r
+              if (aa[i].graph!=aa[i].NO_GRAPH) {\r
+                an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote -\r
+                // originally we\r
+              // were going to\r
+              // store\r
+              // graphGroup in\r
+              // the Jalview\r
+              // specific\r
+              // bits.\r
+                an.setGraph(true);\r
+              } else {\r
+                an.setGraph(false);\r
+              }\r
+              AnnotationElement ae;\r
+\r
+              for (int a = 0; a < aa[i].annotations.length; a++)\r
+              {\r
+                if ((aa[i] == null) || (aa[i].annotations[a] == null))\r
+                {\r
+                  continue;\r
+                }\r
+\r
+                ae = new AnnotationElement();\r
+                ae.setDescription(aa[i].annotations[a].description);\r
+                ae.addGlyph(new Glyph());\r
+                ae.getGlyph(0)\r
+                .setContent(aa[i].annotations[a].displayCharacter); // assume\r
+                // jax-b\r
+                // takes\r
+                // care\r
+                // of\r
+                // utf8\r
+                // translation\r
+                ae.addValue(aa[i].annotations[a].value);\r
+                ae.setPosition(a+1);\r
+                if (aa[i].annotations[a].secondaryStructure != ' ')\r
+                {\r
+                  Glyph ss = new Glyph();\r
+                  ss\r
+                  .setDict(org.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE);\r
+                  ss.setContent(String\r
+                      .valueOf(aa[i].annotations[a].secondaryStructure));\r
+                  ae.addGlyph(ss);\r
+                }\r
+                an.addAnnotationElement(ae);\r
+              }\r
+              if (aa[i].editable) {\r
+                //an.addProperty(newProperty("jalview:editable", null, "true"));\r
+                an.setModifiable(true);\r
+              }\r
+              if (aa[i].graph!=jalview.datamodel.AlignmentAnnotation.NO_GRAPH) {\r
+                an.setGraph(true);\r
+                an.setGroup(Integer.toString(aa[i].graphGroup));\r
+                an.addProperty(newProperty("jalview:graphType",null,\r
+                    ((aa[i].graph==jalview.datamodel.AlignmentAnnotation.BAR_GRAPH) ? "BAR_GRAPH" : "LINE_GRAPH")));\r
+\r
+                /** and on and on.. \r
+                 vProperty=new Property();\r
+                  vProperty.setName("jalview:graphThreshhold");\r
+                  vProperty.setContent(aa[i].threshold);\r
+                 */\r
+\r
+              }\r
+            }\r
+            else\r
+            {\r
+              if (an.getModifiable())\r
+              {\r
+                // verify annotation - update (perhaps)\r
+                Cache.log.info("update alignment sequence annotation. not yet implemented.");\r
+              }\r
+              else\r
+              {\r
+                // verify annotation - update (perhaps)\r
+                Cache.log.info("updated alignment sequence annotation added.");\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+      // /////////////////////////////////////////////////////\r
+\r
+      // //////////////////////////////////////////////\r
+      // /SAVE THE TREES\r
+      // /////////////////////////////////\r
+      // FIND ANY ASSOCIATED TREES\r
+      if (Desktop.desktop != null)\r
+      {\r
+        javax.swing.JInternalFrame[] frames = Desktop.desktop.getAllFrames();\r
+\r
+        for (int t = 0; t < frames.length; t++)\r
+        {\r
+          if (frames[t] instanceof TreePanel)\r
+          {\r
+            TreePanel tp = (TreePanel) frames[t];\r
+\r
+            if (tp.getAlignment() == jal)\r
+            {\r
+              Tree tree = (Tree) getjv2vObj(tp);\r
+              if (tree == null)\r
+              {\r
+                tree = new Tree();\r
+                bindjvvobj(tp, tree);\r
+                tree.setTitle(tp.getTitle());\r
+                Newick newick = new Newick();\r
+                // TODO: translate sequenceI to leaf mappings to vamsas\r
+                // references - see tree specification in schema.\r
+                newick.setContent(tp.getTree().toString());\r
+                newick.setTitle(tp.getTitle());\r
+                tree.addNewick(newick);\r
+                tree.setProvenance(makeTreeProvenance(jal, tp));\r
+                alignment.addTree(tree);\r
+              }\r
+              else\r
+              {\r
+                if (tree.getModifiable())\r
+                {\r
+                  // verify any changes.\r
+                  System.out.println("Update tree in document.");\r
+                }\r
+                else\r
+                {\r
+                  System.out\r
+                  .println("Add modified tree as new tree in document.");\r
+                }\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+      // Store Jalview specific stuff in the Jalview appData\r
+      // not implemented in the SimpleDoc interface.\r
+    }\r
+\r
+    catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    }\r
+\r
+  }\r
+\r
+  private Property newProperty(String name, String type, String content) {\r
+    Property vProperty=new Property();\r
+    vProperty.setName(name);\r
+    if (type!=null)\r
+      vProperty.setType(type);\r
+    else\r
+      vProperty.setType("String");\r
+    vProperty.setContent(content);\r
+    return vProperty;\r
+  }\r
+\r
+  /**\r
+   * correctly create a RangeAnnotation from a jalview sequence feature\r
+   * \r
+   * @param dsa\r
+   *          (typically DataSetAnnotations or AlignmentSequenceAnnotation)\r
+   * @param feature\r
+   *          (the feature to be mapped from)\r
+   * @return\r
+   */\r
+  private RangeAnnotation getDSAnnotationFromJalview(RangeAnnotation dsa,\r
+      SequenceFeature feature) {\r
+    dsa.setType(feature.getType());\r
+    Seg vSeg = new Seg();\r
+    vSeg.setStart(feature.getBegin());\r
+    vSeg.setEnd(feature.getEnd());\r
+    vSeg.setInclusive(true);\r
+    dsa.addSeg(vSeg);\r
+    dsa.setDescription(feature.getDescription());\r
+    dsa.setStatus(feature.getStatus());\r
+    if (feature.links != null && feature.links.size() > 0)\r
+    {\r
+      for (int i = 0, iSize = feature.links.size(); i < iSize; i++)\r
+      {\r
+        String link = (String) feature.links.elementAt(i);\r
+        int sep = link.indexOf('|');\r
+        if (sep > -1)\r
+        {\r
+          Link vLink = new Link();\r
+          if (sep > 0)\r
+            vLink.setContent(link.substring(0, sep - 1));\r
+          else\r
+            vLink.setContent("");\r
+          vLink.setHref(link.substring(sep + 1)); // TODO: validate href.\r
+          dsa.addLink(vLink);\r
+        }\r
+      }\r
+    }\r
+    dsa.setGroup(feature.getFeatureGroup());\r
+    return dsa;\r
+  }\r
+\r
+  /**\r
+   * correctly creates provenance for trees calculated on an alignment by\r
+   * jalview.\r
+   * \r
+   * @param jal\r
+   * @param tp\r
+   * @return\r
+   */\r
+  private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp) {\r
+    Provenance prov = new Provenance();\r
+    prov.addEntry(new Entry());\r
+    prov.getEntry(0).setAction("imported "+tp.getTitle());\r
+    prov.getEntry(0).setUser(provEntry.getUser());\r
+    prov.getEntry(0).setApp(provEntry.getApp());\r
+    prov.getEntry(0).setDate(provEntry.getDate());\r
+    if (tp.getTree().hasOriginalSequenceData())\r
+    {\r
+      Input vInput = new Input();\r
+      // LATER: check to see if tree input data is contained in this alignment -\r
+      // or just correctly resolve the tree's seqData to the correct alignment in\r
+      // the document.\r
+      // vInput.setObjRef(getjv2vObj(jal));\r
+      vInput.setObjRef(getjv2vObj(tp.getViewPort()));\r
+      prov.getEntry(0).setAction("created "+tp.getTitle());\r
+      prov.getEntry(0).addInput(vInput);\r
+      vInput.setName("jalview:seqdist");\r
+      prov.getEntry(0).addParam(new Param());\r
+      prov.getEntry(0).getParam(0).setName("treeType");\r
+      prov.getEntry(0).getParam(0).setType("utf8");\r
+      prov.getEntry(0).getParam(0).setContent("NJ");\r
+      \r
+      int ranges[] = tp.getTree().seqData.getVisibleContigs();\r
+      // VisibleContigs are with respect to alignment coordinates. Still need offsets\r
+      int start= tp.getTree().seqData.getAlignmentOrigin();\r
+      for (int r = 0; r < ranges.length; r += 2)\r
+      {\r
+        Seg visSeg = new Seg();\r
+        visSeg.setStart(1+start+ranges[r]);\r
+        visSeg.setEnd(start+ranges[r + 1]);\r
+        visSeg.setInclusive(true);\r
+        vInput.addSeg(visSeg);\r
+      }\r
+    }\r
+    return prov;\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param tp\r
+   * @return Object[] { AlignmentView, AlignmentI - reference alignment for\r
+   *         input }\r
+   */\r
+  private Object[] recoverInputData(Provenance tp) {\r
+    for (int pe = 0; pe < tp.getEntryCount(); pe++)\r
+    {\r
+      if (tp.getEntry(pe).getInputCount() > 0)\r
+      {\r
+        if (tp.getEntry(pe).getInputCount() > 1)\r
+          Cache.log.warn("Ignoring additional input spec in provenance entry "\r
+              + tp.getEntry(pe).toString());\r
+        // LATER: deal sensibly with multiple inputs.\r
+        Input vInput = tp.getEntry(pe).getInput(0);\r
+        if (vInput.getObjRef() instanceof org.vamsas.objects.core.Alignment)\r
+        {\r
+          // recover an AlignmentView for the input data\r
+          AlignViewport javport = (AlignViewport) getvObj2jv((org.vamsas.client.Vobject) vInput\r
+              .getObjRef());\r
+          jalview.datamodel.AlignmentI jal = javport.getAlignment();\r
+          jalview.datamodel.CigarArray view = javport.getAlignment().getCompactAlignment();\r
+          int from = 1, to = jal.getWidth();\r
+          int offset=0; // deleteRange modifies its frame of reference\r
+          for (int r = 0, s = vInput.getSegCount(); r < s; r++)\r
+          {\r
+            Seg visSeg = vInput.getSeg(r);\r
+            int se[] = getSegRange(visSeg,true); // jalview doesn't do bidirection alignments yet.\r
+            if (to < se[1])\r
+              Cache.log.warn("Ignoring invalid segment in InputData spec.");\r
+            else\r
+            {\r
+              if (se[0] > from)\r
+              {\r
+                view.deleteRange(offset+from-1, offset+se[0] - 2);\r
+                offset-=se[0]-from;\r
+              }\r
+              from = se[1] + 1;\r
+            }\r
+          }\r
+          if (from < to)\r
+          {\r
+            view.deleteRange(offset+from-1, offset+to-1); // final deletion - TODO: check off by\r
+            // one for to\r
+          }\r
+          return new Object[] { new AlignmentView(view), jal };\r
+        }\r
+      }\r
+    }\r
+    Cache.log.debug("Returning null for input data recovery from provenance.");\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * get start<end range of segment, adjusting for inclusivity flag and\r
+   * polarity.\r
+   *  \r
+   * @param visSeg\r
+   * @param ensureDirection when true - always ensure start is less than end.\r
+   * @return int[] { start, end, direction} where direction==1 for range running from end to start.\r
+   */\r
+  private int[] getSegRange(Seg visSeg, boolean ensureDirection) {\r
+    boolean incl = visSeg.getInclusive();\r
+    // adjust for inclusive flag.\r
+    int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of\r
+    // region.\r
+    int start = visSeg.getStart() + (incl ? 0 : pol);\r
+    int end = visSeg.getEnd() + (incl ? 0 : -pol);\r
+    if (ensureDirection && pol==-1)\r
+    {\r
+      // jalview doesn't deal with inverted ranges, yet.\r
+      int t = end;\r
+      end = start;\r
+      start = t;\r
+    }\r
+    return new int[] { start, end, pol<0 ? 1 : 0 };\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param annotation\r
+   * @return true if annotation is not to be stored in document\r
+   */\r
+  private boolean isJalviewOnly(AlignmentAnnotation annotation) {\r
+    return annotation.label.equals("Quality")\r
+    || annotation.label.equals("Conservation")\r
+    || annotation.label.equals("Consensus");\r
+  }\r
+  /**\r
+   * This will return the first AlignFrame viewing AlignViewport av.\r
+   * It will break if there are more than one AlignFrames viewing a particular av.\r
+   * This also shouldn't be in the io package.\r
+   * @param av\r
+   * @return alignFrame for av\r
+   */\r
+  public AlignFrame getAlignFrameFor(AlignViewport av) {\r
+    if (Desktop.desktop != null)\r
+    {\r
+      javax.swing.JInternalFrame[] frames = Desktop.desktop.getAllFrames();\r
+\r
+      for (int t = 0; t < frames.length; t++)\r
+      {\r
+        if (frames[t] instanceof AlignFrame) {\r
+          if (((AlignFrame) frames[t]).getViewport()==av)\r
+            return (AlignFrame) frames[t];\r
+        }\r
+      }\r
+    }\r
+    return null;\r
+  }\r
+  public void updateToJalview() {\r
+    VAMSAS _roots[] = cdoc.getVamsasRoots();\r
+\r
+    for (int _root = 0; _root<_roots.length; _root++) {\r
+      VAMSAS root = _roots[_root];\r
+      boolean newds=false;\r
+      for (int _ds=0,_nds=root.getDataSetCount(); _ds<_nds; _ds++) {\r
+        // ///////////////////////////////////\r
+        // ///LOAD DATASET\r
+        DataSet dataset = root.getDataSet(_ds);\r
+        int i, iSize = dataset.getSequenceCount();\r
+        Vector dsseqs;\r
+        jalview.datamodel.Alignment jdataset = (jalview.datamodel.Alignment) getvObj2jv(dataset);\r
+        int jremain=0;\r
+        if (jdataset==null) {\r
+          Cache.log.debug("Initialising new jalview dataset fields");\r
+          newds=true;\r
+          dsseqs=new Vector();\r
+        } else {\r
+          Cache.log.debug("Update jalview dataset from vamsas.");\r
+          jremain=jdataset.getHeight();\r
+          dsseqs=jdataset.getSequences();\r
+        }\r
+\r
+        // TODO: test sequence merging - we preserve existing non vamsas\r
+        // sequences but add in any new vamsas ones, and don't yet update any\r
+        // sequence attributes\r
+        for (i = 0; i < iSize ; i++)\r
+        {\r
+          Sequence vdseq = dataset.getSequence(i);\r
+          jalview.datamodel.SequenceI dsseq = (SequenceI) getvObj2jv(vdseq);\r
+          if (dsseq!=null) {\r
+            if (!dsseq.getSequence().equals(vdseq.getSequence()))\r
+              throw new Error("Broken! - mismatch of dataset sequence and jalview internal dataset sequence.");\r
+            jremain--;\r
+          } else {\r
+            dsseq = new jalview.datamodel.Sequence(\r
+                dataset.getSequence(i).getName(),\r
+                dataset.getSequence(i).getSequence(),\r
+                dataset.getSequence(i).getStart(),\r
+                dataset.getSequence(i).getEnd()  );\r
+            bindjvvobj(dsseq, dataset.getSequence(i));\r
+            dsseq.setVamsasId(dataset.getSequence(i).getVorbaId().getId());\r
+            dsseqs.add(dsseq);\r
+          }\r
+          if (vdseq.getDbRefCount()>0) {\r
+            DbRef [] dbref = vdseq.getDbRef();\r
+            for(int db=0; db<dbref.length; db++)\r
+            {\r
+              jalview.datamodel.DBRefEntry dbr=(jalview.datamodel.DBRefEntry) getvObj2jv(dbref[db]);\r
+              if (dbr==null) {\r
+                // add new dbref\r
+                dsseq.addDBRef(dbr= new jalview.datamodel.DBRefEntry\r
+                    (\r
+                        dbref[db].getSource().toString(),\r
+                        dbref[db].getVersion().toString(),\r
+                        dbref[db].getAccessionId().toString()));\r
+                bindjvvobj(dbr, dbref[db]);\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        if (newds) {\r
+          SequenceI[] seqs = new SequenceI[dsseqs.size()];\r
+          for (i=0,iSize=dsseqs.size(); i<iSize; i++) {\r
+            seqs[i]=(SequenceI) dsseqs.elementAt(i);\r
+            dsseqs.setElementAt(null, i);\r
+          }\r
+          jdataset = new jalview.datamodel.Alignment(seqs);\r
+          Cache.log.debug("New vamsas dataset imported into jalview.");\r
+          bindjvvobj(jdataset, dataset);\r
+        }\r
+        // ////////\r
+        // add any new dataset sequence feature annotations\r
+        if (dataset.getDataSetAnnotations() != null) {\r
+          for (int dsa = 0; dsa < dataset.getDataSetAnnotationsCount(); dsa++) {\r
+            DataSetAnnotations dseta=dataset.getDataSetAnnotations(dsa);\r
+            SequenceI dsSeq=(SequenceI) getvObj2jv((Vobject) dseta.getSeqRef());\r
+            if (dsSeq==null) {\r
+              jalview.bin.Cache.log.warn("Couldn't resolve jalview sequenceI for dataset object reference "+((Vobject)dataset.getDataSetAnnotations(dsa).getSeqRef()).getVorbaId().getId());\r
+            } else {\r
+              if (dseta.getAnnotationElementCount()==0) {\r
+                jalview.datamodel.SequenceFeature sf=(jalview.datamodel.SequenceFeature) getvObj2jv(dseta);\r
+                if (sf==null) {\r
+                  dsSeq.addSequenceFeature(sf=getJalviewSeqFeature(dseta));\r
+                  bindjvvobj(sf, dseta);\r
+                }\r
+              } else {\r
+                // TODO: deal with alignmentAnnotation style annotation\r
+                // appearing on dataset sequences.\r
+                // JBPNote: we could just add them to all alignments but\r
+                // that may complicate cross references in the jalview\r
+                // datamodel\r
+                Cache.log.warn("Ignoring dataset annotation with annotationElements. Not yet supported in jalview.");\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        if (dataset.getAlignmentCount()>0) {\r
+          // LOAD ALIGNMENTS from DATASET \r
+\r
+          for (int al=0,nal=dataset.getAlignmentCount(); al<nal; al++) {\r
+            org.vamsas.objects.core.Alignment alignment = dataset.getAlignment(al);\r
+            AlignViewport av = (AlignViewport) getvObj2jv(alignment);\r
+            jalview.datamodel.AlignmentI jal=null;\r
+            if (av!=null)\r
+              jal = av.getAlignment(); \r
+            iSize = alignment.getAlignmentSequenceCount();\r
+            boolean newal=(jal==null) ? true : false;\r
+            Vector newasAnnots=new Vector();\r
+            char gapChar=' '; // default for new alignments read in from the document\r
+            if (jal!=null) {\r
+              dsseqs=jal.getSequences(); // for merge/update\r
+              gapChar=jal.getGapCharacter();\r
+            } else {\r
+              dsseqs=new Vector();\r
+            }\r
+            char valGapchar=alignment.getGapChar().charAt(0);\r
+            for (i = 0; i < iSize; i++)\r
+            {\r
+              AlignmentSequence valseq = alignment.getAlignmentSequence(i);\r
+              jalview.datamodel.SequenceI alseq = (SequenceI) getvObj2jv(valseq);\r
+              if (alseq!=null) {\r
+                //TODO: upperCase/LowerCase situation here ? do we allow it ?\r
+                //if (!alseq.getSequence().equals(valseq.getSequence())) {\r
+                // throw new Error("Broken! - mismatch of dataset sequence and jalview internal dataset sequence.");\r
+                if (Cache.log.isDebugEnabled())\r
+                  Cache.log.debug("Updating apparently edited sequence "+alseq.getName());\r
+                // this might go *horribly* wrong\r
+                alseq.setSequence(new String(valseq.getSequence()).replace(valGapchar, gapChar));\r
+                jremain--;\r
+              } else {\r
+                alseq = new jalview.datamodel.Sequence(\r
+                    valseq.getName(),\r
+                    valseq.getSequence().replace(valGapchar, gapChar),\r
+                    valseq.getStart(),\r
+                    valseq.getEnd()  );\r
+                \r
+                Vobject datsetseq = (Vobject)valseq.getRefid();\r
+                if (datsetseq!=null) {\r
+                  alseq.setDatasetSequence((SequenceI)getvObj2jv(datsetseq)); // exceptions if AlignemntSequence reference isn't a simple SequenceI\r
+                } else {\r
+                  Cache.log.error("Invalid dataset sequence id (null) for alignment sequence "+valseq.getVorbaId());\r
+                }\r
+                bindjvvobj(alseq, valseq);\r
+                alseq.setVamsasId(valseq.getVorbaId().getId());\r
+                dsseqs.add(alseq);\r
+              }\r
+              if (valseq.getAlignmentSequenceAnnotationCount()>0) {\r
+                AlignmentSequenceAnnotation[] vasannot=valseq.getAlignmentSequenceAnnotation();\r
+                for (int a=0; a<vasannot.length; a++) {\r
+                  jalview.datamodel.AlignmentAnnotation asa = (jalview.datamodel.AlignmentAnnotation) getvObj2jv(vasannot[a]); // TODO: 1:many jalview alignment sequence annotations\r
+                  if (asa==null) {\r
+                    int se[] = getBounds(vasannot[a]);\r
+                    asa = getjAlignmentAnnotation(jal, vasannot[a]);\r
+                    asa.sequenceRef=alseq;\r
+                    asa.createSequenceMapping(alseq, alseq.getStart()+se[0], false); // TODO: verify that positions in alseqAnnotation correspond to ungapped residue positions.\r
+                    bindjvvobj(asa, vasannot[a]);\r
+                    newasAnnots.add(asa);\r
+                  } else {\r
+                    // update existing annotation - can do this in place\r
+                    if (vasannot[a].getModifiable()) {\r
+                      Cache.log.info("UNIMPLEMENTED: not recovering user modifiable sequence alignment annotation");\r
+                      // TODO: should at least replace with new one - otherwise things will break\r
+                      // basically do this:\r
+                      // int se[] = getBounds(vasannot[a]);\r
+                      // asa.update(getjAlignmentAnnotation(jal, vasannot[a])); //  update from another annotation object in place.\r
+                      // asa.createSequenceMapping(alseq, se[0], false); \r
+\r
+                    }\r
+                  }\r
+                }\r
+              }\r
+            }\r
+            if (jal==null) {\r
+              SequenceI[] seqs = new SequenceI[dsseqs.size()];\r
+              for (i=0,iSize=dsseqs.size(); i<iSize; i++) {\r
+                seqs[i]=(SequenceI) dsseqs.elementAt(i);\r
+                dsseqs.setElementAt(null, i);\r
+              }\r
+              jal = new jalview.datamodel.Alignment(seqs);\r
+              Cache.log.debug("New vamsas alignment imported into jalview "+alignment.getVorbaId().getId());\r
+              jal.setDataset(jdataset);\r
+            }\r
+            if (newasAnnots!=null && newasAnnots.size()>0) {\r
+              // Add the new sequence annotations in to the alignment.\r
+              for (int an=0,anSize=newasAnnots.size(); an<anSize; an++) {\r
+                jal.addAnnotation((AlignmentAnnotation) newasAnnots.elementAt(an));\r
+                // TODO: check if anything has to be done - like calling adjustForAlignment or something.\r
+                newasAnnots.setElementAt(null, an);\r
+              }\r
+              newasAnnots=null;\r
+            }\r
+            // //////////////////////////////////////////\r
+            // //LOAD ANNOTATIONS FOR THE ALIGNMENT\r
+            // ////////////////////////////////////\r
+            if (alignment.getAlignmentAnnotationCount()>0)\r
+            {\r
+              org.vamsas.objects.core.AlignmentAnnotation[] an = alignment.getAlignmentAnnotation();\r
+\r
+              for (int j = 0; j < an.length; j++)\r
+              {\r
+                jalview.datamodel.AlignmentAnnotation jan=(jalview.datamodel.AlignmentAnnotation) getvObj2jv(an[j]);\r
+                if (jan!=null) {\r
+                  // update or stay the same.\r
+                  // TODO: should at least replace with a new one - otherwise things will break\r
+                  // basically do this:\r
+                  // jan.update(getjAlignmentAnnotation(jal, an[a])); //  update from another annotation object in place.\r
+\r
+                  Cache.log.debug("update from vamsas alignment annotation to existing jalview alignment annotation.");\r
+                  if (an[j].getModifiable()) {\r
+                    // TODO: user defined annotation is totally mutable... - so load it up or throw away if locally edited.\r
+                    Cache.log.info("NOT IMPLEMENTED - Recovering user-modifiable annotation - yet...");\r
+                  }\r
+                  // TODO: compare annotation element rows\r
+                  // TODO: compare props.\r
+                } else {\r
+                  jan = getjAlignmentAnnotation(jal, an[j]);\r
+                  jal.addAnnotation(jan);\r
+                  bindjvvobj(jan, an[j]);\r
+                }\r
+              }\r
+            }\r
+            AlignFrame alignFrame;\r
+            if (av==null) {\r
+              Cache.log.debug("New alignframe for alignment "+alignment.getVorbaId());\r
+              // ///////////////////////////////\r
+              // construct alignment view\r
+              alignFrame = new AlignFrame(jal, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);\r
+              av=alignFrame.getViewport();\r
+              String title = alignment.getProvenance().getEntry(alignment.getProvenance().getEntryCount()-1).getAction();\r
+              if (alignment.getPropertyCount()>0) {\r
+                for (int p=0,pe=alignment.getPropertyCount(); p<pe; p++) {\r
+                  if (alignment.getProperty(p).getName().equals("jalview:AlTitle")) {\r
+                    title = alignment.getProperty(p).getContent();\r
+                  }\r
+                }\r
+              }\r
+              // TODO: automatically create meaningful title for a vamsas alignment using its provenance.\r
+              jalview.gui.Desktop.addInternalFrame(alignFrame, title + "("+alignment.getVorbaId()+")",\r
+                  AlignFrame.DEFAULT_WIDTH,\r
+                  AlignFrame.DEFAULT_HEIGHT);\r
+              bindjvvobj(av, alignment);\r
+            } else {\r
+              // find the alignFrame for jal.\r
+              // TODO: fix this so we retrieve the alignFrame handing av *directly*\r
+              alignFrame=getAlignFrameFor(av);\r
+            }\r
+            // LOAD TREES\r
+            // /////////////////////////////////////\r
+            if (alignment.getTreeCount() > 0)\r
+            {\r
+\r
+              for (int t = 0; t < alignment.getTreeCount(); t++)\r
+              {\r
+                Tree tree = alignment.getTree(t);\r
+                TreePanel tp=(TreePanel) getvObj2jv(tree);\r
+                if (tp!=null) {\r
+                  Cache.log.info("Update from vamsas document to alignment associated tree not implemented yet.");\r
+                } else {\r
+                  // make a new tree\r
+                  Object[] idata = this.recoverInputData(tree.getProvenance());\r
+                  try {\r
+                    AlignmentView inputData=null;\r
+                    if (idata!=null && idata[0]!=null)\r
+                      inputData = (AlignmentView) idata[0];\r
+                    tp = alignFrame.ShowNewickTree(\r
+                        new jalview.io.NewickFile(tree.getNewick(0).getContent()),\r
+                        tree.getNewick(0).getTitle()+" ("+tree.getVorbaId()+")",inputData,\r
+                        600, 500,\r
+                        t * 20 + 50, t * 20 + 50);\r
+                    bindjvvobj(tp, tree);\r
+                  } catch (Exception e) {\r
+                    Cache.log.warn("Problems parsing treefile '"+tree.getNewick(0).getContent()+"'",e);\r
+                  }\r
+                }\r
+              }\r
+            }\r
+\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  // bitfields - should be a template in j1.5\r
+  private static int HASSECSTR=0;\r
+  private static int HASVALS=1;\r
+  private static int HASHPHOB=2;\r
+  private static int HASDC=3;\r
+  private static int HASDESCSTR=4;\r
+  private static int HASTWOSTATE=5; // not used yet.\r
+  /**\r
+   * parses the AnnotationElements - if they exist - into jalview.datamodel.Annotation[] rows\r
+   * Two annotation rows are made if there are distinct annotation for both at 'pos' and 'after pos' at any particular site.\r
+   * @param annotation\r
+   * @return { boolean[static int constants ], int[ae.length] - map to annotated object frame, jalview.datamodel.Annotation[], jalview.datamodel.Annotation[] (after)}\r
+   */\r
+  private Object[] parseRangeAnnotation(org.vamsas.objects.core.RangeAnnotation annotation) {\r
+    // set these attributes by looking in the annotation to decide what kind of alignment annotation rows will be made\r
+    // TODO: potentially we might make several annotation rows from one vamsas alignment annotation. the jv2Vobj binding mechanism\r
+    // may not quite cope with this (without binding an array of annotations to a vamsas alignment annotation)\r
+    // summary flags saying what we found over the set of annotation rows.\r
+    boolean[] AeContent = new boolean[] { false, false, false, false, false};\r
+    int[] rangeMap = getMapping(annotation);\r
+    jalview.datamodel.Annotation[][] anot=new jalview.datamodel.Annotation[][] { \r
+        new jalview.datamodel.Annotation[rangeMap.length],\r
+        new jalview.datamodel.Annotation[rangeMap.length]\r
+    };\r
+    boolean mergeable=true; //false  if 'after positions cant be placed on same annotation row as positions. \r
+    \r
+    if (annotation.getAnnotationElementCount()>0) {\r
+      AnnotationElement ae[] = annotation.getAnnotationElement();\r
+      for (int aa = 0; aa < ae.length; aa++)\r
+      {\r
+        int pos = ae[aa].getPosition()-1;// pos counts from 1 to (|seg.start-seg.end|+1)\r
+        if (pos>=0 && pos<rangeMap.length) { \r
+          int row=ae[aa].getAfter()?1:0;\r
+          if (anot[row][pos]!=null) {\r
+            // only time this should happen is if the After flag is set.\r
+            Cache.log.debug("Ignoring duplicate annotation site at "+pos);\r
+            continue;\r
+          }\r
+          if (anot[1-row][pos]!=null)\r
+            mergeable=false;\r
+          String desc = "";\r
+          if (ae[aa].getDescription()!=null) {\r
+            desc = ae[aa].getDescription();\r
+            if (desc.length()>0) {\r
+              // have imported valid description string\r
+              AeContent[HASDESCSTR]=true;\r
+            }\r
+          }\r
+          String dc = null;//ae[aa].getDisplayCharacter()==null ? "dc" : ae[aa].getDisplayCharacter();\r
+          String ss = null;//ae[aa].getSecondaryStructure()==null ? "ss" : ae[aa].getSecondaryStructure();\r
+          java.awt.Color colour = null;\r
+          if (ae[aa].getGlyphCount()>0) {\r
+            Glyph[] glyphs = ae[aa].getGlyph();\r
+            for (int g=0; g<glyphs.length; g++) {\r
+              if (glyphs[g].getDict().equals(org.vamsas.objects.utils.GlyphDictionary.PROTEIN_SS_3STATE)) {\r
+                ss=glyphs[g].getContent();\r
+                AeContent[HASSECSTR]=true;\r
+              } else if (glyphs[g].getDict().equals(org.vamsas.objects.utils.GlyphDictionary.PROTEIN_HD_HYDRO)) {\r
+                Cache.log.debug("ignoring hydrophobicity glyph marker.");\r
+                AeContent[HASHPHOB]=true;\r
+                char c=(dc=glyphs[g].getContent()).charAt(0);\r
+                // dc may get overwritten - but we still set the colour.\r
+                colour = new java.awt.Color(c=='+'?255:0,c=='.'?255:0,c=='-'?255:0);\r
+\r
+              } else if (glyphs[g].getDict().equals(org.vamsas.objects.utils.GlyphDictionary.DEFAULT)) {\r
+                dc = glyphs[g].getContent();\r
+                AeContent[HASDC]=true;\r
+              } else {\r
+                Cache.log.debug("Ignoring unknown glyph type "+glyphs[g].getDict());\r
+              }\r
+            }\r
+          }\r
+          float val=0;\r
+          if (ae[aa].getValueCount()>0) {\r
+            AeContent[HASVALS]=true;\r
+            if (ae[aa].getValueCount()>1) {\r
+              Cache.log.warn("ignoring additional "+(ae[aa].getValueCount()-1)+"values in annotation element.");\r
+            }\r
+            val = ae[aa].getValue(0);\r
+          }\r
+          if (colour==null) {\r
+            anot[row][pos]=new jalview.datamodel.Annotation((dc!=null) ? dc : "", desc, (ss!=null)?ss.charAt(0):' ', val);\r
+          } else {\r
+            anot[row][pos]=new jalview.datamodel.Annotation((dc!=null) ? dc : "", desc, (ss!=null)?ss.charAt(0):' ', val, colour);\r
+          }\r
+        } else {\r
+          Cache.log.warn("Ignoring out of bound annotation element "+aa+" in "+annotation.getVorbaId().getId());\r
+        }\r
+      }\r
+      // decide on how many annotation rows are needed.\r
+      if (mergeable) {\r
+        for (int i=0; i<anot[0].length;i++) {\r
+          if (anot[1][i]!=null) {\r
+            anot[0][i] = anot[1][i];\r
+            anot[0][i].description = anot[0][i].description+" (after)";\r
+            AeContent[HASDESCSTR]=true; // we have valid description string data\r
+            anot[1][i] = null;\r
+          }\r
+        }\r
+        anot[1] = null;\r
+      } else {\r
+        for (int i=0; i<anot[0].length;i++) {\r
+          anot[1][i].description = anot[1][i].description+" (after)";\r
+        }\r
+      }\r
+      return new Object[] { AeContent, rangeMap, anot[0], anot[1] };\r
+    } else {\r
+      // no annotations to parse. Just return an empty annotationElement[] array.\r
+      return new Object[] { AeContent, rangeMap, anot[0], anot[1] };\r
+    }\r
+    // return null;\r
+  }\r
+  /**\r
+   * @param jal the jalview alignment to which the annotation will be attached (ideally - freshly updated from corresponding vamsas alignment)\r
+   * @param annotation\r
+   * @return unbound jalview alignment annotation object.\r
+   */\r
+  private jalview.datamodel.AlignmentAnnotation getjAlignmentAnnotation(jalview.datamodel.AlignmentI jal, org.vamsas.objects.core.RangeAnnotation annotation) {\r
+    jalview.datamodel.AlignmentAnnotation jan =null;\r
+    if (annotation==null)\r
+      return null;\r
+    // boolean hasSequenceRef=annotation.getClass().equals(org.vamsas.objects.core.AlignmentSequenceAnnotation.class);\r
+    //boolean hasProvenance=hasSequenceRef || (annotation.getClass().equals(org.vamsas.objects.core.AlignmentAnnotation.class));\r
+    /*int se[] = getBounds(annotation);\r
+    if (se==null)\r
+      se=new int[] {0,jal.getWidth()-1};\r
+     */\r
+    Object[] parsedRangeAnnotation = parseRangeAnnotation(annotation);\r
+    String a_label=annotation.getLabel();\r
+    String a_descr=annotation.getDescription();\r
+    if (a_label==null || a_label.length()==0) {\r
+      a_label = annotation.getType();\r
+      if (a_label.length()==0)\r
+        a_label = "Unamed annotation";\r
+    }\r
+    if (a_descr==null || a_descr.length()==0) {\r
+      a_descr = "Annotation of type '"+annotation.getType()+"'";\r
+    }\r
+    if (parsedRangeAnnotation==null) {\r
+      Cache.log.debug("Inserting empty annotation row elements for a whole-alignment annotation.");\r
+      \r
+      \r
+    } else {\r
+      if (parsedRangeAnnotation[3]!=null) {\r
+        Cache.log.warn("Ignoring 'After' annotation row in "+annotation.getVorbaId());\r
+      }\r
+      jalview.datamodel.Annotation[] arow = (jalview.datamodel.Annotation[]) parsedRangeAnnotation[2];\r
+      boolean[] has=(boolean[])parsedRangeAnnotation[0];\r
+      // VAMSAS: getGraph is only on derived annotation for alignments - in this way its 'odd' - there is already an existing TODO about removing this flag as being redundant\r
+      /*if ((annotation.getClass().equals(org.vamsas.objects.core.AlignmentAnnotation.class) && ((org.vamsas.objects.core.AlignmentAnnotation)annotation).getGraph())\r
+          || (hasSequenceRef=true && ((org.vamsas.objects.core.AlignmentSequenceAnnotation)annotation).getGraph())) {\r
+      */\r
+      if (has[HASVALS]) {\r
+        // make bounds and automatic description strings for jalview user's benefit (these shouldn't be written back to vamsas document)\r
+        boolean first=true;\r
+        float min=0,max=1;\r
+        int lastval=0;\r
+        for (int i=0;i<arow.length; i++) {\r
+          if (arow[i]!=null) {\r
+            if (i-lastval>1) {\r
+              // do some interpolation *between* points\r
+              if (arow[lastval]!=null) {\r
+                float interval = arow[i].value-arow[lastval].value;\r
+                interval/=i-lastval;\r
+                float base = arow[lastval].value;\r
+                for (int ip=lastval+1,np=0; ip<i; np++,ip++) {\r
+                  arow[ip] = new jalview.datamodel.Annotation("","",' ', interval*np+base);\r
+                  // NB - Interpolated points don't get a tooltip and description.\r
+                }\r
+              }\r
+            }\r
+            lastval=i;\r
+            // check range - shouldn't we have a min and max property in the annotation object ?\r
+            if (first) { min=max=arow[i].value; first=false;}\r
+            else { if (arow[i].value<min) { min=arow[i].value; }\r
+            else if (arow[i].value>max) { max=arow[i].value; }\r
+            }\r
+            // make tooltip and display char value\r
+            if (!has[HASDESCSTR]) arow[i].description = arow[i].value + "";\r
+            if (!has[HASDC]) arow[i].displayCharacter=arow[i].value+"";\r
+          } \r
+        }\r
+        int type=jalview.datamodel.AlignmentAnnotation.LINE_GRAPH;\r
+        if (has[HASHPHOB]) {\r
+          type = jalview.datamodel.AlignmentAnnotation.BAR_GRAPH;\r
+        }\r
+        jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr, arow, min, max, type);\r
+      } else {\r
+        jan = new jalview.datamodel.AlignmentAnnotation(a_label, a_descr, arow);\r
+        jan.setThreshold(null);\r
+      }\r
+      if (annotation.getLinkCount()>0) {\r
+        Cache.log.warn("Ignoring "+annotation.getLinkCount()+"links added to AlignmentAnnotation.");\r
+      }\r
+      if (annotation.getModifiable()) {\r
+        jan.editable=true;\r
+      }\r
+\r
+      if (annotation.getPropertyCount()>0) {\r
+        // look for special jalview properties\r
+        org.vamsas.objects.core.Property[] props=annotation.getProperty();\r
+        for (int p=0;p<props.length; p++) {\r
+          if (props[p].getName().equalsIgnoreCase("jalview:graphType")) {\r
+            try { \r
+              // probably a jalview annotation graph so recover the visualization hints.\r
+              jan.graph = jalview.datamodel.AlignmentAnnotation.getGraphValueFromString(props[p].getContent());\r
+            } catch (Exception e) {\r
+              Cache.log.debug("Invalid graph type value in jalview:graphType property.");\r
+            }\r
+            try {\r
+              if (annotation.getGroup()!=null && annotation.getGroup().length()>0)\r
+                jan.graphGroup = Integer.parseInt(annotation.getGroup());\r
+            } catch (Exception e) {\r
+              Cache.log.info("UNIMPLEMENTED : Couldn't parse non-integer group value for setting graphGroup correctly.");\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      return jan;\r
+\r
+    } \r
+\r
+    return null;\r
+  }\r
+\r
+  private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta) {\r
+    int[] se = getBounds(dseta);\r
+    SequenceFeature sf = new jalview.datamodel.SequenceFeature(dseta.getType(),\r
+        dseta.getDescription(), dseta.getStatus(), se[0], se[1], dseta\r
+        .getGroup());\r
+    if (dseta.getLinkCount() > 0)\r
+    {\r
+      Link[] links = dseta.getLink();\r
+      for (int i = 0; i < links.length; i++)\r
+      {\r
+        sf.addLink(links[i].getContent() + "|" + links[i].getHref());\r
+      }\r
+    }\r
+    return sf;\r
+  }\r
+\r
+  /**\r
+   * get real bounds of a RangeType's specification. start and end are an\r
+   * inclusive range within which all segments and positions lie.\r
+   * TODO: refactor to vamsas utils\r
+   * @param dseta\r
+   * @return int[] { start, end}\r
+   */\r
+  private int[] getBounds(RangeType dseta) {\r
+    if (dseta != null)\r
+    {\r
+      int[] se = null;\r
+      if (dseta.getSegCount()>0 && dseta.getPosCount()>0)\r
+        throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+      if (dseta.getSegCount() > 0)\r
+      {\r
+        se = getSegRange(dseta.getSeg(0),true);\r
+        for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)\r
+        {\r
+          int nse[] = getSegRange(dseta.getSeg(s), true);\r
+          if (se[0] > nse[0])\r
+            se[0] = nse[0];\r
+          if (se[1] < nse[1])\r
+            se[1] = nse[1];\r
+        }\r
+      }\r
+      if (dseta.getPosCount() > 0)\r
+      {\r
+        // could do a polarity for pos range too. and pass back indication of discontinuities.\r
+        int pos = dseta.getPos(0).getI();\r
+        se = new int[] { pos, pos };\r
+        for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+        {\r
+          pos = dseta.getPos(p).getI();\r
+          if (se[0] > pos)\r
+            se[0] = pos;\r
+          if (se[1] < pos)\r
+            se[1] = pos;\r
+        }\r
+      }\r
+      return se;\r
+    }\r
+    return null;\r
+  }\r
+  /**\r
+   * map from a rangeType's internal frame to the referenced object's coordinate frame.\r
+   * @param dseta\r
+   * @return int [] { ref(pos)...} for all pos in rangeType's frame.\r
+   */\r
+  private int[] getMapping(RangeType dseta) {\r
+    Vector posList=new Vector();\r
+    if (dseta != null)\r
+    {\r
+      int[] se = null;\r
+      if (dseta.getSegCount()>0 && dseta.getPosCount()>0)\r
+        throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+      if (dseta.getSegCount() > 0)\r
+      {\r
+        for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)\r
+        {\r
+          se = getSegRange(dseta.getSeg(s), false);\r
+          int se_end=se[1-se[2]]+(se[2]==0 ? 1 : -1);\r
+          for (int p=se[se[2]]; p!=se_end; p+=se[2]==0 ? 1 : -1 ) {\r
+            posList.add(new Integer(p));\r
+          }\r
+        }\r
+      } \r
+      else if (dseta.getPosCount() > 0)\r
+      {\r
+        int pos = dseta.getPos(0).getI();\r
+\r
+        for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+        {\r
+          pos = dseta.getPos(p).getI();\r
+          posList.add(new Integer(pos));\r
+        }\r
+      }\r
+    }\r
+    if (posList!=null && posList.size()>0) {\r
+      int[] range=new int[posList.size()];\r
+      for (int i=0; i<range.length; i++)\r
+        range[i] = ((Integer)posList.elementAt(i)).intValue();\r
+      posList.clear();\r
+      return range;\r
+    }\r
+    return null;\r
+  }\r
+  /* not needed now. \r
+   * Provenance getVamsasProvenance(jalview.datamodel.Provenance jprov) {\r
+    jalview.datamodel.ProvenanceEntry[] entries = null;\r
+    // TODO: fix App and Action here.\r
+    Provenance prov = new Provenance();\r
+    org.exolab.castor.types.Date date = new org.exolab.castor.types.Date(\r
+        new java.util.Date());\r
+    Entry provEntry;\r
+\r
+    if (jprov != null)\r
+    {\r
+      entries = jprov.getEntries();\r
+      for (int i = 0; i < entries.length; i++)\r
+      {\r
+        provEntry = new Entry();\r
+        try\r
+        {\r
+          date = new org.exolab.castor.types.Date(entries[i].getDate());\r
+        } catch (Exception ex)\r
+        {\r
+          ex.printStackTrace();\r
+\r
+          date = new org.exolab.castor.types.Date(entries[i].getDate());\r
+        }\r
+        provEntry.setDate(date);\r
+        provEntry.setUser(entries[i].getUser());\r
+        provEntry.setAction(entries[i].getAction());\r
+        prov.addEntry(provEntry);\r
+      }\r
+    }\r
+    else\r
+    {\r
+      provEntry = new Entry();\r
+      provEntry.setDate(date);\r
+      provEntry.setUser(System.getProperty("user.name")); // TODO: ext string\r
+      provEntry.setApp("JVAPP"); // TODO: ext string\r
+      provEntry.setAction(action);\r
+      prov.addEntry(provEntry);\r
+    }\r
+\r
+    return prov;\r
+  }\r
+   */\r
+  jalview.datamodel.Provenance getJalviewProvenance(Provenance prov) {\r
+    // TODO: fix App and Action entries and check use of provenance in jalview.\r
+    jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();\r
+    for (int i = 0; i < prov.getEntryCount(); i++)\r
+    {\r
+      jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i).getAction(),\r
+          prov.getEntry(i).getDate().toDate(), prov.getEntry(i).getId());\r
+    }\r
+\r
+    return jprov;\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @return default initial provenance list for a Jalview created vamsas\r
+   *         object.\r
+   */\r
+  Provenance dummyProvenance() {\r
+    return dummyProvenance(null);\r
+  }\r
+\r
+  Entry dummyPEntry(String action) {\r
+    Entry entry = new Entry();\r
+    entry.setApp(this.provEntry.getApp());\r
+    if (action != null)\r
+      entry.setAction(action);\r
+    else\r
+      entry.setAction("created.");\r
+    entry.setDate(new org.exolab.castor.types.Date(new java.util.Date()));\r
+    entry.setUser(this.provEntry.getUser());\r
+    return entry;\r
+  }\r
+\r
+  Provenance dummyProvenance(String action) {\r
+    Provenance prov = new Provenance();\r
+    prov.addEntry(dummyPEntry(action));\r
+    return prov;\r
+  }\r
+\r
+  void addProvenance(Provenance p, String action) {\r
+    p.addEntry(dummyPEntry(action));\r
+  }\r
+\r
+}\r
index 1d3cbd0..d908bde 100755 (executable)
-/*\r
-* Jalview - A Sequence Alignment Editor and Viewer\r
-* Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
-*\r
-* This program is free software; you can redistribute it and/or\r
-* modify it under the terms of the GNU General Public License\r
-* as published by the Free Software Foundation; either version 2\r
-* of the License, or (at your option) any later version.\r
-*\r
-* This program is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with this program; if not, write to the Free Software\r
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
-*/\r
-package jalview.jbgui;\r
-\r
-import java.awt.*;\r
-import java.awt.event.*;\r
-\r
-import javax.swing.*;\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class GDesktop extends JFrame\r
-{\r
-    protected static JMenu windowMenu = new JMenu();\r
-    JMenuBar DesktopMenubar = new JMenuBar();\r
-    JMenu FileMenu = new JMenu();\r
-    JMenu HelpMenu = new JMenu();\r
-    JMenuItem inputLocalFileMenuItem = new JMenuItem();\r
-    JMenuItem inputURLMenuItem = new JMenuItem();\r
-    JMenuItem inputTextboxMenuItem = new JMenuItem();\r
-    JMenuItem quit = new JMenuItem();\r
-    JMenuItem aboutMenuItem = new JMenuItem();\r
-    JMenuItem documentationMenuItem = new JMenuItem();\r
-    FlowLayout flowLayout1 = new FlowLayout();\r
-    JMenu toolsMenu = new JMenu();\r
-    JMenuItem preferences = new JMenuItem();\r
-    JMenuItem saveState = new JMenuItem();\r
-    JMenuItem loadState = new JMenuItem();\r
-    JMenu jMenu1 = new JMenu();\r
-  JMenuItem vamsasLoad = new JMenuItem();\r
-  JMenuItem inputSequence = new JMenuItem();\r
-\r
-  /**\r
-     * Creates a new GDesktop object.\r
-     */\r
-    public GDesktop()\r
-    {\r
-        try\r
-        {\r
-            jbInit();\r
-            this.setJMenuBar(DesktopMenubar);\r
-        }\r
-        catch (Exception e)\r
-        {\r
-            e.printStackTrace();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @throws Exception DOCUMENT ME!\r
-     */\r
-    private void jbInit() throws Exception\r
-    {\r
-        FileMenu.setMnemonic('F');\r
-        FileMenu.setText("File");\r
-        HelpMenu.setText("Help");\r
-        inputLocalFileMenuItem.setMnemonic('L');\r
-        inputLocalFileMenuItem.setText("from File");\r
-        inputLocalFileMenuItem.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    inputLocalFileMenuItem_actionPerformed(null);\r
-                }\r
-            });\r
-        inputURLMenuItem.setMnemonic('U');\r
-        inputURLMenuItem.setText("from URL");\r
-        inputURLMenuItem.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    inputURLMenuItem_actionPerformed(null);\r
-                }\r
-            });\r
-        inputTextboxMenuItem.setMnemonic('C');\r
-        inputTextboxMenuItem.setText("from Textbox");\r
-        inputTextboxMenuItem.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    inputTextboxMenuItem_actionPerformed(null);\r
-                }\r
-            });\r
-        quit.setMnemonic('Q');\r
-        quit.setText("Quit");\r
-        quit.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    quit();\r
-                }\r
-            });\r
-        aboutMenuItem.setText("About");\r
-        aboutMenuItem.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    aboutMenuItem_actionPerformed(e);\r
-                }\r
-            });\r
-        documentationMenuItem.setText("Documentation");\r
-        documentationMenuItem.addActionListener(new java.awt.event.ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    documentationMenuItem_actionPerformed(e);\r
-                }\r
-            });\r
-        this.getContentPane().setLayout(flowLayout1);\r
-        windowMenu.setText("Window");\r
-        preferences.setText("Preferences...");\r
-        preferences.addActionListener(new ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    preferences_actionPerformed(e);\r
-                }\r
-            });\r
-        toolsMenu.setText("Tools");\r
-        saveState.setMnemonic('S');\r
-        saveState.setText("Save Project");\r
-        saveState.addActionListener(new ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    saveState_actionPerformed(e);\r
-                }\r
-            });\r
-        loadState.setMnemonic('L');\r
-        loadState.setText("Load Project");\r
-        loadState.addActionListener(new ActionListener()\r
-            {\r
-                public void actionPerformed(ActionEvent e)\r
-                {\r
-                    loadState_actionPerformed(e);\r
-                }\r
-            });\r
-        jMenu1.setMnemonic('I');\r
-        jMenu1.setText("Input Alignment");\r
-    vamsasLoad.setText("Vamsas");\r
-    vamsasLoad.setVisible(false);\r
-    vamsasLoad.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent e)\r
-      {\r
-        vamsasLoad_actionPerformed(e);\r
-      }\r
-    });\r
-    inputSequence.setText("Fetch Sequence(s)...");\r
-    inputSequence.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent e)\r
-      {\r
-        inputSequence_actionPerformed(e);\r
-      }\r
-    });\r
-    DesktopMenubar.add(FileMenu);\r
-        DesktopMenubar.add(toolsMenu);\r
-        DesktopMenubar.add(HelpMenu);\r
-        DesktopMenubar.add(windowMenu);\r
-    FileMenu.add(jMenu1);\r
-    FileMenu.add(inputSequence);\r
-    FileMenu.addSeparator();\r
-        FileMenu.add(saveState);\r
-        FileMenu.add(loadState);\r
-        FileMenu.addSeparator();\r
-        FileMenu.add(quit);\r
-        HelpMenu.add(aboutMenuItem);\r
-        HelpMenu.add(documentationMenuItem);\r
-        toolsMenu.add(preferences);\r
-        jMenu1.add(inputLocalFileMenuItem);\r
-        jMenu1.add(inputURLMenuItem);\r
-        jMenu1.add(inputTextboxMenuItem);\r
-    jMenu1.add(vamsasLoad);\r
-  }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void inputLocalFileMenuItem_actionPerformed(jalview.gui.AlignViewport av)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void inputURLMenuItem_actionPerformed(jalview.gui.AlignViewport av)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void inputTextboxMenuItem_actionPerformed(jalview.gui.AlignViewport av)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     */\r
-    protected void quit()\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void aboutMenuItem_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void documentationMenuItem_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void SaveState_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    protected void preferences_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void saveState_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void loadState_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param e DOCUMENT ME!\r
-     */\r
-    public void loadJalviewAlign_actionPerformed(ActionEvent e)\r
-    {\r
-    }\r
-\r
-  public void vamsasLoad_actionPerformed(ActionEvent e)\r
-  {\r
-\r
-  }\r
-\r
-  public void inputSequence_actionPerformed(ActionEvent e)\r
-  {\r
-\r
-  }\r
-}\r
+/*
+* Jalview - A Sequence Alignment Editor and Viewer
+* Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+*
+* 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
+*/
+package jalview.jbgui;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.*;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class GDesktop extends JFrame
+{
+    protected static JMenu windowMenu = new JMenu();
+    JMenuBar DesktopMenubar = new JMenuBar();
+    JMenu FileMenu = new JMenu();
+    JMenu HelpMenu = new JMenu();
+    protected JMenu VamsasMenu = new JMenu();
+    JMenuItem inputLocalFileMenuItem = new JMenuItem();
+    JMenuItem inputURLMenuItem = new JMenuItem();
+    JMenuItem inputTextboxMenuItem = new JMenuItem();
+    JMenuItem quit = new JMenuItem();
+    JMenuItem aboutMenuItem = new JMenuItem();
+    JMenuItem documentationMenuItem = new JMenuItem();
+    FlowLayout flowLayout1 = new FlowLayout();
+    JMenu toolsMenu = new JMenu();
+    JMenuItem preferences = new JMenuItem();
+    JMenuItem saveState = new JMenuItem();
+    JMenuItem loadState = new JMenuItem();
+    JMenu jMenu1 = new JMenu();
+  protected JMenuItem vamsasLoad = new JMenuItem();
+  JMenuItem inputSequence = new JMenuItem();
+  protected JMenuItem vamsasStop = new JMenuItem();
+
+  /**
+     * Creates a new GDesktop object.
+     */
+    public GDesktop()
+    {
+        try
+        {
+            jbInit();
+            this.setJMenuBar(DesktopMenubar);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @throws Exception DOCUMENT ME!
+     */
+    private void jbInit() throws Exception
+    {
+        FileMenu.setMnemonic('F');
+        FileMenu.setText("File");
+        HelpMenu.setText("Help");
+        VamsasMenu.setText("Vamsas");
+        VamsasMenu.setMnemonic('V');
+        VamsasMenu.setToolTipText("Share data with other vamsas applications.");
+        inputLocalFileMenuItem.setMnemonic('L');
+        inputLocalFileMenuItem.setText("from File");
+        inputLocalFileMenuItem.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    inputLocalFileMenuItem_actionPerformed(null);
+                }
+            });
+        inputURLMenuItem.setMnemonic('U');
+        inputURLMenuItem.setText("from URL");
+        inputURLMenuItem.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    inputURLMenuItem_actionPerformed(null);
+                }
+            });
+        inputTextboxMenuItem.setMnemonic('C');
+        inputTextboxMenuItem.setText("from Textbox");
+        inputTextboxMenuItem.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    inputTextboxMenuItem_actionPerformed(null);
+                }
+            });
+        quit.setMnemonic('Q');
+        quit.setText("Quit");
+        quit.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    quit();
+                }
+            });
+        aboutMenuItem.setText("About");
+        aboutMenuItem.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    aboutMenuItem_actionPerformed(e);
+                }
+            });
+        documentationMenuItem.setText("Documentation");
+        documentationMenuItem.addActionListener(new java.awt.event.ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    documentationMenuItem_actionPerformed(e);
+                }
+            });
+        this.getContentPane().setLayout(flowLayout1);
+        windowMenu.setText("Window");
+        preferences.setText("Preferences...");
+        preferences.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    preferences_actionPerformed(e);
+                }
+            });
+        toolsMenu.setText("Tools");
+        saveState.setMnemonic('S');
+        saveState.setText("Save Project");
+        saveState.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    saveState_actionPerformed(e);
+                }
+            });
+        loadState.setMnemonic('L');
+        loadState.setText("Load Project");
+        loadState.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    loadState_actionPerformed(e);
+                }
+            });
+        jMenu1.setMnemonic('I');
+        jMenu1.setText("Input Alignment");
+    vamsasLoad.setText("Start Vamsas Session...");
+    vamsasLoad.setVisible(false);
+    vamsasLoad.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        vamsasLoad_actionPerformed(e);
+      }
+    });
+    inputSequence.setText("Fetch Sequence(s)...");
+    inputSequence.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        inputSequence_actionPerformed(e);
+      }
+    });
+    vamsasStop.setText("Stop Vamsas Session");
+    vamsasStop.setVisible(false);
+    vamsasStop.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        vamsasStop_actionPerformed(e);
+      }
+    });    DesktopMenubar.add(FileMenu);
+        DesktopMenubar.add(toolsMenu);
+        VamsasMenu.setVisible(false);
+        DesktopMenubar.add(VamsasMenu);
+        DesktopMenubar.add(HelpMenu);
+        DesktopMenubar.add(windowMenu);
+        FileMenu.addSeparator();
+    FileMenu.add(jMenu1);
+    FileMenu.add(inputSequence);
+    FileMenu.addSeparator();
+        FileMenu.add(saveState);
+        FileMenu.add(loadState);
+        FileMenu.addSeparator();
+        FileMenu.add(quit);
+        HelpMenu.add(aboutMenuItem);
+        HelpMenu.add(documentationMenuItem);
+        VamsasMenu.add(vamsasLoad);
+        VamsasMenu.add(vamsasStop);
+        toolsMenu.add(preferences);
+        jMenu1.add(inputLocalFileMenuItem);
+        jMenu1.add(inputURLMenuItem);
+        jMenu1.add(inputTextboxMenuItem);
+       //    jMenu1.add(vamsasLoad);
+  }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void inputLocalFileMenuItem_actionPerformed(jalview.gui.AlignViewport av)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void inputURLMenuItem_actionPerformed(jalview.gui.AlignViewport av)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void inputTextboxMenuItem_actionPerformed(jalview.gui.AlignViewport av)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     */
+    protected void quit()
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void aboutMenuItem_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void documentationMenuItem_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void SaveState_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    protected void preferences_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void saveState_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void loadState_actionPerformed(ActionEvent e)
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @param e DOCUMENT ME!
+     */
+    public void loadJalviewAlign_actionPerformed(ActionEvent e)
+    {
+    }
+
+  public void vamsasLoad_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  public void inputSequence_actionPerformed(ActionEvent e)
+  {
+
+  }
+  public void vamsasStop_actionPerformed(ActionEvent e)
+  {
+
+       }
+}