NPE fix
[jalview.git] / src / jalview / appletgui / SeqPanel.java
old mode 100755 (executable)
new mode 100644 (file)
index 6486647..f961212
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
- * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
+ * Copyright (C) 2011 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
  * 
  * This file is part of Jalview.
  * 
@@ -25,6 +25,7 @@ import java.awt.event.*;
 import jalview.commands.*;
 import jalview.datamodel.*;
 import jalview.schemes.*;
+import jalview.structure.SelectionSource;
 import jalview.structure.SequenceListener;
 import jalview.structure.StructureSelectionManager;
 
@@ -90,7 +91,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     seqCanvas.addMouseMotionListener(this);
     seqCanvas.addMouseListener(this);
-    ssm = StructureSelectionManager.getStructureSelectionManager();
+    ssm = StructureSelectionManager.getStructureSelectionManager(av.applet);
     ssm.addStructureViewerListener(this);
 
     seqCanvas.repaint();
@@ -302,8 +303,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       sg.addSequence(sequence, false);
       av.setSelectionGroup(sg);
     }
-
     ap.paintAlignment(false);
+    av.sendSelection();
   }
 
   void insertGapAtCursor(boolean group)
@@ -457,21 +458,21 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     SequenceI sequence = av.alignment.getSequenceAt(findSeq(evt));
     if (evt.getClickCount() > 1)
     {
-      if (av.getSelectionGroup().getSize() == 1
+      if (av.getSelectionGroup()!=null && av.getSelectionGroup().getSize() == 1
               && av.getSelectionGroup().getEndRes()
                       - av.getSelectionGroup().getStartRes() < 2)
       {
         av.setSelectionGroup(null);
       }
 
-      SequenceFeature[] features = findFeaturesAtRes(sequence, sequence
-              .findPosition(findRes(evt)));
+      SequenceFeature[] features = findFeaturesAtRes(sequence,
+              sequence.findPosition(findRes(evt)));
 
       if (features != null && features.length > 0)
       {
         SearchResults highlight = new SearchResults();
-        highlight.addResult(sequence, features[0].getBegin(), features[0]
-                .getEnd());
+        highlight.addResult(sequence, features[0].getBegin(),
+                features[0].getEnd());
         seqCanvas.highlightSearchResults(highlight);
       }
       if (features != null && features.length > 0)
@@ -580,8 +581,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       y -= hgap;
 
-      seq = Math.min((y % cHeight) / av.getCharHeight(), av.alignment
-              .getHeight() - 1);
+      seq = Math.min((y % cHeight) / av.getCharHeight(),
+              av.alignment.getHeight() - 1);
       if (seq < 0)
       {
         seq = -1;
@@ -631,18 +632,22 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
     String tmp = sequence.hashCode() + index + "";
     if (lastMessage == null || !lastMessage.equals(tmp))
-      ssm.mouseOverSequence(sequence, index, pos);
+      ssm.mouseOverSequence(sequence, index, pos, av);
 
     lastMessage = tmp;
   }
 
   public void highlightSequence(SearchResults results)
   {
-    seqCanvas.highlightSearchResults(results);
     if (av.followHighlight)
     {
-      ap.scrollToPosition(results);
+      if (ap.scrollToPosition(results, true))
+      {
+        ap.alignFrame.repaint();
+      }
     }
+    seqCanvas.highlightSearchResults(results);
+
   }
 
   public void updateColours(SequenceI seq, int index)
@@ -734,8 +739,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
 
     // use aa to see if the mouse pointer is on a
-    SequenceFeature[] allFeatures = findFeaturesAtRes(sequence, sequence
-            .findPosition(res));
+    SequenceFeature[] allFeatures = findFeaturesAtRes(sequence,
+            sequence.findPosition(res));
 
     int index = 0;
     while (index < allFeatures.length)
@@ -836,9 +841,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
           fontSize = 1;
         }
 
-        av
-                .setFont(new Font(av.font.getName(), av.font.getStyle(),
-                        fontSize));
+        av.setFont(new Font(av.font.getName(), av.font.getStyle(), fontSize));
         av.charWidth = oldWidth;
       }
       else
@@ -1348,8 +1351,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     // DETECT RIGHT MOUSE BUTTON IN AWT
     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
-      SequenceFeature[] allFeatures = findFeaturesAtRes(sequence, sequence
-              .findPosition(res));
+      SequenceFeature[] allFeatures = findFeaturesAtRes(sequence,
+              sequence.findPosition(res));
 
       Vector links = null;
       if (allFeatures != null)
