JAL-845 linked protein/dna 'slave' further PoC functionality
[jalview.git] / src / jalview / gui / SeqPanel.java
index e923be7..cca1685 100644 (file)
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
 import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.commands.EditCommand.Edit;
+import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.Sequence;
@@ -1869,52 +1871,67 @@ public class SeqPanel extends JPanel implements MouseListener,
     // handles selection messages...
     // TODO: extend config options to allow user to control if selections may be
     // shared between viewports.
-    if (av == source
-            || !av.followSelection
-            || (av.isSelectionGroupChanged(false) || av
-                    .isColSelChanged(false))
+    boolean iSentTheSelection = (av == source
             || (source instanceof AlignViewport && ((AlignViewport) source)
-                    .getSequenceSetId().equals(av.getSequenceSetId())))
+            .getSequenceSetId().equals(av.getSequenceSetId())));
+    if (iSentTheSelection || !av.followSelection)
     {
       return;
     }
+
+    /*
+     * Ignore the selection if there is one of our own pending.
+     */
+    if (av.isSelectionGroupChanged(false) || av.isColSelChanged(false))
+    {
+      return;
+    }
+
+    /*
+     * Check for selection in a view of which this one is a 'slave'.
+     */
+    if (selectionAsSlave(seqsel, colsel, source))
+    {
+      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.isSelectionGroupChanged(false))
+    boolean repaint = false;
+    boolean copycolsel = true;
+
+    SequenceGroup sgroup = null;
+    if (seqsel != null && seqsel.getSize() > 0)
     {
-      SequenceGroup sgroup = null;
-      if (seqsel != null && seqsel.getSize() > 0)
-      {
-        if (av.getAlignment() == null)
-        {
-          jalview.bin.Cache.log.warn("alignviewport av SeqSetId="
-                  + av.getSequenceSetId() + " ViewId=" + av.getViewId()
-                  + " 's alignment is NULL! returning immediatly.");
-          return;
-        }
-        sgroup = seqsel.intersect(av.getAlignment(),
-                (av.hasHiddenRows()) ? av.getHiddenRepSequences() : 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)
+      if (av.getAlignment() == null)
       {
-        av.setSelectionGroup(sgroup);
+        jalview.bin.Cache.log.warn("alignviewport av SeqSetId="
+                + av.getSequenceSetId() + " ViewId=" + av.getViewId()
+                + " 's alignment is NULL! returning immediately.");
+        return;
       }
-      else
+      sgroup = seqsel.intersect(av.getAlignment(),
+              (av.hasHiddenRows()) ? av.getHiddenRepSequences() : null);
+      if ((sgroup == null || sgroup.getSize() == 0)
+              || (colsel == null || colsel.size() == 0))
       {
-        av.setSelectionGroup(null);
+        // don't copy columns if the region didn't intersect.
+        copycolsel = false;
       }
-      av.isSelectionGroupChanged(true);
-      repaint = true;
     }
+    if (sgroup != null && sgroup.getSize() > 0)
+    {
+      av.setSelectionGroup(sgroup);
+    }
+    else
+    {
+      av.setSelectionGroup(null);
+    }
+    av.isSelectionGroupChanged(true);
+    repaint = true;
+
     if (copycolsel)
     {
       // the current selection is unset or from a previous message
@@ -1942,6 +1959,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       av.isColSelChanged(true);
       repaint = true;
     }
+
     if (copycolsel
             && av.hasHiddenColumns()
             && (av.getColumnSelection() == null || av.getColumnSelection()
@@ -1949,11 +1967,73 @@ public class SeqPanel extends JPanel implements MouseListener,
     {
       System.err.println("Bad things");
     }
-    if (repaint)
+    if (repaint) // always true!
     {
       // probably finessing with multiple redraws here
       PaintRefresher.Refresh(this, av.getSequenceSetId());
       // ap.paintAlignment(false);
     }
   }
+
+  /**
+   * If this panel is a 'slave' of the selection source, tries to map the source
+   * selection to a local one, and returns true. Else returns false.
+   * 
+   * @param seqsel
+   * @param colsel
+   * @param source
+   */
+  protected boolean selectionAsSlave(SequenceGroup seqsel,
+          ColumnSelection colsel, SelectionSource source)
+  {
+    if (!(source instanceof AlignViewportI)) {
+      return false;
+    }
+    final AlignViewportI sourceAv = (AlignViewportI) source;
+    if (sourceAv.getSlave() != av)
+    {
+      return false;
+    }
+
+    /*
+     * Map sequence selection. Note the SequenceGroup holds aligned sequences,
+     * the mappings hold dataset sequences.
+     */
+    AlignedCodonFrame[] codonFrames = sourceAv.getAlignment()
+            .getCodonFrames();
+    SequenceGroup sg = new SequenceGroup();
+    for (SequenceI selected : seqsel.getSequences())
+    {
+      for (AlignedCodonFrame acf : codonFrames)
+      {
+        SequenceI dnaSeq = acf.getDnaForAaSeq(selected);
+        if (dnaSeq != null)
+        {
+          for (SequenceI seq : av.getAlignment().getSequences())
+          {
+            if (seq.getDatasetSequence() == dnaSeq)
+            {
+              sg.addSequence(seq, false);
+              break;
+            }
+          }
+        }
+      }
+    }
+    av.setSelectionGroup(sg);
+    av.isSelectionGroupChanged(true);
+    // ((AlignmentViewport) slave).firePropertyChange("alignment", null, slave
+    // .getAlignment()
+    // .getSequences());
+
+    /*
+     * Map column selection
+     */
+    // TODO
+
+    AlignmentPanel ap = av.getAlignPanel();
+    PaintRefresher.Refresh(this, av.getSequenceSetId());
+
+    return true;
+  }
 }