X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FFeatureSettings.java;h=b87e4bf92c10de36e2a0b7cf827a5dd5341871f3;hb=7634f98934b049825723fac41c8821ee38a355cd;hp=8ce090f33329b7e1c23fb3796e773d76e0649135;hpb=5fefa2921f96368c895ff07e8340653a477cd68b;p=jalview.git diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 8ce090f..b87e4bf 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -24,7 +24,9 @@ import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; +import jalview.api.SplitContainerI; import jalview.api.ViewStyleI; +import jalview.controller.FeatureSettingsControllerGuiI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.datamodel.features.FeatureMatcher; @@ -48,6 +50,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.Font; import java.awt.Graphics; import java.awt.GridLayout; @@ -112,7 +115,7 @@ import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; public class FeatureSettings extends JPanel - implements FeatureSettingsControllerI + implements FeatureSettingsControllerI, FeatureSettingsControllerGuiI { private static final String SEQUENCE_FEATURE_COLOURS = MessageManager .getString("label.sequence_feature_colours"); @@ -161,6 +164,10 @@ public class FeatureSettings extends JPanel JSlider transparency = new JSlider(); + private JCheckBox showComplementOnTop; + + private JCheckBox showComplement; + /* * when true, constructor is still executing - so ignore UI events */ @@ -176,10 +183,36 @@ public class FeatureSettings extends JPanel private boolean handlingUpdate = false; /* + * a change listener to ensure the dialog is updated if + * FeatureRenderer discovers new features + */ + private PropertyChangeListener change; + + /* * holds {featureCount, totalExtent} for each feature type */ Map typeWidth = null; + private void storeOriginalSettings() + { + // save transparency for restore on Cancel + originalTransparency = fr.getTransparency(); + + updateTransparencySliderFromFR(); + + originalFilters = new HashMap<>(fr.getFeatureFilters()); // shallow copy + originalViewStyle = new ViewStyle(af.viewport.getViewStyle()); + } + + private void updateTransparencySliderFromFR() + { + boolean incon = inConstruction; + inConstruction = true; + + int transparencyAsPercent = (int) (fr.getTransparency() * 100); + transparency.setValue(100 - transparencyAsPercent); + inConstruction = incon; + } /** * Constructor * @@ -190,13 +223,7 @@ public class FeatureSettings extends JPanel this.af = alignFrame; fr = af.getFeatureRenderer(); - // save transparency for restore on Cancel - originalTransparency = fr.getTransparency(); - int originalTransparencyAsPercent = (int) (originalTransparency * 100); - transparency.setMaximum(100 - originalTransparencyAsPercent); - - originalFilters = new HashMap<>(fr.getFeatureFilters()); // shallow copy - originalViewStyle = new ViewStyle(af.viewport.getViewStyle()); + storeOriginalSettings(); try { @@ -356,7 +383,6 @@ public class FeatureSettings extends JPanel } discoverAllFeatureData(); - final PropertyChangeListener change; final FeatureSettings fs = this; fr.addPropertyChangeListener(change = new PropertyChangeListener() { @@ -373,37 +399,88 @@ public class FeatureSettings extends JPanel } }); - - frame = new JInternalFrame(); - frame.setContentPane(this); - if (Platform.isAMac()) + SplitContainerI splitframe = af.getSplitViewContainer(); + if (splitframe != null) { - Desktop.addInternalFrame(frame, - MessageManager.getString("label.sequence_feature_settings"), - 600, 480); + frame = null; // keeps eclipse happy + splitframe.addFeatureSettingsUI(this); } else { - Desktop.addInternalFrame(frame, - MessageManager.getString("label.sequence_feature_settings"), - 600, 450); - } - frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT)); + frame = new JInternalFrame(); + frame.setContentPane(this); + Rectangle bounds = af.getFeatureSettingsGeometry(); + String title; + if (af.getAlignPanels().size() > 1 || Desktop.getAlignmentPanels( + af.alignPanel.av.getSequenceSetId()).length > 1) + { + title = MessageManager.formatMessage( + "label.sequence_feature_settings_for_view", + af.alignPanel.getViewName()); + } + else + { + title = MessageManager.getString("label.sequence_feature_settings"); + } + if (bounds == null) + { + if (Platform.isAMac()) + { + Desktop.addInternalFrame(frame, title, 600, 480); + } + else + { + Desktop.addInternalFrame(frame, title, 600, 450); + } + } + else + { + Desktop.addInternalFrame(frame, title, + false, bounds.width, bounds.height); + frame.setBounds(bounds); + frame.setVisible(true); + } + frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT)); - frame.addInternalFrameListener( - new javax.swing.event.InternalFrameAdapter() - { - @Override - public void internalFrameClosed( - javax.swing.event.InternalFrameEvent evt) + frame.addInternalFrameListener( + new javax.swing.event.InternalFrameAdapter() { - fr.removePropertyChangeListener(change); - }; - }); - frame.setLayer(JLayeredPane.PALETTE_LAYER); + @Override + public void internalFrameClosed( + javax.swing.event.InternalFrameEvent evt) + { + featureSettings_isClosed(); + }; + }); + frame.setLayer(JLayeredPane.PALETTE_LAYER); + } inConstruction = false; } + /** + * Sets the state of buttons to show complement features from viewport + * settings + */ + private void updateComplementButtons() + { + showComplement.setSelected(af.getViewport().isShowComplementFeatures()); + showComplementOnTop + .setSelected(af.getViewport().isShowComplementFeaturesOnTop()); + } + + @Override + public AlignViewControllerGuiI getAlignframe() + { + return af; + } + + @Override + public void featureSettings_isClosed() + { + fr.removePropertyChangeListener(change); + change = null; + } + protected void popupSort(final int rowSelected, final String type, final Object typeCol, final Map minmax, int x, int y) @@ -414,32 +491,23 @@ public class FeatureSettings extends JPanel JMenuItem scr = new JMenuItem( MessageManager.getString("label.sort_by_score")); men.add(scr); - final FeatureSettings me = this; scr.addActionListener(new ActionListener() { - @Override public void actionPerformed(ActionEvent e) { - me.af.avc - .sortAlignmentByFeatureScore(Arrays.asList(new String[] - { type })); + sortByScore(Arrays.asList(new String[] { type })); } - }); JMenuItem dens = new JMenuItem( MessageManager.getString("label.sort_by_density")); dens.addActionListener(new ActionListener() { - @Override public void actionPerformed(ActionEvent e) { - me.af.avc - .sortAlignmentByFeatureDensity(Arrays.asList(new String[] - { type })); + sortByDensity(Arrays.asList(new String[] { type })); } - }); men.add(dens); @@ -496,6 +564,47 @@ public class FeatureSettings extends JPanel men.show(table, x, y); } + /** + * Sort the sequences in the alignment by the number of features for the given + * feature types (or all features if null) + * + * @param featureTypes + */ + protected void sortByDensity(List featureTypes) + { + af.avc.sortAlignmentByFeatureDensity(featureTypes); + } + + /** + * Sort the sequences in the alignment by average score for the given feature + * types (or all features if null) + * + * @param featureTypes + */ + protected void sortByScore(List featureTypes) + { + af.avc.sortAlignmentByFeatureScore(featureTypes); + } + + /** + * Returns true if at least one feature type is visible. Else shows a warning + * dialog and returns false. + * + * @param title + * @return + */ + private boolean canSortBy(String title) + { + if (fr.getDisplayedFeatureTypes().isEmpty()) + { + JvOptionPane.showMessageDialog(this, + MessageManager.getString("label.no_features_to_sort_by"), + title, JvOptionPane.OK_OPTION); + return false; + } + return true; + } + @Override synchronized public void discoverAllFeatureData() { @@ -1079,11 +1188,38 @@ public class FeatureSettings extends JPanel table.repaint(); } + /** + * close ourselves but leave any existing UI handlers (e.g a CDS/Protein tabbed + * feature settings dialog) intact + */ + public void closeOldSettings() + { + closeDialog(false); + } + + /** + * close the feature settings dialog (and any containing frame) + */ public void close() { + closeDialog(true); + } + + private void closeDialog(boolean closeContainingFrame) + { try { - frame.setClosed(true); + if (frame != null) + { + af.setFeatureSettingsGeometry(frame.getBounds()); + frame.setClosed(true); + } + else + { + SplitContainerI sc = af.getSplitViewContainer(); + sc.closeFeatureSettings(this, closeContainingFrame); + af.featureSettings = null; + } } catch (Exception exe) { } @@ -1134,6 +1270,9 @@ public class FeatureSettings extends JPanel { this.setLayout(new BorderLayout()); + final boolean hasComplement = af.getViewport() + .getCodingComplement() != null; + JPanel settingsPane = new JPanel(); settingsPane.setLayout(new BorderLayout()); @@ -1167,26 +1306,32 @@ public class FeatureSettings extends JPanel } }); - JButton sortByScore = new JButton( - MessageManager.getString("label.seq_sort_by_score")); + final String byScoreLabel = MessageManager.getString("label.seq_sort_by_score"); + JButton sortByScore = new JButton(byScoreLabel); sortByScore.setFont(JvSwingUtils.getLabelFont()); sortByScore.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - af.avc.sortAlignmentByFeatureScore(null); + if (canSortBy(byScoreLabel)) + { + sortByScore(null); + } } }); - JButton sortByDens = new JButton( - MessageManager.getString("label.sequence_sort_by_density")); + final String byDensityLabel = MessageManager.getString("label.sequence_sort_by_density"); + JButton sortByDens = new JButton(byDensityLabel); sortByDens.setFont(JvSwingUtils.getLabelFont()); sortByDens.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - af.avc.sortAlignmentByFeatureDensity(null); + if (canSortBy(byDensityLabel)) + { + sortByDensity(null); + } } }); @@ -1206,30 +1351,48 @@ public class FeatureSettings extends JPanel } } }); - - JButton cancel = new JButton(MessageManager.getString("action.cancel")); + // Cancel for a SplitFrame should just revert changes to the currently displayed + // settings. May want to do this for either or both - so need a splitview + // feature settings cancel/OK. + JButton cancel = new JButton(MessageManager + .getString(hasComplement ? "action.revert" : "action.cancel")); + cancel.setToolTipText(MessageManager.getString(hasComplement + ? "action.undo_changes_to_feature_settings" + : "action.undo_changes_to_feature_settings_and_close_the_dialog")); cancel.setFont(JvSwingUtils.getLabelFont()); + // TODO: disable cancel (and apply!) until current settings are different cancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - fr.setTransparency(originalTransparency); - fr.setFeatureFilters(originalFilters); - updateFeatureRenderer(originalData); - af.getViewport().setViewStyle(originalViewStyle); - close(); + revert(); + refreshDisplay(); + if (!hasComplement) + { + close(); + } } }); - - JButton ok = new JButton(MessageManager.getString("action.ok")); + // Cancel for the whole dialog should cancel both CDS and Protein. + // OK for an individual feature settings just applies changes, but dialog + // remains open + JButton ok = new JButton(MessageManager + .getString(hasComplement ? "action.apply" : "action.ok")); ok.setFont(JvSwingUtils.getLabelFont()); ok.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - close(); + if (!hasComplement) + { + close(); + } + else + { + storeOriginalSettings(); + } } }); @@ -1283,8 +1446,7 @@ public class FeatureSettings extends JPanel ? MessageManager.getString("label.protein") .toLowerCase() : "CDS"); - JCheckBox showComplement = new JCheckBox(text); - showComplement.setSelected(af.getViewport().isShowComplementFeatures()); + showComplement = new JCheckBox(text); showComplement.addActionListener(new ActionListener() { @Override @@ -1296,10 +1458,8 @@ public class FeatureSettings extends JPanel } }); - JCheckBox showComplementOnTop = new JCheckBox( + showComplementOnTop = new JCheckBox( MessageManager.getString("label.on_top")); - showComplementOnTop - .setSelected(af.getViewport().isShowComplementFeaturesOnTop()); showComplementOnTop.addActionListener(new ActionListener() { @Override @@ -1310,38 +1470,9 @@ public class FeatureSettings extends JPanel refreshDisplay(); } }); - JButton viewComplementSettings = new JButton(MessageManager - .formatMessage("label.show_linked_feature_settings", - nucleotide - ? MessageManager.getString("label.protein") - .toLowerCase() - : "CDS")); - viewComplementSettings.addActionListener(new ActionListener() - { - - @Override - public void actionPerformed(ActionEvent e) - { - AlignViewControllerGuiI complAf = af.getSplitViewContainer() - .getComplementAlignFrame(af); - FeatureSettings complFeatureSettings = (FeatureSettings) complAf - .getFeatureSettingsUI(); - if (complFeatureSettings != null) - { - complFeatureSettings.frame.setVisible(true); - try - { - complFeatureSettings.frame.setSelected(true); - return; - } catch (Exception q) - { - } - } - { - complAf.showFeatureSettingsUI(); - } - } - }); + + updateComplementButtons(); + JPanel lowerPanel = new JPanel(new GridLayout(1, 2)); bigPanel.add(lowerPanel, BorderLayout.SOUTH); @@ -1352,17 +1483,15 @@ public class FeatureSettings extends JPanel transbuttons.add(sortByDens); transbuttons.add(help); - boolean hasComplement = af.getViewport().getCodingComplement() != null; JPanel transPanelLeft = new JPanel( new GridLayout(hasComplement ? 4 : 2, 1)); transPanelLeft.add(new JLabel(" Colour transparency" + ":")); transPanelLeft.add(transparency); if (hasComplement) { - JPanel cp = new JPanel(new GridLayout(3, 2)); + JPanel cp = new JPanel(new FlowLayout(FlowLayout.LEFT)); cp.add(showComplement); cp.add(showComplementOnTop); - cp.add(viewComplementSettings); transPanelLeft.add(cp); } lowerPanel.add(transPanelLeft); @@ -1935,6 +2064,27 @@ public class FeatureSettings extends JPanel return button; } } + + public boolean isOpen() + { + if (af.getSplitViewContainer() != null) + { + return af.getSplitViewContainer().isFeatureSettingsOpen(); + } + return frame != null && !frame.isClosed(); + } + + @Override + public void revert() + { + fr.setTransparency(originalTransparency); + fr.setFeatureFilters(originalFilters); + updateFeatureRenderer(originalData); + af.getViewport().setViewStyle(originalViewStyle); + updateTransparencySliderFromFR(); + updateComplementButtons(); + refreshDisplay(); + } } class FeatureIcon implements Icon