eea181f476701e4d2a58abcf7b5068100d337692
[jalview.git] / src / jalview / gui / TreeCanvas.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.analysis.*;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 import jalview.schemes.*;\r
26 \r
27 import jalview.util.*;\r
28 \r
29 import java.awt.*;\r
30 import java.awt.event.*;\r
31 import java.awt.print.*;\r
32 \r
33 import java.util.*;\r
34 \r
35 import javax.swing.*;\r
36 \r
37 \r
38 /**\r
39  * DOCUMENT ME!\r
40  *\r
41  * @author $author$\r
42  * @version $Revision$\r
43  */\r
44 public class TreeCanvas extends JPanel implements MouseListener, Runnable,\r
45     Printable\r
46 {\r
47     /** DOCUMENT ME!! */\r
48     public static final String PLACEHOLDER = " * ";\r
49     NJTree tree;\r
50     JScrollPane scrollPane;\r
51     AlignViewport av;\r
52     Font font;\r
53     int fontSize;\r
54     boolean fitToWindow = true;\r
55     boolean showDistances = false;\r
56     boolean showBootstrap = false;\r
57     boolean markPlaceholders = false;\r
58     int offx = 20;\r
59     int offy = 20;\r
60     float threshold;\r
61     String longestName;\r
62     int labelLength = -1;\r
63 \r
64     //RubberbandRectangle rubberband;\r
65     Vector listeners;\r
66     Hashtable nameHash = new Hashtable();\r
67     Hashtable nodeHash = new Hashtable();\r
68 \r
69     /**\r
70      * Creates a new TreeCanvas object.\r
71      *\r
72      * @param av DOCUMENT ME!\r
73      * @param tree DOCUMENT ME!\r
74      * @param scroller DOCUMENT ME!\r
75      * @param label DOCUMENT ME!\r
76      */\r
77     public TreeCanvas(AlignViewport av, JScrollPane scroller)\r
78     {\r
79         this.av = av;\r
80         font = av.getFont();\r
81         scrollPane = scroller;\r
82         addMouseListener(this);\r
83         PaintRefresher.Register(this, av.alignment);\r
84     }\r
85 \r
86 \r
87     /**\r
88      * DOCUMENT ME!\r
89      *\r
90      * @param sequence DOCUMENT ME!\r
91      */\r
92     public void TreeSelectionChanged(Sequence sequence)\r
93     {\r
94         SequenceGroup selected = av.getSelectionGroup();\r
95 \r
96         if (selected == null)\r
97         {\r
98             selected = new SequenceGroup();\r
99             av.setSelectionGroup(selected);\r
100         }\r
101 \r
102         selected.setEndRes(av.alignment.getWidth()-1);\r
103         selected.addOrRemove(sequence, true);\r
104 \r
105         PaintRefresher.Refresh(this, av.alignment);\r
106         repaint();\r
107     }\r
108 \r
109     /**\r
110      * DOCUMENT ME!\r
111      *\r
112      * @param tree DOCUMENT ME!\r
113      */\r
114     public void setTree(NJTree tree)\r
115     {\r
116         this.tree = tree;\r
117         tree.findHeight(tree.getTopNode());\r
118 \r
119         // Now have to calculate longest name based on the leaves\r
120         Vector leaves = tree.findLeaves(tree.getTopNode(), new Vector());\r
121         boolean has_placeholders = false;\r
122         longestName = "";\r
123 \r
124         for (int i = 0; i < leaves.size(); i++)\r
125         {\r
126           SequenceNode lf = (SequenceNode) leaves.elementAt(i);\r
127 \r
128           if (lf.isPlaceholder())\r
129           {\r
130             has_placeholders = true;\r
131           }\r
132 \r
133           if (longestName.length() < ( (Sequence) lf.element()).getName()\r
134               .length())\r
135           {\r
136             longestName = TreeCanvas.PLACEHOLDER +\r
137                 ( (Sequence) lf.element()).getName();\r
138           }\r
139         }\r
140 \r
141         setMarkPlaceholders(has_placeholders);\r
142     }\r
143 \r
144     /**\r
145      * DOCUMENT ME!\r
146      *\r
147      * @param g DOCUMENT ME!\r
148      * @param node DOCUMENT ME!\r
149      * @param chunk DOCUMENT ME!\r
150      * @param scale DOCUMENT ME!\r
151      * @param width DOCUMENT ME!\r
152      * @param offx DOCUMENT ME!\r
153      * @param offy DOCUMENT ME!\r
154      */\r
155     public void drawNode(Graphics g, SequenceNode node, float chunk,\r
156         float scale, int width, int offx, int offy)\r
157     {\r
158         if (node == null)\r
159         {\r
160             return;\r
161         }\r
162 \r
163         if ((node.left() == null) && (node.right() == null))\r
164         {\r
165             // Drawing leaf node\r
166             float height = node.height;\r
167             float dist = node.dist;\r
168 \r
169             int xstart = (int) ((height - dist) * scale) + offx;\r
170             int xend = (int) (height * scale) + offx;\r
171 \r
172             int ypos = (int) (node.ycount * chunk) + offy;\r
173 \r
174             if (node.element() instanceof SequenceI)\r
175             {\r
176                 if (((SequenceI) ((SequenceNode) node).element()).getColor() == Color.white)\r
177                 {\r
178                     g.setColor(Color.black);\r
179                 }\r
180                 else\r
181                 {\r
182                     g.setColor(((SequenceI) ((SequenceNode) node).element()).getColor()\r
183                                 .darker());\r
184                 }\r
185             }\r
186             else\r
187             {\r
188                 g.setColor(Color.black);\r
189             }\r
190 \r
191             // Draw horizontal line\r
192             g.drawLine(xstart, ypos, xend, ypos);\r
193 \r
194             String nodeLabel = "";\r
195 \r
196             if (showDistances && (node.dist > 0))\r
197             {\r
198                 nodeLabel = new Format("%5.2f").form(node.dist);\r
199             }\r
200 \r
201             if (showBootstrap)\r
202             {\r
203                 if (showDistances)\r
204                 {\r
205                     nodeLabel = nodeLabel + " : ";\r
206                 }\r
207 \r
208                 nodeLabel = nodeLabel + String.valueOf(node.getBootstrap());\r
209             }\r
210 \r
211             if (!nodeLabel.equals(""))\r
212             {\r
213                 g.drawString(nodeLabel, xstart, ypos - 10);\r
214             }\r
215 \r
216             String name = (markPlaceholders && node.isPlaceholder())\r
217                 ? (PLACEHOLDER + node.getName()) : node.getName();\r
218             FontMetrics fm = g.getFontMetrics(font);\r
219             int charWidth = fm.stringWidth(name) + 3;\r
220             int charHeight = fm.getHeight();\r
221 \r
222             Rectangle rect = new Rectangle(xend + 20, ypos - charHeight,\r
223                     charWidth, charHeight);\r
224 \r
225             nameHash.put((SequenceI) node.element(), rect);\r
226 \r
227             // Colour selected leaves differently\r
228             SequenceGroup selected = av.getSelectionGroup();\r
229 \r
230             if ((selected != null) &&\r
231                     selected.sequences.contains((SequenceI) node.element()))\r
232             {\r
233                 g.setColor(Color.gray);\r
234 \r
235                 g.fillRect(xend + 10, ypos - charHeight + 3, charWidth,\r
236                     charHeight);\r
237                 g.setColor(Color.white);\r
238             }\r
239 \r
240             g.drawString(name, xend + 10, ypos);\r
241             g.setColor(Color.black);\r
242         }\r
243         else\r
244         {\r
245             drawNode(g, (SequenceNode) node.left(), chunk, scale, width, offx,\r
246                 offy);\r
247             drawNode(g, (SequenceNode) node.right(), chunk, scale, width, offx,\r
248                 offy);\r
249 \r
250             float height = node.height;\r
251             float dist = node.dist;\r
252 \r
253             int xstart = (int) ((height - dist) * scale) + offx;\r
254             int xend = (int) (height * scale) + offx;\r
255             int ypos = (int) (node.ycount * chunk) + offy;\r
256 \r
257             g.setColor(((SequenceNode) node).color.darker());\r
258 \r
259             // Draw horizontal line\r
260             g.drawLine(xstart, ypos, xend, ypos);\r
261             g.fillRect(xend - 2, ypos - 2, 4, 4);\r
262 \r
263             int ystart = (int) (((SequenceNode) node.left()).ycount * chunk) +\r
264                 offy;\r
265             int yend = (int) (((SequenceNode) node.right()).ycount * chunk) +\r
266                 offy;\r
267 \r
268             Rectangle pos = new Rectangle(xend - 2, ypos - 2, 5, 5);\r
269             nodeHash.put(node, pos);\r
270 \r
271             g.drawLine((int) (height * scale) + offx, ystart,\r
272                 (int) (height * scale) + offx, yend);\r
273 \r
274             if (showDistances && (node.dist > 0))\r
275             {\r
276                 g.drawString(new Format("%5.2f").form(node.dist), xstart,\r
277                     ypos - 5);\r
278             }\r
279         }\r
280     }\r
281 \r
282     /**\r
283      * DOCUMENT ME!\r
284      *\r
285      * @param x DOCUMENT ME!\r
286      * @param y DOCUMENT ME!\r
287      *\r
288      * @return DOCUMENT ME!\r
289      */\r
290     public Object findElement(int x, int y)\r
291     {\r
292         Enumeration keys = nameHash.keys();\r
293 \r
294         while (keys.hasMoreElements())\r
295         {\r
296             Object ob = keys.nextElement();\r
297             Rectangle rect = (Rectangle) nameHash.get(ob);\r
298 \r
299             if ((x >= rect.x) && (x <= (rect.x + rect.width)) && (y >= rect.y) &&\r
300                     (y <= (rect.y + rect.height)))\r
301             {\r
302                 return ob;\r
303             }\r
304         }\r
305 \r
306         keys = nodeHash.keys();\r
307 \r
308         while (keys.hasMoreElements())\r
309         {\r
310             Object ob = keys.nextElement();\r
311             Rectangle rect = (Rectangle) nodeHash.get(ob);\r
312 \r
313             if ((x >= rect.x) && (x <= (rect.x + rect.width)) && (y >= rect.y) &&\r
314                     (y <= (rect.y + rect.height)))\r
315             {\r
316                 return ob;\r
317             }\r
318         }\r
319 \r
320         return null;\r
321     }\r
322 \r
323     /**\r
324      * DOCUMENT ME!\r
325      *\r
326      * @param pickBox DOCUMENT ME!\r
327      */\r
328     public void pickNodes(Rectangle pickBox)\r
329     {\r
330         int width = getWidth();\r
331         int height = getHeight();\r
332 \r
333         SequenceNode top = tree.getTopNode();\r
334 \r
335         float wscale = (float) ((width * .8) - (offx * 2)) / tree.getMaxHeight();\r
336 \r
337         if (top.count == 0)\r
338         {\r
339             top.count = ((SequenceNode) top.left()).count +\r
340                 ((SequenceNode) top.right()).count;\r
341         }\r
342 \r
343         float chunk = (float) (height - (offy * 2)) / top.count;\r
344 \r
345         pickNode(pickBox, top, chunk, wscale, width, offx, offy);\r
346     }\r
347 \r
348     /**\r
349      * DOCUMENT ME!\r
350      *\r
351      * @param pickBox DOCUMENT ME!\r
352      * @param node DOCUMENT ME!\r
353      * @param chunk DOCUMENT ME!\r
354      * @param scale DOCUMENT ME!\r
355      * @param width DOCUMENT ME!\r
356      * @param offx DOCUMENT ME!\r
357      * @param offy DOCUMENT ME!\r
358      */\r
359     public void pickNode(Rectangle pickBox, SequenceNode node, float chunk,\r
360         float scale, int width, int offx, int offy)\r
361     {\r
362         if (node == null)\r
363         {\r
364             return;\r
365         }\r
366 \r
367         if ((node.left() == null) && (node.right() == null))\r
368         {\r
369             float height = node.height;\r
370             float dist = node.dist;\r
371 \r
372             int xstart = (int) ((height - dist) * scale) + offx;\r
373             int xend = (int) (height * scale) + offx;\r
374 \r
375             int ypos = (int) (node.ycount * chunk) + offy;\r
376 \r
377             if (pickBox.contains(new Point(xend, ypos)))\r
378             {\r
379                 if (node.element() instanceof SequenceI)\r
380                 {\r
381                     SequenceI seq = (SequenceI) node.element();\r
382                     SequenceGroup sg = av.getSelectionGroup();\r
383 \r
384                     if (sg != null)\r
385                     {\r
386                         sg.addOrRemove(seq, true);\r
387                     }\r
388                 }\r
389             }\r
390         }\r
391         else\r
392         {\r
393             pickNode(pickBox, (SequenceNode) node.left(), chunk, scale, width,\r
394                 offx, offy);\r
395             pickNode(pickBox, (SequenceNode) node.right(), chunk, scale, width,\r
396                 offx, offy);\r
397         }\r
398     }\r
399 \r
400     /**\r
401      * DOCUMENT ME!\r
402      *\r
403      * @param node DOCUMENT ME!\r
404      * @param c DOCUMENT ME!\r
405      */\r
406     public void setColor(SequenceNode node, Color c)\r
407     {\r
408         if (node == null)\r
409         {\r
410             return;\r
411         }\r
412 \r
413         if ((node.left() == null) && (node.right() == null))\r
414         {\r
415             node.color = c;\r
416 \r
417             if (node.element() instanceof SequenceI)\r
418             {\r
419                 ((SequenceI) node.element()).setColor(c);\r
420             }\r
421         }\r
422         else\r
423         {\r
424             node.color = c;\r
425             setColor((SequenceNode) node.left(), c);\r
426             setColor((SequenceNode) node.right(), c);\r
427         }\r
428     }\r
429 \r
430     /**\r
431      * DOCUMENT ME!\r
432      */\r
433     void startPrinting()\r
434     {\r
435         Thread thread = new Thread(this);\r
436         thread.start();\r
437     }\r
438 \r
439     // put printing in a thread to avoid painting problems\r
440     public void run()\r
441     {\r
442         PrinterJob printJob = PrinterJob.getPrinterJob();\r
443         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
444 \r
445         printJob.setPrintable(this, pf);\r
446 \r
447         if (printJob.printDialog())\r
448         {\r
449             try\r
450             {\r
451                 printJob.print();\r
452             }\r
453             catch (Exception PrintException)\r
454             {\r
455                 PrintException.printStackTrace();\r
456             }\r
457         }\r
458     }\r
459 \r
460     /**\r
461      * DOCUMENT ME!\r
462      *\r
463      * @param pg DOCUMENT ME!\r
464      * @param pf DOCUMENT ME!\r
465      * @param pi DOCUMENT ME!\r
466      *\r
467      * @return DOCUMENT ME!\r
468      *\r
469      * @throws PrinterException DOCUMENT ME!\r
470      */\r
471     public int print(Graphics pg, PageFormat pf, int pi)\r
472         throws PrinterException\r
473     {\r
474         pg.setFont(font);\r
475         pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());\r
476 \r
477         int pwidth = (int) pf.getImageableWidth();\r
478         int pheight = (int) pf.getImageableHeight();\r
479 \r
480         int noPages = getHeight() / pheight;\r
481 \r
482         if (pi > noPages)\r
483         {\r
484             return Printable.NO_SUCH_PAGE;\r
485         }\r
486 \r
487         if (pwidth > getWidth())\r
488         {\r
489             pwidth = getWidth();\r
490         }\r
491 \r
492         if (fitToWindow)\r
493         {\r
494             if (pheight > getHeight())\r
495             {\r
496                 pheight = getHeight();\r
497             }\r
498 \r
499             noPages = 0;\r
500         }\r
501         else\r
502         {\r
503             FontMetrics fm = pg.getFontMetrics(font);\r
504             int height = fm.getHeight() * nameHash.size();\r
505             pg.translate(0, -pi * pheight);\r
506             pg.setClip(0, pi * pheight, pwidth, (pi * pheight) + pheight);\r
507 \r
508             // translate number of pages,\r
509             // height is screen size as this is the\r
510             // non overlapping text size\r
511             pheight = height;\r
512         }\r
513 \r
514         draw(pg, pwidth, pheight);\r
515 \r
516         return Printable.PAGE_EXISTS;\r
517     }\r
518 \r
519     /**\r
520      * DOCUMENT ME!\r
521      *\r
522      * @param g DOCUMENT ME!\r
523      */\r
524     public void paintComponent(Graphics g)\r
525     {\r
526         super.paintComponent(g);\r
527         g.setFont(font);\r
528 \r
529         if(tree==null)\r
530         {\r
531           g.drawString("Calculating tree....", 20, getHeight()/2);\r
532         }\r
533         else\r
534         {\r
535           FontMetrics fm = g.getFontMetrics(font);\r
536 \r
537           if (nameHash.size() == 0)\r
538           {\r
539             repaint();\r
540           }\r
541 \r
542           if (fitToWindow ||\r
543               (!fitToWindow &&\r
544                (scrollPane.getHeight() > ( (fm.getHeight() * nameHash.size()) +\r
545                                           offy))))\r
546           {\r
547             draw(g, scrollPane.getWidth(), scrollPane.getHeight());\r
548             setPreferredSize(null);\r
549           }\r
550           else\r
551           {\r
552             setPreferredSize(new Dimension(scrollPane.getWidth(),\r
553                                            fm.getHeight() * nameHash.size()));\r
554             draw(g, scrollPane.getWidth(), fm.getHeight() * nameHash.size());\r
555           }\r
556 \r
557           scrollPane.revalidate();\r
558         }\r
559     }\r
560 \r
561     /**\r
562      * DOCUMENT ME!\r
563      *\r
564      * @return DOCUMENT ME!\r
565      */\r
566     public int getFontSize()\r
567     {\r
568         return fontSize;\r
569     }\r
570 \r
571     /**\r
572      * DOCUMENT ME!\r
573      *\r
574      * @param fontSize DOCUMENT ME!\r
575      */\r
576     public void setFontSize(int fontSize)\r
577     {\r
578         this.fontSize = fontSize;\r
579         font = new Font(font.getName(), font.getStyle(), fontSize);\r
580         repaint();\r
581     }\r
582 \r
583     /**\r
584      * DOCUMENT ME!\r
585      *\r
586      * @param g1 DOCUMENT ME!\r
587      * @param width DOCUMENT ME!\r
588      * @param height DOCUMENT ME!\r
589      */\r
590     public void draw(Graphics g1, int width, int height)\r
591     {\r
592         Graphics2D g2 = (Graphics2D) g1;\r
593         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
594             RenderingHints.VALUE_ANTIALIAS_ON);\r
595         g2.setColor(Color.white);\r
596         g2.fillRect(0, 0, width, height);\r
597 \r
598         g2.setFont(font);\r
599 \r
600         labelLength = g2.getFontMetrics(font).stringWidth(longestName) + 20; //20 allows for scrollbar\r
601 \r
602         float wscale = (float) (width - labelLength - (offx * 2)) / tree.getMaxHeight();\r
603 \r
604         SequenceNode top = tree.getTopNode();\r
605 \r
606         if (top.count == 0)\r
607         {\r
608             top.count = ((SequenceNode) top.left()).count +\r
609                 ((SequenceNode) top.right()).count;\r
610         }\r
611 \r
612         float chunk = (float) (height - (offy * 2)) / top.count;\r
613 \r
614         drawNode(g2, tree.getTopNode(), chunk, wscale, width, offx, offy);\r
615 \r
616         if (threshold != 0)\r
617         {\r
618             if (av.getCurrentTree() == tree)\r
619             {\r
620                 g2.setColor(Color.red);\r
621             }\r
622             else\r
623             {\r
624                 g2.setColor(Color.gray);\r
625             }\r
626 \r
627             int x = (int) ((threshold * (float) (getWidth() - labelLength -\r
628                 (2 * offx))) + offx);\r
629 \r
630             g2.drawLine(x, 0, x, getHeight());\r
631         }\r
632     }\r
633 \r
634     /**\r
635      * DOCUMENT ME!\r
636      *\r
637      * @param e DOCUMENT ME!\r
638      */\r
639     public void mouseReleased(MouseEvent e)\r
640     {\r
641     }\r
642 \r
643     /**\r
644      * DOCUMENT ME!\r
645      *\r
646      * @param e DOCUMENT ME!\r
647      */\r
648     public void mouseEntered(MouseEvent e)\r
649     {\r
650     }\r
651 \r
652     /**\r
653      * DOCUMENT ME!\r
654      *\r
655      * @param e DOCUMENT ME!\r
656      */\r
657     public void mouseExited(MouseEvent e)\r
658     {\r
659     }\r
660 \r
661     /**\r
662      * DOCUMENT ME!\r
663      *\r
664      * @param e DOCUMENT ME!\r
665      */\r
666     public void mouseClicked(MouseEvent e)\r
667     {\r
668     }\r
669 \r
670     /**\r
671      * DOCUMENT ME!\r
672      *\r
673      * @param e DOCUMENT ME!\r
674      */\r
675     public void mousePressed(MouseEvent e)\r
676     {\r
677         av.setCurrentTree(tree);\r
678 \r
679         int x = e.getX();\r
680         int y = e.getY();\r
681 \r
682         Object ob = findElement(x, y);\r
683 \r
684         if (ob instanceof SequenceI)\r
685         {\r
686             TreeSelectionChanged((Sequence) ob);\r
687             repaint();\r
688 \r
689             return;\r
690         }\r
691         else if (ob instanceof SequenceNode)\r
692         {\r
693             SequenceNode tmpnode = (SequenceNode) ob;\r
694             tree.swapNodes(tmpnode);\r
695             tree.reCount(tree.getTopNode());\r
696             tree.findHeight(tree.getTopNode());\r
697         }\r
698         else\r
699         {\r
700             // Find threshold\r
701             if (tree.getMaxHeight() != 0)\r
702             {\r
703                 threshold = (float) (x - offx) / (float) (getWidth() -\r
704                     labelLength - (2 * offx));\r
705 \r
706                 tree.getGroups().removeAllElements();\r
707                 tree.groupNodes(tree.getTopNode(), threshold);\r
708                 setColor(tree.getTopNode(), Color.black);\r
709 \r
710                 av.setSelectionGroup(null);\r
711                 av.alignment.deleteAllGroups();\r
712 \r
713                 for (int i = 0; i < tree.getGroups().size(); i++)\r
714                 {\r
715                     Color col = new Color((int) (Math.random() * 255),\r
716                             (int) (Math.random() * 255),\r
717                             (int) (Math.random() * 255));\r
718                     setColor((SequenceNode) tree.getGroups().elementAt(i),\r
719                         col.brighter());\r
720 \r
721                     Vector l = tree.findLeaves((SequenceNode) tree.getGroups()\r
722                                                                   .elementAt(i),\r
723                             new Vector());\r
724 \r
725                     Vector sequences = new Vector();\r
726 \r
727                     for (int j = 0; j < l.size(); j++)\r
728                     {\r
729                         SequenceI s1 = (SequenceI) ((SequenceNode) l.elementAt(j)).element();\r
730 \r
731                         if (!sequences.contains(s1))\r
732                         {\r
733                             sequences.addElement(s1);\r
734                         }\r
735                     }\r
736 \r
737                     ColourSchemeI cs = null;\r
738 \r
739                     if (av.getGlobalColourScheme() != null)\r
740                     {\r
741                       if (av.getGlobalColourScheme() instanceof UserColourScheme)\r
742                       {\r
743                         cs = new UserColourScheme(\r
744                             ( (UserColourScheme) av.getGlobalColourScheme()).getColours());\r
745 \r
746                       }\r
747                       else\r
748                         cs = ColourSchemeProperty.getColour(sequences,\r
749                                                             av.alignment.getWidth(),\r
750                                                             ColourSchemeProperty.getColourName(\r
751                                                                 av.getGlobalColourScheme()));\r
752 \r
753                         cs.setThreshold(av.getGlobalColourScheme().getThreshold(),\r
754                                                              av.getIgnoreGapsConsensus());\r
755                     }\r
756 \r
757 \r
758                     SequenceGroup sg = new SequenceGroup(sequences,\r
759                             "TreeGroup", cs, true, true, false, 0,\r
760                             av.alignment.getWidth());\r
761 \r
762 \r
763                     if (  av.getGlobalColourScheme()!=null\r
764                        && av.getGlobalColourScheme().conservationApplied())\r
765                     {\r
766                         Conservation c = new Conservation("Group",\r
767                                 ResidueProperties.propHash, 3, sg.sequences,\r
768                                 sg.getStartRes(), sg.getEndRes());\r
769 \r
770                         c.calculate();\r
771                         c.verdict(false, av.ConsPercGaps);\r
772                         sg.cs.setConservation(c);\r
773                     }\r
774 \r
775                     av.alignment.addGroup(sg);\r
776                 }\r
777             }\r
778         }\r
779 \r
780         PaintRefresher.Refresh(this, av.alignment);\r
781         repaint();\r
782     }\r
783 \r
784     /**\r
785      * DOCUMENT ME!\r
786      *\r
787      * @param state DOCUMENT ME!\r
788      */\r
789     public void setShowDistances(boolean state)\r
790     {\r
791         this.showDistances = state;\r
792         repaint();\r
793     }\r
794 \r
795     /**\r
796      * DOCUMENT ME!\r
797      *\r
798      * @param state DOCUMENT ME!\r
799      */\r
800     public void setShowBootstrap(boolean state)\r
801     {\r
802         this.showBootstrap = state;\r
803         repaint();\r
804     }\r
805 \r
806     /**\r
807      * DOCUMENT ME!\r
808      *\r
809      * @param state DOCUMENT ME!\r
810      */\r
811     public void setMarkPlaceholders(boolean state)\r
812     {\r
813         this.markPlaceholders = state;\r
814         repaint();\r
815     }\r
816 }\r