JAL-4134 hold ctrl to select groups containing rows and columns under mouse over...
authorJames Procter <j.procter@dundee.ac.uk>
Wed, 1 Mar 2023 17:31:26 +0000 (17:31 +0000)
committerJames Procter <j.procter@dundee.ac.uk>
Wed, 1 Mar 2023 17:31:26 +0000 (17:31 +0000)
src/jalview/gui/AnnotationPanel.java

index 84443e7..b112383 100755 (executable)
@@ -605,29 +605,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
         {
           GraphLine thr = aa[graphStretch].getThreshold();
           
-          // possible alternative for interactive selection - threshold gives 'ceiling' for forming a cluster
-          // when a row+column is selected, farthest common ancestor less than thr is used to compute cluster  
           int currentX = getColumnForXPos(evt.getX());
-          ContactMatrixI matrix = av.getContactMatrix(aa[graphStretch]);
-          if (matrix!=null)
-          {
-            if (matrix.hasGroups())
-            {
-            SequenceI rseq = aa[graphStretch].sequenceRef;
-            BitSet grp = matrix.getGroupsFor(currentX);
-            ColumnSelection cs = av.getColumnSelection();
-            HiddenColumns hc = av.getAlignment().getHiddenColumns();
-            for (int p=grp.nextSetBit(0); p>=0; p = grp.nextSetBit(p+1))
-            {
-              int offp = (rseq!=null) ? rseq.findIndex(rseq.getStart()-1+p) : p;
-              
-              if (!av.hasHiddenColumns() || hc.isVisible(offp))
-              { 
-                av.getColumnSelection().addElement(offp);
-              }
-            }
-          } else 
-          {
           ContactListI forCurrentX = av.getContactList(aa[graphStretch],
                   currentX);
           if (forCurrentX != null)
@@ -636,61 +614,110 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
                     aa[graphStretch].graphHeight);
             ContactGeometry.contactInterval cXci = cXcgeom.mapFor(yOffset,
                     yOffset);
+            /**
+             * start and end range corresponding to the row range under the
+             * mouse at column currentX
+             */
             int fr, to;
             fr = Math.min(cXci.cStart, cXci.cEnd);
             to = Math.max(cXci.cStart, cXci.cEnd);
-            // select corresponding range in segment under mouse
+
+            if (evt.isControlDown())
             {
-              for (int c = fr; c <= to; c++)
+              ContactMatrixI matrix = av.getContactMatrix(aa[graphStretch]);
+              
+              if (matrix != null)
               {
-                av.getColumnSelection().addElement(c);
+                // simplest approach is to select all group containing column
+                if (matrix.hasGroups())
+                {
+                  SequenceI rseq = aa[graphStretch].sequenceRef;
+                  BitSet grp = matrix.getGroupsFor(currentX);
+                  for (int c=fr;c<=to; c++)
+                  {
+                    BitSet additionalGrp = matrix.getGroupsFor(c);
+                    grp.or(additionalGrp);
+                  }
+                  HiddenColumns hc = av.getAlignment().getHiddenColumns();
+                  for (int p = grp.nextSetBit(0); p >= 0; p = grp
+                          .nextSetBit(p + 1))
+                  {
+                    int offp = (rseq != null)
+                            ? rseq.findIndex(rseq.getStart() - 1 + p)
+                            : p;
+
+                    if (!av.hasHiddenColumns() || hc.isVisible(offp))
+                    {
+                      av.getColumnSelection().addElement(offp);
+                    }
+                  }
+                }
+                // possible alternative for interactive selection - threshold
+                // gives 'ceiling' for forming a cluster
+                // when a row+column is selected, farthest common ancestor less
+                // than thr is used to compute cluster
+
               }
-              av.getColumnSelection().addElement(currentX);
             }
-            // PAE SPECIFIC
-            // and also select everything lower than the max range adjacent
-            // (kind of works)
-            if (PAEContactMatrix.PAEMATRIX.equals(aa[graphStretch].getCalcId()))
+            else
             {
-              int c = fr - 1;
-              ContactRange cr = forCurrentX.getRangeFor(fr, to);
-              double cval;
-              // TODO: could use GraphLine instead of arbitrary picking
-              // TODO: could report mean/median/variance for partitions (contiguous selected vs unselected regions and inter-contig regions)
-              // controls feathering - what other elements in row/column should we select
-              double thresh=cr.getMean()+(cr.getMax()-cr.getMean())*.15;
-              while (c > 0)
+              // select corresponding range in segment under mouse
               {
-                cval = forCurrentX.getContactAt(c);
-                if (// cr.getMin() <= cval &&
-                cval <= thresh)
+                for (int c = fr; c <= to; c++)
                 {
-                  av.getColumnSelection().addElement(c--);
-                }
-                else
-                {
-                  break;
+                  av.getColumnSelection().addElement(c);
                 }
+                av.getColumnSelection().addElement(currentX);
               }
-              c = to;
-              while (c < forCurrentX.getContactHeight())
+              // PAE SPECIFIC
+              // and also select everything lower than the max range adjacent
+              // (kind of works)
+              if (PAEContactMatrix.PAEMATRIX
+                      .equals(aa[graphStretch].getCalcId()))
               {
-                cval = forCurrentX.getContactAt(c);
-                if (// cr.getMin() <= cval &&
-                cval <= thresh)
+                int c = fr - 1;
+                ContactRange cr = forCurrentX.getRangeFor(fr, to);
+                double cval;
+                // TODO: could use GraphLine instead of arbitrary picking
+                // TODO: could report mean/median/variance for partitions
+                // (contiguous selected vs unselected regions and inter-contig
+                // regions)
+                // controls feathering - what other elements in row/column
+                // should we select
+                double thresh = cr.getMean()
+                        + (cr.getMax() - cr.getMean()) * .15;
+                while (c > 0)
                 {
-                  av.getColumnSelection().addElement(c++);
+                  cval = forCurrentX.getContactAt(c);
+                  if (// cr.getMin() <= cval &&
+                  cval <= thresh)
+                  {
+                    av.getColumnSelection().addElement(c--);
+                  }
+                  else
+                  {
+                    break;
+                  }
                 }
-                else
+                c = to;
+                while (c < forCurrentX.getContactHeight())
                 {
-                  break;
+                  cval = forCurrentX.getContactAt(c);
+                  if (// cr.getMin() <= cval &&
+                  cval <= thresh)
+                  {
+                    av.getColumnSelection().addElement(c++);
+                  }
+                  else
+                  {
+                    break;
+                  }
                 }
               }
             }
-            }
           }
         }
-      }}
+      }
     }
     else
     {