JAL-4435 Menu option and colouring for sec struct providers feature/JAL-4386_JAL-4435_reformat_node_labels
authorRenia Correya <rcorreya001@dundee.ac.uk>
Thu, 7 Nov 2024 10:09:50 +0000 (10:09 +0000)
committerRenia Correya <rcorreya001@dundee.ac.uk>
Thu, 7 Nov 2024 10:09:50 +0000 (10:09 +0000)
Added menu option in tree panel for the users to choose between coloured
lines or labels or none for secondary structure providers in tree panel.

Code changes for using jcolorbrewer colouring palette

THIRDPARTYLIBS
j11lib/jcolorbrewer-5.2.jar [new file with mode: 0644]
j8lib/jcolorbrewer-5.2.jar [new file with mode: 0644]
resources/lang/Messages.properties
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/TreeBuilder.java
src/jalview/gui/TreeCanvas.java
src/jalview/gui/TreePanel.java
src/jalview/jbgui/GTreePanel.java

index e52f3f6..f41a5f9 100644 (file)
@@ -35,6 +35,7 @@ intervalstore-v1.1.jar
 jabaws-min-client-NO_LOG4J-2.2.1.jar   Apache license - pre-release of JABAWS 2.2.1 client built from https://source.jalview.org/crucible/changelog/jabaws?cs=586260b9f877e0954513fcffb0aa27eaddc5d0ff 
 java-json.jar
 jaxrpc.jar
+jcolorbrewer-5.2.jar      GNU LGPL v2 - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
 jersey-client-1.19.4.jar       CDDL 1.1 + GPL2 w/ CPE - http://glassfish.java.net/public/CDDL+GPL_1_1.html
 jersey-core-1.19.4.jar CDDL 1.1 + GPL2 w/ CPE - http://glassfish.java.net/public/CDDL+GPL_1_1.html
 jersey-json-1.19.4.jar CDDL 1.1 + GPL2 w/ CPE - http://glassfish.java.net/public/CDDL+GPL_1_1.html
@@ -112,6 +113,7 @@ javax.xml.soap-api.jar      CDDL + GPLv2 with classpath exception - https://github.co
 jaxb-api-2.3.1.jar     CDDL 1.1 + GPL2 w/ CPE - https://oss.oracle.com/licenses/CDDL+GPL-1.1
 jaxb-runtime-2.3.2.jar Eclipse Distribution License - v 1.0 - http://www.eclipse.org/org/documents/edl-v10.php
 jaxws-api-2.3.1.jar    CDDL + GPLv2 with classpath exception - https://github.com/javaee/jax-ws-spec/blob/master/LICENSE.md
+jcolorbrewer-5.2.jar      GNU LGPL v2 - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
 jsr311-api-1.1.1.jar   CDDL License - http://www.opensource.org/licenses/cddl1.php
 mimepull-1.9.11.jar    Eclipse Distribution License - v 1.0 - http://www.eclipse.org/org/documents/edl-v10.php
 policy-2.7.6.jar       Eclipse Distribution License - v 1.0 - http://www.eclipse.org/org/documents/edl-v10.php
diff --git a/j11lib/jcolorbrewer-5.2.jar b/j11lib/jcolorbrewer-5.2.jar
new file mode 100644 (file)
index 0000000..5a6e59c
Binary files /dev/null and b/j11lib/jcolorbrewer-5.2.jar differ
diff --git a/j8lib/jcolorbrewer-5.2.jar b/j8lib/jcolorbrewer-5.2.jar
new file mode 100644 (file)
index 0000000..5a6e59c
Binary files /dev/null and b/j8lib/jcolorbrewer-5.2.jar differ
index b9738a0..27e9404 100644 (file)
@@ -335,6 +335,9 @@ label.protein_matrix = Protein matrix
 label.show_bootstrap_values = Show Bootstrap Values
 label.show_distances = Show distances
 label.show_secondary_structure_provider = Show Secondary Structure Providers
