Merge branch 'develop' into features/JAL-518_justify_seqs_in_region
authorJim Procter <jprocter@dundee.ac.uk>
Mon, 13 May 2024 12:44:27 +0000 (13:44 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Mon, 13 May 2024 12:44:27 +0000 (13:44 +0100)
 Conflicts:
src/jalview/api/AlignViewControllerI.java
src/jalview/api/AlignViewportI.java
src/jalview/controller/AlignViewController.java

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

index 7384cda..a5bc366 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 c3c8589..bf88520 100644 (file)
@@ -66,8 +66,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 3e689d1..25e4873 100644 (file)
@@ -119,4 +119,10 @@ public interface AlignViewControllerI
    */
   boolean copyHighlightedRegionsToClipboard();
 
+  /**
+   * Justify alignment or currently selected region left or right
+   * @param left - true - means justify left
+   * @return
+   */
+  boolean justify_Region(boolean left);
 }
index 0cfd03d..e7afee0 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;
@@ -38,13 +45,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
  * 
@@ -565,6 +565,16 @@ 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();
 
+  /**
+   * retrieve a matrix associated with the view's alignment's annotation 
+   * @param alignmentAnnotation
+   * @return contact matrix or NULL
+   */
   ContactMatrixI getContactMatrix(AlignmentAnnotation alignmentAnnotation);
 }
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 4434331..bccacfa 100644 (file)
@@ -500,4 +500,36 @@ public class AlignViewController implements AlignViewControllerI
     // Technically we should return false, since view has not changed
     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 c49626b..9aa8733 100644 (file)
@@ -5638,9 +5638,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);
   }
 
   /**
@@ -5649,9 +5647,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 8875288..83f424b 100644 (file)
@@ -1386,6 +1386,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 +1557,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 7daeb37..9b9a44a 100755 (executable)
@@ -441,7 +441,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
@@ -451,7 +453,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
@@ -1840,11 +1845,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 3e1bc63..de30b28 100644 (file)
@@ -1377,6 +1377,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()