From f16c439627f599f52a372704e72ae5464134fa2b Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Thu, 20 Jul 2023 00:34:55 +0100 Subject: [PATCH] JAL-244 Changes to Annotation labels width now adjusts the overall idWidth if larger than the alignment idWidth. Will not shrink the width if a manual adjustment has been made. Can be overridden by preference. Also fixed buglet of scroll bar not adjusting with manual changes to idWidth. --- src/jalview/gui/AlignViewport.java | 1 - src/jalview/gui/AlignmentPanel.java | 22 +++- src/jalview/gui/AnnotationLabels.java | 231 ++++++++++++++++++++++++--------- src/jalview/gui/IdwidthAdjuster.java | 25 +++- 4 files changed, 205 insertions(+), 74 deletions(-) diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index 5613f16..ef9e575 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -45,7 +45,6 @@ import jalview.bin.Console; import jalview.commands.CommandI; import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.Alignment; -import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.ContactMatrixI; diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 3dfb510..db193f1 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -269,10 +269,7 @@ public class AlignmentPanel extends GAlignmentPanel implements Dimension r = null; if (av.getIdWidth() < 0) { - int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300); - int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3); - int maxwidth = Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth); - r = calculateIdWidth(maxwidth); + r = calculateDefaultAlignmentIdWidth(); av.setIdWidth(r.width); } else @@ -294,6 +291,14 @@ public class AlignmentPanel extends GAlignmentPanel implements return r; } + public Dimension calculateDefaultAlignmentIdWidth() + { + int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300); + int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3); + int maxwidth = Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth); + return calculateIdWidth(-1); + } + /** * Calculate the width of the alignment labels based on the displayed names * and any bounds on label width set in preferences. @@ -1175,7 +1180,8 @@ public class AlignmentPanel extends GAlignmentPanel implements return (w > 0 ? w : calculateIdWidth().width); } - void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer) throws ImageOutputException + void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer) + throws ImageOutputException { makeAlignmentImage(type, file, renderer, BitmapImageSizing.nullBitmapImageSizing()); @@ -1266,7 +1272,8 @@ public class AlignmentPanel extends GAlignmentPanel implements } - public void makePNGImageMap(File imgMapFile, String imageName) throws ImageOutputException + public void makePNGImageMap(File imgMapFile, String imageName) + throws ImageOutputException { // /////ONLY WORKS WITH NON WRAPPED ALIGNMENTS // //////////////////////////////////////////// @@ -1391,7 +1398,8 @@ public class AlignmentPanel extends GAlignmentPanel implements } catch (Exception ex) { - throw new ImageOutputException("couldn't write ImageMap due to unexpected error",ex); + throw new ImageOutputException( + "couldn't write ImageMap due to unexpected error", ex); } } // /////////END OF IMAGE MAP diff --git a/src/jalview/gui/AnnotationLabels.java b/src/jalview/gui/AnnotationLabels.java index 6b82a37..d459217 100755 --- a/src/jalview/gui/AnnotationLabels.java +++ b/src/jalview/gui/AnnotationLabels.java @@ -50,6 +50,8 @@ import javax.swing.ToolTipManager; import jalview.analysis.AlignSeq; import jalview.analysis.AlignmentUtils; +import jalview.bin.Cache; +import jalview.bin.Jalview; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; @@ -113,6 +115,8 @@ public class AnnotationLabels extends JPanel private static final String COPYCONS_SEQ = MessageManager .getString("label.copy_consensus_sequence"); + private static final String ADJUST_ANNOTATION_LABELS_WIDTH_PREF = "ADJUST_ANNOTATION_LABELS_WIDTH"; + private final boolean debugRedraw = false; private AlignmentPanel ap; @@ -138,7 +142,6 @@ public class AnnotationLabels extends JPanel */ public AnnotationLabels(AlignmentPanel ap) { - this.ap = ap; av = ap.av; ToolTipManager.sharedInstance().registerComponent(this); @@ -418,65 +421,74 @@ public class AnnotationLabels extends JPanel pop.add(consclipbrd); } - addColourOrFilterByOptions(ap,aa[selectedRow],pop); - + addColourOrFilterByOptions(ap, aa[selectedRow], pop); + if (aa[selectedRow].graph == AlignmentAnnotation.CONTACT_MAP) { - addContactMatrixOptions(ap,aa[selectedRow],pop); - // Set/adjust threshold for grouping ? - // colour alignment by this [type] - // select/hide columns by this row - - } + addContactMatrixOptions(ap, aa[selectedRow], pop); + // Set/adjust threshold for grouping ? + // colour alignment by this [type] + // select/hide columns by this row + } - + } + pop.show(this, evt.getX(), evt.getY()); } static void addColourOrFilterByOptions(final AlignmentPanel ap, - final AlignmentAnnotation alignmentAnnotation, final JPopupMenu pop) + final AlignmentAnnotation alignmentAnnotation, + final JPopupMenu pop) { JMenuItem item; - item = new JMenuItem(MessageManager.getString("label.colour_by_annotation")); + item = new JMenuItem( + MessageManager.getString("label.colour_by_annotation")); item.addActionListener(new ActionListener() { - + @Override public void actionPerformed(ActionEvent e) { - AnnotationColourChooser.displayFor(ap.av, ap,alignmentAnnotation,false); + AnnotationColourChooser.displayFor(ap.av, ap, alignmentAnnotation, + false); }; }); pop.add(item); - if (alignmentAnnotation.sequenceRef!=null) + if (alignmentAnnotation.sequenceRef != null) { - item = new JMenuItem(MessageManager.getString("label.colour_by_annotation")+" ("+MessageManager.getString("label.per_seq")+")"); + item = new JMenuItem( + MessageManager.getString("label.colour_by_annotation") + " (" + + MessageManager.getString("label.per_seq") + ")"); item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - AnnotationColourChooser.displayFor(ap.av, ap,alignmentAnnotation,true); + AnnotationColourChooser.displayFor(ap.av, ap, alignmentAnnotation, + true); }; }); pop.add(item); } - item = new JMenuItem(MessageManager.getString("action.select_by_annotation")); + item = new JMenuItem( + MessageManager.getString("action.select_by_annotation")); item.addActionListener(new ActionListener() { - + @Override public void actionPerformed(ActionEvent e) { - AnnotationColumnChooser.displayFor(ap.av,ap,alignmentAnnotation); + AnnotationColumnChooser.displayFor(ap.av, ap, alignmentAnnotation); }; }); pop.add(item); } + static void addContactMatrixOptions(final AlignmentPanel ap, - final AlignmentAnnotation alignmentAnnotation, final JPopupMenu pop) + final AlignmentAnnotation alignmentAnnotation, + final JPopupMenu pop) { - + final ContactMatrixI cm = ap.av.getContactMatrix(alignmentAnnotation); JMenuItem item; if (cm != null) @@ -485,10 +497,13 @@ public class AnnotationLabels extends JPanel if (cm.hasGroups()) { - JCheckBoxMenuItem chitem = new JCheckBoxMenuItem(MessageManager.getString("action.show_groups_on_matrix")); - chitem.setToolTipText(MessageManager.getString("action.show_groups_on_matrix_tooltip")); - boolean showGroups = alignmentAnnotation.isShowGroupsForContactMatrix(); - final AlignmentAnnotation sel_row=alignmentAnnotation; + JCheckBoxMenuItem chitem = new JCheckBoxMenuItem( + MessageManager.getString("action.show_groups_on_matrix")); + chitem.setToolTipText(MessageManager + .getString("action.show_groups_on_matrix_tooltip")); + boolean showGroups = alignmentAnnotation + .isShowGroupsForContactMatrix(); + final AlignmentAnnotation sel_row = alignmentAnnotation; chitem.setState(showGroups); chitem.addActionListener(new ActionListener() { @@ -498,15 +513,17 @@ public class AnnotationLabels extends JPanel { sel_row.setShowGroupsForContactMatrix(chitem.getState()); ap.getAnnotationPanel() - .paint(ap.getAnnotationPanel().getGraphics()); + .paint(ap.getAnnotationPanel().getGraphics()); } }); pop.add(chitem); } if (cm.hasTree()) { - item = new JMenuItem(MessageManager.getString("action.show_tree_for_matrix")); - item.setToolTipText(MessageManager.getString("action.show_tree_for_matrix_tooltip")); + item = new JMenuItem( + MessageManager.getString("action.show_tree_for_matrix")); + item.setToolTipText(MessageManager + .getString("action.show_tree_for_matrix_tooltip")); item.addActionListener(new ActionListener() { @@ -522,8 +539,10 @@ public class AnnotationLabels extends JPanel } else { - item = new JMenuItem(MessageManager.getString("action.cluster_matrix")); - item.setToolTipText(MessageManager.getString("action.cluster_matrix_tooltip")); + item = new JMenuItem( + MessageManager.getString("action.cluster_matrix")); + item.setToolTipText( + MessageManager.getString("action.cluster_matrix_tooltip")); item.addActionListener(new ActionListener() { @Override @@ -535,7 +554,11 @@ public class AnnotationLabels extends JPanel public void run() { final long progBar; - ap.alignFrame.setProgressBar(MessageManager.formatMessage("action.clustering_matrix_for",cm.getAnnotDescr(),5f), progBar = System.currentTimeMillis()); + ap.alignFrame.setProgressBar( + MessageManager.formatMessage( + "action.clustering_matrix_for", + cm.getAnnotDescr(), 5f), + progBar = System.currentTimeMillis()); cm.setGroupSet(GroupSet.makeGroups(cm, 5f, true)); ap.alignFrame.showContactMapTree(alignmentAnnotation, cm); ap.alignFrame.setProgressBar(null, progBar); @@ -1166,8 +1189,58 @@ public class AnnotationLabels extends JPanel * @param width * Width for scaling labels */ - public void drawComponent(Graphics g, boolean clip, int width) + public void drawComponent(Graphics g, boolean clip, int givenWidth) + { + int width = givenWidth; + IdwidthAdjuster iwa = ap.idwidthAdjuster; + if ((Cache.getDefault(ADJUST_ANNOTATION_LABELS_WIDTH_PREF, true) + || Jalview.isHeadlessMode()) && !iwa.manuallyAdjusted()) + { + Graphics2D g2d = (Graphics2D) g; + Graphics dummy = g2d.create(); + int annotationIdWidth = drawLabels(dummy, clip, width, false); + Dimension d = ap.calculateDefaultAlignmentIdWidth(); + int alignmentIdWidth = d.width; + if (!iwa.manuallyAdjusted()) + { + // If no manual adjustment to ID column with has been made then adjust + // width match widest of alignment or annotation id widths + width = Math.max(alignmentIdWidth, annotationIdWidth); + } + else if (annotationIdWidth > givenWidth + && annotationIdWidth > alignmentIdWidth) + { + // otherwise if the annotation id width has become larger than the + // current id width, increase + width = annotationIdWidth; + } + // set the width if it's changed + if (width != ap.av.getIdWidth()) + { + iwa.setWidth(width); + ap.validateAnnotationDimensions(false); + } + } + drawLabels(g, clip, width, true); + } + + /** + * Render the full set of annotation Labels for the alignment at the given + * cursor. If actuallyDraw is false then no actual drawing will occur, but the + * widest label width will be returned. + * + * @param g + * Graphics2D instance (needed for font scaling) + * @param clip + * - true indicates that only current visible area needs to be + * rendered + * @param width + * Width for scaling labels + */ + public int drawLabels(Graphics g, boolean clip, int width, + boolean actuallyDraw) { + int actualWidth = 0; if (av.getFont().getSize() < 10) { g.setFont(font); @@ -1178,11 +1251,17 @@ public class AnnotationLabels extends JPanel } FontMetrics fm = g.getFontMetrics(g.getFont()); - g.setColor(Color.white); - g.fillRect(0, 0, getWidth(), getHeight()); + if (actuallyDraw) + { + g.setColor(Color.white); + g.fillRect(0, 0, getWidth(), getHeight()); + } - g.translate(0, getScrollOffset()); - g.setColor(Color.black); + if (actuallyDraw) + { + g.translate(0, getScrollOffset()); + g.setColor(Color.black); + } SequenceI lastSeqRef = null; String lastLabel = null; AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation(); @@ -1255,8 +1334,10 @@ public class AnnotationLabels extends JPanel continue; } } - g.setColor(Color.black); - + if (actuallyDraw) + { + g.setColor(Color.black); + } offset = -aa[i].height / 2; if (aa[i].hasText) @@ -1301,7 +1382,9 @@ public class AnnotationLabels extends JPanel vertBar = true; } } - x = width - fm.stringWidth(label) - 3; + + int labelWidth = fm.stringWidth(label) + 3; + x = width - labelWidth; if (aa[i].graphGroup > -1) { @@ -1346,19 +1429,23 @@ public class AnnotationLabels extends JPanel { if (aa[gg].graphGroup == aa[i].graphGroup) { - x = width - fm.stringWidth(aa[gg].label) - 3; - g.drawString(aa[gg].label, x, y - graphExtras); - - if (aa[gg]._linecolour != null) + labelWidth = fm.stringWidth(aa[gg].label) + 3; + x = width - labelWidth; + if (actuallyDraw) { + g.drawString(aa[gg].label, x, y - graphExtras); - g.setColor(aa[gg]._linecolour); - g.drawLine(x, y - graphExtras + 3, - x + fm.stringWidth(aa[gg].label), - y - graphExtras + 3); - } + if (aa[gg]._linecolour != null) + { + + g.setColor(aa[gg]._linecolour); + g.drawLine(x, y - graphExtras + 3, + x + fm.stringWidth(aa[gg].label), + y - graphExtras + 3); + } - g.setColor(Color.black); + g.setColor(Color.black); + } graphExtras += fontHeight + 8; } } @@ -1369,35 +1456,51 @@ public class AnnotationLabels extends JPanel } else { - if (vertBar) + if (actuallyDraw) { - g.drawLine(width - 3, y + offset - fontHeight, width - 3, - (int) (y - 1.5 * aa[i].height - offset - fontHeight)); - // g.drawLine(20, y + offset, x - 20, y + offset); + if (vertBar) + { + g.drawLine(width - 3, y + offset - fontHeight, width - 3, + (int) (y - 1.5 * aa[i].height - offset - fontHeight)); + // g.drawLine(20, y + offset, x - 20, y + offset); + } + g.drawString(label, x, y + offset); } - g.drawString(label, x, y + offset); } lastSeqRef = aa[i].sequenceRef; + + if (labelWidth > actualWidth) + { + actualWidth = labelWidth; + } } } if (!resizePanel && dragEvent != null && aa != null) { - g.setColor(Color.lightGray); - g.drawString( - (aa[selectedRow].sequenceRef == null ? "" - : aa[selectedRow].sequenceRef.getName()) - + aa[selectedRow].label, - dragEvent.getX(), dragEvent.getY() - getScrollOffset()); + if (actuallyDraw) + { + g.setColor(Color.lightGray); + g.drawString( + (aa[selectedRow].sequenceRef == null ? "" + : aa[selectedRow].sequenceRef.getName()) + + aa[selectedRow].label, + dragEvent.getX(), dragEvent.getY() - getScrollOffset()); + } } if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1))) { - g.drawString(MessageManager.getString("label.right_click"), 2, 8); - g.drawString(MessageManager.getString("label.to_add_annotation"), 2, - 18); + if (actuallyDraw) + { + g.drawString(MessageManager.getString("label.right_click"), 2, 8); + g.drawString(MessageManager.getString("label.to_add_annotation"), 2, + 18); + } } + + return actualWidth; } public int getScrollOffset() diff --git a/src/jalview/gui/IdwidthAdjuster.java b/src/jalview/gui/IdwidthAdjuster.java index 4ba0699..eef5bfb 100755 --- a/src/jalview/gui/IdwidthAdjuster.java +++ b/src/jalview/gui/IdwidthAdjuster.java @@ -20,8 +20,6 @@ */ package jalview.gui; -import jalview.api.AlignViewportI; - import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics; @@ -31,6 +29,8 @@ import java.awt.event.MouseMotionListener; import javax.swing.JPanel; +import jalview.api.AlignViewportI; + /** * DOCUMENT ME! * @@ -46,6 +46,8 @@ public class IdwidthAdjuster extends JPanel AlignmentPanel ap; + private boolean manuallyAdjusted = false; + /** * Creates a new IdwidthAdjuster object. * @@ -146,7 +148,26 @@ public class IdwidthAdjuster extends JPanel return; } viewport.setIdWidth(newWidth); + ap.validateAnnotationDimensions(false); ap.paintAlignment(true, false); + + manuallyAdjusted = true; + } + + public void setWidth(int newWidth) + { + if (newWidth < MIN_ID_WIDTH) + { + return; + } + final AlignViewportI viewport = ap.getAlignViewport(); + viewport.setIdWidth(newWidth); + ap.paintAlignment(true, false); + } + + public boolean manuallyAdjusted() + { + return manuallyAdjusted; } @Override -- 1.7.10.2