@@ -1420,9 +1423,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       if (stretchGroup.cs instanceof ClustalxColourScheme)
       {
-        ((ClustalxColourScheme) stretchGroup.cs).resetClustalX(stretchGroup
-                .getSequences(av.hiddenRepSequences), stretchGroup
-                .getWidth());
+        ((ClustalxColourScheme) stretchGroup.cs).resetClustalX(
+                stretchGroup.getSequences(av.hiddenRepSequences),
+                stretchGroup.getWidth());
       }
 
       if (stretchGroup.cs instanceof Blosum62ColourScheme
@@ -1435,14 +1438,14 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       if (stretchGroup.cs.conservationApplied())
       {
-        SliderPanel.setConservationSlider(ap, stretchGroup.cs, stretchGroup
-                .getName());
+        SliderPanel.setConservationSlider(ap, stretchGroup.cs,
+                stretchGroup.getName());
         stretchGroup.recalcConservation();
       }
       else
       {
-        SliderPanel.setPIDSliderSource(ap, stretchGroup.cs, stretchGroup
-                .getName());
+        SliderPanel.setPIDSliderSource(ap, stretchGroup.cs,
+                stretchGroup.getName());
       }
     }
     changeEndRes = false;
@@ -1450,6 +1453,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     stretchGroup = null;
     PaintRefresher.Refresh(ap, av.getSequenceSetId());
     ap.paintAlignment(true);
+    av.sendSelection();
   }
 
   public void doMouseDraggedDefineMode(MouseEvent evt)
@@ -1684,4 +1688,128 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
   }
 
+  /**
+   * modify current selection according to a received message.
+   */
+  public void selection(SequenceGroup seqsel, ColumnSelection colsel,
+          SelectionSource source)
+  {
+    // TODO: fix this hack - source of messages is align viewport, but SeqPanel
+    // handles selection messages...
+    // TODO: extend config options to allow user to control if selections may be
+    // shared between viewports.
+    if (av != null
+            && (av == source || !av.followSelection || (source instanceof AlignViewport && ((AlignViewport) source)
+                    .getSequenceSetId().equals(av.getSequenceSetId()))))
+    {
+      return;
+    }
+    // do we want to thread this ? (contention with seqsel and colsel locks, I
+    // suspect)
+    // rules are: colsel is copied if there is a real intersection between
+    // sequence selection
+    boolean repaint = false, copycolsel = true;
+    if (av.selectionGroup == null || !av.isSelectionGroupChanged())
+    {
+      SequenceGroup sgroup = null;
+      if (seqsel != null && seqsel.getSize()>0)
+      {
+        if (av.alignment == null)
+        {
+          System.out
+                  .println("Selection message: alignviewport av SeqSetId="
+                          + av.getSequenceSetId() + " ViewId="
+                          + av.getViewId()
+                          + " 's alignment is NULL! returning immediatly.");
+          return;
+        }
+        sgroup = seqsel.intersect(av.alignment,
+                (av.hasHiddenRows) ? av.hiddenRepSequences : null);
+        if ((sgroup == null || sgroup.getSize() == 0)
+                && (colsel == null || colsel.size() == 0))
+        {
+          // don't copy columns if the region didn't intersect.
+          copycolsel = false;
+        }
+      }
+      if (sgroup != null && sgroup.getSize() > 0)
+      {
+        av.setSelectionGroup(sgroup);
+      }
+      else
+      {
+        av.setSelectionGroup(null);
+      }
+      repaint = av.isSelectionGroupChanged();
+    }
+    if (copycolsel && (av.colSel == null || !av.isColSelChanged()))
+    {
+      // the current selection is unset or from a previous message
+      // so import the new colsel.
+      if (colsel == null || colsel.size() == 0)
+      {
+        if (av.colSel != null)
+        {
+          av.colSel.clear();
+        }
+      }
+      else
+      {
+        // TODO: shift colSel according to the intersecting sequences
+        if (av.colSel == null)
+        {
+          av.colSel = new ColumnSelection(colsel);
+        }
+        else
+        {
+          av.colSel.setElementsFrom(colsel);
+        }
+      }
+      repaint |= av.isColSelChanged();
+    }
+    if (copycolsel && av.hasHiddenColumns
+            && (av.colSel == null || av.colSel.getHiddenColumns() == null))
+    {
+      System.err.println("Bad things");
+    }
+    if (repaint)
+    {
+      ap.scalePanelHolder.repaint();
+      ap.repaint();
+    }
+  }
+
+  /**
+   * scroll to the given row/column - or nearest visible location
+   * @param row
+   * @param column
+   */
+  public void scrollTo(int row, int column)
+  {
+    
+    row = row<0 ? ap.av.startSeq : row;
+    column = column<0 ? ap.av.startRes : column;
+    ap.scrollTo(row, row, column, true, true);
+  }
+  /**
+   * scroll to the given row - or nearest visible location
+   * @param row
+   */
+  public void scrollToRow(int row)
+  {
+    
+    row = row<0 ? ap.av.startSeq : row;
+    ap.scrollTo(row, row, ap.av.startRes, true, true);
+  }
+  /**
+   * scroll to the given column - or nearest visible location
+   * @param column
+   */
+  public void scrollToColumn(int column)
+  {
+    
+    column = column<0 ? ap.av.startRes : column;
+    ap.scrollTo(ap.av.startRes, ap.av.startRes, column, true, true);
+  }
+
 }