into project.name
- def EXCLUDE_FILES=["build/*","bin/*","test-output/","test-reports","tests","clover*/*"
- ,".*"
- ,"benchmarking/*"
- ,"**/.*"
- ,"*.class"
- ,"**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales"
- ,"*locales/**",
- ,"utils/InstallAnywhere"]
- def PROCESS_FILES=[ "AUTHORS",
- "CITATION",
- "FEATURETODO",
- "JAVA-11-README",
- "FEATURETODO",
- "LICENSE",
- "**/README",
- "RELEASE",
- "THIRDPARTYLIBS","TESTNG",
- "build.gradle",
- "gradle.properties",
- "**/*.java",
- "**/*.html",
- "**/*.xml",
- "**/*.gradle",
- "**/*.groovy",
- "**/*.properties",
- "**/*.perl",
- "**/*.sh"]
+ def EXCLUDE_FILES=[
+ "build/*",
+ "bin/*",
+ "test-output/",
+ "test-reports",
+ "tests",
+ "clover*/*",
+ ".*",
+ "benchmarking/*",
+ "**/.*",
+ "*.class",
+ "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
+ "*locales/**",
+ "utils/InstallAnywhere",
+ "**/*.log",
+ ]
+ def PROCESS_FILES=[
+ "AUTHORS",
+ "CITATION",
+ "FEATURETODO",
+ "JAVA-11-README",
+ "FEATURETODO",
+ "LICENSE",
+ "**/README",
+ "RELEASE",
+ "THIRDPARTYLIBS",
+ "TESTNG",
+ "build.gradle",
+ "gradle.properties",
+ "**/*.java",
+ "**/*.html",
+ "**/*.xml",
+ "**/*.gradle",
+ "**/*.groovy",
+ "**/*.properties",
+ "**/*.perl",
+ "**/*.sh",
+ ]
+ def INCLUDE_FILES=[
+ ".settings/org.eclipse.jdt.core.jalview.prefs",
+ ]
from(jalviewDir) {
exclude (EXCLUDE_FILES)
from(jalviewDir) {
exclude (EXCLUDE_FILES)
exclude (PROCESS_FILES)
- exclude ("appletlib")
- exclude ("**/*locales")
- exclude ("*locales/**")
- exclude ("utils/InstallAnywhere")
+ exclude ("appletlib")
+ exclude ("**/*locales")
+ exclude ("*locales/**")
+ exclude ("utils/InstallAnywhere")
exclude (getdown_files_dir)
- exclude (getdown_website_dir)
+ exclude (getdown_website_dir)
- // exluding these as not using jars as modules yet
- exclude ("$j11modDir/**/*.jar")
-}
+ // exluding these as not using jars as modules yet
+ exclude ("$j11modDir/**/*.jar")
+ }
+ from(jalviewDir) {
+ include(INCLUDE_FILES)
+ }
// from (jalviewDir) {
// // explicit includes for stuff that seemed to not get included
// include(fileTree("test/**/*."))
<tr>
<td width="60" align="center" nowrap><strong><a
name="Jalview.2.11.1">2.11.1</a><a name="Jalview.2.11.1.0">.0</a><br />
- <em>16/2/2020</em></strong></td>
+ <em>25/2/2020</em></strong></td>
<td align="left" valign="top">
<ul>
+ <li><!-- JAL-3121 -->Feature attributes from VCF files can be exported and re-imported as GFF3 files
+ </li>
<li>
- <!-- JAL-3376 -->Record "fixed column" values POS, ID, QUAL, FILTER from VCF as Feature Attributes
+ <!-- JAL-3376 -->Record "fixed column" values POS,
+ ID, QUAL, FILTER from VCF as Feature Attributes
</li>
<li>
- <!-- JAL-3375 -->More robust VCF numeric data field validation
- while parsing (e.g. AF* attributes)
+ <!-- JAL-3375 -->More robust VCF numeric data field
+ validation while parsing (e.g. AF* attributes)
+ </li>
+ <li>
+ <!-- JAL-3538 -->Font anti-aliasing in alignment views
+ enabled by default
</li>
-
<li>
<!-- JAL -->
</li>
action.deselect_all = Deselect all
action.invert_selection = Invert selection
action.using_jmol = Using Jmol
+action.undo_changes_to_feature_settings = Undo all unapplied changes to feature settings
+action.undo_changes_to_feature_settings_and_close_the_dialog = Undo all pending changes and close the feature settings dialog
action.link = Link
action.group_link = Group Link
action.show_chain = Show Chain
label.protein = Protein
label.nucleotides = Nucleotides
label.proteins = Proteins
+label.CDS = CDS
label.to_new_alignment = To New Alignment
label.to_this_alignment = Add To This Alignment
label.apply_colour_to_all_groups = Apply Colour To All Groups
label.generating_annotations_for_params = Generating annotations for - {0}
label.varna_params = VARNA - {0}
label.sequence_feature_settings = Sequence Feature Settings
+label.sequence_feature_settings_for = Sequence Feature Settings for {0}
+label.sequence_feature_settings_for_view = Sequence Feature Settings for view "{0}"
+label.sequence_feature_settings_for_CDS_and_Protein = Sequence Feature Settings for CDS and Protein
label.pairwise_aligned_sequences = Pairwise Aligned Sequences
label.original_data_for_params = Original Data for {0}
label.points_for_params = Points for {0}
label.click_to_edit = Click to edit, right-click for menu
label.by_annotation_tooltip = Annotation Colour is configured from the main Colour menu
label.show_linked_features = Show {0} features
+label.show_linked_feature_settings = Open {0} settings
label.on_top = on top
label.include_linked_features = Include {0} features
label.include_linked_tooltip = Include visible {0} features<br>converted to local sequence coordinates
\ No newline at end of file
import jalview.commands.CommandI;
import jalview.schemes.ColourSchemeI;
+import java.awt.Rectangle;
+
/**
* Interface implemented by gui implementations managing a Jalview Alignment
* View
* @return
*/
FeatureSettingsControllerI getFeatureSettingsUI();
+
+ /**
+ * displays the Feature Settigns control panel for the alignment view - if one
+ * exists it is closed and re-opened.
+ *
+ * @return the current feature settings controller
+ */
+ FeatureSettingsControllerI showFeatureSettingsUI();
+
+ /**
+ * record the last position of a feature settings dialog before it was closed
+ *
+ * @param bounds
+ */
+ void setFeatureSettingsGeometry(Rectangle bounds);
+
+ /**
+ *
+ * @return last position of feature settings for this alignment view GUI
+ */
+ Rectangle getFeatureSettingsGeometry();
}
*/
package jalview.api;
+import jalview.controller.FeatureSettingsControllerGuiI;
import jalview.datamodel.AlignmentI;
/**
*/
String getComplementTitle(Object af);
+ /**
+ * get the 'other' alignFrame in the SplitFrame
+ *
+ * @param alignFrame
+ * @return the complement alignFrame - or null if alignFrame wasn't held by this
+ * frame
+ */
+ AlignViewControllerGuiI getComplementAlignFrame(
+ AlignViewControllerGuiI alignFrame);
+
+ /**
+ * add the given UI to the splitframe's feature settings UI holder
+ *
+ * @param featureSettings
+ * @return
+ */
+ void addFeatureSettingsUI(
+ FeatureSettingsControllerGuiI featureSettings);
+
+ /**
+ * Request to close all feature settings originating from a particular panel.
+ *
+ * @param featureSettings
+ * @param closeContainingFrame
+ * - if false then the tab containing the feature
+ * settings will be 'reset' ready for a new
+ * feature settings
+ */
+ void closeFeatureSettings(FeatureSettingsControllerI featureSettings,
+ boolean closeContainingFrame);
+
+ /**
+ *
+ * @return true if a feature settings panel is currently open
+ */
+ boolean isFeatureSettingsOpen();
+
}
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
+import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
}
else if (source == featureSettings)
{
- new FeatureSettings(alignPanel);
+ showFeatureSettingsUI();
}
else if (source == alProperties)
{
return alignPanel.av.featureSettings;
}
+ @Override
+ public FeatureSettingsControllerI showFeatureSettingsUI()
+ {
+ return new FeatureSettings(alignPanel);
+ }
+
+ private Rectangle fs_bounds = null;
+
+ @Override
+ public void setFeatureSettingsGeometry(Rectangle bounds)
+ {
+ fs_bounds = bounds;
+ }
+
+ @Override
+ public Rectangle getFeatureSettingsGeometry()
+ {
+ return fs_bounds;
+ }
+
}
*/
package jalview.controller;
+import jalview.api.AlignViewControllerGuiI;
+
public interface FeatureSettingsControllerGuiI
{
+ AlignViewControllerGuiI getAlignframe();
+
+ void featureSettings_isClosed();
+
+ /**
+ * undo any changes made to feature settings whilst the dialog has been visible,
+ * since the last 'apply'
+ */
+ void revert();
+
}
closeView(alignPanel);
}
}
-
if (closeAllTabs)
{
+ if (featureSettings != null && featureSettings.isOpen())
+ {
+ featureSettings.close();
+ featureSettings = null;
+ }
/*
* this will raise an INTERNAL_FRAME_CLOSED event and this method will
* be called recursively, with the frame now in 'closed' state
@Override
public void featureSettings_actionPerformed(ActionEvent e)
{
+ showFeatureSettingsUI();
+ }
+
+ @Override
+ public FeatureSettingsControllerI showFeatureSettingsUI()
+ {
if (featureSettings != null)
{
- featureSettings.close();
+ featureSettings.closeOldSettings();
featureSettings = null;
}
if (!showSeqFeatures.isSelected())
showSeqFeatures_actionPerformed(null);
}
featureSettings = new FeatureSettings(this);
+ return featureSettings;
}
/**
{
if (parseFeaturesFile(file, sourceType))
{
- alignPanel.paintAlignment(true, true);
+ SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
+ if (splitFrame != null)
+ {
+ splitFrame.repaint();
+ }
+ else
+ {
+ alignPanel.paintAlignment(true, true);
+ }
}
}
else
viewport = alignPanel.av;
avc.setViewportAndAlignmentPanel(viewport, alignPanel);
setMenusFromViewport(viewport);
+ if (featureSettings != null && featureSettings.isOpen()
+ && featureSettings.fr.getViewport() != viewport)
+ {
+ if (viewport.isShowSequenceFeatures())
+ {
+ // refresh the featureSettings to reflect UI change
+ showFeatureSettingsUI();
+ }
+ else
+ {
+ // close feature settings for this view.
+ featureSettings.close();
+ }
+ }
+
}
/*
}
}
+
+ private Rectangle lastFeatureSettingsBounds = null;
+ @Override
+ public void setFeatureSettingsGeometry(Rectangle bounds)
+ {
+ lastFeatureSettingsBounds = bounds;
+ }
+
+ @Override
+ public Rectangle getFeatureSettingsGeometry()
+ {
+ return lastFeatureSettingsBounds;
+ }
}
class PrintThread extends Thread
boolean antiAlias = false;
- private Rectangle explodedGeometry;
+ private Rectangle explodedGeometry = null;
- private String viewName;
+ private String viewName = null;
/*
* Flag set true on the view that should 'gather' multiple views of the same
*/
private void applyViewProperties()
{
- antiAlias = Cache.getDefault("ANTI_ALIAS", false);
+ antiAlias = Cache.getDefault("ANTI_ALIAS", true);
viewStyle.setShowJVSuffix(Cache.getDefault("SHOW_JVSUFFIX", true));
setShowAnnotation(Cache.getDefault("SHOW_ANNOTATIONS", true));
return;
}
+ // FIXME: ideally should use UI interface API
+ FeatureSettings viewFeatureSettings = (af.featureSettings != null
+ && af.featureSettings.isOpen())
+ ? af.featureSettings
+ : null;
+ Rectangle fsBounds = af.getFeatureSettingsGeometry();
for (int i = 0; i < size; i++)
{
AlignmentPanel ap = af.alignPanels.get(i);
+
AlignFrame newaf = new AlignFrame(ap);
+ // transfer reference for existing feature settings to new alignFrame
+ if (ap == af.alignPanel)
+ {
+ if (viewFeatureSettings != null && viewFeatureSettings.fr.ap == ap)
+ {
+ newaf.featureSettings = viewFeatureSettings;
+ }
+ newaf.setFeatureSettingsGeometry(fsBounds);
+ }
+
/*
* Restore the view's last exploded frame geometry if known. Multiple
* views from one exploded frame share and restore the same (frame)
addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
+ // and materialise a new feature settings dialog instance for the new alignframe
+ // (closes the old as if 'OK' was pressed)
+ if (ap == af.alignPanel && newaf.featureSettings != null
+ && newaf.featureSettings.isOpen()
+ && af.alignPanel.getAlignViewport().isShowSequenceFeatures())
+ {
+ newaf.showFeatureSettingsUI();
+ }
}
+ af.featureSettings = null;
af.alignPanels.clear();
af.closeMenuItem_actionPerformed(true);
source.viewport.setExplodedGeometry(source.getBounds());
JInternalFrame[] frames = desktop.getAllFrames();
String viewId = source.viewport.getSequenceSetId();
-
for (int t = 0; t < frames.length; t++)
{
if (frames[t] instanceof AlignFrame && frames[t] != source)
if (gatherThis)
{
+ if (af.featureSettings != null && af.featureSettings.isOpen())
+ {
+ if (source.featureSettings == null)
+ {
+ // preserve the feature settings geometry for this frame
+ source.featureSettings = af.featureSettings;
+ source.setFeatureSettingsGeometry(
+ af.getFeatureSettingsGeometry());
+ }
+ else
+ {
+ // close it and forget
+ af.featureSettings.close();
+ }
+ }
af.alignPanels.clear();
af.closeMenuItem_actionPerformed(true);
}
}
}
+ // refresh the feature setting UI for the source frame if it exists
+ if (source.featureSettings != null
+ && source.featureSettings.isOpen())
+ {
+ source.showFeatureSettingsUI();
+ }
}
*/
package jalview.gui;
+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;
import java.util.Set;
import javax.help.HelpSetException;
+import javax.swing.AbstractButton;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.Icon;
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");
*/
Map<String, float[]> 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
*
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
{
}
discoverAllFeatureData();
- final PropertyChangeListener change;
final FeatureSettings fs = this;
fr.addPropertyChangeListener(change = new PropertyChangeListener()
{
}
});
-
- 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;
}
+ PropertyChangeListener change;
+
+ private JCheckBox showComplementOnTop;
+
+ private AbstractButton showComplement;
+
+ 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<String, float[][]> minmax, int x,
int y)
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)
{
}
{
this.setLayout(new BorderLayout());
+ final boolean hasComplement = af.getViewport()
+ .getCodingComplement() != null;
+
JPanel settingsPane = new JPanel();
settingsPane.setLayout(new BorderLayout());
}
}
});
-
- 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();
+ }
}
});
? 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
}
});
- JCheckBox showComplementOnTop = new JCheckBox(
+ showComplementOnTop = new JCheckBox(
MessageManager.getString("label.on_top"));
- showComplementOnTop
- .setSelected(af.getViewport().isShowComplementFeaturesOnTop());
showComplementOnTop.addActionListener(new ActionListener()
{
@Override
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();
+ // }
+ // }
+ // });
JPanel lowerPanel = new JPanel(new GridLayout(1, 2));
bigPanel.add(lowerPanel, BorderLayout.SOUTH);
transbuttons.add(sortByDens);
transbuttons.add(help);
- boolean hasComplement = af.getViewport().getCodingComplement() != null;
JPanel transPanelLeft = new JPanel(
- new GridLayout(hasComplement ? 3 : 2, 1));
+ new GridLayout(hasComplement ? 4 : 2, 1));
transPanelLeft.add(new JLabel(" Colour transparency" + ":"));
transPanelLeft.add(transparency);
if (hasComplement)
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
fontStyleCB.setSelectedItem(
Cache.getDefault("FONT_STYLE", Font.PLAIN + ""));
- smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", false));
+ smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", true));
scaleProteinToCdna
.setSelected(Cache.getDefault(SCALE_PROTEIN_TO_CDNA, false));
doReset.addActionListener(onReset);
// filter to display only custom urls
- final RowFilter<TableModel, Object> customUrlFilter = new RowFilter<TableModel, Object>()
+ final RowFilter<TableModel, Object> customUrlFilter = new RowFilter<>()
{
@Override
public boolean include(
*/
package jalview.gui;
+import jalview.api.AlignViewControllerGuiI;
+import jalview.api.FeatureSettingsControllerI;
import jalview.api.SplitContainerI;
+import jalview.controller.FeatureSettingsControllerGuiI;
import jalview.datamodel.AlignmentI;
import jalview.jbgui.GAlignFrame;
import jalview.jbgui.GSplitFrame;
import jalview.structure.StructureSelectionManager;
+import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.AlignmentViewport;
+import java.awt.BorderLayout;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
+import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
+import javax.swing.JLayeredPane;
import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
private static final long serialVersionUID = 1L;
+ /**
+ * geometry for Feature Settings Holder
+ */
+ private static final int FS_MIN_WIDTH = 400;
+
+ private static final int FS_MIN_HEIGHT = 400;
+
public SplitFrame(GAlignFrame top, GAlignFrame bottom)
{
super(top, bottom);
{ (AlignFrame) getTopFrame(), (AlignFrame) getBottomFrame() });
}
+ @Override
+ public AlignFrame getComplementAlignFrame(
+ AlignViewControllerGuiI alignFrame)
+ {
+ if (getTopFrame() == alignFrame)
+ {
+ return (AlignFrame) getBottomFrame();
+ }
+ if (getBottomFrame() == alignFrame)
+ {
+ return (AlignFrame) getTopFrame();
+ }
+ // we didn't know anything about this frame...
+ return null;
+ }
+
/**
* Replace Cmd-F Find action with our version. This is necessary because the
* 'default' Finder searches in the first AlignFrame it finds. We need it to
}
super.setSelected(selected);
}
-}
+
+ /**
+ * holds the frame for feature settings, so Protein and DNA tabs can be managed
+ */
+ JInternalFrame featureSettingsUI;
+
+ JTabbedPane featureSettingsPanels;
+
+ @Override
+ public void addFeatureSettingsUI(
+ FeatureSettingsControllerGuiI featureSettings)
+ {
+ boolean showInternalFrame = false;
+ if (featureSettingsUI == null || featureSettingsPanels == null)
+ {
+ showInternalFrame = true;
+ featureSettingsPanels = new JTabbedPane();
+ featureSettingsPanels.addChangeListener(new ChangeListener()
+ {
+
+ @Override
+ public void stateChanged(ChangeEvent e)
+ {
+ if (e.getSource() != featureSettingsPanels
+ || featureSettingsUI == null
+ || featureSettingsUI.isClosed()
+ || !featureSettingsUI.isVisible())
+ {
+ // not our tabbed pane
+ return;
+ }
+ int tab = featureSettingsPanels.getSelectedIndex();
+ if (tab < 0 || featureSettingsPanels
+ .getSelectedComponent() instanceof FeatureSettingsControllerGuiI)
+ {
+ // no tab selected or already showing a feature settings GUI
+ return;
+ }
+ getAlignFrames().get(tab).showFeatureSettingsUI();
+ }
+ });
+ featureSettingsUI = new JInternalFrame(MessageManager.getString(
+ "label.sequence_feature_settings_for_CDS_and_Protein"));
+ featureSettingsPanels.setOpaque(true);
+
+ JPanel dialog = new JPanel();
+ dialog.setOpaque(true);
+ dialog.setLayout(new BorderLayout());
+ dialog.add(featureSettingsPanels, BorderLayout.CENTER);
+ JPanel buttons = new JPanel();
+ JButton ok = new JButton(MessageManager.getString("action.ok"));
+ ok.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ try
+ {
+ featureSettingsUI.setClosed(true);
+ } catch (PropertyVetoException pv)
+ {
+ pv.printStackTrace();
+ }
+ }
+ });
+ JButton cancel = new JButton(
+ MessageManager.getString("action.cancel"));
+ cancel.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ try
+ {
+ for (Component fspanel : featureSettingsPanels.getComponents())
+ {
+ if (fspanel instanceof FeatureSettingsControllerGuiI)
+ {
+ ((FeatureSettingsControllerGuiI) fspanel).revert();
+ }
+ }
+ featureSettingsUI.setClosed(true);
+ } catch (Exception pv)
+ {
+ pv.printStackTrace();
+ }
+ }
+ });
+ buttons.add(ok);
+ buttons.add(cancel);
+ dialog.add(buttons, BorderLayout.SOUTH);
+ featureSettingsUI.setContentPane(dialog);
+ createDummyTabs();
+ }
+ if (featureSettingsPanels
+ .indexOfTabComponent((Component) featureSettings) > -1)
+ {
+ // just show the feature settings !
+ featureSettingsPanels
+ .setSelectedComponent((Component) featureSettings);
+ return;
+ }
+ // otherwise replace the dummy tab with the given feature settings
+ int pos = getAlignFrames().indexOf(featureSettings.getAlignframe());
+ // if pos==-1 then alignFrame isn't managed by this splitframe
+ if (pos == 0)
+ {
+ featureSettingsPanels.removeTabAt(0);
+ featureSettingsPanels.insertTab(tabName[0], null,
+ (Component) featureSettings,
+ MessageManager.formatMessage(
+ "label.sequence_feature_settings_for", tabName[0]),
+ 0);
+ }
+ if (pos == 1)
+ {
+ featureSettingsPanels.removeTabAt(1);
+ featureSettingsPanels.insertTab(tabName[1], null,
+ (Component) featureSettings,
+ MessageManager.formatMessage(
+ "label.sequence_feature_settings_for", tabName[1]),
+ 1);
+ }
+ featureSettingsPanels.setSelectedComponent((Component) featureSettings);
+
+ // TODO: JAL-3535 - construct a feature settings title including names of
+ // currently selected CDS and Protein names
+
+ if (showInternalFrame)
+ {
+ if (Platform.isAMac())
+ {
+ Desktop.addInternalFrame(featureSettingsUI,
+ MessageManager.getString(
+ "label.sequence_feature_settings_for_CDS_and_Protein"),
+ 600, 480);
+ }
+ else
+ {
+ Desktop.addInternalFrame(featureSettingsUI,
+ MessageManager.getString(
+ "label.sequence_feature_settings_for_CDS_and_Protein"),
+ 600, 450);
+ }
+ featureSettingsUI
+ .setMinimumSize(new Dimension(FS_MIN_WIDTH, FS_MIN_HEIGHT));
+
+ featureSettingsUI.addInternalFrameListener(
+ new javax.swing.event.InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(
+ javax.swing.event.InternalFrameEvent evt)
+ {
+ for (int tab = 0; tab < featureSettingsPanels
+ .getTabCount();)
+ {
+ FeatureSettingsControllerGuiI fsettings = (FeatureSettingsControllerGuiI) featureSettingsPanels
+ .getTabComponentAt(tab);
+ if (fsettings != null)
+ {
+ featureSettingsPanels.removeTabAt(tab);
+ fsettings.featureSettings_isClosed();
+ }
+ else
+ {
+ tab++;
+ }
+ }
+ featureSettingsPanels = null;
+ featureSettingsUI = null;
+ };
+ });
+ featureSettingsUI.setLayer(JLayeredPane.PALETTE_LAYER);
+ }
+ }
+
+ /**
+ * tab names for feature settings
+ */
+ private String[] tabName = new String[] {
+ MessageManager.getString("label.CDS"),
+ MessageManager.getString("label.protein") };
+
+ /**
+ * create placeholder tabs which materialise the feature settings for a given
+ * view. Also reinitialises any tabs containing stale feature settings
+ */
+ private void createDummyTabs()
+ {
+ for (int tabIndex = 0; tabIndex < 2; tabIndex++)
+ {
+ JPanel dummyTab = new JPanel();
+ featureSettingsPanels.addTab(tabName[tabIndex], dummyTab);
+ }
+ }
+
+ private void replaceWithDummyTab(FeatureSettingsControllerI toClose)
+ {
+ Component dummyTab = null;
+ for (int tabIndex = 0; tabIndex < 2; tabIndex++)
+ {
+ if (featureSettingsPanels.getTabCount() > tabIndex)
+ {
+ dummyTab = featureSettingsPanels.getTabComponentAt(tabIndex);
+ if (dummyTab instanceof FeatureSettingsControllerGuiI
+ && !dummyTab.isVisible())
+ {
+ featureSettingsPanels.removeTabAt(tabIndex);
+ // close the feature Settings tab
+ ((FeatureSettingsControllerGuiI) dummyTab)
+ .featureSettings_isClosed();
+ // create a dummy tab in its place
+ dummyTab = new JPanel();
+ featureSettingsPanels.insertTab(tabName[tabIndex], null, dummyTab,
+ MessageManager.formatMessage(
+ "label.sequence_feature_settings_for",
+ tabName[tabIndex]),
+ tabIndex);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void closeFeatureSettings(
+ FeatureSettingsControllerI featureSettings,
+ boolean closeContainingFrame)
+ {
+ if (featureSettingsUI != null)
+ {
+ if (closeContainingFrame)
+ {
+ try
+ {
+ featureSettingsUI.setClosed(true);
+ } catch (Exception x)
+ {
+ }
+ featureSettingsUI = null;
+ }
+ else
+ {
+ replaceWithDummyTab(featureSettings);
+ }
+ }
+ }
+
+ @Override
+ public boolean isFeatureSettingsOpen()
+ {
+ return featureSettingsUI != null && !featureSettingsUI.isClosed();
+ }
+}
\ No newline at end of file
public static String formatMessage(String key, Object... params)
{
- return MessageFormat.format(rb.getString(key), params);
+ try
+ {
+ return MessageFormat.format(rb.getString(key), params);
+ } catch (Exception e)
+ {
+ log.warning("I18N missing: " + loc + "\t" + key);
+ // e.printStackTrace();
+
+ }
+ String value = "[missing key] " + key + "";
+ for (Object p : params)
+ {
+ value += " '" + p.toString() + "'";
+ }
+ return value;
}
public static String formatMessage(String key, String[] params)
{
- return MessageFormat.format(rb.getString(key), (Object[]) params);
+ return formatMessage(key, (Object[]) params);
}
/**