Multiple Views
[jalview.git] / src / jalview / gui / TreeCanvas.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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, MouseMotionListener\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     AlignmentPanel ap;\r
53     Font font;\r
54     FontMetrics fm;\r
55     boolean fitToWindow = true;\r
56     boolean showDistances = false;\r
57     boolean showBootstrap = false;\r
58     boolean markPlaceholders = false;\r
59     int offx = 20;\r
60     int offy;\r
61     float threshold;\r
62     String longestName;\r
63     int labelLength = -1;\r
64 \r
65     Hashtable nameHash = new Hashtable();\r
66     Hashtable nodeHash = new Hashtable();\r
67     SequenceNode highlightNode;\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(AlignmentPanel ap, JScrollPane scroller)\r
78     {\r
79         this.av = ap.av;\r
80         this.ap = ap;\r
81         font = av.getFont();\r
82         scrollPane = scroller;\r
83         addMouseListener(this);\r
84         addMouseMotionListener(this);\r
85         PaintRefresher.Register(this, ap.av.getSequenceSetId());\r
86     }\r
87 \r
88 \r
89     /**\r
90      * DOCUMENT ME!\r
91      *\r
92      * @param sequence DOCUMENT ME!\r
93      */\r
94     public void treeSelectionChanged(SequenceI sequence)\r
95     {\r
96         SequenceGroup selected = av.getSelectionGroup();\r
97 \r
98         if (selected == null)\r
99         {\r
100             selected = new SequenceGroup();\r
101             av.setSelectionGroup(selected);\r
102         }\r
103 \r
104         selected.setEndRes(av.alignment.getWidth()-1);\r
105         selected.addOrRemove(sequence, true);\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("%-.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+2, ypos - 2);\r
213             }\r
214 \r
215             String name = (markPlaceholders && node.isPlaceholder())\r
216                 ? (PLACEHOLDER + node.getName()) : node.getName();\r
217 \r
218             int charWidth = fm.stringWidth(name) + 3;\r
219             int charHeight = font.getSize();\r
220 \r
221             Rectangle rect = new Rectangle(xend+10, ypos-charHeight/2,\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.getSequences(false).contains((SequenceI) node.element()))\r
231             {\r
232                 g.setColor(Color.gray);\r
233 \r
234                 g.fillRect(xend + 10, ypos-charHeight/2, charWidth,\r
235                     charHeight);\r
236                 g.setColor(Color.white);\r
237             }\r
238 \r
239             g.drawString(name, xend + 10, ypos+fm.getDescent());\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             if (node == highlightNode)\r
261               g.fillRect(xend - 3, ypos - 3, 6, 6);\r
262             else\r
263               g.fillRect(xend - 2, ypos - 2, 4, 4);\r
264 \r
265             int ystart = (int) (((SequenceNode) node.left()).ycount * chunk) +\r
266                 offy;\r
267             int yend = (int) (((SequenceNode) node.right()).ycount * chunk) +\r
268                 offy;\r
269 \r
270             Rectangle pos = new Rectangle(xend - 2, ypos - 2, 5, 5);\r
271             nodeHash.put(node, pos);\r
272 \r
273             g.drawLine((int) (height * scale) + offx, ystart,\r
274                 (int) (height * scale) + offx, yend);\r
275 \r
276             if (showDistances && (node.dist > 0))\r
277             {\r
278                 g.drawString(new Format("%-.2f").form(node.dist).trim(), xstart+2,\r
279                     ypos - 2);\r
280             }\r
281         }\r
282     }\r
283 \r
284     /**\r
285      * DOCUMENT ME!\r
286      *\r
287      * @param x DOCUMENT ME!\r
288      * @param y DOCUMENT ME!\r
289      *\r
290      * @return DOCUMENT ME!\r
291      */\r
292     public Object findElement(int x, int y)\r
293     {\r
294         Enumeration keys = nameHash.keys();\r
295 \r
296         while (keys.hasMoreElements())\r
297         {\r
298             Object ob = keys.nextElement();\r
299             Rectangle rect = (Rectangle) nameHash.get(ob);\r
300 \r
301             if ((x >= rect.x) && (x <= (rect.x + rect.width)) && (y >= rect.y) &&\r
302                     (y <= (rect.y + rect.height)))\r
303             {\r
304                 return ob;\r
305             }\r
306         }\r
307 \r
308         keys = nodeHash.keys();\r
309 \r
310         while (keys.hasMoreElements())\r
311         {\r
312             Object ob = keys.nextElement();\r
313             Rectangle rect = (Rectangle) nodeHash.get(ob);\r
314 \r
315             if ((x >= rect.x) && (x <= (rect.x + rect.width)) && (y >= rect.y) &&\r
316                     (y <= (rect.y + rect.height)))\r
317             {\r
318                 return ob;\r
319             }\r
320         }\r
321 \r
322         return null;\r
323     }\r
324 \r
325     /**\r
326      * DOCUMENT ME!\r
327      *\r
328      * @param pickBox DOCUMENT ME!\r
329      */\r
330     public void pickNodes(Rectangle pickBox)\r
331     {\r
332         int width = getWidth();\r
333         int height = getHeight();\r
334 \r
335         SequenceNode top = tree.getTopNode();\r
336 \r
337         float wscale = (float) ((width * .8) - (offx * 2)) / tree.getMaxHeight();\r
338 \r
339         if (top.count == 0)\r
340         {\r
341             top.count = ((SequenceNode) top.left()).count +\r
342                 ((SequenceNode) top.right()).count;\r
343         }\r
344 \r
345         float chunk = (float) (height - (offy)) / top.count;\r
346 \r
347         pickNode(pickBox, top, chunk, wscale, width, offx, offy);\r
348     }\r
349 \r
350     /**\r
351      * DOCUMENT ME!\r
352      *\r
353      * @param pickBox DOCUMENT ME!\r
354      * @param node DOCUMENT ME!\r
355      * @param chunk DOCUMENT ME!\r
356      * @param scale DOCUMENT ME!\r
357      * @param width DOCUMENT ME!\r
358      * @param offx DOCUMENT ME!\r
359      * @param offy DOCUMENT ME!\r
360      */\r
361     public void pickNode(Rectangle pickBox, SequenceNode node, float chunk,\r
362         float scale, int width, int offx, int offy)\r
363     {\r
364         if (node == null)\r
365         {\r
366             return;\r
367         }\r
368 \r
369         if ((node.left() == null) && (node.right() == null))\r
370         {\r
371             float height = node.height;\r
372             float dist = node.dist;\r
373 \r
374             int xstart = (int) ((height - dist) * scale) + offx;\r
375             int xend = (int) (height * scale) + offx;\r
376 \r
377             int ypos = (int) (node.ycount * chunk) + offy;\r
378 \r
379             if (pickBox.contains(new Point(xend, ypos)))\r
380             {\r
381                 if (node.element() instanceof SequenceI)\r
382                 {\r
383                     SequenceI seq = (SequenceI) node.element();\r
384                     SequenceGroup sg = av.getSelectionGroup();\r
385 \r
386                     if (sg != null)\r
387                     {\r
388                         sg.addOrRemove(seq, true);\r
389                     }\r
390                 }\r
391             }\r
392         }\r
393         else\r
394         {\r
395             pickNode(pickBox, (SequenceNode) node.left(), chunk, scale, width,\r
396                 offx, offy);\r
397             pickNode(pickBox, (SequenceNode) node.right(), chunk, scale, width,\r
398                 offx, offy);\r
399         }\r
400     }\r
401 \r
402     /**\r
403      * DOCUMENT ME!\r
404      *\r
405      * @param node DOCUMENT ME!\r
406      * @param c DOCUMENT ME!\r
407      */\r
408     public void setColor(SequenceNode node, Color c)\r
409     {\r
410         if (node == null)\r
411         {\r
412             return;\r
413         }\r
414 \r
415         if ((node.left() == null) && (node.right() == null))\r
416         {\r
417             node.color = c;\r
418 \r
419             if (node.element() instanceof SequenceI)\r
420             {\r
421                 ((SequenceI) node.element()).setColor(c);\r
422             }\r
423         }\r
424         else\r
425         {\r
426             node.color = c;\r
427             setColor((SequenceNode) node.left(), c);\r
428             setColor((SequenceNode) node.right(), c);\r
429         }\r
430     }\r
431 \r
432     /**\r
433      * DOCUMENT ME!\r
434      */\r
435     void startPrinting()\r
436     {\r
437         Thread thread = new Thread(this);\r
438         thread.start();\r
439     }\r
440 \r
441     // put printing in a thread to avoid painting problems\r
442     public void run()\r
443     {\r
444         PrinterJob printJob = PrinterJob.getPrinterJob();\r
445         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
446 \r
447         printJob.setPrintable(this, pf);\r
448 \r
449         if (printJob.printDialog())\r
450         {\r
451             try\r
452             {\r
453                 printJob.print();\r
454             }\r
455             catch (Exception PrintException)\r
456             {\r
457                 PrintException.printStackTrace();\r
458             }\r
459         }\r
460     }\r
461 \r
462     /**\r
463      * DOCUMENT ME!\r
464      *\r
465      * @param pg DOCUMENT ME!\r
466      * @param pf DOCUMENT ME!\r
467      * @param pi DOCUMENT ME!\r
468      *\r
469      * @return DOCUMENT ME!\r
470      *\r
471      * @throws PrinterException DOCUMENT ME!\r
472      */\r
473     public int print(Graphics pg, PageFormat pf, int pi)\r
474         throws PrinterException\r
475     {\r
476         pg.setFont(font);\r
477         pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());\r
478 \r
479         int pwidth = (int) pf.getImageableWidth();\r
480         int pheight = (int) pf.getImageableHeight();\r
481 \r
482         int noPages = getHeight() / pheight;\r
483 \r
484         if (pi > noPages)\r
485         {\r
486             return Printable.NO_SUCH_PAGE;\r
487         }\r
488 \r
489         if (pwidth > getWidth())\r
490         {\r
491             pwidth = getWidth();\r
492         }\r
493 \r
494         if (fitToWindow)\r
495         {\r
496             if (pheight > getHeight())\r
497             {\r
498                 pheight = getHeight();\r
499             }\r
500 \r
501             noPages = 0;\r
502         }\r
503         else\r
504         {\r
505             FontMetrics fm = pg.getFontMetrics(font);\r
506             int height = fm.getHeight() * nameHash.size();\r
507             pg.translate(0, -pi * pheight);\r
508             pg.setClip(0, pi * pheight, pwidth, (pi * pheight) + pheight);\r
509 \r
510             // translate number of pages,\r
511             // height is screen size as this is the\r
512             // non overlapping text size\r
513             pheight = height;\r
514         }\r
515 \r
516         draw(pg, pwidth, pheight);\r
517 \r
518         return Printable.PAGE_EXISTS;\r
519     }\r
520 \r
521     /**\r
522      * DOCUMENT ME!\r
523      *\r
524      * @param g DOCUMENT ME!\r
525      */\r
526     public void paintComponent(Graphics g)\r
527     {\r
528         super.paintComponent(g);\r
529         g.setFont(font);\r
530 \r
531         if(tree==null)\r
532         {\r
533           g.drawString("Calculating tree....", 20, getHeight()/2);\r
534         }\r
535         else\r
536         {\r
537           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     /**\r
565      * DOCUMENT ME!\r
566      *\r
567      * @param fontSize DOCUMENT ME!\r
568      */\r
569     public void setFont(Font font)\r
570     {\r
571         this.font = font;\r
572         repaint();\r
573     }\r
574 \r
575     /**\r
576      * DOCUMENT ME!\r
577      *\r
578      * @param g1 DOCUMENT ME!\r
579      * @param width DOCUMENT ME!\r
580      * @param height DOCUMENT ME!\r
581      */\r
582     public void draw(Graphics g1, int width, int height)\r
583     {\r
584         Graphics2D g2 = (Graphics2D) g1;\r
585         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
586             RenderingHints.VALUE_ANTIALIAS_ON);\r
587         g2.setColor(Color.white);\r
588         g2.fillRect(0, 0, width, height);\r
589 \r
590         g2.setFont(font);\r
591 \r
592         offy = font.getSize()+10;\r
593 \r
594         fm = g2.getFontMetrics(font);\r
595 \r
596         labelLength = fm.stringWidth(longestName) + 20; //20 allows for scrollbar\r
597 \r
598         float wscale = (float) (width - labelLength - (offx * 2)) / tree.getMaxHeight();\r
599 \r
600         SequenceNode top = tree.getTopNode();\r
601 \r
602         if (top.count == 0)\r
603         {\r
604             top.count = ((SequenceNode) top.left()).count +\r
605                 ((SequenceNode) top.right()).count;\r
606         }\r
607 \r
608         float chunk = (float) (height - (offy)) / top.count;\r
609 \r
610         drawNode(g2, tree.getTopNode(), chunk, wscale, width, offx, offy);\r
611 \r
612         if (threshold != 0)\r
613         {\r
614             if (av.getCurrentTree() == tree)\r
615             {\r
616                 g2.setColor(Color.red);\r
617             }\r
618             else\r
619             {\r
620                 g2.setColor(Color.gray);\r
621             }\r
622 \r
623             int x = (int) ((threshold * (float) (getWidth() - labelLength -\r
624                 (2 * offx))) + offx);\r
625 \r
626             g2.drawLine(x, 0, x, getHeight());\r
627         }\r
628     }\r
629 \r
630     /**\r
631      * DOCUMENT ME!\r
632      *\r
633      * @param e DOCUMENT ME!\r
634      */\r
635     public void mouseReleased(MouseEvent e)\r
636     {\r
637     }\r
638 \r
639     /**\r
640      * DOCUMENT ME!\r
641      *\r
642      * @param e DOCUMENT ME!\r
643      */\r
644     public void mouseEntered(MouseEvent e)\r
645     {\r
646     }\r
647 \r
648     /**\r
649      * DOCUMENT ME!\r
650      *\r
651      * @param e DOCUMENT ME!\r
652      */\r
653     public void mouseExited(MouseEvent e)\r
654     {\r
655     }\r
656 \r
657     /**\r
658      * DOCUMENT ME!\r
659      *\r
660      * @param e DOCUMENT ME!\r
661      */\r
662     public void mouseClicked(MouseEvent evt)\r
663     {\r
664       if(highlightNode!=null)\r
665       {\r
666         if(evt.getClickCount()>1)\r
667         {\r
668           tree.swapNodes(highlightNode);\r
669           tree.reCount(tree.getTopNode());\r
670           tree.findHeight(tree.getTopNode());\r
671         }\r
672         else\r
673         {\r
674           Vector leaves = new Vector();\r
675           tree.findLeaves(highlightNode, leaves);\r
676 \r
677           for (int i = 0; i < leaves.size(); i++)\r
678           {\r
679             SequenceI seq =\r
680                 (SequenceI) ( (SequenceNode) leaves.elementAt(i)).element();\r
681             treeSelectionChanged(seq);\r
682           }\r
683         }\r
684 \r
685         PaintRefresher.Refresh(this, av.getSequenceSetId());\r
686         repaint();\r
687       }\r
688     }\r
689 \r
690 \r
691 \r
692     public void mouseMoved(MouseEvent evt)\r
693     {\r
694       av.setCurrentTree(tree);\r
695 \r
696       Object ob = findElement(evt.getX(), evt.getY());\r
697 \r
698       if (ob instanceof SequenceNode)\r
699       {\r
700         highlightNode = (SequenceNode) ob;\r
701         repaint();\r
702       }\r
703       else\r
704       {\r
705         if (highlightNode != null)\r
706         {\r
707           highlightNode = null;\r
708           repaint();\r
709         }\r
710       }\r
711   }\r
712 \r
713     public void mouseDragged(MouseEvent ect)\r
714     {}\r
715 \r
716     /**\r
717      * DOCUMENT ME!\r
718      *\r
719      * @param e DOCUMENT ME!\r
720      */\r
721     public void mousePressed(MouseEvent e)\r
722     {\r
723         av.setCurrentTree(tree);\r
724 \r
725         int x = e.getX();\r
726         int y = e.getY();\r
727 \r
728         Object ob = findElement(x, y);\r
729 \r
730         if (ob instanceof SequenceI)\r
731         {\r
732           treeSelectionChanged( (Sequence) ob);\r
733           PaintRefresher.Refresh(this, ap.av.getSequenceSetId());\r
734           repaint();\r
735           return;\r
736         }\r
737         else if( !(ob instanceof SequenceNode) )\r
738         {\r
739             // Find threshold\r
740             if (tree.getMaxHeight() != 0)\r
741             {\r
742                 threshold = (float) (x - offx) / (float) (getWidth() -\r
743                     labelLength - (2 * offx));\r
744 \r
745                 tree.getGroups().removeAllElements();\r
746                 tree.groupNodes(tree.getTopNode(), threshold);\r
747                 setColor(tree.getTopNode(), Color.black);\r
748 \r
749                 av.setSelectionGroup(null);\r
750                 av.alignment.deleteAllGroups();\r
751 \r
752                 colourGroups();\r
753               }\r
754 \r
755               PaintRefresher.Refresh(this, ap.av.getSequenceSetId());\r
756               repaint();\r
757         }\r
758 \r
759 \r
760     }\r
761 \r
762     void colourGroups()\r
763     {\r
764       for (int i = 0; i < tree.getGroups().size(); i++)\r
765       {\r
766         Color col = new Color( (int) (Math.random() * 255),\r
767                               (int) (Math.random() * 255),\r
768                               (int) (Math.random() * 255));\r
769         setColor( (SequenceNode) tree.getGroups().elementAt(i),\r
770                  col.brighter());\r
771 \r
772         Vector l = tree.findLeaves( (SequenceNode) tree.getGroups()\r
773                                    .elementAt(i),\r
774                                    new Vector());\r
775 \r
776         Vector sequences = new Vector();\r
777 \r
778         for (int j = 0; j < l.size(); j++)\r
779         {\r
780           SequenceI s1 = (SequenceI) ( (SequenceNode) l.elementAt(j)).element();\r
781 \r
782           if (!sequences.contains(s1))\r
783           {\r
784             sequences.addElement(s1);\r
785           }\r
786         }\r
787 \r
788         ColourSchemeI cs = null;\r
789 \r
790         if (av.getGlobalColourScheme() != null)\r
791         {\r
792           if (av.getGlobalColourScheme() instanceof UserColourScheme)\r
793           {\r
794             cs = new UserColourScheme(\r
795                 ( (UserColourScheme) av.getGlobalColourScheme()).getColours());\r
796 \r
797           }\r
798           else\r
799             cs = ColourSchemeProperty.getColour(sequences,\r
800                                                 av.alignment.getWidth(),\r
801                                                 ColourSchemeProperty.\r
802                                                 getColourName(\r
803                                                     av.getGlobalColourScheme()));\r
804 \r
805           cs.setThreshold(av.getGlobalColourScheme().getThreshold(),\r
806                           av.getIgnoreGapsConsensus());\r
807         }\r
808 \r
809         SequenceGroup sg = new SequenceGroup(sequences,\r
810                                              "TreeGroup", cs, true, true, false,\r
811                                              0,\r
812                                              av.alignment.getWidth() - 1);\r
813 \r
814         if (av.getGlobalColourScheme() != null\r
815             && av.getGlobalColourScheme().conservationApplied())\r
816         {\r
817           Conservation c = new Conservation("Group",\r
818                                             ResidueProperties.propHash, 3,\r
819                                             sg.getSequences(false),\r
820                                             sg.getStartRes(), sg.getEndRes());\r
821 \r
822           c.calculate();\r
823           c.verdict(false, av.ConsPercGaps);\r
824           sg.cs.setConservation(c);\r
825         }\r
826 \r
827         av.alignment.addGroup(sg);\r
828       }\r
829 \r
830     }\r
831 \r
832     /**\r
833      * DOCUMENT ME!\r
834      *\r
835      * @param state DOCUMENT ME!\r
836      */\r
837     public void setShowDistances(boolean state)\r
838     {\r
839         this.showDistances = state;\r
840         repaint();\r
841     }\r
842 \r
843     /**\r
844      * DOCUMENT ME!\r
845      *\r
846      * @param state DOCUMENT ME!\r
847      */\r
848     public void setShowBootstrap(boolean state)\r
849     {\r
850         this.showBootstrap = state;\r
851         repaint();\r
852     }\r
853 \r
854     /**\r
855      * DOCUMENT ME!\r
856      *\r
857      * @param state DOCUMENT ME!\r
858      */\r
859     public void setMarkPlaceholders(boolean state)\r
860     {\r
861         this.markPlaceholders = state;\r
862         repaint();\r
863     }\r
864 }\r