+label.hide_structure_provider = None
+label.show_structure_provider_as_labels = As Labels
+label.show_structure_provider_as_coloured_lines = As Coloured Lines
 label.mark_unassociated_leaves = Mark Unassociated Leaves
 label.fit_to_window = Fit To Window
 label.newick_format = Newick Format
index 7b632d8..a7d03c4 100644 (file)
@@ -40,6 +40,8 @@ import java.util.TreeMap;
 import java.util.Vector;
 import java.util.stream.Collectors;
 
+import org.jcolorbrewer.ColorBrewer;
+
 import jalview.api.AlignCalcWorkerI;
 import jalview.bin.Console;
 import jalview.commands.RemoveGapColCommand;
@@ -3238,4 +3240,27 @@ public class AlignmentUtils
       c = Color.BLACK;
     return c;
   }
+  
+  
+  public static void assignSecondaryStructureProviderColor(Map<String, Color> secondaryStructureProviderColorMap,
+          List<String> labels) {
+    
+    // Use a Set to track unique labels
+    Set<String> uniqueLabels = new HashSet<>(labels);
+    
+    Color[] palette = ColorBrewer.Paired.getColorPalette(uniqueLabels.size()); 
+    
+
+    List<Color> colorList = new ArrayList<>();
+    Collections.addAll(colorList, palette);
+    Collections.shuffle(colorList);
+    int i = 0;    
+    
+    // Loop through each unique label and add it to the map with a color.
+    for (String label : uniqueLabels) {
+        // Generate or retrieve a color for the label.
+      secondaryStructureProviderColorMap.put(label.toUpperCase().trim(), colorList.get(i));
+      i++;
+    }
+  }
 }
\ No newline at end of file
index 156657a..f388051 100644 (file)
@@ -31,6 +31,7 @@ import jalview.datamodel.SequenceNode;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
+
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.List;
@@ -45,7 +46,7 @@ public abstract class TreeBuilder extends TreeEngine
   protected SequenceI[] sequences;
 
   protected List<String> labels;
-
+  
   public AlignmentView seqData;
 
   private AlignmentView seqStrings;
@@ -110,6 +111,10 @@ public abstract class TreeBuilder extends TreeEngine
   {
     return true;
   }
+  
+  public List<String> getLabels(){
+    return this.labels;
+  }
 
   /**
    * Calculates the tree using the given score model and parameters, and the
index 4efedc3..494360f 100755 (executable)
@@ -30,6 +30,7 @@ import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.RenderingHints;
+import java.awt.Stroke;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
@@ -39,6 +40,7 @@ import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
 import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.LinkedHashSet;
@@ -46,6 +48,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Vector;
+import org.jcolorbrewer.ColorBrewer;
 
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -87,7 +90,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
   /** DOCUMENT ME!! */
   public static final String PLACEHOLDER = " * ";
   
-  private static final int DASHED_LINE_Y_OFFSET = 5;
+  private static final int DASHED_LINE_Y_OFFSET = 6;
 
   TreeModel tree;
 
@@ -106,8 +109,10 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
   boolean fitToWindow = true;
 
   boolean showDistances = false;
-  
-  boolean showSecondaryStructureProvider = false;
+
+  boolean showStructureProviderLabels = false;
+
+  boolean showStructureProviderColouredLines = false;
 
   boolean showBootstrap = false;
 
@@ -302,8 +307,12 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       return;
     }
 
+    Vector<BinaryNode> leaves = tree.findLeaves(node);
+    gatherLabelsTo(node, leaves);
+
     if ((node.left() == null) && (node.right() == null))
     {
+      Color originalColor, translucentColor = Color.WHITE;
       // Drawing leaf node
       double height = node.height;
       double dist = node.dist;
@@ -323,7 +332,9 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         }
         else
         {
-          g.setColor(av.getSequenceColour(seq).darker());
+          originalColor = av.getSequenceColour(seq);
+          translucentColor = new Color(originalColor.getRed(), originalColor.getGreen(), originalColor.getBlue(), 128); // 128 for 50% transparency
+          g.setColor(Color.black);
         }
       }
       else
