JAL-518 refactored groovy script into main codebase as an Edit Command and alignment... features/JAL-518_justify_seqs_in_region
authorJim Procter <j.procter@dundee.ac.uk>
Fri, 16 Sep 2022 16:52:25 +0000 (17:52 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Fri, 16 Sep 2022 16:52:25 +0000 (17:52 +0100)
examples/groovy/justifyRegionQuick.groovy [deleted file]
help/help/html/menus/alwedit.html
resources/lang/Messages.properties
src/jalview/api/AlignViewControllerI.java
src/jalview/api/AlignViewportI.java
src/jalview/commands/JustifyLeftOrRightCommand.java [new file with mode: 0644]
src/jalview/controller/AlignViewController.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/PopupMenu.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/viewmodel/AlignmentViewport.java

diff --git a/examples/groovy/justifyRegionQuick.groovy b/examples/groovy/justifyRegionQuick.groovy
deleted file mode 100644 (file)
index 7316b5e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-
-// Prototype Right/Left Justify Script
-boolean left=true;
-
-import jalview.datamodel.*;
-
-def msaf = jalview.bin.Jalview.getCurrentAlignFrame();
-if (msaf==null)
-{
-    return;
-}
-
-def al = msaf.getViewport().getAlignment();
-al.padGaps();
-def reg = msaf.getViewport().getSelectionGroup();
-int from,to;
-SequenceI[] seqs;
-
-from=0;
-to=al.getWidth()-1;
-seqs = al.getSequences();
-if (reg!=null) {
-  seqs = reg.getSequences();
-  from=reg.getStartRes();
-  to=reg.getEndRes();
-}
-
-if ((to-from)<1) {
-  return;
-}
-
-jalview.commands.EditCommand[] edits=new jalview.commands.EditCommand[seqs.length];
-int s=0;
-for (SequenceI seq:seqs) {
-  ContiguousI cont = seq.findPositions(from+1,to+1);
-  if (cont==null) { continue; }
-  int dsstart=seq.getDatasetSequence().getStart();
-  char[] sqchar=seq.getDatasetSequence().getSequence(-dsstart+cont.getBegin(),-dsstart+cont.getEnd()+1);
-  println sqchar;
-  char[] alseq = new char[to-from+1];
-  int sqstart = left ? 0 : alseq.length-sqchar.length;
-  int gaps = alseq.length-sqchar.length;
-  int gapstart=left ? sqchar.length : 0;
-  char gc = al.getGapCharacter();
-  for (int gp=0;gp<gaps;gp++) {
-    alseq[gapstart+gp]=gc;
-  }
-
-  for (int sqp=0;sqp<sqchar.length;sqp++) {
-    alseq[sqp+sqstart]=sqchar[sqp];
-  }
-  SequenceI[] sqa=new SequenceI[1];
-  sqa[0]=seq;
-  // cant do this because the edit command isn't visible.
-  //  edits[s++]=new jalview.commands.EditCommand.Edit(jalview.commands.EditCommand.Action.REPLACE,sqa,(from).intValue(),(int)alseq.length,al, new String(alseq));
-  edits[s++]=new jalview.commands.EditCommand("justify",jalview.commands.EditCommand.Action.REPLACE, new String(alseq),sqa,(from).intValue(),(to).intValue()+1,al);
-  println alseq;
-}
-jalview.commands.EditCommand finalEdit=new jalview.commands.EditCommand("Justify "+(left ? "Left" : "Right"));
-for (jalview.commands.EditCommand edit:edits) {
-  if (edit!=null) {finalEdit.addEdit(edit.getEdits().get(0)); }
-}
-msaf.addHistoryItem(finalEdit);
-msaf.getViewport().firePropertyChange("alignment",null,seqs);
index eb8e839..97d6b28 100755 (executable)
         one of the sequences (the shorter) is discarded. Press the
         &quot;Apply&quot; button to remove redundant sequences. The
         &quot;Undo&quot; button will undo the last redundancy deletion.</em></li>
+    <li><strong>Left Justify</strong> and <strong>Right
+        Justify<br>
+    </strong> <em>Moves all gaps to either right or left of the sequences in
+        the alignment or the currently selected region.</em></li>
     <li><strong>Pad Gaps<br>
     </strong><em>When selected, the alignment will be kept at minimal width
         (so there are no empty columns before or after the first or last
index 3843ddb..dbe3a77 100644 (file)
@@ -53,8 +53,10 @@ action.remove_left = Remove left
 action.remove_right = Remove right
 action.remove_empty_columns = Remove Empty Columns
 action.remove_all_gaps = Remove All Gaps
-action.left_justify_alignment = Left Justify Alignment
-action.right_justify_alignment = Right Justify Alignment
+tooltip.left_justify = Left justify whole alignment or selected region
+tooltip.right_justify = Right justify whole alignment or selected region
+action.left_justify = Left Justify
+action.right_justify = Right Justify
 action.boxes = Boxes
 action.text = Text
 action.by_pairwise_id = By Pairwise Identity
index 58a58e9..4d92d8e 100644 (file)
  */
 package jalview.api;
 
-import jalview.io.DataSourceType;
-
 import java.util.List;
 
+import jalview.io.DataSourceType;
+
 /**
  * prototype abstract controller for a Jalview alignment view
  * 
@@ -111,4 +111,6 @@ public interface AlignViewControllerI
   boolean markHighlightedColumns(boolean invert, boolean extendCurrent,
           boolean toggle);
 
+  boolean justify_Region(boolean left);
+
 }
index d15c5fb..43c6a13 100644 (file)
  */
 package jalview.api;
 
+import java.awt.Color;
+import java.awt.Font;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
 import jalview.analysis.Conservation;
 import jalview.analysis.TreeModel;
 import jalview.datamodel.AlignmentAnnotation;
@@ -36,13 +43,6 @@ import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
 import jalview.viewmodel.ViewportRanges;
 
-import java.awt.Color;
-import java.awt.Font;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 /**
  * @author jimp
  * 
@@ -552,4 +552,10 @@ public interface AlignViewportI extends ViewStyleI
    * @return
    */
   Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly);
+
+  /**
+   * notify all concerned that the alignment data has changed and derived data
+   * needs to be recalculated
+   */
+  public void notifyAlignmentChanged();
 }
