import jalview.api.FeatureColourI;
import jalview.api.FeatureSettingsControllerI;
import jalview.bin.Cache;
-import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceI;
import jalview.gui.Help.HelpId;
import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
import jalview.schemabinding.version2.JalviewUserColours;
import jalview.schemes.FeatureColour;
import jalview.util.Format;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
JPanel transPanel = new JPanel(new GridLayout(1, 2));
+ private static final int MIN_WIDTH = 400;
+
+ private static final int MIN_HEIGHT = 400;
+
public FeatureSettings(AlignFrame af)
{
this.af = af;
public void mousePressed(MouseEvent evt)
{
selectedRow = table.rowAtPoint(evt.getPoint());
- if (SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
table.getValueAt(selectedRow, 1), fr.getMinMax(),
else if (evt.getClickCount() == 2)
{
boolean invertSelection = evt.isAltDown();
- boolean ctrlDown = Platform.isControlDown(evt);
- boolean toggleSelection = ctrlDown;
- boolean extendSelection = evt.isShiftDown() || ctrlDown;
+ boolean toggleSelection = Platform.isControlDown(evt);
+ boolean extendSelection = evt.isShiftDown();
fr.ap.alignFrame.avc.markColumnsContainingFeatures(
invertSelection, extendSelection, toggleSelection,
(String) table.getValueAt(selectedRow, 0));
}
}
- // isPopupTrigger fires on mouseReleased on Mac
+ // isPopupTrigger fires on mouseReleased on Windows
@Override
public void mouseReleased(MouseEvent evt)
{
MessageManager.getString("label.sequence_feature_settings"),
400, 450);
}
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
{
private boolean handlingUpdate = false;
/**
- * contains a float[3] for each feature type string. created by setTableData
+ * holds {featureCount, totalExtent} for each feature type
*/
Map<String, float[]> typeWidth = null;
@Override
synchronized public void discoverAllFeatureData()
{
- Vector<String> allFeatures = new Vector<String>();
- Vector<String> allGroups = new Vector<String>();
- SequenceFeature[] tmpfeatures;
- String group;
- for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
- {
- tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
- .getSequenceFeatures();
- if (tmpfeatures == null)
- {
- continue;
- }
+ Set<String> allGroups = new HashSet<String>();
+ AlignmentI alignment = af.getViewport().getAlignment();
- int index = 0;
- while (index < tmpfeatures.length)
+ for (int i = 0; i < alignment.getHeight(); i++)
+ {
+ SequenceI seq = alignment.getSequenceAt(i);
+ for (String group : seq.getFeatures().getFeatureGroups(true))
{
- if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
+ if (group != null && !allGroups.contains(group))
{
- index++;
- continue;
+ allGroups.add(group);
+ checkGroupState(group);
}
-
- if (tmpfeatures[index].getFeatureGroup() != null)
- {
- group = tmpfeatures[index].featureGroup;
- if (!allGroups.contains(group))
- {
- allGroups.addElement(group);
- checkGroupState(group);
- }
- }
-
- if (!allFeatures.contains(tmpfeatures[index].getType()))
- {
- allFeatures.addElement(tmpfeatures[index].getType());
- }
- index++;
}
}
synchronized void resetTable(String[] groupChanged)
{
- if (resettingTable == true)
+ if (resettingTable)
{
return;
}
typeWidth = new Hashtable<String, float[]>();
// TODO: change avWidth calculation to 'per-sequence' average and use long
// rather than float
- float[] avWidth = null;
- SequenceFeature[] tmpfeatures;
- String group = null, type;
- Vector<String> visibleChecks = new Vector<String>();
-
- // Find out which features should be visible depending on which groups
- // are selected / deselected
- // and recompute average width ordering
+
+ Set<String> displayableTypes = new HashSet<String>();
+
+ /*
+ * determine which feature types may be visible depending on
+ * which groups are selected, and recompute average width data
+ */
for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
{
- tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
- .getSequenceFeatures();
- if (tmpfeatures == null)
- {
- continue;
- }
+ SequenceI seq = af.getViewport().getAlignment().getSequenceAt(i);
- int index = 0;
- while (index < tmpfeatures.length)
+ /*
+ * get the sequence's groups for positional features
+ * and keep track of which groups are visible
+ */
+ Set<String> groups = seq.getFeatures().getFeatureGroups(true);
+ Set<String> visibleGroups = new HashSet<String>();
+ for (String group : groups)
{
- group = tmpfeatures[index].featureGroup;
-
- if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
- {
- index++;
- continue;
- }
-
if (group == null || checkGroupState(group))
{
- type = tmpfeatures[index].getType();
- if (!visibleChecks.contains(type))
- {
- visibleChecks.addElement(type);
- }
- }
- if (!typeWidth.containsKey(tmpfeatures[index].getType()))
- {
- typeWidth.put(tmpfeatures[index].getType(),
- avWidth = new float[3]);
- }
- else
- {
- avWidth = typeWidth.get(tmpfeatures[index].getType());
- }
- avWidth[0]++;
- if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
- {
- avWidth[1] += 1 + tmpfeatures[index].getBegin()
- - tmpfeatures[index].getEnd();
+ visibleGroups.add(group);
}
- else
+ }
+
+ /*
+ * get distinct feature types for visible groups
+ * record distinct visible types, and their count and total length
+ */
+ Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
+ visibleGroups.toArray(new String[visibleGroups.size()]));
+ for (String type : types)
+ {
+ displayableTypes.add(type);
+ float[] avWidth = typeWidth.get(type);
+ if (avWidth == null)
{
- avWidth[1] += 1 + tmpfeatures[index].getEnd()
- - tmpfeatures[index].getBegin();
+ avWidth = new float[2];
+ typeWidth.put(type, avWidth);
}
- index++;
+ // todo this could include features with a non-visible group
+ // - do we greatly care?
+ // todo should we include non-displayable features here, and only
+ // update when features are added?
+ avWidth[0] += seq.getFeatures().getFeatureCount(true, type);
+ avWidth[1] += seq.getFeatures().getTotalFeatureLength(type);
}
}
- int fSize = visibleChecks.size();
- Object[][] data = new Object[fSize][3];
+ Object[][] data = new Object[displayableTypes.size()][3];
int dataIndex = 0;
if (fr.hasRenderOrder())
List<String> frl = fr.getRenderOrder();
for (int ro = frl.size() - 1; ro > -1; ro--)
{
- type = frl.get(ro);
+ String type = frl.get(ro);
- if (!visibleChecks.contains(type))
+ if (!displayableTypes.contains(type))
{
continue;
}
data[dataIndex][2] = new Boolean(af.getViewport()
.getFeaturesDisplayed().isVisible(type));
dataIndex++;
- visibleChecks.removeElement(type);
+ displayableTypes.remove(type);
}
}
- fSize = visibleChecks.size();
- for (int i = 0; i < fSize; i++)
+ /*
+ * process any extra features belonging only to
+ * a group which was just selected
+ */
+ while (!displayableTypes.isEmpty())
{
- // These must be extra features belonging to the group
- // which was just selected
- type = visibleChecks.elementAt(i).toString();
+ String type = displayableTypes.iterator().next();
data[dataIndex][0] = type;
data[dataIndex][1] = fr.getFeatureStyle(type);
data[dataIndex][2] = new Boolean(true);
dataIndex++;
+ displayableTypes.remove(type);
}
if (originalData == null)
void load()
{
- JalviewFileChooser chooser = new JalviewFileChooser(
- jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
- new String[] { "fc" },
- new String[] { "Sequence Feature Colours" },
+ JalviewFileChooser chooser = new JalviewFileChooser("fc",
"Sequence Feature Colours");
- chooser.setFileView(new jalview.io.JalviewFileView());
+ chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(MessageManager
.getString("label.load_feature_colours"));
chooser.setToolTipText(MessageManager.getString("action.load"));
void save()
{
- JalviewFileChooser chooser = new JalviewFileChooser(
- Cache.getProperty("LAST_DIRECTORY"),
- new String[] { "fc" },
- new String[] { "Sequence Feature Colours" },
+ JalviewFileChooser chooser = new JalviewFileChooser("fc",
"Sequence Feature Colours");
- chooser.setFileView(new jalview.io.JalviewFileView());
+ chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(MessageManager
.getString("label.save_feature_colours"));
chooser.setToolTipText(MessageManager.getString("action.save"));
public void noDasSourceActive()
{
complete();
- JOptionPane
+ JvOptionPane
.showInternalConfirmDialog(
Desktop.desktop,
MessageManager
.getString("label.no_das_sources_selected_warn"),
MessageManager
.getString("label.no_das_sources_selected_title"),
- JOptionPane.DEFAULT_OPTION,
- JOptionPane.INFORMATION_MESSAGE);
+ JvOptionPane.DEFAULT_OPTION,
+ JvOptionPane.INFORMATION_MESSAGE);
}
// ///////////////////////////////////////////////////////////////////////