@@ -331,7 +342,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         g.setColor(Color.black);
       }
 
-      // Draw horizontal line
+      // horizontal line
       g.drawLine(xstart, ypos, xend, ypos);
 
       String nodeLabel = "";
@@ -350,8 +361,17 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
 
         nodeLabel = nodeLabel + String.valueOf(node.bootstrap);
       }
+      if(node.hasLabel() && showStructureProviderColouredLines) {
 
-      if (!nodeLabel.equals(""))
+          drawLinesAndLabelsForSecondaryStructureProvider(g, node, xstart, xend, ypos, nodeLabel);
+    
+          Rectangle labelBounds = new Rectangle(xstart, ypos, xend, ypos + DASHED_LINE_Y_OFFSET);
+    
+          // Add the bounding box to the map for this node 
+          labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds);  
+          
+      }
+      else if (!nodeLabel.equals(""))
       {
         g.drawString(nodeLabel, xstart + 2, ypos - 2);
       }
@@ -368,7 +388,13 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
               charWidth, charHeight);
 
       nameHash.put(node, rect);
-
+      
+      g.setColor(translucentColor);
+      g.fillRect(xend + 10,  ypos - charHeight / 2, charWidth, charHeight);
+      //g.fillRect(xstart - 2, ypos - 10, (xend + 20 + charWidth) - xstart, 20);
+      
+      g.setColor(Color.black);
+      
       // Colour selected leaves differently
       boolean isSelected = false;
       if (tp.isColumnWise())
@@ -410,8 +436,11 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       int xend = (int) (height * wscale) + offx;
       int ypos = (int) (node.ycount * chunk) + offy;
 
-      g.setColor(node.color.darker());
+      //g.setColor(node.color.darker());
+      
 
+      g.setColor(Color.black);
+      
       // Draw horizontal line
       g.drawLine(xstart, ypos, xend, ypos);
       if (node == highlightNode)
@@ -452,66 +481,65 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       }
       
 
-      boolean showColouredLinesForSSProviders = true;
-
-      //Display secondary structure providers as labels only if:
+      //Display secondary structure providers only if:
       // ~ node has Label assigned (Secondary structure providers)