diff --git a/src/jalview/commands/JustifyLeftOrRightCommand.java b/src/jalview/commands/JustifyLeftOrRightCommand.java
new file mode 100644 (file)
index 0000000..f83f754
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.commands;
+
+import java.util.List;
+
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ContiguousI;
+import jalview.datamodel.SequenceI;
+
+public class JustifyLeftOrRightCommand extends EditCommand
+{
+  /**
+   * Constructs and performs a trim alignment command
+   * 
+   * @param description
+   *          (to show in Undo/Redo menu)
+   * @param justifyLeft
+   *          if true left justify, otherwise right
+   * @param seqs
+   *          the sequences to justify
+   * @param start
+   *          - leftmost column (base 0) to justify
+   * 
+   * @param end
+   *          - rightmost column (base 0) to justify
+   * 
+   * @param al
+   */
+  public JustifyLeftOrRightCommand(String description, boolean left,
+          List<SequenceI> seqs, int from, int to, AlignmentI al)
+  {
+    this.description = description;
+
+    for (SequenceI seq : seqs)
+    {
+      ContiguousI cont = seq.findPositions(from + 1, to + 1);
+      if (cont == null)
+      {
+        continue;
+      }
+      int dsstart = seq.getDatasetSequence().getStart();
+      char[] sqchar = seq.getDatasetSequence().getSequence(
+              -dsstart + cont.getBegin(), -dsstart + cont.getEnd() + 1);
+      // debug
+      // println sqchar;
+      char[] alseq = new char[to - from + 1];
+      int sqstart = left ? 0 : alseq.length - sqchar.length;
+      int gaps = alseq.length - sqchar.length;
+      int gapstart = left ? sqchar.length : 0;
+      char gc = al.getGapCharacter();
+      for (int gp = 0; gp < gaps; gp++)
+      {
+        alseq[gapstart + gp] = gc;
+      }
+
+      for (int sqp = 0; sqp < sqchar.length; sqp++)
+      {
+        alseq[sqp + sqstart] = sqchar[sqp];
+      }
+      SequenceI[] sqa = new SequenceI[1];
+      sqa[0] = seq;
+
+      addEdit(new jalview.commands.EditCommand.Edit(
+              jalview.commands.EditCommand.Action.REPLACE, sqa, from,
+              to + 1, al, new String(alseq)));
+      // addEdit(new jalview.commands.EditCommand("justify",
+      // jalview.commands.EditCommand.Action.REPLACE,
+      // new String(alseq), sqa, from, to + 1, al).getEdit(0));
+    }
+
+    performEdit(0, null);
+  }
+}
index 2fb9cdd..756fe5a 100644 (file)
  */
 package jalview.controller;
 
