From 1b1f995b3eb83dc3496510bfc2278f1f72fcfd8a Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Fri, 16 Sep 2022 17:52:25 +0100 Subject: [PATCH] JAL-518 refactored groovy script into main codebase as an Edit Command and alignment view controller method. Left and Right Justify operations now in Edit menu on alignment window and selection popup. --- examples/groovy/justifyRegionQuick.groovy | 84 ------------------ help/help/html/menus/alwedit.html | 4 + resources/lang/Messages.properties | 6 +- src/jalview/api/AlignViewControllerI.java | 6 +- src/jalview/api/AlignViewportI.java | 20 +++-- .../commands/JustifyLeftOrRightCommand.java | 92 ++++++++++++++++++++ src/jalview/controller/AlignViewController.java | 39 ++++++++- src/jalview/gui/AlignFrame.java | 11 +-- src/jalview/gui/PopupMenu.java | 28 +++++- src/jalview/jbgui/GAlignFrame.java | 43 +++++---- src/jalview/viewmodel/AlignmentViewport.java | 30 ++++--- 11 files changed, 223 insertions(+), 140 deletions(-) delete mode 100644 examples/groovy/justifyRegionQuick.groovy create mode 100644 src/jalview/commands/JustifyLeftOrRightCommand.java diff --git a/examples/groovy/justifyRegionQuick.groovy b/examples/groovy/justifyRegionQuick.groovy deleted file mode 100644 index 7316b5e..0000000 --- a/examples/groovy/justifyRegionQuick.groovy +++ /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 . - * 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 +
  • Left Justify and Right + Justify
    +
    Moves all gaps to either right or left of the sequences in + the alignment or the currently selected region.
  • Pad Gaps
    When selected, the alignment will be kept at minimal width (so there are no empty columns before or after the first or last diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 3843ddb..dbe3a77 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -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 diff --git a/src/jalview/api/AlignViewControllerI.java b/src/jalview/api/AlignViewControllerI.java index 58a58e9..4d92d8e 100644 --- a/src/jalview/api/AlignViewControllerI.java +++ b/src/jalview/api/AlignViewControllerI.java @@ -20,10 +20,10 @@ */ 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); + } diff --git a/src/jalview/api/AlignViewportI.java b/src/jalview/api/AlignViewportI.java index d15c5fb..43c6a13 100644 --- a/src/jalview/api/AlignViewportI.java +++ b/src/jalview/api/AlignViewportI.java @@ -20,6 +20,13 @@ */ 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 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 index 0000000..f83f754 --- /dev/null +++ b/src/jalview/commands/JustifyLeftOrRightCommand.java @@ -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 . + * 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 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); + } +} diff --git a/src/jalview/controller/AlignViewController.java b/src/jalview/controller/AlignViewController.java index 2fb9cdd..756fe5a 100644 --- a/src/jalview/controller/AlignViewController.java +++ b/src/jalview/controller/AlignViewController.java @@ -20,6 +20,10 @@ */ 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 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; + } } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index e24cbea..d8a5fbb 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -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 diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 6903034..7670ed3 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -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); diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index 71b6b9e..4627197 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -20,18 +20,6 @@ */ 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); diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 08af2ec..c0dd7d7 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -20,6 +20,18 @@ */ 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() -- 1.7.10.2