From 08c587d9947f357382199bdb6900c263efc62739 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Fri, 12 Feb 2016 14:51:28 +0000 Subject: [PATCH] JAL-2008 avoid unnecessary repaints; signatures changed from String[] to List --- .../analysis/scoremodels/FeatureScoreModel.java | 9 +- src/jalview/api/AlignViewControllerI.java | 6 +- src/jalview/api/FeatureRenderer.java | 10 +-- src/jalview/appletgui/FeatureSettings.java | 9 +- src/jalview/controller/AlignViewController.java | 42 ++-------- src/jalview/gui/FeatureSettings.java | 77 ++++++++++++++---- .../renderer/seqfeatures/FeatureRenderer.java | 6 +- .../seqfeatures/FeatureRendererModel.java | 86 +++++++++++++++----- .../scoremodels/FeatureScoreModelTest.java | 2 +- 9 files changed, 155 insertions(+), 92 deletions(-) diff --git a/src/jalview/analysis/scoremodels/FeatureScoreModel.java b/src/jalview/analysis/scoremodels/FeatureScoreModel.java index 69538d5..1ca3342 100644 --- a/src/jalview/analysis/scoremodels/FeatureScoreModel.java +++ b/src/jalview/analysis/scoremodels/FeatureScoreModel.java @@ -28,7 +28,6 @@ import jalview.datamodel.SequenceI; import jalview.util.Comparison; import java.util.ArrayList; -import java.util.Arrays; import java.util.Hashtable; import java.util.List; @@ -48,12 +47,9 @@ public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI public float[][] findDistances(AlignmentView seqData) { int nofeats = 0; - List dft = Arrays.asList(fr.getDisplayedFeatureTypes()); + List dft = fr.getDisplayedFeatureTypes(); - if (dft != null) - { - nofeats = dft.size(); - } + nofeats = dft.size(); SequenceI[] sequenceString = seqData.getVisibleAlignment( Comparison.GapChars.charAt(0)).getSequencesArray(); @@ -151,6 +147,7 @@ public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI return true; } + @Override public String toString() { return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column"; diff --git a/src/jalview/api/AlignViewControllerI.java b/src/jalview/api/AlignViewControllerI.java index a2f2204..17a1563 100644 --- a/src/jalview/api/AlignViewControllerI.java +++ b/src/jalview/api/AlignViewControllerI.java @@ -20,6 +20,8 @@ */ package jalview.api; +import java.util.List; + /** * prototype abstract controller for a Jalview alignment view * @@ -71,7 +73,7 @@ public interface AlignViewControllerI * @param typ * list of feature names or null to use currently displayed features */ - void sortAlignmentByFeatureScore(String[] typ); + void sortAlignmentByFeatureScore(List typ); /** * sort the alignment or current selection by distribution of the given set of @@ -80,7 +82,7 @@ public interface AlignViewControllerI * @param typ * list of feature names or null to use currently displayed features */ - void sortAlignmentByFeatureDensity(String[] typ); + void sortAlignmentByFeatureDensity(List typ); /** * add a features file of some kind to the current view diff --git a/src/jalview/api/FeatureRenderer.java b/src/jalview/api/FeatureRenderer.java index 0d0adaa..5b15cad 100644 --- a/src/jalview/api/FeatureRenderer.java +++ b/src/jalview/api/FeatureRenderer.java @@ -149,19 +149,19 @@ public interface FeatureRenderer boolean isTransparencyAvailable(); /** - * get current displayed types + * get current displayed types, in ordering of rendering (on top last) * - * @return + * @return a (possibly empty) list of feature types */ - String[] getDisplayedFeatureTypes(); + List getDisplayedFeatureTypes(); /** * get current displayed groups * - * @return + * @return a (possibly empty) list of feature groups */ - String[] getDisplayedFeatureGroups(); + List getDisplayedFeatureGroups(); /** * display all features of these types diff --git a/src/jalview/appletgui/FeatureSettings.java b/src/jalview/appletgui/FeatureSettings.java index 23ca5ae..584a69a 100755 --- a/src/jalview/appletgui/FeatureSettings.java +++ b/src/jalview/appletgui/FeatureSettings.java @@ -57,6 +57,7 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; @@ -217,8 +218,8 @@ public class FeatureSettings extends Panel implements ItemListener, @Override public void actionPerformed(ActionEvent e) { - me.ap.alignFrame.avc - .sortAlignmentByFeatureScore(new String[] { type }); + me.ap.alignFrame.avc.sortAlignmentByFeatureScore(Arrays + .asList(new String[] { type })); } }); @@ -230,8 +231,8 @@ public class FeatureSettings extends Panel implements ItemListener, @Override public void actionPerformed(ActionEvent e) { - me.ap.alignFrame.avc - .sortAlignmentByFeatureDensity(new String[] { type }); + me.ap.alignFrame.avc.sortAlignmentByFeatureDensity(Arrays + .asList(new String[] { type })); } }); diff --git a/src/jalview/controller/AlignViewController.java b/src/jalview/controller/AlignViewController.java index be84bbf..ca2ae6d 100644 --- a/src/jalview/controller/AlignViewController.java +++ b/src/jalview/controller/AlignViewController.java @@ -37,7 +37,6 @@ import jalview.io.FeaturesFile; import jalview.util.MessageManager; import java.awt.Color; -import java.util.ArrayList; import java.util.BitSet; import java.util.List; @@ -317,46 +316,23 @@ public class AlignViewController implements AlignViewControllerI } @Override - public void sortAlignmentByFeatureDensity(String[] typ) + public void sortAlignmentByFeatureDensity(List typ) { sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY); } - protected void sortBy(String[] typ, String methodText, final String method) + protected void sortBy(List typ, String methodText, + final String method) { FeatureRenderer fr = alignPanel.getFeatureRenderer(); - if (typ == null) + if (typ == null && fr != null) { - typ = fr == null ? null : fr.getDisplayedFeatureTypes(); + typ = fr.getDisplayedFeatureTypes(); } - String gps[] = null; - gps = fr == null ? null : fr.getDisplayedFeatureGroups(); - if (typ != null) + List gps = null; + if (fr != null) { - List types = new ArrayList(); - for (String displayed : typ) - { - if (displayed != null) - { - types.add(displayed); - } - } - typ = new String[types.size()]; - types.toArray(typ); - } - if (gps != null) - { - List grps = new ArrayList(); - - for (int i = 0; i < gps.length; i++) - { - if (gps[i] != null) - { - grps.add(gps[i]); - } - } - gps = new String[grps.size()]; - grps.toArray(gps); + gps = fr.getDisplayedFeatureGroups(); } AlignmentI al = viewport.getAlignment(); @@ -381,7 +357,7 @@ public class AlignViewController implements AlignViewControllerI } @Override - public void sortAlignmentByFeatureScore(String[] typ) + public void sortAlignmentByFeatureScore(List typ) { sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE); } diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 6b58b51..6ca0769 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -54,6 +54,7 @@ import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.util.Arrays; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -164,6 +165,7 @@ public class FeatureSettings extends JPanel implements table.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent evt) { selectedRow = table.rowAtPoint(evt.getPoint()); @@ -198,24 +200,19 @@ public class FeatureSettings extends JPanel implements table.addMouseMotionListener(new MouseMotionAdapter() { + @Override public void mouseDragged(MouseEvent evt) { int newRow = table.rowAtPoint(evt.getPoint()); if (newRow != selectedRow && selectedRow != -1 && newRow != -1) { - Object[] temp = new Object[3]; - temp[0] = table.getValueAt(selectedRow, 0); - temp[1] = table.getValueAt(selectedRow, 1); - temp[2] = table.getValueAt(selectedRow, 2); - - table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0); - table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1); - table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2); - - table.setValueAt(temp[0], newRow, 0); - table.setValueAt(temp[1], newRow, 1); - table.setValueAt(temp[2], newRow, 2); - + Object[][] data = ((FeatureTableModel) table.getModel()) + .getData(); + Object[] temp = data[selectedRow]; + data[selectedRow] = data[newRow]; + data[newRow] = temp; + updateFeatureRenderer(data); + table.repaint(); selectedRow = newRow; } } @@ -237,6 +234,7 @@ public class FeatureSettings extends JPanel implements final FeatureSettings fs = this; fr.addPropertyChangeListener(change = new PropertyChangeListener() { + @Override public void propertyChange(PropertyChangeEvent evt) { if (!fs.resettingTable && !fs.handlingUpdate) @@ -267,6 +265,7 @@ public class FeatureSettings extends JPanel implements frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() { + @Override public void internalFrameClosed( javax.swing.event.InternalFrameEvent evt) { @@ -289,9 +288,11 @@ public class FeatureSettings extends JPanel implements scr.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - me.af.avc.sortAlignmentByFeatureScore(new String[] { type }); + me.af.avc.sortAlignmentByFeatureScore(Arrays + .asList(new String[] { type })); } }); @@ -300,9 +301,11 @@ public class FeatureSettings extends JPanel implements dens.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - me.af.avc.sortAlignmentByFeatureDensity(new String[] { type }); + me.af.avc.sortAlignmentByFeatureDensity(Arrays + .asList(new String[] { type })); } }); @@ -337,6 +340,7 @@ public class FeatureSettings extends JPanel implements { JColorChooser colorChooser; + @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == mxcol) @@ -507,6 +511,7 @@ public class FeatureSettings extends JPanel implements check.setFont(new Font("Serif", Font.BOLD, 12)); check.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent evt) { fr.setGroupVisibility(check.getText(), check.isSelected()); @@ -969,10 +974,19 @@ public class FeatureSettings extends JPanel implements updateFeatureRenderer(data, true); } + /** + * Update the priority order of features; only repaint if this changed the + * order of visible features + * + * @param data + * @param visibleNew + */ private void updateFeatureRenderer(Object[][] data, boolean visibleNew) { - fr.setFeaturePriority(data, visibleNew); - af.alignPanel.paintAlignment(true); + if (fr.setFeaturePriority(data, visibleNew)) + { + af.alignPanel.paintAlignment(true); + } } int selectedRow = -1; @@ -1029,6 +1043,7 @@ public class FeatureSettings extends JPanel implements invert.setText(MessageManager.getString("label.invert_selection")); invert.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { invertSelection(); @@ -1038,6 +1053,7 @@ public class FeatureSettings extends JPanel implements optimizeOrder.setText(MessageManager.getString("label.optimise_order")); optimizeOrder.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { orderByAvWidth(); @@ -1048,6 +1064,7 @@ public class FeatureSettings extends JPanel implements .setText(MessageManager.getString("label.seq_sort_by_score")); sortByScore.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { af.avc.sortAlignmentByFeatureScore(null); @@ -1058,6 +1075,7 @@ public class FeatureSettings extends JPanel implements .getString("label.sequence_sort_by_density")); sortByDens.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { af.avc.sortAlignmentByFeatureDensity(null); @@ -1067,6 +1085,7 @@ public class FeatureSettings extends JPanel implements help.setText(MessageManager.getString("action.help")); help.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { try @@ -1082,6 +1101,7 @@ public class FeatureSettings extends JPanel implements help.setText(MessageManager.getString("action.help")); help.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { try @@ -1097,6 +1117,7 @@ public class FeatureSettings extends JPanel implements cancel.setText(MessageManager.getString("action.cancel")); cancel.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { fr.setTransparency(originalTransparency); @@ -1108,6 +1129,7 @@ public class FeatureSettings extends JPanel implements ok.setText(MessageManager.getString("action.ok")); ok.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { close(); @@ -1117,6 +1139,7 @@ public class FeatureSettings extends JPanel implements loadColours.setText(MessageManager.getString("label.load_colours")); loadColours.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { load(); @@ -1126,6 +1149,7 @@ public class FeatureSettings extends JPanel implements saveColours.setText(MessageManager.getString("label.save_colours")); saveColours.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { save(); @@ -1133,6 +1157,7 @@ public class FeatureSettings extends JPanel implements }); transparency.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent evt) { fr.setTransparency((100 - transparency.getValue()) / 100f); @@ -1146,6 +1171,7 @@ public class FeatureSettings extends JPanel implements fetchDAS.setText(MessageManager.getString("label.fetch_das_features")); fetchDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { fetchDAS_actionPerformed(e); @@ -1154,6 +1180,7 @@ public class FeatureSettings extends JPanel implements saveDAS.setText(MessageManager.getString("action.save_as_default")); saveDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { saveDAS_actionPerformed(e); @@ -1165,6 +1192,7 @@ public class FeatureSettings extends JPanel implements cancelDAS.setText(MessageManager.getString("action.cancel_fetch")); cancelDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { cancelDAS_actionPerformed(e); @@ -1304,6 +1332,7 @@ public class FeatureSettings extends JPanel implements Runnable fetcher = new Runnable() { + @Override public void run() { doDasFeatureFetch(dassources, true, false); @@ -1385,6 +1414,7 @@ public class FeatureSettings extends JPanel implements this.data = data; } + @Override public int getColumnCount() { return columnNames.length; @@ -1395,31 +1425,37 @@ public class FeatureSettings extends JPanel implements return data[row]; } + @Override public int getRowCount() { return data.length; } + @Override public String getColumnName(int col) { return columnNames[col]; } + @Override public Object getValueAt(int row, int col) { return data[row][col]; } + @Override public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } + @Override public boolean isCellEditable(int row, int col) { return col == 0 ? false : true; } + @Override public void setValueAt(Object value, int row, int col) { data[row][col] = value; @@ -1444,6 +1480,7 @@ public class FeatureSettings extends JPanel implements setVerticalTextPosition(SwingConstants.CENTER); } + @Override public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) @@ -1609,16 +1646,19 @@ class FeatureIcon implements Icon } } + @Override public int getIconWidth() { return width; } + @Override public int getIconHeight() { return height; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { @@ -1699,6 +1739,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, /** * Handles events from the editor button and from the dialog's OK button. */ + @Override public void actionPerformed(ActionEvent e) { @@ -1744,6 +1785,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, } // Implement the one CellEditor method that AbstractCellEditor doesn't. + @Override public Object getCellEditorValue() { if (currentColor == null) @@ -1754,6 +1796,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, } // Implement the one method defined by TableCellEditor. + @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java index 26bc895..2276913 100644 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -22,6 +22,7 @@ package jalview.renderer.seqfeatures; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.AlphaComposite; import java.awt.Color; @@ -30,8 +31,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; -public class FeatureRenderer extends - jalview.viewmodel.seqfeatures.FeatureRendererModel +public class FeatureRenderer extends FeatureRendererModel { FontMetrics fm; @@ -168,6 +168,7 @@ public class FeatureRenderer extends BufferedImage offscreenImage; + @Override public Color findFeatureColour(Color initialCol, SequenceI seq, int res) { return new Color(findFeatureColour(initialCol.getRGB(), seq, res)); @@ -415,6 +416,7 @@ public class FeatureRenderer extends * discover and display. * */ + @Override public void featuresAdded() { lastSeq = null; diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 8db907c..e912720 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -34,6 +34,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -56,6 +57,9 @@ public abstract class FeatureRendererModel implements protected Object currentColour; + /* + * ordering of rendering, where last means on top + */ protected String[] renderOrder; protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( @@ -63,6 +67,7 @@ public abstract class FeatureRendererModel implements protected AlignmentViewport av; + @Override public AlignViewportI getViewport() { return av; @@ -537,6 +542,7 @@ public abstract class FeatureRendererModel implements * @param featureType * @return java.awt.Color or GraduatedColor */ + @Override public Object getFeatureStyle(String featureType) { Object fc = featureColours.get(featureType); @@ -617,6 +623,7 @@ public abstract class FeatureRendererModel implements return av.getFeaturesDisplayed().isVisible(type); } + @Override public void setColour(String featureType, Object col) { // overwrite @@ -691,21 +698,32 @@ public abstract class FeatureRendererModel implements * * @param data * { String(Type), Colour(Type), Boolean(Displayed) } + * @return true if any visible features have been reordered, else false */ - public void setFeaturePriority(Object[][] data) + public boolean setFeaturePriority(Object[][] data) { - setFeaturePriority(data, true); + return setFeaturePriority(data, true); } /** + * Sets the priority order for features * * @param data * { String(Type), Colour(Type), Boolean(Displayed) } * @param visibleNew * when true current featureDisplay list will be cleared + * @return true if any visible features have been reordered or recoloured, + * else false (i.e. no need to repaint) */ - public void setFeaturePriority(Object[][] data, boolean visibleNew) + public boolean setFeaturePriority(Object[][] data, boolean visibleNew) { + /* + * note visible feature ordering and colours before update + */ + List visibleFeatures = getDisplayedFeatureTypes(); + Map visibleColours = new HashMap( + getFeatureColours()); + FeaturesDisplayedI av_featuresdisplayed = null; if (visibleNew) { @@ -724,10 +742,10 @@ public abstract class FeatureRendererModel implements } if (data == null) { - return; + return false; } // The feature table will display high priority - // features at the top, but theses are the ones + // features at the top, but these are the ones // we need to render last, so invert the data renderOrder = new String[data.length]; @@ -747,6 +765,30 @@ public abstract class FeatureRendererModel implements } } + /* + * get the new visible ordering and return true if it has changed + * order or any colour has changed + */ + List reorderedVisibleFeatures = getDisplayedFeatureTypes(); + if (!visibleFeatures.equals(reorderedVisibleFeatures)) + { + /* + * the list of ordered visible features has changed + */ + return true; + } + + /* + * return true if any feature colour has changed + */ + for (String feature : visibleFeatures) + { + if (visibleColours.get(feature) != getFeatureStyle(feature)) + { + return true; + } + } + return false; } /** @@ -902,39 +944,39 @@ public abstract class FeatureRendererModel implements return av.getFeaturesDisplayed(); } + /** + * Returns a (possibly empty) list of visible feature types, in render order + * (last is on top) + */ @Override - public String[] getDisplayedFeatureTypes() + public List getDisplayedFeatureTypes() { - String[] typ = null; - typ = getRenderOrder().toArray(new String[0]); + List typ = getRenderOrder(); + List displayed = new ArrayList(); FeaturesDisplayedI feature_disp = av.getFeaturesDisplayed(); if (feature_disp != null) { synchronized (feature_disp) { - for (int i = 0; i < typ.length; i++) + for (String type : typ) { - if (!feature_disp.isVisible(typ[i])) + if (feature_disp.isVisible(type)) { - typ[i] = null; + displayed.add(type); } } } } - return typ; + return displayed; } @Override - public String[] getDisplayedFeatureGroups() + public List getDisplayedFeatureGroups() { - String[] gps = null; - ArrayList _gps = new ArrayList(); - Iterator en = getFeatureGroups().iterator(); - int g = 0; + List _gps = new ArrayList(); boolean valid = false; - while (en.hasNext()) + for (String gp : getFeatureGroups()) { - String gp = (String) en.next(); if (checkGroupVisibility(gp, false)) { valid = true; @@ -946,11 +988,11 @@ public abstract class FeatureRendererModel implements } else { - gps = new String[_gps.size()]; - _gps.toArray(gps); + // gps = new String[_gps.size()]; + // _gps.toArray(gps); } } - return gps; + return _gps; } } diff --git a/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java b/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java index a70fac2..2dc2ac3 100644 --- a/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java +++ b/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java @@ -73,7 +73,7 @@ public class FeatureScoreModelTest alf.getFeatureRenderer().setVisible("sf3"); alf.getFeatureRenderer().findAllFeatures(true); AssertJUnit.assertEquals("Number of feature types", 3, alf - .getFeatureRenderer().getDisplayedFeatureTypes().length); + .getFeatureRenderer().getDisplayedFeatureTypes().size()); AssertJUnit.assertTrue(alf.getCurrentView().areFeaturesDisplayed()); FeatureScoreModel fsm = new FeatureScoreModel(); AssertJUnit.assertTrue(fsm.configureFromAlignmentView(alf -- 1.7.10.2