+import java.awt.Color;
+import java.util.BitSet;
+import java.util.List;
+
 import jalview.analysis.AlignmentSorter;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
@@ -38,10 +42,6 @@ import jalview.io.FeaturesFile;
 import jalview.schemes.ColourSchemeI;
 import jalview.util.MessageManager;
 
-import java.awt.Color;
-import java.util.BitSet;
-import java.util.List;
-
 public class AlignViewController implements AlignViewControllerI
 {
   AlignViewportI viewport = null;
@@ -471,4 +471,35 @@ public class AlignViewController implements AlignViewControllerI
     return false;
   }
 
+  @Override
+  public boolean justify_Region(boolean left)
+  {
+    AlignmentI al = viewport.getAlignment();
+    SequenceGroup reg = viewport.getSelectionGroup();
+    int from, to;
+    List<SequenceI> seqs;
+
+    from = 0;
+    to = al.getWidth() - 1;
+    seqs = al.getSequences();
+    if (reg != null)
+    {
+      seqs = reg.getSequences();
+      from = reg.getStartRes();
+      to = reg.getEndRes();
+    }
+
+    if ((to - from) < 1)
+    {
+      return false;
+    }
+
+    al.padGaps();
+    jalview.commands.JustifyLeftOrRightCommand finalEdit = new jalview.commands.JustifyLeftOrRightCommand(
+            "Justify " + (left ? "Left" : "Right"), left, seqs, from, to,
+            al);
+    avcg.addHistoryItem(finalEdit);
+    viewport.notifyAlignmentChanged();
+    return true;
+  }
 }
index e24cbea..d8a5fbb 100644 (file)
@@ -20,8 +20,6 @@
  */
 package jalview.gui;
 
-import java.util.Locale;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
@@ -59,6 +57,7 @@ import java.util.Deque;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Locale;
 import java.util.Vector;
 
 import javax.swing.ButtonGroup;
@@ -5431,9 +5430,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
   {
-    AlignmentI al = viewport.getAlignment();
-    al.justify(false);
-    viewport.firePropertyChange("alignment", null, al);
+    avc.justify_Region(true);
   }
 
   /**
@@ -5442,9 +5439,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
   {
-    AlignmentI al = viewport.getAlignment();
-    al.justify(true);
-    viewport.firePropertyChange("alignment", null, al);
+    avc.justify_Region(false);
   }
 
   @Override
index 6903034..7670ed3 100644 (file)
@@ -20,8 +20,6 @@
  */
 package jalview.gui;
 
-import java.util.Locale;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
@@ -34,6 +32,7 @@ import java.util.Collections;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.SortedMap;
@@ -1386,6 +1385,29 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         cut_actionPerformed();
       }
     });
