JAL-3583 consistent last[Formatted]Tooltip, show once only per residue
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 12 Apr 2020 11:51:12 +0000 (12:51 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 12 Apr 2020 11:51:12 +0000 (12:51 +0100)
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/SeqPanel.java

index 4ead210..35ae242 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.SequenceI;
-import jalview.gui.JalviewColourChooser.ColourChooserListener;
-import jalview.renderer.AnnotationRenderer;
-import jalview.renderer.AwtRenderPanelI;
-import jalview.schemes.ResidueProperties;
-import jalview.util.Comparison;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.viewmodel.ViewportListenerI;
-import jalview.viewmodel.ViewportRanges;
-
 import java.awt.AlphaComposite;
 import java.awt.Color;
 import java.awt.Dimension;
@@ -66,6 +50,22 @@ import javax.swing.JPopupMenu;
 import javax.swing.Scrollable;
 import javax.swing.ToolTipManager;
 
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SequenceI;
+import jalview.gui.JalviewColourChooser.ColourChooserListener;
+import jalview.renderer.AnnotationRenderer;
+import jalview.renderer.AwtRenderPanelI;
+import jalview.schemes.ResidueProperties;
+import jalview.util.Comparison;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
+
 /**
  * AnnotationPanel displays visible portion of annotation rows below unwrapped
  * alignment
@@ -786,7 +786,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     if (row > -1 && ann.annotations != null
             && column < ann.annotations.length)
     {
-      setToolTipText(buildToolTip(ann, column, aa));
+      String toolTip = buildToolTip(ann, column, aa);
+      setToolTipText(toolTip == null ? null
+              : JvSwingUtils.wrapTooltip(true, toolTip));
       String msg = getStatusMessage(av.getAlignment(), column, ann);
       ap.alignFrame.setStatus(msg);
     }
@@ -833,7 +835,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
   }
 
   /**
-   * Answers a tooltip for the annotation at the current mouse position
+   * Answers a tooltip for the annotation at the current mouse position, not
+   * wrapped in &lt;html&gt; tags (apply if wanted). Answers null if there is no
+   * tooltip to show.
    * 
    * @param ann
    * @param column
@@ -846,45 +850,33 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     if (ann.graphGroup > -1)
     {
       StringBuilder tip = new StringBuilder(32);
-      tip.append("<html>");
+      boolean first = true;
       for (int i = 0; i < anns.length; i++)
       {
         if (anns[i].graphGroup == ann.graphGroup
                 && anns[i].annotations[column] != null)
         {
+          if (!first)
+          {
+            tip.append("<br>");
+          }
+          first = false;
           tip.append(anns[i].label);
           String description = anns[i].annotations[column].description;
           if (description != null && description.length() > 0)
           {
             tip.append(" ").append(description);
           }
-          tip.append("<br>");
         }
       }
-      if (tip.length() != 6)
-      {
-        tip.setLength(tip.length() - 4);
-        tooltip = tip.toString() + "</html>";
-      }
+      tooltip = first ? null : tip.toString();
     }
     else if (column < ann.annotations.length
             && ann.annotations[column] != null)
     {
-      String description = ann.annotations[column].description;
-      if (description != null && description.length() > 0)
-      {
-        tooltip = JvSwingUtils.wrapTooltip(true, description);
-      }
-      else
-      {
-        tooltip = null; // no tooltip if null or empty description
-      }
-    }
-    else
-    {
-      // clear the tooltip.
-      tooltip = null;
+      tooltip = ann.annotations[column].description;
     }
+
     return tooltip;
   }
 
index 18e9365..f433aec 100644 (file)
  */
 package jalview.gui;
 
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JToolTip;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.ToolTipManager;
+
 import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.commands.EditCommand;
@@ -53,29 +76,6 @@ import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Point;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JToolTip;
-import javax.swing.SwingUtilities;
-import javax.swing.Timer;
-import javax.swing.ToolTipManager;
-
 /**
  * DOCUMENT ME!
  * 
@@ -216,9 +216,19 @@ public class SeqPanel extends JPanel
 
   private final SequenceAnnotationReport seqARep;
 
-  StringBuilder tooltipText = new StringBuilder();
+  /*
+   * the last tooltip on mousing over the alignment (or annotation in wrapped mode)
+   * - the tooltip is not set again if unchanged
+   * - this is the tooltip text _before_ formatting as html
+   */
+  private String lastTooltip;
 
-  String tmpString;
+  /*
+   * the last tooltip on mousing over the alignment (or annotation in wrapped mode)
+   * - used to decide where to place the tooltip in getTooltipLocation() 
+   * - this is the tooltip text _after_ formatting as html
+   */
+  private String lastFormattedTooltip;
 
   EditCommand editCommand;
 
@@ -822,8 +832,6 @@ public class SeqPanel extends JPanel
 
   String lastMessage;
 
-  private String formattedTooltipText;
-
   @Override
   public void mouseOverSequence(SequenceI sequence, int index, int pos)
   {
@@ -984,8 +992,10 @@ public class SeqPanel extends JPanel
       /*
        * just a pixel move without change of 'cell'
        */
+      moveTooltip = false;
       return;
     }
+    moveTooltip = true;
     lastMousePosition = mousePos;
 
     if (mousePos.isOverAnnotation())
@@ -1001,6 +1011,7 @@ public class SeqPanel extends JPanel
       lastMousePosition = null;
       setToolTipText(null);
       lastTooltip = null;
+      lastFormattedTooltip = null;
       ap.alignFrame.setStatus("");
       return;
     }
