From 23deaf6a1371e81b2e6547d5df697bf60e442e84 Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Thu, 20 Oct 2022 10:08:39 +0100 Subject: [PATCH] JAL-2349 JAL-3855 - interactive point-wise row/column selection, and first attempt at alt-drag for region selections (not yet working!) --- src/jalview/gui/AnnotationPanel.java | 163 ++++++++++++++++++++++++++++++---- src/jalview/gui/SeqPanel.java | 2 +- 2 files changed, 149 insertions(+), 16 deletions(-) diff --git a/src/jalview/gui/AnnotationPanel.java b/src/jalview/gui/AnnotationPanel.java index d80c749..ba02a3f 100755 --- a/src/jalview/gui/AnnotationPanel.java +++ b/src/jalview/gui/AnnotationPanel.java @@ -82,7 +82,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, { enum DragMode { - Select, Resize, Undefined + Select, Resize, Undefined, MatrixSelect }; String HELIX = MessageManager.getString("label.helix"); @@ -132,6 +132,10 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, int mouseDragLastY = -1; + int firstDragX = -1; + + int firstDragY = -1; + DragMode dragMode = DragMode.Undefined; boolean mouseDragging = false; @@ -539,8 +543,10 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, */ int height = 0; activeRow = -1; - + int yOffset = 0; + // todo could reuse getRowIndexAndOffset ? final int y = evt.getY(); + for (int i = 0; i < aa.length; i++) { if (aa[i].visible) @@ -560,6 +566,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, * we have clicked on a resizable graph annotation */ graphStretch = i; + yOffset = height - y; } break; } @@ -575,7 +582,34 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, return; } - ap.getScalePanel().mousePressed(evt); + if (graphStretch != -1) + { + if (aa[graphStretch].graph == AlignmentAnnotation.CUSTOMRENDERER) + { + int currentX = getColumnForXPos(evt.getX()); + ContactListI forCurrentX = av.getContactList(aa[graphStretch], + currentX); + if (forCurrentX != null) + { + ContactGeometry cXcgeom = new ContactGeometry(forCurrentX, + aa[graphStretch].graphHeight); + ContactGeometry.contactInterval cXci = cXcgeom.mapFor(yOffset, + yOffset); + int fr, to; + fr = Math.min(cXci.cStart, cXci.cEnd); + to = Math.max(cXci.cStart, cXci.cEnd); + for (int c = fr; c <= to; c++) + { + av.getColumnSelection().addElement(c); + } + av.getColumnSelection().addElement(currentX); + } + } + } + else + { + ap.getScalePanel().mousePressed(evt); + } } /** @@ -635,6 +669,10 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, @Override public void mouseReleased(MouseEvent evt) { + if (dragMode == DragMode.MatrixSelect) + { + matrixSelectRange(evt); + } graphStretch = -1; mouseDragLastX = -1; mouseDragLastY = -1; @@ -725,10 +763,25 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, * mostly vertical drag */ dragMode = DragMode.Resize; + + /* + * but could also be a matrix drag + */ + if ((evt.isAltDown() || evt.isAltGraphDown()) && (av.getAlignment() + .getAlignmentAnnotation()[graphStretch].graph == AlignmentAnnotation.CUSTOMRENDERER)) + { + /* + * dragging in a matrix + */ + dragMode = DragMode.MatrixSelect; + firstDragX = mouseDragLastX; + firstDragY = mouseDragLastY; + } } } if (dragMode == DragMode.Undefined) + { /* * drag is diagonal - defer deciding whether to @@ -755,6 +808,12 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, ap.paintAlignment(false, false); } } + else if (dragMode == DragMode.MatrixSelect) + { + /* + * TODO draw a rubber band for range + */ + } else { /* @@ -770,6 +829,70 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, } } + public void matrixSelectRange(MouseEvent evt) + { + /* + * get geometry of drag + */ + int fromY = Math.min(firstDragY, evt.getY()); + int deltaY = Math.abs(firstDragY - evt.getY()); + int toY = Math.max(firstDragY, evt.getY()); + + int[] rowIndex = getRowIndexAndOffset(fromY, + av.getAlignment().getAlignmentAnnotation()); + + // rectangular selection on matrix style annotation + AlignmentAnnotation cma = av.getAlignment() + .getAlignmentAnnotation()[rowIndex[0]]; + + int fromXp = Math.min(firstDragX, evt.getX()); + int toXp = Math.max(firstDragX, evt.getX()); + int lastX = getColumnForXPos(fromXp); + int currentX = getColumnForXPos(toXp); + ContactListI forLastX = av.getContactList(cma, lastX); + ContactListI forCurrentX = av.getContactList(cma, currentX); + if (forLastX != null && forCurrentX != null) + { + ContactGeometry lastXcgeom = new ContactGeometry(forLastX, + cma.graphHeight); + ContactGeometry.contactInterval lastXci = lastXcgeom.mapFor( + rowIndex[1], + rowIndex[1] + ((fromY == firstDragY) ? -deltaY : deltaY)); + ContactGeometry cXcgeom = new ContactGeometry(forCurrentX, + cma.graphHeight); + ContactGeometry.contactInterval cXci = cXcgeom.mapFor(rowIndex[1], + rowIndex[1] + deltaY); + // mark rectangular region formed by drag + System.err.println("Matrix Selection from last(" + lastXci.cStart + + "," + lastXci.cEnd + ") to cur(" + cXci.cStart + "," + + cXci.cEnd + ")"); + int fr, to; + fr = Math.min(lastXci.cStart, lastXci.cEnd); + to = Math.max(lastXci.cStart, lastXci.cEnd); + System.err.println("Marking " + fr + " to " + to); + for (int c = fr; c <= to; c++) + { + av.getColumnSelection().addElement(c); + } + fr = Math.min(cXci.cStart, cXci.cEnd); + to = Math.max(cXci.cStart, cXci.cEnd); + System.err.println("Marking " + fr + " to " + to); + for (int c = fr; c <= to; c++) + { + av.getColumnSelection().addElement(c); + } + fr = Math.min(lastX, currentX); + to = Math.max(lastX, currentX); + + System.err.println("Marking " + fr + " to " + to); + for (int c = fr; c <= to; c++) + { + av.getColumnSelection().addElement(c); + } + } + + } + /** * Constructs the tooltip, and constructs and displays a status message, for * the current mouse position @@ -790,21 +913,14 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, return; } - int column = (evt.getX() / av.getCharWidth()) - + av.getRanges().getStartRes(); - column = Math.min(column, av.getRanges().getEndRes()); - - if (av.hasHiddenColumns()) - { - column = av.getAlignment().getHiddenColumns() - .visibleToAbsoluteColumn(column); - } + int column = getColumnForXPos(evt.getX()); AlignmentAnnotation ann = aa[row]; if (row > -1 && ann.annotations != null && column < ann.annotations.length) { - String toolTip = buildToolTip(ann, column, aa, rowAndOffset[1], av); + String toolTip = buildToolTip(ann, column, aa, rowAndOffset[1], av, + ap); setToolTipText(toolTip == null ? null : JvSwingUtils.wrapTooltip(true, toolTip)); String msg = getStatusMessage(av.getAlignment(), column, ann, @@ -818,6 +934,19 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, } } + private int getColumnForXPos(int x) + { + int column = (x / av.getCharWidth()) + av.getRanges().getStartRes(); + column = Math.min(column, av.getRanges().getEndRes()); + + if (av.hasHiddenColumns()) + { + column = av.getAlignment().getHiddenColumns() + .visibleToAbsoluteColumn(column); + } + return column; + } + /** * Answers the index in the annotations array of the visible annotation at the * given y position. This is done by adding the heights of visible annotations @@ -861,7 +990,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, { row = i; res[0] = row; - res[1] = yPos - lheight; + res[1] = height - yPos; break; } } @@ -879,7 +1008,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, * @param rowAndOffset */ static String buildToolTip(AlignmentAnnotation ann, int column, - AlignmentAnnotation[] anns, int rowAndOffset, AlignViewportI av) + AlignmentAnnotation[] anns, int rowAndOffset, AlignViewportI av, + AlignmentPanel ap) { String tooltip = null; if (ann.graphGroup > -1) @@ -921,6 +1051,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, ContactGeometry.contactInterval ci = cgeom.mapFor(rowAndOffset, rowAndOffset); tooltip += "Contact from " + ci.cStart + " to " + ci.cEnd; + + // ap.getStructureSelectionManager().mouseOverSequence(ann.sequenceRef, + // new int[] {column, ci.cStart,ci.cEnd}, -1, null) } } return tooltip; diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index 6918811..20ec5e4 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -1184,7 +1184,7 @@ public class SeqPanel extends JPanel AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation(); String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column, - anns, 0, av); + anns, 0, av, ap); if (tooltip == null ? tooltip != lastTooltip : !tooltip.equals(lastTooltip)) { -- 1.7.10.2