-      // ~ node count is greater than 3
-      // ~ showSecondaryStructureProvider option is set to true by the user
-      if ( node.hasLabel() && showSecondaryStructureProvider && showColouredLinesForSSProviders)
-      {
-
-        drawLinesAndLabelsForSecondaryStructureProvider(g, node, xstart, xend, ypos, nodeLabel);
-        
-        int labelWidth = 20;
-        int labelHeight = fm.getHeight();
-
-        // Calculate the bounding box of the string
-        int xLabelPos = xstart + 2;
-        int yLabelPos = ypos - 2;
-        Rectangle labelBounds = new Rectangle(xLabelPos, yLabelPos - labelHeight, labelWidth, labelHeight);
-
-        // Add the bounding box to the map for this node (list allows multiple bounding boxes)
-        labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds);  
-        
-      }
-      else if ( node.hasLabel() && showSecondaryStructureProvider && node.count > 3) 
-      {
-
-        String label = node.getLabel();
+      // ~ either label or coloured lines option is selected by the user
+      boolean labelHandled = false; 
+      if(node.hasLabel()) {
         
-        if(label.length() > labelLengthThreshold) {
+        if (showStructureProviderColouredLines)
+        {
+          drawLinesAndLabelsForSecondaryStructureProvider(g, node, xstart, xend, ypos, nodeLabel);
+    
+          Rectangle labelBounds = new Rectangle(xstart, ypos, xend, ypos + DASHED_LINE_Y_OFFSET);
+    
+          // Add the bounding box to the map for this node (list allows multiple bounding boxes)
+          labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds);  
+          labelHandled = true;
           
-          //label = AlignmentUtils.reduceLabelLength(label);
         }
         
-        nodeLabel = label + " | " + nodeLabel;
-
-        // Split the nodeLabel by "|"
-        String[] lines = nodeLabel.split("\\|");
-
-        // Iterate over the lines and draw each string separately
-        String longestLabelString = "";
-        int i = 0;
-        for (i = 0; i < lines.length; i++) {
-            g.drawString(lines[i].trim(), xstart + 2, ypos - 2 - (i * fm.getHeight()));
-            if(longestLabelString.length() < lines[i].trim().length()) {
-              longestLabelString = lines[i].trim();
-            }
+        if (showStructureProviderLabels && node.count > 3) 
+        {
+    
+          String label = node.getLabel();
+          
+          if(label.length() > labelLengthThreshold) {
+            
+            //label = AlignmentUtils.reduceLabelLength(label);
+          }
+          
+          nodeLabel = label + " | " + nodeLabel;
+    
+          // Split the nodeLabel by "|"
+          String[] lines = nodeLabel.split("\\|");
+    
+          // Draw each string separately
+          String longestLabelString = "";
+          int i = 0;
+          for (i = 0; i < lines.length; i++) {
+              g.drawString(lines[i].trim(), xstart + 2, ypos - 2 - (i * fm.getHeight()));
+              if(longestLabelString.length() < lines[i].trim().length()) {
+                longestLabelString = lines[i].trim();
+              }
+          }
+          
+          int labelWidth = fm.stringWidth(longestLabelString);
+          int labelHeight = fm.getHeight() * (i-1);
+    
+          // Bounding box of the string
+          int xLabelPos = xstart + 2;
+          int yLabelPos = ypos - 2;
+          Rectangle labelBounds = new Rectangle(xLabelPos, yLabelPos - labelHeight, labelWidth, labelHeight);
+    
+          // Add the bounding box to the map for the node 
+          labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds);
+          
+          labelHandled = true;
         }
-        
-        int labelWidth = fm.stringWidth(longestLabelString);
-        int labelHeight = fm.getHeight() * (i-1);
-
-        // Calculate the bounding box of the string
-        int xLabelPos = xstart + 2;
-        int yLabelPos = ypos - 2;
-        Rectangle labelBounds = new Rectangle(xLabelPos, yLabelPos - labelHeight, labelWidth, labelHeight);
-
-        // Add the bounding box to the map for this node (list allows multiple bounding boxes)
-        labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds);
       }
-      else if (!nodeLabel.equals(""))
+      
+      if (!nodeLabel.equals("") && !labelHandled)
       {
         g.drawString(nodeLabel, xstart + 2, ypos - 2);
       }
@@ -521,18 +549,24 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
   
   private void drawLinesAndLabelsForSecondaryStructureProvider(Graphics g, BinaryNode node, 
           int xstart, int xend, int ypos, String nodeLabel) {
-    // Cast the Graphics object to Graphics2D
+    
     Graphics2D g2d = (Graphics2D) g.create();
 
     // Set dash pattern
-    float[] dashPattern = {2, 3};
+//    float[] dashPattern = {2, 2};
+//    g2d.setStroke(new BasicStroke(
+//            2.5f, 
+//            BasicStroke.CAP_BUTT,
+//            BasicStroke.JOIN_ROUND, 
+//            0.0f, 
+//            dashPattern, 
+//            0.0f));
+    
     g2d.setStroke(new BasicStroke(
-            1.5f, 
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_ROUND, 
-            0.0f, 
-            dashPattern, 
-            0.0f));
+            4.0f,                 
+            BasicStroke.CAP_BUTT, 
+            BasicStroke.JOIN_ROUND 
+    ));
 
     String label = node.getLabel();
     String[] lines = label.split("\\|");