@@ -1022,7 +1033,7 @@ public class SeqPanel extends JPanel
       mouseOverSequence(sequence, column, pos);
     }
 
-    tooltipText.setLength(6); // "<html>"
+    StringBuilder tooltipText = new StringBuilder(64);
 
     SequenceGroup[] groups = av.getAlignment().findAllGroups(sequence);
     if (groups != null)
@@ -1083,7 +1094,7 @@ public class SeqPanel extends JPanel
         }
       }
     }
-    if (tooltipText.length() == 6) // "<html>"
+    if (tooltipText.length() == 0) // nothing added
     {
       setToolTipText(null);
       lastTooltip = null;
@@ -1103,12 +1114,12 @@ public class SeqPanel extends JPanel
                 .append("</i>");
       }
       String textString = tooltipText.toString();
-      if (lastTooltip == null || !lastTooltip.equals(textString))
+      if (!textString.equals(lastTooltip))
       {
-        formattedTooltipText = JvSwingUtils.wrapTooltip(true,
-                textString);
-        setToolTipText(formattedTooltipText);        
         lastTooltip = textString;
+        lastFormattedTooltip = JvSwingUtils.wrapTooltip(true,
+                textString);
+        setToolTipText(lastFormattedTooltip);
       }
     }
   }
@@ -1134,16 +1145,35 @@ public class SeqPanel extends JPanel
 
     String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column,
             anns);
-    setToolTipText(tooltip);
-    lastTooltip = tooltip;
+    if (true || !tooltip.equals(lastTooltip))
+    {
+      System.out.println("wrapped tooltip set");
+      lastTooltip = tooltip;
+      lastFormattedTooltip = tooltip == null ? null
+              : JvSwingUtils.wrapTooltip(true, tooltip);
+      setToolTipText(lastFormattedTooltip);
+    }
 
     String msg = AnnotationPanel.getStatusMessage(av.getAlignment(), column,
             anns[rowIndex]);
     ap.alignFrame.setStatus(msg);
   }
 
-  private Point lastp = null;
+  /*
+   * if Shift key is held down while moving the mouse, 
+   * the tooltip location is not changed once shown
+   */
+  private Point lastTooltipLocation = null;
+
+  /*
+   * this flag is false for pixel moves within a residue,
+   * to reduce tooltip flicker
+   */
+  private boolean moveTooltip = true;
 
+  /*
+   * a dummy tooltip used to estimate where to position tooltips
+   */
   private JToolTip tempTip = new JLabel().createToolTip();
 
   /*
@@ -1156,33 +1186,30 @@ public class SeqPanel extends JPanel
   {
     // BH 2018
 
-    if (tooltipText == null || tooltipText.length() <= 6)
+    if (lastTooltip == null || !moveTooltip)
     {
       return null;
     }
 
-    if (lastp != null && event.isShiftDown())
+    if (lastTooltipLocation != null && event.isShiftDown())
     {
-      return lastp;
+      return lastTooltipLocation;
     }
 
-    Point p = lastp;
     int x = event.getX();
     int y = event.getY();
     int w = getWidth();
 
-    tempTip.setTipText(formattedTooltipText);
+    tempTip.setTipText(lastFormattedTooltip);
     int tipWidth = (int) tempTip.getPreferredSize().getWidth();
     
     // was      x += (w - x < 200) ? -(w / 2) : 5;
     x = (x + tipWidth < w ? x + 10 : w - tipWidth);
-    p = new Point(x, y + 20); // BH 2018 was - 20?
+    Point p = new Point(x, y + av.getCharHeight()); // BH 2018 was - 20?
 
-    return lastp = p;
+    return lastTooltipLocation = p;
   }
 
-  String lastTooltip;
-
   /**
    * set when the current UI interaction has resulted in a change that requires
    * shading in overviews and structures to be recalculated. this could be