+    JMenuItem justifyLeftMenuItem = new JMenuItem(
+            MessageManager.getString("action.left_justify"));
+    justifyLeftMenuItem.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        ap.alignFrame.avc.justify_Region(true);
+      }
+    });
+    JMenuItem justifyRightMenuItem = new JMenuItem(
+            MessageManager.getString("action.right_justify"));
+    justifyRightMenuItem.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        ap.alignFrame.avc.justify_Region(false);
+      }
+    });
+
     upperCase.setText(MessageManager.getString("label.to_upper_case"));
     upperCase.addActionListener(new ActionListener()
     {
@@ -1534,6 +1556,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
     editMenu.add(copy);
     editMenu.add(cut);
+    editMenu.add(justifyLeftMenuItem);
+    editMenu.add(justifyRightMenuItem);
     editMenu.add(editSequence);
     editMenu.add(upperCase);
     editMenu.add(lowerCase);
index 71b6b9e..4627197 100755 (executable)
  */
 package jalview.jbgui;
 
-import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
-import jalview.analysis.GeneticCodeI;
-import jalview.analysis.GeneticCodes;
-import jalview.api.SplitContainerI;
-import jalview.bin.Cache;
-import jalview.gui.JvSwingUtils;
-import jalview.gui.Preferences;
-import jalview.io.FileFormats;
-import jalview.schemes.ResidueColourScheme;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.GridLayout;
@@ -61,6 +49,18 @@ import javax.swing.event.ChangeEvent;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
 
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.analysis.GeneticCodeI;
+import jalview.analysis.GeneticCodes;
+import jalview.api.SplitContainerI;
+import jalview.bin.Cache;
+import jalview.gui.JvSwingUtils;
+import jalview.gui.Preferences;
+import jalview.io.FileFormats;
+import jalview.schemes.ResidueColourScheme;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+
 @SuppressWarnings("serial")
 public class GAlignFrame extends JInternalFrame
 {
@@ -437,7 +437,9 @@ public class GAlignFrame extends JInternalFrame
     addMenuActionAndAccelerator(keyStroke, removeAllGapsMenuItem, al);
 
     JMenuItem justifyLeftMenuItem = new JMenuItem(
-            MessageManager.getString("action.left_justify_alignment"));
+            MessageManager.getString("action.left_justify"));
+    justifyLeftMenuItem.setToolTipText(
+            MessageManager.getString("tooltip.left_justify"));
     justifyLeftMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -447,7 +449,10 @@ public class GAlignFrame extends JInternalFrame
       }
     });
     JMenuItem justifyRightMenuItem = new JMenuItem(
-            MessageManager.getString("action.right_justify_alignment"));
+            MessageManager.getString("action.right_justify"));
+    justifyRightMenuItem.setToolTipText(
+            MessageManager.getString("action.left_justify"));
+
     justifyRightMenuItem.addActionListener(new ActionListener()
     {
       @Override
@@ -1815,11 +1820,11 @@ public class GAlignFrame extends JInternalFrame
     editMenu.add(removeAllGapsMenuItem);
     editMenu.add(removeRedundancyMenuItem);
     editMenu.addSeparator();
-    // dont add these yet in the CVS build - they cannot be undone!
-    // Excluded from Jalview 2.5 release - undo needs to be implemented.
-    // editMenu.add(justifyLeftMenuItem);
-    // editMenu.add(justifyRightMenuItem);
-    // editMenu.addSeparator();
+
+    editMenu.add(justifyLeftMenuItem);
+    editMenu.add(justifyRightMenuItem);
+
+    editMenu.addSeparator();
     editMenu.add(padGapsMenuitem);
 
     showMenu.add(showAllColumns);
index 08af2ec..c0dd7d7 100644 (file)
  */
 package jalview.viewmodel;
 
+import java.awt.Color;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.Conservation;
 import jalview.analysis.TreeModel;
@@ -61,18 +73,6 @@ import jalview.workers.ComplementConsensusThread;
 import jalview.workers.ConsensusThread;
 import jalview.workers.StrucConsensusThread;
 
-import java.awt.Color;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 /**
  * base class holding visualization and analysis attributes and common logic for
  * an active alignment view displayed in the GUI
@@ -1366,6 +1366,12 @@ public abstract class AlignmentViewport
     changeSupport.firePropertyChange(prop, oldvalue, newvalue);
   }
 
+  @Override
+  public void notifyAlignmentChanged()
+  {
+    firePropertyChange("alignment", null, alignment);
+  }
+
   // common hide/show column stuff
 
   public void hideSelectedColumns()