@@ -552,7 +586,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
     int secondHalfLinesCount = lines.length - mid;
     drawSecondaryStructureProviderLinesSection(g2d, 
             lines, mid, lines.length, xstart, xend, 
-            ypos + DASHED_LINE_Y_OFFSET,
+            ypos,
             false);
     drawVerticalLineAndLabel(g, xstart, ypos, secondHalfLinesCount, false, nodeLabel); 
 
@@ -560,26 +594,36 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
 }
 
   private void drawSecondaryStructureProviderLinesSection(Graphics2D g2d, String[] lines, int start, int end, int xstart, int xend, int baseY, boolean above) {
-      for (int i = start; i < end; i++) {
+            
+    for (int i = start, j=0; i < end; i++, j++) {
           int adjustedY = above 
                   ? baseY - ((i - start) * DASHED_LINE_Y_OFFSET) 
                           : baseY +((i - start) * DASHED_LINE_Y_OFFSET);
-          Color providerColor = AlignmentUtils.getSecondaryStructureProviderColor(lines[i]);
+          //Color providerColor = AlignmentUtils.getSecondaryStructureProviderColor(lines[i]);
+
+          Map<String, Color> secondaryStructureProviderColorMap = tp.getSecondaryStructureProviderColorMap();
+          Color providerColor = secondaryStructureProviderColorMap.getOrDefault(lines[i].toUpperCase().trim(), Color.BLACK);
           g2d.setColor(providerColor);
-          g2d.drawLine(xstart, adjustedY, xend, adjustedY);
+          if(i==start && !above) {            
+            g2d.drawLine(xstart, adjustedY, xend-3, adjustedY);
+          }
+          else
+          {
+            g2d.drawLine(xstart, adjustedY, xend, adjustedY);
+          }
       }
   }
   
   private void drawVerticalLineAndLabel(Graphics g, int xstart, int ypos, 
-          int linesCount, boolean above, String nodeLabel) {
-    int adjustedY = above 
-            ? ypos - (linesCount) * DASHED_LINE_Y_OFFSET 
-            : ypos + (linesCount) * DASHED_LINE_Y_OFFSET;
+          int linesCount, boolean above, String nodeLabel) {    
+    
+    int adjustment = (linesCount * DASHED_LINE_Y_OFFSET) + (DASHED_LINE_Y_OFFSET / 3);
+    int adjustedY = ypos + (above ? -adjustment : adjustment - DASHED_LINE_Y_OFFSET);
 
-    // Draw vertical line
+    // draw vertical line
     g.drawLine(xstart, ypos, xstart, adjustedY);
 
-    // Draw label
+    // draw label
     if(above && !nodeLabel.equals(""))
       g.drawString(nodeLabel, xstart + 2, adjustedY - 2);
 }
@@ -1232,7 +1276,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
       setColor(groups.get(i), col.brighter());
 
       Vector<BinaryNode> l = tree.findLeaves(groups.get(i));
-      gatherLabelsTo(groups.get(i), l);
+      //gatherLabelsTo(groups.get(i), l);
       if (!tp.isColumnWise())
       {
         createSeqGroupFor(aps, l, col, groups.get(i).getLabel());
@@ -1574,15 +1618,30 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
     repaint();
   }
   
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param state
-   *          DOCUMENT ME!
-   */
-  public void setShowSecondaryStructureProvider(boolean state)
+  public void hideStructureProviders(boolean state)
+  {
+    if(state) {
+      this.showStructureProviderColouredLines = false;
+      this.showStructureProviderLabels = false;
+      repaint();
+    }
+  }
+  
+  public void setShowStructureProviderColouredLines(boolean state)
   {
-    this.showSecondaryStructureProvider = state;
+    this.showStructureProviderColouredLines = state;
+    if(state) {
+      this.showStructureProviderLabels = false;
+    }
+    repaint();
+  }
+  
+  public void setShowStructureProviderLabels(boolean state)
+  {
+    this.showStructureProviderLabels = state;
+    if(state) {
+      this.showStructureProviderColouredLines = false;
+    }
     repaint();
   }
   
index 6a1b381..0fae337 100755 (executable)
 package jalview.gui;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.Graphics;
+import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
@@ -32,14 +36,17 @@ import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import javax.swing.ButtonGroup;
 import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
 import javax.swing.SwingConstants;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
@@ -47,6 +54,7 @@ import javax.swing.event.InternalFrameEvent;
 import org.jibble.epsgraphics.EpsGraphics2D;
 
 import jalview.analysis.AlignmentSorter;
+import jalview.analysis.AlignmentUtils;
 import jalview.analysis.AverageDistanceTree;
 import jalview.analysis.NJTree;
 import jalview.analysis.TreeBuilder;
@@ -103,6 +111,8 @@ public class TreePanel extends GTreePanel
 
   // New JLabel for subtitle
   private JLabel subtitleLabel;
+  
+  private Map<String, Color> secondaryStructureProviderColorMap;
 
   /**
    * Creates a new TreePanel object.
@@ -191,6 +201,12 @@ public class TreePanel extends GTreePanel
     // @Mungo - Why don't we return our own viewport ???
     return getTreeCanvas().getViewport();
   }
+  
+
+  public Map<String, Color> getSecondaryStructureProviderColorMap()
+  {
+    return secondaryStructureProviderColorMap;
+  }
 
   private void addSubtitlePanel(String subTitle)
   {
@@ -446,6 +462,11 @@ public class TreePanel extends GTreePanel
         TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING)
                 ? new NJTree(av, sm, similarityParams)
                 : new AverageDistanceTree(av, sm, similarityParams);
+        List<String> labels = njtree.getLabels();
+        if(labels != null && labels.size()>0) {
+          secondaryStructureProviderColorMap = new HashMap<String, Color>();
+          AlignmentUtils.assignSecondaryStructureProviderColor(secondaryStructureProviderColorMap, labels);
+        }
         tree = new TreeModel(njtree);
         // don't display distances for columnwise trees
       }
@@ -769,16 +790,22 @@ public class TreePanel extends GTreePanel
     treeCanvas.setShowDistances(distanceMenu.isSelected());
   }
   
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
   @Override
-  public void showSecondaryStructureProviderMenu_actionPerformed(ActionEvent e)
+  public void hideStructureProviders_actionPerformed(ActionEvent e)
+  {
+    treeCanvas.hideStructureProviders(hideStructureProviders.isSelected());
+  }
+  
+  @Override
+  public void showStructureProviderColouredLines_actionPerformed(ActionEvent e)
+  {
+    treeCanvas.setShowStructureProviderColouredLines(showStructureProviderColouredLines.isSelected());
+  }
+  
+  @Override
+  public void showStructureProviderLabels_actionPerformed(ActionEvent e)
   {
-    treeCanvas.setShowSecondaryStructureProvider(showSecondaryStructureProviderMenu.isSelected());
+    treeCanvas.setShowStructureProviderLabels(showStructureProviderLabels.isSelected());
   }
 
   /**
index 884f3eb..9120b15 100755 (executable)
@@ -24,12 +24,16 @@ import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 
+import javax.swing.ButtonGroup;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
+import javax.swing.JRadioButtonMenuItem;
 import javax.swing.JScrollPane;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
@@ -65,7 +69,16 @@ public class GTreePanel extends JInternalFrame
   //Menu option for the user to select their preference in 
   //displaying secondary structure providers as labels. 
   //Visible only for secondary structure similarity.
-  public JCheckBoxMenuItem showSecondaryStructureProviderMenu = new JCheckBoxMenuItem();
+  
+  public JMenu showSecondaryStructureProviderMenu = new JMenu();
+
+  ButtonGroup showSecondaryStructureProviderButtonGroup = new ButtonGroup();
+
+  public JRadioButtonMenuItem hideStructureProviders = new JRadioButtonMenuItem();
+  
+  public JRadioButtonMenuItem showStructureProviderLabels = new JRadioButtonMenuItem();
+
+  public JRadioButtonMenuItem showStructureProviderColouredLines = new JRadioButtonMenuItem();
 
   public JCheckBoxMenuItem fitToWindow = new JCheckBoxMenuItem();
 
@@ -179,15 +192,43 @@ public class GTreePanel extends JInternalFrame
         distanceMenu_actionPerformed(e);
       }
     });
+
+    showSecondaryStructureProviderButtonGroup.add(hideStructureProviders);
+    showSecondaryStructureProviderButtonGroup.add(showStructureProviderLabels);
+    showSecondaryStructureProviderButtonGroup.add(showStructureProviderColouredLines);
     showSecondaryStructureProviderMenu.setText(MessageManager.getString("label.show_secondary_structure_provider"));
-    showSecondaryStructureProviderMenu.addActionListener(new java.awt.event.ActionListener()
+    hideStructureProviders.setText(MessageManager.getString("label.hide_structure_provider"));
+    hideStructureProviders.setSelected(true);
+    hideStructureProviders.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        showSecondaryStructureProviderMenu_actionPerformed(e);
+        hideStructureProviders_actionPerformed(e);
       }
     });
+    
+    showStructureProviderLabels.setText(MessageManager.getString("label.show_structure_provider_as_labels"));
+    showStructureProviderLabels.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        showStructureProviderLabels_actionPerformed(e);
+      }
+    });
+
+    showStructureProviderColouredLines.setText(MessageManager.getString("label.show_structure_provider_as_coloured_lines"));
+    showStructureProviderColouredLines.addActionListener(new java.awt.event.ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        showStructureProviderColouredLines_actionPerformed(e);
+      }
+      
+    });
+
     fitToWindow.setSelected(true);
     fitToWindow.setText(MessageManager.getString("label.fit_to_window"));
     fitToWindow.addActionListener(new java.awt.event.ActionListener()
@@ -259,7 +300,7 @@ public class GTreePanel extends JInternalFrame
     viewMenu.add(fitToWindow);
     viewMenu.add(font);
     viewMenu.add(distanceMenu);
-    viewMenu.add(showSecondaryStructureProviderMenu); 
+    viewMenu.add(showSecondaryStructureProviderMenu);
     viewMenu.add(bootstrapMenu);
     viewMenu.add(placeholdersMenu);
     viewMenu.add(sortAssocViews);
@@ -267,6 +308,10 @@ public class GTreePanel extends JInternalFrame
     saveAsMenu.add(saveAsNewick);
     saveAsMenu.add(epsTree);
     saveAsMenu.add(pngTree);
+    showSecondaryStructureProviderMenu.add(hideStructureProviders);
+    showSecondaryStructureProviderMenu.add(showStructureProviderLabels);
+    showSecondaryStructureProviderMenu.add(showStructureProviderColouredLines);
+    
   }
 
   public void printMenu_actionPerformed(ActionEvent e)
@@ -284,6 +329,18 @@ public class GTreePanel extends JInternalFrame
   public void showSecondaryStructureProviderMenu_actionPerformed(ActionEvent e)
   {
   }
+  
+  public void hideStructureProviders_actionPerformed(ActionEvent e)
+  {
+  }
+
+  public void showStructureProviderColouredLines_actionPerformed(ActionEvent e)
+  {
+  }
+  
+  public void showStructureProviderLabels_actionPerformed(ActionEvent e)
+  {
+  }
 
   public void bootstrapMenu_actionPerformed(ActionEvent e)
   {