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