JAL-2272 Cmd-drag to group edit sequences on Mac (Ctrl-click for popup
[jalview.git] / src / jalview / gui / SeqPanel.java
index 8ebcc87..3266fab 100644 (file)
@@ -43,6 +43,7 @@ import jalview.structure.VamsasSource;
 import jalview.util.Comparison;
 import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.BorderLayout;
@@ -582,6 +583,13 @@ public class SeqPanel extends JPanel implements MouseListener,
     mouseDragging = false;
     mouseWheelPressed = false;
 
+    if (evt.isPopupTrigger()) // Windows: mouseReleased
+    {
+      showPopupMenu(evt);
+      evt.consume();
+      return;
+    }
+
     if (!editingSeqs)
     {
       doMouseReleasedDefineMode(evt);
@@ -608,13 +616,14 @@ public class SeqPanel extends JPanel implements MouseListener,
       return;
     }
 
-    if (evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())
+    boolean isControlDown = Platform.isControlDown(evt);
+    if (evt.isShiftDown() || isControlDown)
     {
-      if (evt.isAltDown() || evt.isControlDown())
+      editingSeqs = true;
+      if (isControlDown)
       {
         groupEditing = true;
       }
-      editingSeqs = true;
     }
     else
     {
@@ -836,7 +845,8 @@ public class SeqPanel extends JPanel implements MouseListener,
    * set if av.getSelectionGroup() refers to a group that is defined on the
    * alignment view, rather than a transient selection
    */
-  private boolean editingDefinedGroup = false;  // TODO: refactor to avcontroller or viewModel
+  // private boolean editingDefinedGroup = false; // TODO: refactor to
+  // avcontroller or viewModel
 
   /**
    * Set status message in alignment panel
@@ -857,7 +867,8 @@ public class SeqPanel extends JPanel implements MouseListener,
      * Sequence number (if known), and sequence name.
      */
     String seqno = seq == -1 ? "" : " " + (seq + 1);
-    text.append("Sequence" + seqno + " ID: " + sequence.getName());
+    text.append("Sequence").append(seqno).append(" ID: ")
+            .append(sequence.getName());
 
     String residue = null;
     /*
@@ -1545,9 +1556,10 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   public void doMousePressedDefineMode(MouseEvent evt)
   {
-    int res = findRes(evt);
-    int seq = findSeq(evt);
+    final int res = findRes(evt);
+    final int seq = findSeq(evt);
     oldSeq = seq;
+    needOverviewUpdate = false;
 
     startWrapBlock = wrappedBlock;
 
@@ -1582,12 +1594,10 @@ public class SeqPanel extends JPanel implements MouseListener,
               && (res < stretchGroup.getEndRes()))
       {
         av.setSelectionGroup(stretchGroup);
-        editingDefinedGroup = true;
       }
       else
       {
         stretchGroup = null;
-        editingDefinedGroup = false;
       }
     }
     else if (!stretchGroup.getSequences(null).contains(sequence)
@@ -1606,35 +1616,27 @@ public class SeqPanel extends JPanel implements MouseListener,
                   && (allGroups[i].getEndRes() >= res))
           {
             stretchGroup = allGroups[i];
-            editingDefinedGroup = true;
             break;
           }
         }
       }
 
       av.setSelectionGroup(stretchGroup);
-
     }
 
-    if (evt.isPopupTrigger())
+    if (evt.isPopupTrigger()) // Mac: mousePressed
     {
-      List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
-              .findFeaturesAtRes(sequence.getDatasetSequence(),
-                      sequence.findPosition(res));
-      List<String> links = new ArrayList<String>();
-      for (SequenceFeature sf : allFeatures)
-      {
-        if (sf.links != null)
-        {
-          for (String link : sf.links)
-          {
-            links.add(link);
-          }
-        }
-      }
+      showPopupMenu(evt);
+      return;
+    }
 
-      PopupMenu pop = new PopupMenu(ap, null, links);
-      pop.show(this, evt.getX(), evt.getY());
+    /*
+     * defer right-mouse click handling to mouseReleased on Windows
+     * (where isPopupTrigger() will answer true)
+     * NB isRightMouseButton is also true for Cmd-click on Mac
+     */
+    if (SwingUtilities.isRightMouseButton(evt) && !Platform.isAMac())
+    {
       return;
     }
 
@@ -1656,7 +1658,6 @@ public class SeqPanel extends JPanel implements MouseListener,
       sg.setEndRes(res);
       sg.addSequence(sequence, false);
       av.setSelectionGroup(sg);
-      editingDefinedGroup = false;
       stretchGroup = sg;
 
       if (av.getConservationSelected())
@@ -1688,6 +1689,37 @@ public class SeqPanel extends JPanel implements MouseListener,
   }
 
   /**
+   * Build and show a pop-up menu at the right-click mouse position
+   * 
+   * @param evt
+   * @param res
+   * @param sequence
+   */
+  void showPopupMenu(MouseEvent evt)
+  {
+    final int res = findRes(evt);
+    final int seq = findSeq(evt);
+    SequenceI sequence = av.getAlignment().getSequenceAt(seq);
+    List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
+            .findFeaturesAtRes(sequence.getDatasetSequence(),
+                    sequence.findPosition(res));
+    List<String> links = new ArrayList<String>();
+    for (SequenceFeature sf : allFeatures)
+    {
+      if (sf.links != null)
+      {
+        for (String link : sf.links)
+        {
+          links.add(link);
+        }
+      }
+    }
+
+    PopupMenu pop = new PopupMenu(ap, null, links);
+    pop.show(this, evt.getX(), evt.getY());
+  }
+
+  /**
    * DOCUMENT ME!
    * 
    * @param evt
@@ -1702,7 +1734,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     // always do this - annotation has own state
     // but defer colourscheme update until hidden sequences are passed in
     boolean vischange = stretchGroup.recalcConservation(true);
-    needOverviewUpdate |= vischange && editingDefinedGroup;
+    needOverviewUpdate |= vischange && av.isSelectionDefinedGroup();
     if (stretchGroup.cs != null)
     {
       stretchGroup.cs.alignmentChanged(stretchGroup,
@@ -1721,8 +1753,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
     PaintRefresher.Refresh(this, av.getSequenceSetId());
     ap.paintAlignment(needOverviewUpdate);
-    needOverviewUpdate =false;
-    editingDefinedGroup = false;
+    needOverviewUpdate = false;
     changeEndRes = false;
     changeStartRes = false;
     stretchGroup = null;
@@ -1776,7 +1807,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (res > (stretchGroup.getStartRes() - 1))
       {
         stretchGroup.setEndRes(res);
-        needOverviewUpdate |= editingDefinedGroup;
+        needOverviewUpdate |= av.isSelectionDefinedGroup();
       }
     }
     else if (changeStartRes)
@@ -1784,7 +1815,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (res < (stretchGroup.getEndRes() + 1))
       {
         stretchGroup.setStartRes(res);
-        needOverviewUpdate |= editingDefinedGroup;
+        needOverviewUpdate |= av.isSelectionDefinedGroup();
       }
     }
 
@@ -1818,7 +1849,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (stretchGroup.getSequences(null).contains(nextSeq))
       {
         stretchGroup.deleteSequence(seq, false);
-        needOverviewUpdate |= editingDefinedGroup;
+        needOverviewUpdate |= av.isSelectionDefinedGroup();
       }
       else
       {
@@ -1828,7 +1859,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
 
         stretchGroup.addSequence(nextSeq, false);
-        needOverviewUpdate |= editingDefinedGroup;
+        needOverviewUpdate |= av.isSelectionDefinedGroup();
       }
     }
 
@@ -1982,8 +2013,8 @@ public class SeqPanel extends JPanel implements MouseListener,
     {
       if (av.getAlignment() == null)
       {
-        Cache.log.warn("alignviewport av SeqSetId="
-                + av.getSequenceSetId() + " ViewId=" + av.getViewId()
+        Cache.log.warn("alignviewport av SeqSetId=" + av.getSequenceSetId()
+                + " ViewId=" + av.getViewId()
                 + " 's alignment is NULL! returning immediately.");
         return;
       }