<strong>User Defined Colours</strong>
</p>
<p>
- <img src="userDefined_java6.gif" width="815" height="402">
+ <img src="userDefined_java7.gif" width="815" height="402">
</p>
<p>
You may define any number of new colour schemes, each with a unique
The <strong>Case Sensitive</strong> option allows you to choose
distinct colours for upper and lower case residue codes.
<p>
- The <strong>Lower Case Colour</strong> option allows you to apply a selected colour
+ The <strong>Colour All Lower Case </strong> option allows you to apply a selected colour
to all lower case residues.
<p>
Click <strong>Apply</strong> or <strong>OK</strong> to set your new
<br> Any saved colour schemes will be automatically loaded the
next time you use Jalview.
<br>
- <br>
- <em>Note: the screenshot shows the appearance when running Java
- version 6. For Java 7 (from Jalview 2.8.2) only the Swatches colour
- chooser is currently supported (for reasons of available screen
- space).</em>
- <p />
</body>
</html>
action.show_hidden_markers = Show Hidden Markers
action.find = Find
action.undefine_groups = Undefine Groups
-action.create_groups = Create Groups
action.make_groups_selection = Make Groups For Selection
action.copy = Copy
action.cut = Cut
label.edit_name_and_description_current_group = Edit name and description of current group
label.from_file = From File
label.enter_pdb_id = Enter PDB Id (or pdbid:chaincode)
-label.text_colour = Text Colour
-action.set_text_colour = Text Colour...
+label.text_colour = Text Colour...
label.structure = Structure
label.show_pdbstruct_dialog = 3D Structure Data...
label.view_rna_structure = VARNA 2D Structure
action.show_hidden_markers = Mostrar marcadores ocultos
action.find = Buscar
action.undefine_groups = Grupos sin definir
-action.create_groups = Crear grupos
action.make_groups_selection = Hacer grupos para seleccionar
action.copy = Copiar
action.cut = Cortar
label.edit_name_and_description_current_group = Editar el nombre y la descripción del grupo actual
label.from_file = desde fichero
label.enter_pdb_id = Introducir PDB Id
-label.text_colour = Color del texto
+label.text_colour = Color de texto...
label.structure = Estructura
label.create_sequence_details_report_annotation_for = Anotación para {0}
label.sequence_details_for = Detalles de la secuencia para {0}
action.export_annotations=Exportar Anotaciones
action.set_as_reference=Marcar como Referencia
action.unmark_as_reference=Desmarcar como Referencia
-action.set_text_colour=Color de Texto...
label.chimera_failed=Error al abrir Chimera - está instalado?\nCompruebe ruta en Preferencias, Estructura
label.find=Buscar
label.select_pdb_file=Seleccionar Fichero PDB
warn.name_cannot_be_duplicate = Los nombres URL definidos por el usuario deben ser únicos y no pueden ser ids de MIRIAM
label.invalid_name = Nombre inválido !
label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
-label.urllinks = Enlaces
\ No newline at end of file
+label.urllinks = Enlaces
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
+import java.awt.MenuShortcut;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
{
delete_actionPerformed();
}
+ else if (source == createGroup)
+ {
+ createGroup_actionPerformed();
+ }
+ else if (source == unGroup)
+ {
+ unGroup_actionPerformed();
+ }
else if (source == grpsFromSelection)
{
makeGrpsFromSelection_actionPerformed();
.getString("action.make_groups_selection"));
grpsFromSelection.addActionListener(this);
createGroup.setLabel(MessageManager.getString("action.create_group"));
+ createGroup.addActionListener(this);
unGroup.setLabel(MessageManager.getString("action.remove_group"));
+ unGroup.addActionListener(this);
+
annotationColumnSelection.setLabel(MessageManager
.getString("action.select_by_annotation"));
annotationColumnSelection.addActionListener(this);
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Vector;
public class AnnotationColourChooser extends Panel implements
ColourSchemeI oldcs;
- Hashtable oldgroupColours;
+ Map<SequenceGroup, ColourSchemeI> oldgroupColours;
- jalview.datamodel.AlignmentAnnotation currentAnnotation;
+ /*
+ * map from annotation to its menu item display label
+ * - so we know which item to pre-select on restore
+ */
+ private Map<AlignmentAnnotation, String> annotationLabels;
+
+ AlignmentAnnotation currentAnnotation;
boolean adjusting = false;
oldcs = av.getGlobalColourScheme();
if (av.getAlignment().getGroups() != null)
{
- oldgroupColours = new Hashtable();
+ oldgroupColours = new HashMap<SequenceGroup, ColourSchemeI>();
for (SequenceGroup sg : ap.av.getAlignment().getGroups())
{
- if (sg.getColourScheme() != null)
- {
- oldgroupColours.put(sg, sg.getColourScheme());
- }
- else
- {
- oldgroupColours.put(sg, "null");
- }
+ oldgroupColours.put(sg, sg.getColourScheme());
}
}
this.av = av;
// seqAssociated.setState(acg.isSeqAssociated());
}
- Vector<String> list = new Vector<String>();
- int index = 1;
- for (int i = 0; i < anns.length; i++)
- {
- String label = anns[i].label;
- if (anns[i].sequenceRef != null)
- {
- label = label + "_" + anns[i].sequenceRef.getName();
- }
- if (!list.contains(label))
- {
- list.addElement(label);
- }
- else
- {
- list.addElement(label + "_" + (index++));
- }
- }
+ Vector<String> list = getAnnotationItems();
for (int i = 0; i < list.size(); i++)
{
if (oldcs instanceof AnnotationColourGradient)
{
AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
- annotations.select(acg.getAnnotation());
+ String label = annotationLabels.get(acg.getAnnotation());
+ annotations.select(label);
switch (acg.getAboveThreshold())
{
case AnnotationColourGradient.NO_THRESHOLD:
MessageManager
.getString("error.implementation_error_dont_know_threshold_annotationcolourgradient"));
}
- thresholdIsMin.setState(acg.thresholdIsMinMax);
+ thresholdIsMin.setState(acg.isThresholdIsMinMax());
thresholdValue.setText("" + acg.getAnnotationThreshold());
}
validate();
}
+ /**
+ * Builds and returns a list of menu items (display text) for choice of
+ * annotation. Also builds a map between annotations and their display labels.
+ *
+ * @return
+ */
+ protected Vector<String> getAnnotationItems()
+ {
+ // TODO remove duplication with gui.AnnotationRowFilter
+ // TODO add 'per sequence only' option / parameter
+
+ annotationLabels = new HashMap<AlignmentAnnotation, String>();
+ Vector<String> list = new Vector<String>();
+ AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
+ if (anns == null)
+ {
+ return list;
+ }
+ int index = 1;
+ for (int i = 0; i < anns.length; i++)
+ {
+ String label = anns[i].label;
+ if (anns[i].sequenceRef != null)
+ {
+ /*
+ * be helpful and include sequence id in label for
+ * sequence-associated annotation (JAL-2236)
+ */
+ label = label + "_" + anns[i].sequenceRef.getName();
+ }
+ if (!list.contains(label))
+ {
+ list.addElement(label);
+ annotationLabels.put(anns[i], label);
+ }
+ else
+ {
+ label = label + "_" + (index++);
+ list.addElement(label);
+ annotationLabels.put(anns[i], label);
+ }
+ }
+ return list;
+ }
+
private void setDefaultMinMax()
{
minColour.setBackground(av.applet.getDefaultColourParameter(
acg.setPredefinedColours(true);
}
- acg.thresholdIsMinMax = thresholdIsMin.getState();
+ acg.setThresholdIsMinMax(thresholdIsMin.getState());
av.setGlobalColourScheme(acg);
{
for (SequenceGroup sg : ap.av.getAlignment().getGroups())
{
-
if (sg.getColourScheme() == null)
{
continue;
currentAnnotation, minColour.getBackground(), maxColour
.getBackground(), aboveThreshold));
}
-
}
}
{
for (SequenceGroup sg : ap.av.getAlignment().getGroups())
{
- Object cs = oldgroupColours.get(sg);
- if (cs instanceof ColourSchemeI)
- {
- sg.setColourScheme((ColourSchemeI) cs);
- }
- else
- {
- // probably the "null" string we set it to if it was null originally.
- sg.setColourScheme(null);
- }
+ sg.setColourScheme(oldgroupColours.get(sg));
}
}
ap.paintAlignment(true);
-
}
@Override
import jalview.datamodel.PDBEntry;
import jalview.gui.UserDefinedColours;
+import jalview.schemes.ColourSchemeLoader;
import jalview.schemes.ColourSchemes;
import jalview.schemes.UserColourScheme;
import jalview.structure.StructureImportSettings;
String file = st.nextToken();
try
{
- UserColourScheme ucs = ColourSchemes.loadColourScheme(file);
+ UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
if (ucs != null)
{
if (coloursFound.length() > 0)
}
else if (dataset == null && data != null)
{
+ if (data == this)
+ {
+ throw new IllegalArgumentException("Circular dataset reference");
+ }
if (!(data instanceof Alignment))
{
throw new Error(
*/
package jalview.datamodel;
-import jalview.analysis.Rna;
-import jalview.analysis.SecStrConsensus.SimpleBP;
-import jalview.analysis.WUSSParseException;
-
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import jalview.analysis.Rna;
+import jalview.analysis.SecStrConsensus.SimpleBP;
+import jalview.analysis.WUSSParseException;
+
/**
* DOCUMENT ME!
*
@Override
public String toString()
{
+ if (annotations == null)
+ {
+ return "";
+ }
StringBuilder buffer = new StringBuilder(256);
for (int i = 0; i < annotations.length; i++)
AnnotatedCollectionI ref = ctx;
while (ref != null)
{
- if (ref == this)
+ if (ref == this || ref.getContext() == ctx)
{
throw new IllegalArgumentException(
"Circular reference in SequenceGroup.context");
*/
if (!cs.isVisible(r))
{
- // col = ColorUtils.darkerThan(col);
col = Color.GRAY;
}
*/
if (!cs.isVisible(r))
{
- // colour = ColorUtils.darkerThan(colour);
colour = Color.GRAY;
}
*/
newap.av.replaceMappings(viewport.getAlignment());
+ /*
+ * start up cDNA consensus (if applicable) now mappings are in place
+ */
+ if (newap.av.initComplementConsensus())
+ {
+ newap.refresh(true); // adjust layout of annotations
+ }
+
newap.av.viewName = getNewViewName(viewTitle);
addAlignmentPanel(newap, true);
{
return this.dontScrollComplement;
}
+
+ /**
+ * Redraw sensibly.
+ *
+ * @adjustHeight if true, try to recalculate panel height for visible
+ * annotations
+ */
+ protected void refresh(boolean adjustHeight)
+ {
+ validateAnnotationDimensions(adjustHeight);
+ addNotify();
+ if (adjustHeight)
+ {
+ // sort, repaint, update overview
+ paintAlignment(true);
+ }
+ else
+ {
+ // lightweight repaint
+ repaint();
+ }
+ }
}
package jalview.gui;
import jalview.bin.Cache;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.GraphLine;
import jalview.datamodel.SequenceGroup;
import jalview.schemes.AnnotationColourGradient;
import jalview.schemes.ColourSchemeI;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Hashtable;
+import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JInternalFrame;
@SuppressWarnings("serial")
public class AnnotationColourChooser extends AnnotationRowFilter
{
+ private static final int ONETHOUSAND = 1000;
- ColourSchemeI oldcs;
+ private ColourSchemeI oldcs;
- Hashtable<SequenceGroup, ColourSchemeI> oldgroupColours;
+ private JButton defColours;
- /**
- * enabled if the user is dragging the slider - try to keep updates to a
- * minimun
- */
+ private Hashtable<SequenceGroup, ColourSchemeI> oldgroupColours;
- JComboBox<String> annotations;
+ private JCheckBox useOriginalColours = new JCheckBox();
- JButton defColours = new JButton();
+ private JPanel minColour = new JPanel();
- JPanel jPanel1 = new JPanel();
+ private JPanel maxColour = new JPanel();
- JPanel jPanel2 = new JPanel();
-
- BorderLayout borderLayout1 = new BorderLayout();
-
- private JComboBox<String> threshold = new JComboBox<String>();
+ private JCheckBox thresholdIsMin = new JCheckBox();
public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
{
if (oldcs instanceof AnnotationColourGradient)
{
AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
- currentColours.setSelected(acg.isPredefinedColours()
+ useOriginalColours.setSelected(acg.isPredefinedColours()
|| acg.getBaseColour() != null);
if (!acg.isPredefinedColours() && acg.getBaseColour() == null)
{
seqAssociated.setSelected(acg.isSeqAssociated());
}
- annotations = new JComboBox<String>(
- getAnnotationItems(seqAssociated.isSelected()));
+ Vector<String> annotItems = getAnnotationItems(seqAssociated
+ .isSelected());
+ annotations = new JComboBox<String>(annotItems);
populateThresholdComboBox(threshold);
if (oldcs instanceof AnnotationColourGradient)
{
AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
- annotations.setSelectedItem(acg.getAnnotation());
+ String label = getAnnotationMenuLabel(acg.getAnnotation());
+ annotations.setSelectedItem(label);
switch (acg.getAboveThreshold())
{
case AnnotationColourGradient.NO_THRESHOLD:
MessageManager
.getString("error.implementation_error_dont_know_about_threshold_setting"));
}
- thresholdIsMin.setSelected(acg.thresholdIsMinMax);
+ thresholdIsMin.setSelected(acg.isThresholdIsMinMax());
thresholdValue.setText("" + acg.getAnnotationThreshold());
}
- try
- {
- jbInit();
- } catch (Exception ex)
- {
- }
+ jbInit();
adjusting = false;
updateView();
frame.pack();
}
- public AnnotationColourChooser()
+ @Override
+ protected void jbInit()
{
- try
- {
- jbInit();
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
+ super.jbInit();
- private void jbInit() throws Exception
- {
minColour.setFont(JvSwingUtils.getLabelFont());
minColour.setBorder(BorderFactory.createEtchedBorder());
minColour.setPreferredSize(new Dimension(40, 20));
}
}
});
- ok.setOpaque(false);
- ok.setText(MessageManager.getString("action.ok"));
- ok.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- ok_actionPerformed();
- }
- });
- cancel.setOpaque(false);
- cancel.setText(MessageManager.getString("action.cancel"));
- cancel.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- cancel_actionPerformed();
- }
- });
+
+ defColours = new JButton();
defColours.setOpaque(false);
defColours.setText(MessageManager.getString("action.set_defaults"));
defColours.setToolTipText(MessageManager
}
});
- annotations.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- annotations_actionPerformed();
- }
- });
- getThreshold().addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- threshold_actionPerformed();
- }
- });
- thresholdValue.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- thresholdValue_actionPerformed();
- }
- });
- slider.setPaintLabels(false);
- slider.setPaintTicks(true);
- slider.setBackground(Color.white);
- slider.setEnabled(false);
- slider.setOpaque(false);
- slider.setPreferredSize(new Dimension(100, 32));
- thresholdValue.setEnabled(false);
- thresholdValue.setColumns(7);
- currentColours.setFont(JvSwingUtils.getLabelFont());
- currentColours.setOpaque(false);
- currentColours.setText(MessageManager
+ useOriginalColours.setFont(JvSwingUtils.getLabelFont());
+ useOriginalColours.setOpaque(false);
+ useOriginalColours.setText(MessageManager
.getString("label.use_original_colours"));
- currentColours.addActionListener(new ActionListener()
+ useOriginalColours.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- currentColours_actionPerformed();
+ originalColours_actionPerformed();
}
});
thresholdIsMin.setBackground(Color.white);
}
});
- this.setLayout(borderLayout1);
+ this.setLayout(new BorderLayout());
+ JPanel jPanel1 = new JPanel();
+ JPanel jPanel2 = new JPanel();
jPanel2.setLayout(new MigLayout("", "[left][center][right]", "[][][]"));
jPanel1.setBackground(Color.white);
jPanel2.setBackground(Color.white);
jPanel1.add(cancel);
jPanel2.add(annotations, "grow, wrap");
jPanel2.add(seqAssociated);
- jPanel2.add(currentColours);
+ jPanel2.add(useOriginalColours);
JPanel colpanel = new JPanel(new FlowLayout());
colpanel.setBackground(Color.white);
colpanel.add(minColour);
{
if (slider.isEnabled())
{
- if (currentColours.isSelected()
+ if (useOriginalColours.isSelected()
&& !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
{
updateView();
}
}
- public JComboBox<String> getThreshold()
+ public void originalColours_actionPerformed()
{
- return threshold;
- }
-
- public void setThreshold(JComboBox<String> threshold)
- {
- this.threshold = threshold;
- }
-
- public void currentColours_actionPerformed()
- {
- if (currentColours.isSelected())
+ boolean selected = useOriginalColours.isSelected();
+ if (selected)
{
reset();
}
- maxColour.setEnabled(!currentColours.isSelected());
- minColour.setEnabled(!currentColours.isSelected());
+ maxColour.setEnabled(!selected);
+ minColour.setEnabled(!selected);
+ thresholdIsMin.setEnabled(!selected);
updateView();
}
slider.setEnabled(true);
thresholdValue.setEnabled(true);
- thresholdIsMin.setEnabled(true);
+ thresholdIsMin.setEnabled(!useOriginalColours.isSelected());
if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
{
{
getCurrentAnnotation()
.setThreshold(
- new jalview.datamodel.GraphLine(
+ new GraphLine(
(getCurrentAnnotation().graphMax - getCurrentAnnotation().graphMin) / 2f,
"Threshold", Color.black));
}
if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
{
adjusting = true;
- float range = getCurrentAnnotation().graphMax * 1000
- - getCurrentAnnotation().graphMin * 1000;
+ float range = getCurrentAnnotation().graphMax * ONETHOUSAND
+ - getCurrentAnnotation().graphMin * ONETHOUSAND;
- slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
- slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
- slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
+ slider.setMinimum((int) (getCurrentAnnotation().graphMin * ONETHOUSAND));
+ slider.setMaximum((int) (getCurrentAnnotation().graphMax * ONETHOUSAND));
+ slider.setValue((int) (getCurrentAnnotation().threshold.value * ONETHOUSAND));
thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
slider.setMajorTickSpacing((int) (range / 10f));
slider.setEnabled(true);
thresholdValue.setEnabled(true);
adjusting = false;
}
- colorAlignmContaining(getCurrentAnnotation(), selectedThresholdItem);
+ colorAlignmentContaining(getCurrentAnnotation(), selectedThresholdItem);
ap.alignmentChanged();
// ensure all associated views (overviews, structures, etc) are notified of
ap.paintAlignment(true);
}
+ protected boolean colorAlignmentContaining(AlignmentAnnotation currentAnn, int selectedThresholdOption)
+ {
+
+ AnnotationColourGradient acg = null;
+ if (useOriginalColours.isSelected())
+ {
+ acg = new AnnotationColourGradient(currentAnn,
+ av.getGlobalColourScheme(), selectedThresholdOption);
+ }
+ else
+ {
+ acg = new AnnotationColourGradient(currentAnn,
+ minColour.getBackground(), maxColour.getBackground(),
+ selectedThresholdOption);
+ }
+ acg.setSeqAssociated(seqAssociated.isSelected());
+
+ if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
+ {
+ acg.setPredefinedColours(true);
+ }
+
+ acg.setThresholdIsMinMax(thresholdIsMin.isSelected());
+
+ av.setGlobalColourScheme(acg);
+
+ if (av.getAlignment().getGroups() != null)
+ {
+
+ for (SequenceGroup sg : ap.av.getAlignment().getGroups())
+ {
+ if (sg.cs == null)
+ {
+ continue;
+ }
+
+ if (useOriginalColours.isSelected())
+ {
+ sg.setColourScheme(new AnnotationColourGradient(currentAnn, sg
+ .getColourScheme(), selectedThresholdOption));
+ ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
+ .isSelected());
+ }
+ else
+ {
+ sg.setColourScheme(new AnnotationColourGradient(currentAnn,
+ minColour.getBackground(), maxColour.getBackground(),
+ selectedThresholdOption));
+ ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
+ .isSelected());
+ }
+ }
+ }
+ return false;
+ }
+
}
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
-import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
public class AnnotationColumnChooser extends AnnotationRowFilter implements
ItemListener
{
-
- private JComboBox<String> annotations;
-
- private JPanel actionPanel = new JPanel();
-
- private JPanel thresholdPanel = new JPanel();
-
private JPanel switchableViewsPanel = new JPanel(new CardLayout());
- private CardLayout switchableViewsLayout = (CardLayout) (switchableViewsPanel
- .getLayout());
-
- private JPanel noGraphFilterView = new JPanel();
-
- private JPanel graphFilterView = new JPanel();
-
private JPanel annotationComboBoxPanel = new JPanel();
- private BorderLayout borderLayout1 = new BorderLayout();
-
- private JComboBox<String> threshold = new JComboBox<String>();
-
private StructureFilterPanel gStructureFilterPanel;
private StructureFilterPanel ngStructureFilterPanel;
private ColumnSelection oldColumnSelection;
- public AnnotationColumnChooser()
- {
- try
- {
- jbInit();
- } catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
-
public AnnotationColumnChooser(AlignViewport av, final AlignmentPanel ap)
{
super(av, ap);
frame.pack();
}
- private void jbInit() throws Exception
+ @Override
+ protected void jbInit()
{
- ok.setOpaque(false);
- ok.setText(MessageManager.getString("action.ok"));
- ok.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- ok_actionPerformed();
- }
- });
-
- cancel.setOpaque(false);
- cancel.setText(MessageManager.getString("action.cancel"));
- cancel.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- cancel_actionPerformed();
- }
- });
-
- annotations.addItemListener(this);
- annotations.setToolTipText(MessageManager
- .getString("info.select_annotation_row"));
- threshold.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- threshold_actionPerformed();
- }
- });
-
- thresholdValue.setEnabled(false);
- thresholdValue.setColumns(7);
- thresholdValue.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- thresholdValue_actionPerformed();
- }
- });
-
- slider.setPaintLabels(false);
- slider.setPaintTicks(true);
- slider.setBackground(Color.white);
- slider.setEnabled(false);
- slider.setOpaque(false);
- slider.setPreferredSize(new Dimension(100, 32));
+ super.jbInit();
+ JPanel thresholdPanel = new JPanel();
thresholdPanel.setBorder(new TitledBorder(MessageManager
.getString("label.threshold_filter")));
thresholdPanel.setBackground(Color.white);
thresholdPanel.setFont(JvSwingUtils.getLabelFont());
thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
+ JPanel actionPanel = new JPanel();
actionPanel.setBackground(Color.white);
actionPanel.setFont(JvSwingUtils.getLabelFont());
+ JPanel graphFilterView = new JPanel();
graphFilterView.setLayout(new MigLayout("", "[left][right]", "[][]"));
graphFilterView.setBackground(Color.white);
+ JPanel noGraphFilterView = new JPanel();
noGraphFilterView.setLayout(new MigLayout("", "[left][right]", "[][]"));
noGraphFilterView.setBackground(Color.white);
switchableViewsPanel.add(graphFilterView,
AnnotationColumnChooser.GRAPH_VIEW);
- this.setLayout(borderLayout1);
+ this.setLayout(new BorderLayout());
this.add(annotationComboBoxPanel, java.awt.BorderLayout.PAGE_START);
this.add(switchableViewsPanel, java.awt.BorderLayout.CENTER);
this.add(actionPanel, java.awt.BorderLayout.SOUTH);
this.validate();
}
- public void updateThresholdPanelToolTip()
+ protected void updateThresholdPanelToolTip()
{
thresholdValue.setToolTipText("");
slider.setToolTipText("");
}
@Override
- public void reset()
+ protected void reset()
{
if (this.getOldColumnSelection() != null)
{
}
}
- public JComboBox<String> getThreshold()
- {
- return threshold;
- }
-
- public void setThreshold(JComboBox<String> threshold)
- {
- this.threshold = threshold;
- }
-
- public JComboBox<String> getAnnotations()
- {
- return annotations;
- }
-
- public void setAnnotations(JComboBox<String> annotations)
- {
- this.annotations = annotations;
- }
-
@Override
public void updateView()
{
selectedAnnotationChanged();
}
+ @Override
public void selectedAnnotationChanged()
{
String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
ngFurtherActionPanel.syncState();
ngStructureFilterPanel.syncState();
+ CardLayout switchableViewsLayout = (CardLayout) switchableViewsPanel
+ .getLayout();
switchableViewsLayout.show(switchableViewsPanel, currentView);
updateView();
}
aa[selectedRow].scaleColLabel = !aa[selectedRow].scaleColLabel;
}
- refresh(fullRepaint);
+ ap.refresh(fullRepaint);
}
/**
- * Redraw sensibly.
- *
- * @adjustHeight if true, try to recalculate panel height for visible
- * annotations
- */
- protected void refresh(boolean adjustHeight)
- {
- ap.validateAnnotationDimensions(adjustHeight);
- ap.addNotify();
- if (adjustHeight)
- {
- // sort, repaint, update overview
- ap.paintAlignment(true);
- }
- else
- {
- // lightweight repaint
- ap.repaint();
- }
- }
-
- /**
* DOCUMENT ME!
*
* @param e
// ann.visible = false;
// }
// }
- refresh(true);
+ ap.refresh(true);
}
});
pop.add(hideType);
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.GraphLine;
-import jalview.datamodel.SequenceGroup;
import jalview.schemes.AnnotationColourGradient;
import jalview.util.MessageManager;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Vector;
import javax.swing.JButton;
protected int[] annmap;
- protected boolean enableSeqAss = false;
-
- private AlignmentAnnotation currentAnnotation;
-
protected boolean adjusting = false;
- protected JCheckBox currentColours = new JCheckBox();
-
- protected JPanel minColour = new JPanel();
-
- protected JPanel maxColour = new JPanel();
-
protected JCheckBox seqAssociated = new JCheckBox();
- protected JCheckBox thresholdIsMin = new JCheckBox();
-
protected JSlider slider = new JSlider();
protected JTextField thresholdValue = new JTextField(20);
*/
protected boolean sliderDragging = false;
+ protected JComboBox<String> threshold = new JComboBox<String>();
+
+ protected JComboBox<String> annotations;
+
+ /*
+ * map from annotation to its menu item display label
+ * - so we know which item to pre-select on restore
+ */
+ private Map<AlignmentAnnotation, String> annotationLabels;
+
+ private AlignmentAnnotation currentAnnotation;
+
+ /**
+ * Constructor
+ *
+ * @param viewport
+ * @param alignPanel
+ */
+ public AnnotationRowFilter(AlignViewport viewport, final AlignmentPanel alignPanel)
+ {
+ this.av = viewport;
+ this.ap = alignPanel;
+ thresholdValue.addFocusListener(new FocusAdapter()
+ {
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ thresholdValue_actionPerformed();
+ }
+ });
+ }
+
protected void addSliderChangeListener()
{
});
}
- public AnnotationRowFilter(AlignViewport av, final AlignmentPanel ap)
- {
- this.av = av;
- this.ap = ap;
- thresholdValue.addFocusListener(new FocusAdapter()
- {
- @Override
- public void focusLost(FocusEvent e)
- {
- thresholdValue_actionPerformed();
- }
- });
- }
-
- public AnnotationRowFilter()
- {
-
- }
-
+/**
+ * Builds and returns a list of menu items (display text) for choice of
+ * annotation. Also builds maps between annotations, their positions in the
+ * list, and their display labels in the list.
+ *
+ * @param isSeqAssociated
+ * @return
+ */
public Vector<String> getAnnotationItems(boolean isSeqAssociated)
{
+ annotationLabels = new HashMap<AlignmentAnnotation, String>();
+
Vector<String> list = new Vector<String>();
int index = 1;
int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
+ seqAssociated.setEnabled(false);
for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
{
- if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
+ AlignmentAnnotation annotation = av.getAlignment()
+ .getAlignmentAnnotation()[i];
+ if (annotation.sequenceRef == null)
{
if (isSeqAssociated)
{
}
else
{
- enableSeqAss = true;
+ seqAssociated.setEnabled(true);
}
- String label = av.getAlignment().getAlignmentAnnotation()[i].label;
+ String label = annotation.label;
// add associated sequence ID if available
- if (!isSeqAssociated
- && av.getAlignment().getAlignmentAnnotation()[i].sequenceRef != null)
+ if (!isSeqAssociated && annotation.sequenceRef != null)
{
- label = label
- + "_"
- + av.getAlignment().getAlignmentAnnotation()[i].sequenceRef
- .getName();
+ label = label + "_" + annotation.sequenceRef.getName();
}
// make label unique
if (!list.contains(label))
{
anmap[list.size()] = i;
list.add(label);
+ annotationLabels.put(annotation, label);
}
else
{
if (!isSeqAssociated)
{
anmap[list.size()] = i;
- list.add(label + "_" + (index++));
+ label = label + "_" + (index++);
+ list.add(label);
+ annotationLabels.put(annotation, label);
}
}
}
return selectedThresholdItem;
}
- public void modelChanged()
- {
- seqAssociated.setEnabled(enableSeqAss);
- }
-
public void ok_actionPerformed()
{
try
}
}
- public void thresholdCheck_actionPerformed()
+ protected void thresholdCheck_actionPerformed()
{
updateView();
}
- public void annotations_actionPerformed()
+ protected void selectedAnnotationChanged()
{
updateView();
}
- public void threshold_actionPerformed()
+ protected void threshold_actionPerformed()
{
updateView();
}
- public void thresholdValue_actionPerformed()
+ protected void thresholdValue_actionPerformed()
{
try
{
}
}
- public void thresholdIsMin_actionPerformed()
+ protected void thresholdIsMin_actionPerformed()
{
updateView();
}
- protected void populateThresholdComboBox(JComboBox<String> threshold)
+ protected void populateThresholdComboBox(JComboBox<String> thresh)
{
- threshold.addItem(MessageManager
+ thresh.addItem(MessageManager
.getString("label.threshold_feature_no_threshold"));
- threshold.addItem(MessageManager
+ thresh.addItem(MessageManager
.getString("label.threshold_feature_above_threshold"));
- threshold.addItem(MessageManager
+ thresh.addItem(MessageManager
.getString("label.threshold_feature_below_threshold"));
}
- protected void seqAssociated_actionPerformed(JComboBox<String> annotations)
+ /**
+ * Rebuilds the drop-down list of annotations to choose from when the 'per
+ * sequence only' checkbox is checked or unchecked.
+ *
+ * @param anns
+ */
+ protected void seqAssociated_actionPerformed(JComboBox<String> anns)
{
adjusting = true;
- String cursel = (String) annotations.getSelectedItem();
- boolean isvalid = false, isseqs = seqAssociated.isSelected();
- annotations.removeAllItems();
+ String cursel = (String) anns.getSelectedItem();
+ boolean isvalid = false;
+ boolean isseqs = seqAssociated.isSelected();
+ anns.removeAllItems();
for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
{
if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
isvalid = true;
cursel = anitem;
}
- annotations.addItem(anitem);
+ anns.addItem(anitem);
}
- adjusting = false;
if (isvalid)
{
- annotations.setSelectedItem(cursel);
+ anns.setSelectedItem(cursel);
}
else
{
- if (annotations.getItemCount() > 0)
+ if (anns.getItemCount() > 0)
{
- annotations.setSelectedIndex(0);
+ anns.setSelectedIndex(0);
}
}
+ adjusting = false;
+
+ updateView();
}
protected void propagateSeqAssociatedThreshold(boolean allAnnotation,
}
}
- protected boolean colorAlignmContaining(AlignmentAnnotation currentAnn,
- int selectedThresholdOption)
+ public AlignmentAnnotation getCurrentAnnotation()
{
+ return currentAnnotation;
+ }
- AnnotationColourGradient acg = null;
- if (currentColours.isSelected())
- {
- acg = new AnnotationColourGradient(currentAnn,
- av.getGlobalColourScheme(), selectedThresholdOption);
- }
- else
- {
- acg = new AnnotationColourGradient(currentAnn,
- minColour.getBackground(), maxColour.getBackground(),
- selectedThresholdOption);
- }
- acg.setSeqAssociated(seqAssociated.isSelected());
+ protected void setCurrentAnnotation(AlignmentAnnotation annotation)
+ {
+ this.currentAnnotation = annotation;
+ }
- if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
- {
- acg.setPredefinedColours(true);
- }
+ protected abstract void valueChanged(boolean updateAllAnnotation);
- acg.thresholdIsMinMax = thresholdIsMin.isSelected();
+ protected abstract void updateView();
- av.setGlobalColourScheme(acg);
+ protected abstract void reset();
- if (av.getAlignment().getGroups() != null)
+ protected String getAnnotationMenuLabel(AlignmentAnnotation ann)
+ {
+ return annotationLabels.get(ann);
+ }
+
+ protected void jbInit()
+ {
+ ok.setOpaque(false);
+ ok.setText(MessageManager.getString("action.ok"));
+ ok.addActionListener(new ActionListener()
{
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ ok_actionPerformed();
+ }
+ });
- for (SequenceGroup sg : ap.av.getAlignment().getGroups())
+ cancel.setOpaque(false);
+ cancel.setText(MessageManager.getString("action.cancel"));
+ cancel.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
{
- if (sg.cs == null)
- {
- continue;
- }
+ cancel_actionPerformed();
+ }
+ });
- AnnotationColourGradient scheme = null;
- if (currentColours.isSelected())
- {
- scheme = new AnnotationColourGradient(currentAnn,
- sg.getColourScheme(), selectedThresholdOption);
- }
- else
- {
- scheme = new AnnotationColourGradient(currentAnn,
- minColour.getBackground(), maxColour.getBackground(),
- selectedThresholdOption);
- }
- scheme.setSeqAssociated(seqAssociated.isSelected());
- sg.setColourScheme(scheme);
+ annotations.addItemListener(new ItemListener()
+ {
+ @Override
+ public void itemStateChanged(ItemEvent e)
+ {
+ selectedAnnotationChanged();
}
- }
- return false;
+ });
+ annotations.setToolTipText(MessageManager
+ .getString("info.select_annotation_row"));
+
+ threshold.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ threshold_actionPerformed();
+ }
+ });
+
+ thresholdValue.setEnabled(false);
+ thresholdValue.setColumns(7);
+ thresholdValue.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ thresholdValue_actionPerformed();
+ }
+ });
+
+ slider.setPaintLabels(false);
+ slider.setPaintTicks(true);
+ slider.setBackground(Color.white);
+ slider.setEnabled(false);
+ slider.setOpaque(false);
+ slider.setPreferredSize(new Dimension(100, 32));
}
- public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation()
+ public JComboBox<String> getThreshold()
{
- return currentAnnotation;
+ return threshold;
}
- public void setCurrentAnnotation(
- jalview.datamodel.AlignmentAnnotation currentAnnotation)
+ public void setThreshold(JComboBox<String> thresh)
{
- this.currentAnnotation = currentAnnotation;
+ this.threshold = thresh;
}
- public abstract void valueChanged(boolean updateAllAnnotation);
-
- public abstract void updateView();
+ public JComboBox<String> getAnnotations()
+ {
+ return annotations;
+ }
- public abstract void reset();
+ public void setAnnotations(JComboBox<String> anns)
+ {
+ this.annotations = anns;
+ }
}
import jalview.bin.Cache;
import jalview.datamodel.AnnotatedCollectionI;
import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeLoader;
import jalview.schemes.ColourSchemes;
import jalview.schemes.ResidueColourScheme;
import jalview.schemes.UserColourScheme;
{
try
{
- UserColourScheme ucs = ColourSchemes.loadColourScheme(file);
+ UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
if (ucs != null
&& ColourSchemes.getInstance().nameExists(ucs.getName()))
{
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.GraphLine;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.RnaViewerModel;
import jalview.datamodel.SequenceGroup;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.FeatureColour;
-import jalview.schemes.ResidueColourScheme;
import jalview.schemes.ResidueProperties;
import jalview.schemes.UserColourScheme;
import jalview.structure.StructureSelectionManager;
return matchedFile;
}
+ /**
+ * Populates the AnnotationColours xml for save. This captures the settings of
+ * the options in the 'Colour by Annotation' dialog.
+ *
+ * @param acg
+ * @param userColours
+ * @param jms
+ * @return
+ */
private AnnotationColours constructAnnotationColours(
AnnotationColourGradient acg, List<UserColourScheme> userColours,
JalviewModelSequence jms)
AnnotationColours ac = new AnnotationColours();
ac.setAboveThreshold(acg.getAboveThreshold());
ac.setThreshold(acg.getAnnotationThreshold());
- ac.setAnnotation(acg.getAnnotation());
- if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
+ // 2.10.2 save annotationId (unique) not annotation label
+ ac.setAnnotation(acg.getAnnotation().annotationId);
+ if (acg.getBaseColour() instanceof UserColourScheme)
{
ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
userColours, jms));
@Override
public void run()
{
- JvOptionPane.showInternalMessageDialog(Desktop.desktop,
- finalErrorMessage, "Error "
- + (saving ? "saving" : "loading")
- + " Jalview file", JvOptionPane.WARNING_MESSAGE);
+ JvOptionPane
+ .showInternalMessageDialog(Desktop.desktop,
+ finalErrorMessage, "Error "
+ + (saving ? "saving" : "loading")
+ + " Jalview file",
+ JvOptionPane.WARNING_MESSAGE);
}
});
}
return af;
}
+ /**
+ * Reads saved data to restore Colour by Annotation settings
+ *
+ * @param viewAnnColour
+ * @param af
+ * @param al
+ * @param jms
+ * @param checkGroupAnnColour
+ * @return
+ */
private ColourSchemeI constructAnnotationColour(
AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
JalviewModelSequence jms, boolean checkGroupAnnColour)
{
boolean propagateAnnColour = false;
- ColourSchemeI cs = null;
AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
if (checkGroupAnnColour && al.getGroups() != null
&& al.getGroups().size() > 0)
// pre 2.8.1 behaviour
// check to see if we should transfer annotation colours
propagateAnnColour = true;
- for (jalview.datamodel.SequenceGroup sg : al.getGroups())
+ for (SequenceGroup sg : al.getGroups())
{
if (sg.getColourScheme() instanceof AnnotationColourGradient)
{
}
}
}
- // int find annotation
- if (annAlignment.getAlignmentAnnotation() != null)
+
+ /*
+ * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
+ */
+ String annotationId = viewAnnColour.getAnnotation();
+ AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
+
+ /*
+ * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
+ */
+ if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
{
for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
{
- if (annAlignment.getAlignmentAnnotation()[i].label
- .equals(viewAnnColour.getAnnotation()))
+ if (annotationId
+ .equals(annAlignment.getAlignmentAnnotation()[i].label))
{
- if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
- {
- annAlignment.getAlignmentAnnotation()[i]
- .setThreshold(new jalview.datamodel.GraphLine(
- viewAnnColour.getThreshold(), "Threshold",
- java.awt.Color.black)
-
- );
- }
-
- if (viewAnnColour.getColourScheme().equals(
- ResidueColourScheme.NONE))
- {
- cs = new AnnotationColourGradient(
- annAlignment.getAlignmentAnnotation()[i],
- new java.awt.Color(viewAnnColour.getMinColour()),
- new java.awt.Color(viewAnnColour.getMaxColour()),
- viewAnnColour.getAboveThreshold());
- }
- else if (viewAnnColour.getColourScheme().startsWith("ucs"))
- {
- cs = new AnnotationColourGradient(
- annAlignment.getAlignmentAnnotation()[i],
- getUserColourScheme(jms,
- viewAnnColour.getColourScheme()),
- viewAnnColour.getAboveThreshold());
- }
- else
- {
- cs = new AnnotationColourGradient(
- annAlignment.getAlignmentAnnotation()[i],
- ColourSchemeProperty.getColourScheme(al,
- viewAnnColour.getColourScheme()),
- viewAnnColour.getAboveThreshold());
- }
- if (viewAnnColour.hasPerSequence())
- {
- ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
- .isPerSequence());
- }
- if (viewAnnColour.hasPredefinedColours())
- {
- ((AnnotationColourGradient) cs)
- .setPredefinedColours(viewAnnColour
- .isPredefinedColours());
- }
- if (propagateAnnColour && al.getGroups() != null)
- {
- // Also use these settings for all the groups
- for (int g = 0; g < al.getGroups().size(); g++)
- {
- jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
-
- if (sg.cs == null)
- {
- continue;
- }
+ matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
+ break;
+ }
+ }
+ }
+ if (matchedAnnotation == null)
+ {
+ System.err.println("Failed to match annotation colour scheme for "
+ + annotationId);
+ return null;
+ }
+ if (matchedAnnotation.getThreshold() == null)
+ {
+ matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
+ "Threshold", Color.black));
+ }
- /*
- * if (viewAnnColour.getColourScheme().equals(ResidueColourScheme.NONE)) { sg.cs =
- * new AnnotationColourGradient(
- * annAlignment.getAlignmentAnnotation()[i], new
- * java.awt.Color(viewAnnColour. getMinColour()), new
- * java.awt.Color(viewAnnColour. getMaxColour()),
- * viewAnnColour.getAboveThreshold()); } else
- */
- {
- sg.setColourScheme(new AnnotationColourGradient(
- annAlignment.getAlignmentAnnotation()[i], sg
- .getColourScheme(), viewAnnColour
- .getAboveThreshold()));
- if (cs instanceof AnnotationColourGradient)
- {
- if (viewAnnColour.hasPerSequence())
- {
- ((AnnotationColourGradient) cs)
- .setSeqAssociated(viewAnnColour.isPerSequence());
- }
- if (viewAnnColour.hasPredefinedColours())
- {
- ((AnnotationColourGradient) cs)
- .setPredefinedColours(viewAnnColour
- .isPredefinedColours());
- }
- }
- }
+ AnnotationColourGradient cs = null;
+ if (viewAnnColour.getColourScheme().equals("None"))
+ {
+ cs = new AnnotationColourGradient(matchedAnnotation, new Color(
+ viewAnnColour.getMinColour()), new Color(
+ viewAnnColour.getMaxColour()),
+ viewAnnColour.getAboveThreshold());
+ }
+ else if (viewAnnColour.getColourScheme().startsWith("ucs"))
+ {
+ cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
+ jms, viewAnnColour.getColourScheme()),
+ viewAnnColour.getAboveThreshold());
+ }
+ else
+ {
+ cs = new AnnotationColourGradient(matchedAnnotation,
+ ColourSchemeProperty.getColourScheme(al,
+ viewAnnColour.getColourScheme()),
+ viewAnnColour.getAboveThreshold());
+ }
- }
- }
+ boolean perSequenceOnly = viewAnnColour.isPerSequence();
+ boolean useOriginalColours = viewAnnColour.isPredefinedColours();
+ cs.setSeqAssociated(perSequenceOnly);
+ cs.setPredefinedColours(useOriginalColours);
- break;
+ if (propagateAnnColour && al.getGroups() != null)
+ {
+ // Also use these settings for all the groups
+ for (int g = 0; g < al.getGroups().size(); g++)
+ {
+ SequenceGroup sg = al.getGroups().get(g);
+ if (sg.getGroupColourScheme() == null)
+ {
+ continue;
}
+ AnnotationColourGradient groupScheme = new AnnotationColourGradient(
+ matchedAnnotation, sg.getColourScheme(),
+ viewAnnColour.getAboveThreshold());
+ sg.setColourScheme(groupScheme);
+ groupScheme.setSeqAssociated(perSequenceOnly);
+ groupScheme.setPredefinedColours(useOriginalColours);
}
}
return cs;
import jalview.io.FileFormats;
import jalview.io.FormatAdapter;
import jalview.io.SequenceAnnotationReport;
-import jalview.schemes.AnnotationColourGradient;
import jalview.schemes.Blosum62ColourScheme;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemes;
hideInsertions_actionPerformed(e);
}
});
- /*
- * annotationMenuItem.setText("By Annotation");
- * annotationMenuItem.addActionListener(new ActionListener() { public void
- * actionPerformed(ActionEvent actionEvent) {
- * annotationMenuItem_actionPerformed(actionEvent); } });
- */
+
groupMenu.add(sequenceSelDetails);
add(groupMenu);
add(sequenceMenu);
refresh();
}
- public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
- {
- SequenceGroup sg = getGroup();
- if (sg == null)
- {
- return;
- }
-
- AnnotationColourGradient acg = new AnnotationColourGradient(
- sequence.getAnnotation()[0], null,
- AnnotationColourGradient.NO_THRESHOLD);
-
- acg.setPredefinedColours(true);
- sg.setColourScheme(acg);
-
- refresh();
- }
-
/**
* DOCUMENT ME!
*
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.util.HashMap;
+import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
SequenceGroup sg;
- public void chooseColour(AlignmentPanel ap, SequenceGroup sg)
+ Color original1, original2;
+
+ int originalThreshold;
+
+ Map<SequenceGroup, Color> groupColour1;
+
+ Map<SequenceGroup, Color> groupColour2;
+
+ Map<SequenceGroup, Integer> groupThreshold;
+
+ /**
+ * Show a dialogue which allows the user to select two text colours and adjust
+ * a slider for the cross-over point
+ *
+ * @param alignPanel
+ * the AlignmentPanel context
+ * @param sequenceGroup
+ * the SequenceGroup context (only for group pop-menu option)
+ */
+ public void chooseColour(AlignmentPanel alignPanel, SequenceGroup sequenceGroup)
{
- this.ap = ap;
- this.sg = sg;
+ this.ap = alignPanel;
+ this.sg = sequenceGroup;
- int original1, original2, originalThreshold;
- if (sg == null)
- {
- original1 = ap.av.getTextColour().getRGB();
- original2 = ap.av.getTextColour2().getRGB();
- originalThreshold = ap.av.getThresholdTextColour();
- }
- else
- {
- original1 = sg.textColour.getRGB();
- original2 = sg.textColour2.getRGB();
- originalThreshold = sg.thresholdTextColour;
- }
+ saveInitialSettings();
final JSlider slider = new JSlider(0, 750, originalThreshold);
final JPanel col1 = new JPanel();
col1.setPreferredSize(new Dimension(40, 20));
col1.setBorder(BorderFactory.createEtchedBorder());
col1.setToolTipText(MessageManager.getString("label.dark_colour"));
- col1.setBackground(new Color(original1));
+ col1.setBackground(original1);
final JPanel col2 = new JPanel();
col2.setPreferredSize(new Dimension(40, 20));
col2.setBorder(BorderFactory.createEtchedBorder());
col2.setToolTipText(MessageManager.getString("label.light_colour"));
- col2.setBackground(new Color(original2));
+ col2.setBackground(original2);
final JPanel bigpanel = new JPanel(new BorderLayout());
JPanel panel = new JPanel();
bigpanel.add(panel, BorderLayout.CENTER);
int reply = JvOptionPane
.showInternalOptionDialog(
- ap,
+ alignPanel,
bigpanel,
MessageManager
.getString("label.adjunst_foreground_text_colour_threshold"),
if (reply == JvOptionPane.CANCEL_OPTION)
{
- if (sg == null)
- {
- ap.av.setTextColour(new Color(original1));
- ap.av.setTextColour2(new Color(original2));
- ap.av.setThresholdTextColour(originalThreshold);
- }
- else
+ restoreInitialSettings();
+ }
+ }
+
+ /**
+ * Restore initial settings on Cancel
+ */
+ protected void restoreInitialSettings()
+ {
+ if (sg == null)
+ {
+ ap.av.setTextColour(original1);
+ ap.av.setTextColour2(original2);
+ ap.av.setThresholdTextColour(originalThreshold);
+ }
+ else
+ {
+ sg.textColour = original1;
+ sg.textColour2 = original2;
+ sg.thresholdTextColour = originalThreshold;
+ }
+
+ /*
+ * if 'Apply To All Groups' was in force, there will be
+ * group-specific settings to restore as well
+ */
+ for (SequenceGroup group : this.groupColour1.keySet())
+ {
+ group.textColour = groupColour1.get(group);
+ group.textColour2 = groupColour2.get(group);
+ group.thresholdTextColour = groupThreshold.get(group);
+ }
+ }
+
+ /**
+ * Save settings on entry, for restore on Cancel
+ */
+ protected void saveInitialSettings()
+ {
+ groupColour1 = new HashMap<SequenceGroup, Color>();
+ groupColour2 = new HashMap<SequenceGroup, Color>();
+ groupThreshold = new HashMap<SequenceGroup, Integer>();
+
+ if (sg == null)
+ {
+ /*
+ * alignment scope
+ */
+ original1 = ap.av.getTextColour();
+ original2 = ap.av.getTextColour2();
+ originalThreshold = ap.av.getThresholdTextColour();
+ if (ap.av.getColourAppliesToAllGroups()
+ && ap.av.getAlignment().getGroups() != null)
{
- sg.textColour = new Color(original1);
- sg.textColour2 = new Color(original2);
- sg.thresholdTextColour = originalThreshold;
+ /*
+ * if applying changes to all groups, need to be able to
+ * restore group settings as well
+ */
+ for (SequenceGroup group : ap.av.getAlignment().getGroups())
+ {
+ groupColour1.put(group, group.textColour);
+ groupColour2.put(group, group.textColour2);
+ groupThreshold.put(group, group.thresholdTextColour);
+ }
}
}
+ else
+ {
+ /*
+ * Sequence group scope
+ */
+ original1 = sg.textColour;
+ original2 = sg.textColour2;
+ originalThreshold = sg.thresholdTextColour;
+ }
}
void colour1Changed(Color col)
return;
}
- for (SequenceGroup sg : ap.av.getAlignment().getGroups())
+ for (SequenceGroup group : ap.av.getAlignment().getGroups())
{
- sg.textColour = ap.av.getTextColour();
- sg.textColour2 = ap.av.getTextColour2();
- sg.thresholdTextColour = ap.av.getThresholdTextColour();
+ group.textColour = ap.av.getTextColour();
+ group.textColour2 = ap.av.getTextColour2();
+ group.thresholdTextColour = ap.av.getThresholdTextColour();
}
}
public void run()
{
PrinterJob printJob = PrinterJob.getPrinterJob();
- PageFormat pf = printJob.pageDialog(printJob.defaultPage());
+ PageFormat defaultPage = printJob.defaultPage();
+ PageFormat pf = printJob.pageDialog(defaultPage);
+
+ if (defaultPage == pf)
+ {
+ /*
+ * user cancelled
+ */
+ return;
+ }
printJob.setPrintable(this, pf);
import jalview.schemabinding.version2.Colour;
import jalview.schemabinding.version2.JalviewUserColours;
import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeLoader;
import jalview.schemes.ColourSchemes;
import jalview.schemes.ResidueProperties;
import jalview.schemes.UserColourScheme;
private static final String LAST_DIRECTORY = "LAST_DIRECTORY";
- private static final int MY_FRAME_HEIGHT = 420;
+ private static final int MY_FRAME_HEIGHT = 440;
private static final int MY_FRAME_WIDTH = 810;
{
JButton button = null;
final Color newColour = colorChooser.getColor();
- for (int i = 0; i < selectedButtons.size(); i++)
- {
- button = selectedButtons.get(i);
- button.setBackground(newColour);
- button.setForeground(ColorUtils.brighterThan(newColour));
- }
if (lcaseColour.isSelected())
{
+ selectedButtons.clear();
for (int i = 0; i < lowerCaseButtons.size(); i++)
{
button = lowerCaseButtons.get(i);
button.setForeground(ColorUtils.brighterThan(button.getBackground()));
}
}
+ for (int i = 0; i < selectedButtons.size(); i++)
+ {
+ button = selectedButtons.get(i);
+ button.setBackground(newColour);
+ button.setForeground(ColorUtils.brighterThan(newColour));
+ }
}
/**
ucs.setLowerCaseColours(newColours);
}
- // if (ap != null)
- // {
- // ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
- // }
-
return ucs;
}
File choice = chooser.getSelectedFile();
Cache.setProperty(LAST_DIRECTORY, choice.getParent());
- UserColourScheme ucs = ColourSchemes.loadColourScheme(choice
+ UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(choice
.getAbsolutePath());
Color[] colors = ucs.getColours();
schemeName.setText(ucs.getSchemeName());
{
colours = colours.substring(0, colours.indexOf("|"));
}
- ret = ColourSchemes.loadColourScheme(colours);
+ ret = ColourSchemeLoader.loadColourScheme(colours);
}
if (ret == null)
protected JMenu colourMenu = new JMenu();
- protected JRadioButtonMenuItem textColour;
+ protected JMenuItem textColour;
protected JCheckBoxMenuItem conservationMenuItem;
});
JMenuItem createGroup = new JMenuItem(
- MessageManager.getString("action.create_groups"));
+ MessageManager.getString("action.create_group"));
keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit
.getDefaultToolkit().getMenuShortcutKeyMask(), false);
al = new ActionListener()
formatMenu.setText(MessageManager.getString("action.format"));
JMenu selectMenu = new JMenu(MessageManager.getString("action.select"));
+
idRightAlign.setText(MessageManager
.getString("label.right_align_sequence_id"));
idRightAlign.addActionListener(new ActionListener()
// selectMenu.add(listenToViewSelections);
}
+ protected void configureSelectMenu()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
/**
* Constructs the entries on the Colour menu (but does not add them to the
* menu).
}
});
- textColour = new JRadioButtonMenuItem(
- MessageManager.getString("action.set_text_colour"));
+ textColour = new JMenuItem(
+ MessageManager.getString("label.text_colour"));
textColour.addActionListener(new ActionListener()
{
@Override
import jalview.datamodel.GraphLine;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
+import jalview.renderer.AnnotationRenderer;
+import jalview.util.Comparison;
import java.awt.Color;
import java.util.IdentityHashMap;
public static final int ABOVE_THRESHOLD = 1;
- public AlignmentAnnotation annotation;
+ private final AlignmentAnnotation annotation;
- int aboveAnnotationThreshold = -1;
+ private final int aboveAnnotationThreshold;
public boolean thresholdIsMinMax = false;
- GraphLine annotationThreshold;
+ private GraphLine annotationThreshold;
- float r1, g1, b1, rr, gg, bb;
+ private int redMin;
+
+ private int greenMin;
+
+ private int blueMin;
+
+ private int redRange;
+
+ private int greenRange;
+
+ private int blueRange;
private boolean predefinedColours = false;
*/
private boolean noGradient = false;
- IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
+ private IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
@Override
public ColourSchemeI getInstance(AnnotatedCollectionI sg,
acg.thresholdIsMinMax = thresholdIsMinMax;
acg.annotationThreshold = (annotationThreshold == null) ? null
: new GraphLine(annotationThreshold);
- acg.r1 = r1;
- acg.g1 = g1;
- acg.b1 = b1;
- acg.rr = rr;
- acg.gg = gg;
- acg.bb = bb;
+ acg.redMin = redMin;
+ acg.greenMin = greenMin;
+ acg.blueMin = blueMin;
+ acg.redRange = redRange;
+ acg.greenRange = greenRange;
+ acg.blueRange = blueRange;
acg.predefinedColours = predefinedColours;
acg.seqAssociated = seqAssociated;
acg.noGradient = noGradient;
annotationThreshold = annotation.threshold;
}
// clear values so we don't get weird black bands...
- r1 = 254;
- g1 = 254;
- b1 = 254;
- rr = 0;
- gg = 0;
- bb = 0;
+ redMin = 254;
+ greenMin = 254;
+ blueMin = 254;
+ redRange = 0;
+ greenRange = 0;
+ blueRange = 0;
noGradient = true;
checkLimits();
annotationThreshold = annotation.threshold;
}
- r1 = minColour.getRed();
- g1 = minColour.getGreen();
- b1 = minColour.getBlue();
+ redMin = minColour.getRed();
+ greenMin = minColour.getGreen();
+ blueMin = minColour.getBlue();
- rr = maxColour.getRed() - r1;
- gg = maxColour.getGreen() - g1;
- bb = maxColour.getBlue() - b1;
+ redRange = maxColour.getRed() - redMin;
+ greenRange = maxColour.getGreen() - greenMin;
+ blueRange = maxColour.getBlue() - blueMin;
noGradient = false;
checkLimits();
float aamin = 0f, aamax = 0f;
- public String getAnnotation()
+ public AlignmentAnnotation getAnnotation()
{
- return annotation.label;
+ return annotation;
}
public int getAboveThreshold()
public Color getMinColour()
{
- return new Color((int) r1, (int) g1, (int) b1);
+ return new Color(redMin, greenMin, blueMin);
}
public Color getMaxColour()
{
- return new Color((int) (r1 + rr), (int) (g1 + gg), (int) (b1 + bb));
+ return new Color(redMin + redRange, greenMin + greenRange, blueMin
+ + blueRange);
}
/**
}
/**
- * DOCUMENT ME!
+ * Returns the colour for a given character and position in a sequence
*
- * @param n
- * DOCUMENT ME!
+ * @param c
+ * the residue character
* @param j
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * the aligned position
+ * @param seq
+ * the sequence
+ * @return
*/
@Override
public Color findColour(char c, int j, SequenceI seq)
{
- Color currentColour = Color.white;
- AlignmentAnnotation annotation = (seqAssociated && seqannot != null ? seqannot
+ /*
+ * locate the annotation we are configured to colour by
+ */
+ AlignmentAnnotation ann = (seqAssociated && seqannot != null ? seqannot
.get(seq) : this.annotation);
- if (annotation == null)
+
+ /*
+ * if gap or no annotation at position, no colour (White)
+ */
+ if (ann == null || ann.annotations == null
+ || j >= ann.annotations.length || ann.annotations[j] == null
+ || Comparison.isGap(c))
{
- return currentColour;
+ return Color.white;
}
- // if ((threshold == 0) || aboveThreshold(c, j))
- // {
- if (annotation.annotations != null && j < annotation.annotations.length
- && annotation.annotations[j] != null
- && !jalview.util.Comparison.isGap(c))
+
+ Annotation aj = ann.annotations[j];
+ // 'use original colours' => colourScheme != null
+ // -> look up colour to be used
+ // predefined colours => preconfigured shading
+ // -> only use original colours reference if thresholding enabled &
+ // minmax exists
+ // annotation.hasIcons => null or black colours replaced with glyph
+ // colours
+ // -> reuse original colours if present
+ // -> if thresholding enabled then return colour on non-whitespace glyph
+
+ /*
+ * if threshold applies, and annotation fails the test - no colour (white)
+ */
+ if (annotationThreshold != null)
{
- Annotation aj = annotation.annotations[j];
- // 'use original colours' => colourScheme != null
- // -> look up colour to be used
- // predefined colours => preconfigured shading
- // -> only use original colours reference if thresholding enabled &
- // minmax exists
- // annotation.hasIcons => null or black colours replaced with glyph
- // colours
- // -> reuse original colours if present
- // -> if thresholding enabled then return colour on non-whitespace glyph
-
- if (aboveAnnotationThreshold == NO_THRESHOLD
- || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
- : aj.value <= annotationThreshold.value)))
+ if ((aboveAnnotationThreshold == ABOVE_THRESHOLD && aj.value < annotationThreshold.value)
+ || (aboveAnnotationThreshold == BELOW_THRESHOLD && aj.value > annotationThreshold.value))
{
- if (predefinedColours && aj.colour != null
- && !aj.colour.equals(Color.black))
- {
- currentColour = aj.colour;
- }
- else if (annotation.hasIcons
- && annotation.graph == AlignmentAnnotation.NO_GRAPH)
+ return Color.white;
+ }
+ }
+
+ /*
+ * If 'use original colours' then return the colour of the annotation
+ * at the aligned position - computed using the background colour scheme
+ */
+ if (predefinedColours && aj.colour != null
+ && !aj.colour.equals(Color.black))
+ {
+ return aj.colour;
+ }
+
+ Color result = Color.white;
+ if (ann.hasIcons && ann.graph == AlignmentAnnotation.NO_GRAPH)
+ {
+ /*
+ * secondary structure symbol colouring
+ */
+ if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
+ && aj.secondaryStructure != '-')
+ {
+ if (getColourScheme() != null)
{
- if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
- && aj.secondaryStructure != '-')
- {
- if (getColourScheme() != null)
- {
- currentColour = getColourScheme().findColour(c, j, seq, null,
- 0f);
- }
- else
- {
- if (annotation.isRNA())
- {
- currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value];
- }
- else
- {
- currentColour = annotation.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR
- : annotation.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR
- : jalview.renderer.AnnotationRenderer.STEM_COLOUR;
- }
- }
- }
- else
- {
- //
- return Color.white;
- }
+ result = getColourScheme().findColour(c, j, seq, null, 0f);
}
- else if (noGradient)
+ else
{
- if (getColourScheme() != null)
+ if (ann.isRNA())
{
- currentColour = getColourScheme().findColour(c, j, seq, null,
- 0f);
+ result = ColourSchemeProperty.rnaHelices[(int) aj.value];
}
else
{
- if (aj.colour != null)
- {
- currentColour = aj.colour;
- }
+ result = ann.annotations[j].secondaryStructure == 'H' ? AnnotationRenderer.HELIX_COLOUR
+ : ann.annotations[j].secondaryStructure == 'E' ? AnnotationRenderer.SHEET_COLOUR
+ : AnnotationRenderer.STEM_COLOUR;
}
}
- else
+ }
+ else
+ {
+ return Color.white;
+ }
+ }
+ else if (noGradient)
+ {
+ if (getColourScheme() != null)
+ {
+ result = getColourScheme().findColour(c, j, seq, null, 0f);
+ }
+ else
+ {
+ if (aj.colour != null)
{
- currentColour = shadeCalculation(annotation, j);
+ result = aj.colour;
}
}
- // if (conservationColouring)
- // {
- // currentColour = applyConservation(currentColour, j);
- // }
}
- // }
- return currentColour;
+ else
+ {
+ result = shadeCalculation(ann, j);
+ }
+
+ return result;
}
- private Color shadeCalculation(AlignmentAnnotation annotation, int j)
+ /**
+ * Returns a graduated colour for the annotation at the given column. If there
+ * is a threshold value, and it is used as the top/bottom of the colour range,
+ * and the value satisfies the threshold condition, then a colour
+ * proportionate to the range from the threshold is calculated. For all other
+ * cases, a colour proportionate to the annotation's min-max range is
+ * calulated. Note that thresholding is _not_ done here (a colour is computed
+ * even if threshold is not passed).
+ *
+ * @param ann
+ * @param col
+ * @return
+ */
+ Color shadeCalculation(AlignmentAnnotation ann, int col)
{
-
- // calculate a shade
float range = 1f;
- if (thresholdIsMinMax
- && annotation.threshold != null
+ float value = ann.annotations[col].value;
+ if (thresholdIsMinMax && ann.threshold != null
&& aboveAnnotationThreshold == ABOVE_THRESHOLD
- && annotation.annotations[j].value >= annotation.threshold.value)
+ && value >= ann.threshold.value)
{
- range = (annotation.annotations[j].value - annotation.threshold.value)
- / (annotation.graphMax - annotation.threshold.value);
+ range = (value - ann.threshold.value)
+ / (ann.graphMax - ann.threshold.value);
}
- else if (thresholdIsMinMax && annotation.threshold != null
+ else if (thresholdIsMinMax && ann.threshold != null
&& aboveAnnotationThreshold == BELOW_THRESHOLD
- && annotation.annotations[j].value >= annotation.graphMin)
+ && value <= ann.threshold.value)
{
- range = (annotation.annotations[j].value - annotation.graphMin)
- / (annotation.threshold.value - annotation.graphMin);
+ range = (value - ann.graphMin) / (ann.threshold.value - ann.graphMin);
}
else
{
- if (annotation.graphMax != annotation.graphMin)
+ if (ann.graphMax != ann.graphMin)
{
- range = (annotation.annotations[j].value - annotation.graphMin)
- / (annotation.graphMax - annotation.graphMin);
+ range = (value - ann.graphMin) / (ann.graphMax - ann.graphMin);
}
else
{
}
}
- int dr = (int) (rr * range + r1), dg = (int) (gg * range + g1), db = (int) (bb
- * range + b1);
+ int dr = (int) (redRange * range + redMin);
+ int dg = (int) (greenRange * range + greenMin);
+ int db = (int) (blueRange * range + blueMin);
return new Color(dr, dg, db);
-
}
public boolean isPredefinedColours()
seqAssociated = sassoc;
}
+ public boolean isThresholdIsMinMax()
+ {
+ return thresholdIsMinMax;
+ }
+
+ public void setThresholdIsMinMax(boolean minMax)
+ {
+ this.thresholdIsMinMax = minMax;
+ }
+
@Override
public String getSchemeName()
{
--- /dev/null
+package jalview.schemes;
+
+import jalview.binding.JalviewUserColours;
+
+import java.awt.Color;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+
+import org.exolab.castor.xml.Unmarshaller;
+
+public class ColourSchemeLoader
+{
+
+ /**
+ * Loads a user defined colour scheme from file. The file should contain a
+ * definition of residue colours in XML format as defined in
+ * JalviewUserColours.xsd.
+ *
+ * @param filePath
+ *
+ * @return
+ */
+ public static UserColourScheme loadColourScheme(String filePath)
+ {
+ UserColourScheme ucs = null;
+ Color[] newColours = null;
+ File file = new File(filePath);
+ try
+ {
+ InputStreamReader in = new InputStreamReader(
+ new FileInputStream(file), "UTF-8");
+
+ jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
+
+ org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
+ jucs);
+ jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
+ .unmarshal(in);
+
+ /*
+ * non-case-sensitive colours are for 20 amino acid codes,
+ * B, Z, X and Gap
+ * optionally, lower-case alternatives for all except Gap
+ */
+ newColours = new Color[24];
+ Color[] lowerCase = new Color[23];
+ boolean caseSensitive = false;
+
+ String name;
+ int index;
+ for (int i = 0; i < jucs.getColourCount(); i++)
+ {
+ name = jucs.getColour(i).getName();
+ if (ResidueProperties.aa3Hash.containsKey(name))
+ {
+ index = ResidueProperties.aa3Hash.get(name).intValue();
+ }
+ else
+ {
+ index = ResidueProperties.aaIndex[name.charAt(0)];
+ }
+ if (index == -1)
+ {
+ continue;
+ }
+
+ Color color = new Color(Integer.parseInt(jucs.getColour(i)
+ .getRGB(), 16));
+ if (name.toLowerCase().equals(name))
+ {
+ caseSensitive = true;
+ lowerCase[index] = color;
+ }
+ else
+ {
+ newColours[index] = color;
+ }
+ }
+
+ /*
+ * instantiate the colour scheme
+ */
+ ucs = new UserColourScheme(newColours);
+ ucs.setName(jucs.getSchemeName());
+ if (caseSensitive)
+ {
+ ucs.setLowerCaseColours(lowerCase);
+ }
+ } catch (Exception ex)
+ {
+ // Could be old Jalview Archive format
+ try
+ {
+ InputStreamReader in = new InputStreamReader(new FileInputStream(
+ file), "UTF-8");
+
+ jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
+
+ jucs = JalviewUserColours.unmarshal(in);
+
+ newColours = new Color[jucs.getColourCount()];
+
+ for (int i = 0; i < 24; i++)
+ {
+ newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
+ .getRGB(), 16));
+ }
+ ucs = new UserColourScheme(newColours);
+ ucs.setName(jucs.getSchemeName());
+ } catch (Exception ex2)
+ {
+ ex2.printStackTrace();
+ }
+
+ if (newColours == null)
+ {
+ System.out.println("Error loading User ColourFile\n" + ex);
+ }
+ }
+
+ return ucs;
+ }
+
+}
package jalview.schemes;
-import jalview.binding.JalviewUserColours;
import jalview.datamodel.AnnotatedCollectionI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
-import java.awt.Color;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import java.util.Map;
}
return false;
}
-
- /**
- * Loads a user defined colour scheme from file. The file should contain a
- * definition of residue colours in XML format as defined in
- * JalviewUserColours.xsd.
- *
- * @param filePath
- *
- * @return
- */
- public static UserColourScheme loadColourScheme(String filePath)
- {
- UserColourScheme ucs = null;
- Color[] newColours = null;
- File file = new File(filePath);
- try
- {
- InputStreamReader in = new InputStreamReader(
- new FileInputStream(file), "UTF-8");
-
- jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-
- org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
- jucs);
- jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
- .unmarshal(in);
-
- /*
- * non-case-sensitive colours are for 20 amino acid codes,
- * B, Z, X and Gap
- * optionally, lower-case alternatives for all except Gap
- */
- newColours = new Color[24];
- Color[] lowerCase = new Color[23];
- boolean caseSensitive = false;
-
- String name;
- int index;
- for (int i = 0; i < jucs.getColourCount(); i++)
- {
- name = jucs.getColour(i).getName();
- if (ResidueProperties.aa3Hash.containsKey(name))
- {
- index = ResidueProperties.aa3Hash.get(name).intValue();
- }
- else
- {
- index = ResidueProperties.aaIndex[name.charAt(0)];
- }
- if (index == -1)
- {
- continue;
- }
-
- Color color = new Color(Integer.parseInt(jucs.getColour(i)
- .getRGB(), 16));
- if (name.toLowerCase().equals(name))
- {
- caseSensitive = true;
- lowerCase[index] = color;
- }
- else
- {
- newColours[index] = color;
- }
- }
-
- /*
- * instantiate the colour scheme
- */
- ucs = new UserColourScheme(newColours);
- ucs.setName(jucs.getSchemeName());
- if (caseSensitive)
- {
- ucs.setLowerCaseColours(lowerCase);
- }
- } catch (Exception ex)
- {
- // Could be old Jalview Archive format
- try
- {
- InputStreamReader in = new InputStreamReader(new FileInputStream(
- file), "UTF-8");
-
- jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
-
- jucs = JalviewUserColours.unmarshal(in);
-
- newColours = new Color[jucs.getColourCount()];
-
- for (int i = 0; i < 24; i++)
- {
- newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
- .getRGB(), 16));
- }
- ucs = new UserColourScheme(newColours);
- ucs.setName(jucs.getSchemeName());
- } catch (Exception ex2)
- {
- ex2.printStackTrace();
- }
-
- if (newColours == null)
- {
- System.out.println("Error loading User ColourFile\n" + ex);
- }
- }
-
- return ucs;
- }
}
}
/**
- * If this is a protein alignment and there are mappings to cDNA, add the cDNA
- * consensus annotation.
+ * If this is a protein alignment and there are mappings to cDNA, adds the
+ * cDNA consensus annotation and returns true, else returns false.
*/
- public void initComplementConsensus()
+ public boolean initComplementConsensus()
{
if (!alignment.isNucleotide())
{
"PID for cDNA", new Annotation[1], 0f, 100f,
AlignmentAnnotation.BAR_GRAPH);
initConsensus(complementConsensus);
+ return true;
}
}
}
+ return false;
}
private void initConsensus(AlignmentAnnotation aa)
assertEquals(a.getHiddenSequences().getSize(), 1);
}
+ @Test(
+ groups = "Functional",
+ expectedExceptions = { IllegalArgumentException.class })
+ public void testSetDataset_selfReference()
+ {
+ SequenceI seq = new Sequence("a", "a");
+ AlignmentI alignment = new Alignment(new SequenceI[] { seq });
+ alignment.setDataset(alignment);
+ }
}
import jalview.schemes.NucleotideColourScheme;
+import junit.extensions.PA;
+
import org.testng.annotations.Test;
public class SequenceGroupTest
// expected
assertNull(sg3.getContext());
}
+
+ /*
+ * use PrivilegedAccessor to 'force' a SequenceGroup with
+ * a circular context reference
+ */
+ PA.setValue(sg2, "context", sg2);
+ try
+ {
+ sg3.setContext(sg2); // circular reference in sg2
+ fail("Expected exception");
+ } catch (IllegalArgumentException e)
+ {
+ // expected
+ assertNull(sg3.getContext());
+ }
}
@Test(groups = { "Functional" })
*/
package jalview.ext.jmol;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.gui.JvOptionPane;
import jalview.gui.SequenceRenderer;
+import jalview.schemes.JalviewColourScheme;
+import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
+import java.util.HashMap;
+
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
StructureMappingcommandSet[] commands = JmolCommands
.getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
}
+
+ @Test(groups = { "Functional" })
+ public void testGetColourBySequenceCommands_hiddenColumns()
+ {
+ /*
+ * load these sequences, coloured by Strand propensity,
+ * with columns 2-4 hidden
+ */
+ SequenceI seq1 = new Sequence("seq1", "MHRSQSSSGG");
+ SequenceI seq2 = new Sequence("seq2", "MVRSNGGSSS");
+ AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
+ AlignFrame af = new AlignFrame(al, 800, 500);
+ af.changeColour_actionPerformed(JalviewColourScheme.Strand.toString());
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(2);
+ cs.addElement(3);
+ cs.addElement(4);
+ af.getViewport().setColumnSelection(cs);
+ af.hideSelColumns_actionPerformed(null);
+ SequenceRenderer sr = new SequenceRenderer(af.getViewport());
+ SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } };
+ String[] files = new String[] { "seq1.pdb", "seq2.pdb" };
+ StructureSelectionManager ssm = new StructureSelectionManager();
+
+ /*
+ * map residues 1-10 to residues 21-30 (atoms 105-150) in structures
+ */
+ HashMap<Integer, int[]> map = new HashMap<Integer, int[]>();
+ for (int pos = 1; pos <= seq1.getLength(); pos++)
+ {
+ map.put(pos, new int[] { 20 + pos, 5 * (20 + pos) });
+ }
+ StructureMapping sm1 = new StructureMapping(seq1, "seq1.pdb", "pdb1",
+ "A", map, null);
+ ssm.addStructureMapping(sm1);
+ StructureMapping sm2 = new StructureMapping(seq2, "seq2.pdb", "pdb2",
+ "B", map, null);
+ ssm.addStructureMapping(sm2);
+
+ StructureMappingcommandSet[] commands = JmolCommands
+ .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
+ assertEquals(commands.length, 2);
+ assertEquals(commands[0].commands.length, 1);
+
+ String chainACommand = commands[0].commands[0];
+ // M colour is #82827d == (130, 130, 125) (see strand.html help page)
+ assertTrue(chainACommand
+ .contains(";select 21:A/1.1;color[130,130,125]"));
+ // H colour is #60609f == (96, 96, 159)
+ assertTrue(chainACommand.contains(";select 22:A/1.1;color[96,96,159]"));
+ // hidden columns are Gray (128, 128, 128)
+ assertTrue(chainACommand
+ .contains(";select 23-25:A/1.1;color[128,128,128]"));
+ // S and G are both coloured #4949b6 == (73, 73, 182)
+ assertTrue(chainACommand
+ .contains(";select 26-30:A/1.1;color[73,73,182]"));
+
+ String chainBCommand = commands[1].commands[0];
+ // M colour is #82827d == (130, 130, 125)
+ assertTrue(chainBCommand
+ .contains(";select 21:B/2.1;color[130,130,125]"));
+ // V colour is #ffff00 == (255, 255, 0)
+ assertTrue(chainBCommand
+.contains(";select 22:B/2.1;color[255,255,0]"));
+ // hidden columns are Gray (128, 128, 128)
+ assertTrue(chainBCommand
+ .contains(";select 23-25:B/2.1;color[128,128,128]"));
+ // S and G are both coloured #4949b6 == (73, 73, 182)
+ assertTrue(chainBCommand
+ .contains(";select 26-30:B/2.1;color[73,73,182]"));
+ }
}
assertTrue(theCommand.contains("color #82827d #0:21.A|#1:21.B"));
// H colour is #60609f
assertTrue(theCommand.contains("color #60609f #0:22.A"));
- // V colour is ##ffff00
+ // V colour is #ffff00
assertTrue(theCommand.contains("color #ffff00 #1:22.B"));
// hidden columns are Gray (128, 128, 128)
assertTrue(theCommand.contains("color #808080 #0:23-25.A|#1:23-25.B"));
public void TestSetScrollValues()
{
ViewportRanges ranges = af.getViewport().getRanges();
+ af.alignPanel.setScrollValues(0, 0);
int oldres = ranges.getEndRes();
af.alignPanel.setScrollValues(-1, 5);
--- /dev/null
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.util.Vector;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for methods of base class of annotation column or colour chooser
+ */
+public class AnnotationRowFilterTest
+{
+ AlignFrame af;
+
+ private AnnotationRowFilter testee;
+
+ @BeforeClass(alwaysRun = true)
+ public void setUp()
+ {
+ Cache.loadProperties("test/jalview/io/testProps.jvprops");
+ Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty(
+ Preferences.SHOW_AUTOCALC_ABOVE, Boolean.TRUE.toString());
+ af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
+ DataSourceType.FILE);
+ testee = new AnnotationRowFilter(af.viewport, af.alignPanel)
+ {
+ @Override
+ public void valueChanged(boolean updateAllAnnotation)
+ {
+ }
+
+ @Override
+ public void updateView()
+ {
+ }
+
+ @Override
+ public void reset()
+ {
+ }
+ };
+ }
+
+ /**
+ * Test the method that builds the drop-down list of annotations to choose
+ * from for colour by annotation or select columns by annotation
+ */
+ @Test(groups = "Functional")
+ public void testGetAnnotationItems()
+ {
+ AlignmentI al = af.getViewport().getAlignment();
+ SequenceI seq1 = al.findSequenceMatch("FER_CAPAA")[0];
+ SequenceI seq2 = al.findSequenceMatch("FER_BRANA")[0];
+
+ AlignmentAnnotation ann1 = new AlignmentAnnotation("ann1Label", "ann1",
+ null);
+ al.addAnnotation(ann1);
+ AlignmentAnnotation ann2 = new AlignmentAnnotation("Significance",
+ "ann2", null);
+ al.addAnnotation(ann2);
+ /*
+ * a second Significance alignment annotation
+ */
+ AlignmentAnnotation ann2a = new AlignmentAnnotation("Significance",
+ "ann2", null);
+ al.addAnnotation(ann2a);
+
+ AlignmentAnnotation ann3 = new AlignmentAnnotation("Jronn", "Jronn",
+ null);
+ ann3.setSequenceRef(seq1);
+ al.addAnnotation(ann3);
+ AlignmentAnnotation ann4 = new AlignmentAnnotation("Jronn", "Jronn",
+ null);
+ ann4.setSequenceRef(seq2);
+ al.addAnnotation(ann4);
+ AlignmentAnnotation ann5 = new AlignmentAnnotation("Jnet", "Jnet", null);
+ ann5.setSequenceRef(seq2);
+ al.addAnnotation(ann5);
+ /*
+ * a second Jnet annotation for FER_BRANA
+ */
+ AlignmentAnnotation ann6 = new AlignmentAnnotation("Jnet", "Jnet", null);
+ ann6.setSequenceRef(seq2);
+ al.addAnnotation(ann6);
+
+ /*
+ * drop-down items with 'Per-sequence only' not checked
+ */
+ Vector<String> items = testee.getAnnotationItems(false);
+ assertEquals(
+ items.toString(),
+ "[Conservation, Quality, Consensus, Occupancy, ann1Label, Significance, Significance_1, Jronn_FER_CAPAA, Jronn_FER_BRANA, Jnet_FER_BRANA, Jnet_FER_BRANA_2]");
+ assertEquals(testee.getAnnotationMenuLabel(ann1), "ann1Label");
+ assertEquals(testee.getAnnotationMenuLabel(ann2), "Significance");
+ assertEquals(testee.getAnnotationMenuLabel(ann2a), "Significance_1");
+ assertEquals(testee.getAnnotationMenuLabel(ann3), "Jronn_FER_CAPAA");
+ assertEquals(testee.getAnnotationMenuLabel(ann4), "Jronn_FER_BRANA");
+ assertEquals(testee.getAnnotationMenuLabel(ann5), "Jnet_FER_BRANA");
+ assertEquals(testee.getAnnotationMenuLabel(ann6), "Jnet_FER_BRANA_2");
+
+ /*
+ * drop-down items with 'Per-sequence only' checked
+ */
+ items = testee.getAnnotationItems(true);
+ assertEquals(items.toString(), "[Jronn, Jnet]");
+ // the first annotation of the type is associated with the menu item
+ assertEquals(testee.getAnnotationMenuLabel(ann3), "Jronn");
+ assertEquals(testee.getAnnotationMenuLabel(ann5), "Jnet");
+ }
+}
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.GraphLine;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.awt.Color;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AnnotationColourGradientTest
+{
+ final static int WIDTH = 11;
+
+ final static int THRESHOLD_FIVE = 5;
+
+ private AlignmentAnnotation ann;
+
+ private SequenceI seq;
+
+ private AlignmentI al;
+
+ Color minColour = new Color(50, 200, 150);
+
+ Color maxColour = new Color(150, 100, 250);
+
+ /**
+ * Setup creates an annotation over 11 columns with values 0-10 and threshold
+ * 5
+ */
+ @BeforeClass(alwaysRun = true)
+ public void setUp()
+ {
+ Annotation[] anns = new Annotation[WIDTH];
+ /*
+ * set annotations with values 0-10, graded colours
+ */
+ for (int col = 0; col < WIDTH; col++)
+ {
+ int hue = col * 20;
+ Color colour = new Color(hue, hue, hue);
+ anns[col] = new Annotation("a", "a", 'a', col, colour);
+ }
+
+ seq = new Sequence("", "");
+ al = new Alignment(new SequenceI[]{ seq});
+
+ /*
+ * AlignmentAnnotation constructor works out min-max range
+ */
+ ann = new AlignmentAnnotation("", "", anns);
+ ann.setThreshold(new GraphLine(THRESHOLD_FIVE, "", Color.RED));
+ seq.addAlignmentAnnotation(ann);
+ }
+
+ @Test(groups = "Functional")
+ public void testShadeCalculation_noThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.shadeCalculation(ann, col);
+ /*
+ * column <n> is n/10 of the way from minCol to maxCol
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ /**
+ * Test the 'colour above threshold' case
+ */
+ @Test(groups = "Functional")
+ public void testShadeCalculation_aboveThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.shadeCalculation(ann, col);
+ /*
+ * colour is derived regardless of the threshold value
+ * (the renderer will suppress colouring if above/below threshold)
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+
+ /*
+ * now make 6-10 the span of the colour range
+ * (annotation value == column number in this test)
+ */
+ testee.setThresholdIsMinMax(true);
+ for (int col = 0; col < THRESHOLD_FIVE; col++)
+ {
+ /*
+ * colours below the threshold are computed as before
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ Color result = testee.shadeCalculation(ann, col);
+ assertEquals(result, expected, "for column " + col);
+ }
+ for (int col = THRESHOLD_FIVE; col < WIDTH; col++)
+ {
+ /*
+ * colours for values >= threshold are graduated
+ * range is 6-10 so steps of 100/5 = 20
+ */
+ int factor = col - THRESHOLD_FIVE;
+ Color expected = new Color(50 + 20 * factor, 200 - 20 * factor,
+ 150 + 20 * factor);
+ Color result = testee.shadeCalculation(ann, col);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ /**
+ * Test the 'colour below threshold' case
+ */
+ @Test(groups = "Functional")
+ public void testShadeCalculation_belowThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
+
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.shadeCalculation(ann, col);
+ /*
+ * colour is derived regardless of the threshold value
+ * (the renderer will suppress colouring if above/below threshold)
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+
+ /*
+ * now make 0-5 the span of the colour range
+ * (annotation value == column number in this test)
+ */
+ testee.setThresholdIsMinMax(true);
+ for (int col = THRESHOLD_FIVE + 1; col < WIDTH; col++)
+ {
+ /*
+ * colours above the threshold are computed as before
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ Color result = testee.shadeCalculation(ann, col);
+ assertEquals(result, expected, "for column " + col);
+ }
+
+ for (int col = 0; col <= THRESHOLD_FIVE; col++)
+ {
+ /*
+ * colours for values <= threshold are graduated
+ * range is 0-5 so steps of 100/5 = 20
+ */
+ Color expected = new Color(50 + 20 * col, 200 - 20 * col,
+ 150 + 20 * col);
+ Color result = testee.shadeCalculation(ann, col);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ /**
+ * Test the 'colour above threshold' case
+ */
+ @Test(groups = "Functional")
+ public void testFindColour_aboveThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
+ testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.findColour('a', col, seq);
+ /*
+ * expect white below threshold of 5
+ */
+ Color expected = col < 5 ? Color.white : new Color(50 + 10 * col,
+ 200 - 10 * col,
+ 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+
+ /*
+ * now make 6-10 the span of the colour range
+ * (annotation value == column number in this test)
+ */
+ testee.setThresholdIsMinMax(true);
+ for (int col = 0; col < WIDTH; col++)
+ {
+ /*
+ * colours for values >= threshold are graduated
+ * range is 6-10 so steps of 100/5 = 20
+ */
+ int factor = col - THRESHOLD_FIVE;
+ Color expected = col < 5 ? Color.white : new Color(50 + 20 * factor,
+ 200 - 20 * factor,
+ 150 + 20 * factor);
+ Color result = testee.findColour('a', col, seq);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ /**
+ * Test the 'colour below threshold' case
+ */
+ @Test(groups = "Functional")
+ public void testFindColour_belowThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
+ testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.findColour('a', col, seq);
+ Color expected = col > 5 ? Color.white : new Color(50 + 10 * col,
+ 200 - 10 * col, 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+
+ /*
+ * now make 0-5 the span of the colour range
+ * (annotation value == column number in this test)
+ */
+ testee.setThresholdIsMinMax(true);
+ for (int col = 0; col < WIDTH; col++)
+ {
+ /*
+ * colours for values <= threshold are graduated
+ * range is 0-5 so steps of 100/5 = 20
+ */
+ Color expected = col > 5 ? Color.white : new Color(50 + 20 * col,
+ 200 - 20 * col, 150 + 20 * col);
+ Color result = testee.findColour('a', col, seq);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testFindColour_noThreshold()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+ testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+ for (int col = 0; col < WIDTH; col++)
+ {
+ Color result = testee.findColour('a', col, seq);
+ /*
+ * column <n> is n/10 of the way from minCol to maxCol
+ */
+ Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+ 150 + 10 * col);
+ assertEquals(result, expected, "for column " + col);
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testFindColour_originalColours()
+ {
+ AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+ minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+ testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+ /*
+ * flag corresponding to 'use original colours' checkbox
+ * - just use the individual annotation colours
+ */
+ testee.setPredefinedColours(true);
+
+ /*
+ * the annotation colour is returned, except for column 0 where it is
+ * black - in this case the colour scheme colour overrides it
+ */
+ for (int col = 0; col < WIDTH; col++)
+ {
+ int hue = col * 20;
+ Color c = col == 0 ? minColour : new Color(hue, hue, hue);
+ assertEquals(testee.findColour('a', col, seq), c, "for column " + col);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2004-2012 Sebastian Dietrich (Sebastian.Dietrich@e-movimento.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package junit.extensions;
+
+import java.util.Collection;
+
+/**
+ * This class is used to access a method or field of an object no matter what the access modifier of the method or field. The syntax
+ * for accessing fields and methods is out of the ordinary because this class uses reflection to peel away protection.
+ * <p>
+ * a.k.a. The "ObjectMolester"
+ * <p>
+ * Here is an example of using this to access a private member: <br>
+ * Given the following class <code>MyClass</code>: <br>
+ *
+ * <pre>
+ * public class MyClass {
+ * private String name; // private attribute
+ *
+ * // private constructor
+ * private MyClass() {
+ * super();
+ * }
+ *
+ * // private method
+ * private void setName(String newName) {
+ * this.name = newName;
+ * }
+ * }
+ * </pre>
+ *
+ * We now want to access the class: <br>
+ *
+ * <pre>
+ * MyClass myObj = PA.instantiate(MyClass.class);
+ * PA.invokeMethod(myObj, "setName(java.lang.String)", "myNewName");
+ * String name = PA.getValue(myObj, "name");
+ * </pre>
+ *
+ * This class extends {@link PrivilegedAccessor} by re-throwing checked {@link Exception}s as {@link RuntimeException}s.
+ *
+ *
+ * @see PrivilegedAccessor
+ *
+ * @author Sebastian Dietrich (sebastian.dietrich@e-movimento.com)
+ * @author Lubos Bistak (lubos@bistak.sk)
+ */
+public class PA {
+ private final Object instanceOrClass;
+
+ /**
+ * Private constructor to make it impossible to instantiate this class from outside of PA.
+ *
+ * @param instanceOrClass
+ */
+ private PA(Object instanceOrClass) {
+ this.instanceOrClass = instanceOrClass;
+ }
+
+ /**
+ * Returns a string representation of the given object. The string has the following format: "<classname> {<attributes and values>}"
+ * whereas <attributes and values> is a comma separated list with <attributeName>=<attributeValue> <atributes and values> includes
+ * all attributes of the objects class followed by the attributes of its superclass (if any) and so on.
+ *
+ * @param instanceOrClass the object or class to get a string representation of
+ * @return a string representation of the given object
+ *
+ * @see PrivilegedAccessor#toString(Object)
+ */
+ public static String toString(final Object instanceOrClass) {
+ return PrivilegedAccessor.toString(instanceOrClass);
+ }
+
+ /**
+ * Gets the name of all fields (public, private, protected, default) of the given instance or class. This includes as well all
+ * fields (public, private, protected, default) of all its super classes.
+ *
+ * @param instanceOrClass the instance or class to get the fields of
+ * @return the collection of field names of the given instance or class
+ *
+ * @see PrivilegedAccessor#getFieldNames(Object)
+ */
+ public static Collection<String> getFieldNames(final Object instanceOrClass) {
+ return PrivilegedAccessor.getFieldNames(instanceOrClass);
+ }
+
+ /**
+ * Gets the signatures of all methods (public, private, protected, default) of the given instance or class. This includes as well
+ * all methods (public, private, protected, default) of all its super classes. This does not include constructors.
+ *
+ * @param instanceOrClass the instance or class to get the method signatures of
+ * @return the collection of method signatures of the given instance or class
+ *
+ * @see PrivilegedAccessor#getMethodSignatures(Object)
+ */
+ public static Collection<String> getMethodSignatures(final Object instanceOrClass) {
+ return PrivilegedAccessor.getMethodSignatures(instanceOrClass);
+ }
+
+ /**
+ * Gets the value of the named field and returns it as an object. If instanceOrClass is a class then a static field is returned.
+ *
+ * @param instanceOrClass the instance or class to get the field from
+ * @param fieldName the name of the field
+ * @return an object representing the value of the field
+ * @throws IllegalArgumentException if the field does not exist
+ *
+ * @see PrivilegedAccessor#getValue(Object,String)
+ */
+ public static Object getValue(final Object instanceOrClass, final String fieldName) {
+ try {
+ return PrivilegedAccessor.getValue(instanceOrClass, fieldName);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Can't get value of " + fieldName + " from " + instanceOrClass, e);
+ }
+ }
+
+ /**
+ * Gets the value of the named field and returns it as an object.
+ *
+ * @param fieldName the name of the field
+ * @return an object representing the value of the field
+ * @throws IllegalArgumentException if the field does not exist
+ *
+ * @see PA#getValue(Object,String)
+ */
+ public Object getValue(final String fieldName) {
+ return PA.getValue(instanceOrClass, fieldName);
+ }
+
+ /**
+ * Instantiates an object of the given class with the given arguments and the given argument types. If you want to instantiate a
+ * member class, you must provide the object it is a member of as first argument.
+ *
+ * @param fromClass the class to instantiate an object from
+ * @param arguments the arguments to pass to the constructor
+ * @param argumentTypes the fully qualified types of the arguments of the constructor
+ * @return an object of the given type
+ * @throws IllegalArgumentException if the class can't be instantiated. This could be the case if the number of actual and formal
+ * parameters differ; if an unwrapping conversion for primitive arguments fails; if, after possible unwrapping, a
+ * parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if
+ * this Constructor object enforces Java language access control and the underlying constructor is inaccessible; if the
+ * underlying constructor throws an exception; if the constructor could not be found; or if the class that declares the
+ * underlying constructor represents an abstract class.
+ *
+ * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
+ */
+ public static <T> T instantiate(final Class<? extends T> fromClass, final Class<?>[] argumentTypes, final Object... arguments) {
+ try {
+ return PrivilegedAccessor.instantiate(fromClass, argumentTypes, correctVarargs(arguments));
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Can't instantiate class " + fromClass + " with arguments " + arguments, e);
+ }
+ }
+
+ /**
+ * Instantiates an object of the given class with the given arguments. If you want to instantiate a member class, you must provide
+ * the object it is a member of as first argument.
+ *
+ * @param fromClass the class to instantiate an object from
+ * @param arguments the arguments to pass to the constructor
+ * @return an object of the given type
+ * @throws IllegalArgumentException if the class can't be instantiated. This could be the case if the number of actual and formal
+ * parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a
+ * parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if
+ * this Constructor object enforces Java language access control and the underlying constructor is inaccessible; if the
+ * underlying constructor throws an exception; if the constructor could not be found; or if the class that declares the
+ * underlying constructor represents an abstract class.
+ *
+ * @see PrivilegedAccessor#instantiate(Class,Object[])
+ */
+ public static <T> T instantiate(final Class<? extends T> fromClass, final Object... arguments) {
+ try {
+ return PrivilegedAccessor.instantiate(fromClass, correctVarargs(arguments));
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Can't instantiate class " + fromClass + " with arguments " + arguments, e);
+ }
+ }
+
+ /**
+ * Calls a method on the given object instance with the given arguments. Arguments can be object types or representations for
+ * primitives.
+ *
+ * @param instanceOrClass the instance or class to invoke the method on
+ * @param methodSignature the name of the method and the parameters <br>
+ * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
+ * @param arguments an array of objects to pass as arguments
+ * @return the return value of this method or null if void
+ * @throws IllegalArgumentException if the method could not be invoked. This could be the case if the method is inaccessible; if the
+ * underlying method throws an exception; if no method with the given <code>methodSignature</code> could be found; or if
+ * an argument couldn't be converted to match the expected type
+ *
+ * @see PrivilegedAccessor#invokeMethod(Object,String,Object[])
+ */
+ public static Object invokeMethod(final Object instanceOrClass, final String methodSignature, final Object... arguments) {
+ try {
+ return PrivilegedAccessor.invokeMethod(instanceOrClass, methodSignature, correctVarargs(arguments));
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Can't invoke method " + methodSignature + " on " + instanceOrClass + " with arguments "
+ + arguments, e);
+ }
+ }
+
+ /**
+ * Calls a method with the given arguments. Arguments can be object types or representations for primitives.
+ *
+ * @param methodSignature the name of the method and the parameters <br>
+ * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
+ * @param arguments an array of objects to pass as arguments
+ * @return the return value of this method or null if void
+ * @throws IllegalArgumentException if the method could not be invoked. This could be the case if the method is inaccessible; if the
+ * underlying method throws an exception; if no method with the given <code>methodSignature</code> could be found; or if
+ * an argument couldn't be converted to match the expected type
+ * @see PA#invokeMethod(Object, String, Object...)
+ */
+ public Object invokeMethod(final String methodSignature, final Object... arguments) {
+ return PA.invokeMethod(instanceOrClass, methodSignature, arguments);
+ }
+
+ /**
+ * Corrects varargs to their initial form. If you call a method with an object-array as last argument the Java varargs mechanism
+ * converts this array in single arguments. This method returns an object array if the arguments are all of the same type.
+ *
+ * @param arguments the possibly converted arguments of a vararg method
+ * @return arguments possibly converted
+ */
+ private static Object[] correctVarargs(final Object... arguments) {
+ if ((arguments == null) || changedByVararg(arguments)) return new Object[] {arguments};
+ return arguments;
+ }
+
+ /**
+ * Tests if the arguments were changed by vararg. Arguments are changed by vararg if they are of a non primitive array type. E.g.
+ * arguments[] = Object[String[]] is converted to String[] while e.g. arguments[] = Object[int[]] is not converted and stays
+ * Object[int[]]
+ *
+ * Unfortunately we can't detect the difference for arg = Object[primitive] since arguments[] = Object[Object[primitive]] which is
+ * converted to Object[primitive] and arguments[] = Object[primitive] which stays Object[primitive]
+ *
+ * and we can't detect the difference for arg = Object[non primitive] since arguments[] = Object[Object[non primitive]] is converted
+ * to Object[non primitive] and arguments[] = Object[non primitive] stays Object[non primitive]
+ *
+ * @param parameters the parameters
+ * @return true if parameters were changes by varargs, false otherwise
+ */
+ private static boolean changedByVararg(final Object[] parameters) {
+ if ((parameters.length == 0) || (parameters[0] == null)) return false;
+
+ if (parameters.getClass() == Object[].class) return false;
+
+ return true;
+ }
+
+ /**
+ * Sets the value of the named field. If fieldName denotes a static field, provide a class, otherwise provide an instance. If the
+ * fieldName denotes a final field, this method could fail with an IllegalAccessException, since setting the value of final fields
+ * at other times than instantiation can have unpredictable effects.<br/>
+ * <br/>
+ * Example:<br/>
+ * <br/>
+ * <code>
+ * String myString = "Test"; <br/>
+ * <br/>
+ * //setting the private field value<br/>
+ * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
+ * <br/>
+ * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
+ * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
+ * <br/>
+ * </code>
+ *
+ * @param instanceOrClass the instance or class to set the field
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ * @throws IllegalArgumentException if the value could not be set. This could be the case if no field with the given
+ * <code>fieldName</code> can be found; or if the field was final
+ *
+ * @see PrivilegedAccessor.setValue(Object,String,Object)
+ */
+ public static PA setValue(final Object instanceOrClass, final String fieldName, final Object value) {
+ try {
+ PrivilegedAccessor.setValue(instanceOrClass, fieldName, value);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Can't set value " + value + " at " + fieldName + " in " + instanceOrClass, e);
+ }
+ return new PA(instanceOrClass);
+ }
+
+ /**
+ * Sets the value of the named field. If fieldName denotes a static field, provide a class, otherwise provide an instance. If the
+ * fieldName denotes a final field, this method could fail with an IllegalAccessException, since setting the value of final fields
+ * at other times than instantiation can have unpredictable effects.<br/>
+ * <br/>
+ * Example:<br/>
+ * <br/>
+ * <code>
+ * String myString = "Test"; <br/>
+ * <br/>
+ * //setting the private field value<br/>
+ * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
+ * <br/>
+ * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
+ * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
+ * <br/>
+ * </code>
+ *
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ * @throws IllegalArgumentException if the value could not be set. This could be the case if no field with the given
+ * <code>fieldName</code> can be found; or if the field was final
+ *
+ * @see PA.setValue(Object,String,Object)
+ */
+ public PA setValue(final String fieldName, final Object value) {
+ PA.setValue(instanceOrClass, fieldName, value);
+ return this;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2004-2012 Sebastian Dietrich (Sebastian.Dietrich@e-movimento.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package junit.extensions;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This class is used to access a method or field of an object no matter what the access modifier of the method or field. The syntax
+ * for accessing fields and methods is out of the ordinary because this class uses reflection to peel away protection.
+ * <p>
+ * a.k.a. The "ObjectMolester"
+ * <p>
+ * Here is an example of using this to access a private member: <br>
+ * <code>myObject</code> is an object of type <code>MyClass</code>. <code>setName(String)</code> is a private method of
+ * <code>MyClass</code>.
+ *
+ * <pre>
+ * PrivilegedAccessor.invokeMethod(myObject, "setName(java.lang.String)", "newName");
+ * </pre>
+ *
+ * @author Charlie Hubbard (chubbard@iss.net)
+ * @author Prashant Dhokte (pdhokte@iss.net)
+ * @author Sebastian Dietrich (sebastian.dietrich@e-movimento.com)
+ *
+ * @deprecated use PA instead. PA improves the functionality of PrivilegedAccessor by introducing support for varargs and removal of
+ * the necessity to catch exceptions.
+ */
+@Deprecated
+final class PrivilegedAccessor
+{
+ /**
+ * Private constructor to make it impossible to instantiate this class.
+ */
+ private PrivilegedAccessor() {
+ assert false : "You mustn't instantiate PrivilegedAccessor, use its methods statically";
+ }
+
+ /**
+ * Returns a string representation of the given object. The string has the following format: "<classname> {<attributes and values>}"
+ * whereas <attributes and values> is a comma separated list with <attributeName>=<attributeValue> <atributes and values> includes
+ * all attributes of the objects class followed by the attributes of its superclass (if any) and so on.
+ *
+ * @param instanceOrClass the object or class to get a string representation of
+ * @return a string representation of the given object
+ */
+ public static String toString(final Object instanceOrClass) {
+ Collection<String> fields = getFieldNames(instanceOrClass);
+
+ if (fields.isEmpty())
+ {
+ return getClass(instanceOrClass).getName();
+ }
+
+ StringBuffer stringBuffer = new StringBuffer();
+
+ stringBuffer.append(getClass(instanceOrClass).getName() + " {");
+
+ for (String fieldName : fields) {
+ try {
+ stringBuffer.append(fieldName + "=" + getValue(instanceOrClass, fieldName) + ", ");
+ } catch (NoSuchFieldException e) {
+ assert false : "It should always be possible to get a field that was just here";
+ }
+ }
+
+ stringBuffer.replace(stringBuffer.lastIndexOf(", "), stringBuffer.length(), "}");
+ return stringBuffer.toString();
+ }
+
+ /**
+ * Gets the name of all fields (public, private, protected, default) of the given instance or class. This includes as well all
+ * fields (public, private, protected, default) of all its super classes.
+ *
+ * @param instanceOrClass the instance or class to get the fields of
+ * @return the collection of field names of the given instance or class
+ */
+ public static Collection<String> getFieldNames(final Object instanceOrClass) {
+ if (instanceOrClass == null)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ Class<?> clazz = getClass(instanceOrClass);
+ Field[] fields = clazz.getDeclaredFields();
+ Collection<String> fieldNames = new ArrayList<String>(fields.length);
+
+ for (Field field : fields) {
+ fieldNames.add(field.getName());
+ }
+ fieldNames.addAll(getFieldNames(clazz.getSuperclass()));
+
+ return fieldNames;
+ }
+
+ /**
+ * Gets the signatures of all methods (public, private, protected, default) of the given instance or class. This includes as well
+ * all methods (public, private, protected, default) of all its super classes. This does not include constructors.
+ *
+ * @param instanceOrClass the instance or class to get the method signatures of
+ * @return the collection of method signatures of the given instance or class
+ */
+ public static Collection<String> getMethodSignatures(final Object instanceOrClass) {
+ if (instanceOrClass == null)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ Class<?> clazz = getClass(instanceOrClass);
+ Method[] methods = clazz.getDeclaredMethods();
+ Collection<String> methodSignatures = new ArrayList<String>(methods.length + Object.class.getDeclaredMethods().length);
+
+ for (Method method : methods) {
+ methodSignatures.add(method.getName() + "(" + getParameterTypesAsString(method.getParameterTypes()) + ")");
+ }
+ methodSignatures.addAll(getMethodSignatures(clazz.getSuperclass()));
+
+ return methodSignatures;
+ }
+
+ /**
+ * Gets the value of the named field and returns it as an object. If instanceOrClass is a class then a static field is returned.
+ *
+ * @param instanceOrClass the instance or class to get the field from
+ * @param fieldName the name of the field
+ * @return an object representing the value of the field
+ * @throws NoSuchFieldException if the field does not exist
+ */
+ public static Object getValue(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException {
+ Field field = getField(instanceOrClass, fieldName);
+ try {
+ return field.get(instanceOrClass);
+ } catch (IllegalAccessException e) {
+ assert false : "getField() should have setAccessible(true), so an IllegalAccessException should not occur in this place";
+ return null;
+ }
+ }
+
+ /**
+ * Instantiates an object of the given class with the given arguments. If you want to instantiate a member class, you must provide
+ * the object it is a member of as first argument.
+ *
+ * @param fromClass the class to instantiate an object from
+ * @param args the arguments to pass to the constructor
+ * @return an object of the given type
+ * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive
+ * arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion.
+ * @throws IllegalAccessException if this Constructor object enforces Java language access control and the underlying constructor is
+ * inaccessible.
+ * @throws InvocationTargetException if the underlying constructor throws an exception.
+ * @throws NoSuchMethodException if the constructor could not be found
+ * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
+ *
+ * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
+ */
+ public static <T> T instantiate(final Class<? extends T> fromClass, final Object[] args) throws IllegalArgumentException,
+ InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ return instantiate(fromClass, getParameterTypes(args), args);
+ }
+
+ /**
+ * Instantiates an object of the given class with the given arguments and the given argument types. If you want to instantiate a
+ * member class, you must provide the object it is a member of as first argument.
+ *
+ *
+ * @param fromClass the class to instantiate an object from
+ * @param args the arguments to pass to the constructor
+ * @param argumentTypes the fully qualified types of the arguments of the constructor
+ * @return an object of the given type
+ * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive
+ * arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion.
+ * @throws IllegalAccessException if this Constructor object enforces Java language access control and the underlying constructor is
+ * inaccessible.
+ * @throws InvocationTargetException if the underlying constructor throws an exception.
+ * @throws NoSuchMethodException if the constructor could not be found
+ * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
+ *
+ * @see PrivilegedAccessor#instantiate(Class,Object[])
+ */
+ public static <T> T instantiate(final Class<? extends T> fromClass, final Class<?>[] argumentTypes, final Object[] args)
+ throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+ return getConstructor(fromClass, argumentTypes).newInstance(args);
+ }
+
+ /**
+ * Calls a method on the given object instance with the given arguments. Arguments can be object types or representations for
+ * primitives.
+ *
+ * @param instanceOrClass the instance or class to invoke the method on
+ * @param methodSignature the name of the method and the parameters <br>
+ * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
+ * @param arguments an array of objects to pass as arguments
+ * @return the return value of this method or null if void
+ * @throws IllegalAccessException if the method is inaccessible
+ * @throws InvocationTargetException if the underlying method throws an exception.
+ * @throws NoSuchMethodException if no method with the given <code>methodSignature</code> could be found
+ * @throws IllegalArgumentException if an argument couldn't be converted to match the expected type
+ */
+ public static Object invokeMethod(final Object instanceOrClass, final String methodSignature, final Object[] arguments)
+ throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ if ((methodSignature.indexOf('(') == -1) || (methodSignature.indexOf('(') >= methodSignature.indexOf(')')))
+ {
+ throw new NoSuchMethodException(methodSignature);
+ }
+ Class<?>[] parameterTypes = getParameterTypes(methodSignature);
+ return getMethod(instanceOrClass, getMethodName(methodSignature), parameterTypes).invoke(instanceOrClass,
+ getCorrectedArguments(parameterTypes, arguments));
+ }
+
+ /**
+ * Gets the given arguments corrected to match the given methodSignature. Correction is necessary for array arguments not to be
+ * mistaken by varargs.
+ *
+ * @param parameterTypes the method signatue the given arguments should match
+ * @param arguments the arguments that should be corrected
+ * @return the corrected arguments
+ */
+ private static Object[] getCorrectedArguments(Class<?>[] parameterTypes, Object[] arguments) {
+ if (arguments == null)
+ {
+ return arguments;
+ }
+ if (parameterTypes.length > arguments.length)
+ {
+ return arguments;
+ }
+ if (parameterTypes.length < arguments.length)
+ {
+ return getCorrectedArguments(parameterTypes, new Object[] {arguments});
+ }
+
+ Object[] correctedArguments = new Object[arguments.length];
+ int currentArgument = 0;
+ for (Class<?> parameterType : parameterTypes) {
+ correctedArguments[currentArgument] = getCorrectedArgument(parameterType, arguments[currentArgument]);
+ currentArgument++;
+ }
+ return correctedArguments;
+ }
+
+ /**
+ * Gets the given argument corrected to match the given parameterType. Correction is necessary for array arguments not to be
+ * mistaken by varargs.
+ *
+ * @param parameterType the type to match the given argument upon
+ * @param argument the argument to match the given parameterType
+ * @return the corrected argument
+ */
+ private static Object getCorrectedArgument(Class<?> parameterType, Object argument) {
+ if (!parameterType.isArray() || (argument == null)) {
+ return argument; // normal argument for normal parameterType
+ }
+
+ if (!argument.getClass().isArray()) {
+ return new Object[] {argument};
+ }
+
+ if (parameterType.equals(argument.getClass()))
+ {
+ return argument; // no need to cast
+ }
+
+ // (typed) array argument for (object) array parameterType, elements need to be casted
+ Object correctedArrayArgument = Array.newInstance(parameterType.getComponentType(), Array.getLength(argument));
+ for (int index = 0; index < Array.getLength(argument); index++) {
+ if (parameterType.getComponentType().isPrimitive()) { // rely on autoboxing
+ Array.set(correctedArrayArgument, index, Array.get(argument, index));
+ } else { // cast to expected type
+ try {
+ Array.set(correctedArrayArgument, index, parameterType.getComponentType().cast(Array.get(argument, index)));
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Argument " + argument + " of type " + argument.getClass()
+ + " does not match expected argument type " + parameterType + ".");
+ }
+ }
+ }
+ return correctedArrayArgument;
+ }
+
+ /**
+ * Sets the value of the named field. If fieldName denotes a static field, provide a class, otherwise provide an instance. If the
+ * fieldName denotes a final field, this method could fail with an IllegalAccessException, since setting the value of final fields
+ * at other times than instantiation can have unpredictable effects.<br/>
+ * <br/>
+ * Example:<br/>
+ * <br/>
+ * <code>
+ * String myString = "Test"; <br/>
+ * <br/>
+ * //setting the private field value<br/>
+ * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
+ * <br/>
+ * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
+ * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
+ * <br/>
+ * </code>
+ *
+ * @param instanceOrClass the instance or class to set the field
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ * @throws NoSuchFieldException if no field with the given <code>fieldName</code> can be found
+ * @throws IllegalAccessException possibly if the field was final
+ */
+ public static void setValue(final Object instanceOrClass, final String fieldName, final Object value) throws NoSuchFieldException,
+ IllegalAccessException {
+ Field field = getField(instanceOrClass, fieldName);
+ if (Modifier.isFinal(field.getModifiers())) {
+ PrivilegedAccessor.setValue(field, "modifiers", field.getModifiers() ^ Modifier.FINAL);
+ }
+ field.set(instanceOrClass, value);
+ }
+
+ /**
+ * Gets the class with the given className.
+ *
+ * @param className the name of the class to get
+ * @return the class for the given className
+ * @throws ClassNotFoundException if the class could not be found
+ */
+ private static Class<?> getClassForName(final String className) throws ClassNotFoundException {
+ if (className.indexOf('[') > -1) {
+ Class<?> clazz = getClassForName(className.substring(0, className.indexOf('[')));
+ return Array.newInstance(clazz, 0).getClass();
+ }
+
+ if (className.indexOf("...") > -1) {
+ Class<?> clazz = getClassForName(className.substring(0, className.indexOf("...")));
+ return Array.newInstance(clazz, 0).getClass();
+ }
+
+ try {
+ return Class.forName(className, false, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ return getSpecialClassForName(className);
+ }
+ }
+
+ /**
+ * Maps string representation of primitives to their corresponding classes.
+ */
+ private static final Map<String, Class<?>> PRIMITIVE_MAPPER = new HashMap<String, Class<?>>(8);
+
+ /**
+ * Fills the map with all java primitives and their corresponding classes.
+ */
+ static {
+ PRIMITIVE_MAPPER.put("int", Integer.TYPE);
+ PRIMITIVE_MAPPER.put("float", Float.TYPE);
+ PRIMITIVE_MAPPER.put("double", Double.TYPE);
+ PRIMITIVE_MAPPER.put("short", Short.TYPE);
+ PRIMITIVE_MAPPER.put("long", Long.TYPE);
+ PRIMITIVE_MAPPER.put("byte", Byte.TYPE);
+ PRIMITIVE_MAPPER.put("char", Character.TYPE);
+ PRIMITIVE_MAPPER.put("boolean", Boolean.TYPE);
+ }
+
+ /**
+ * Gets special classes for the given className. Special classes are primitives and "standard" Java types (like String)
+ *
+ * @param className the name of the class to get
+ * @return the class for the given className
+ * @throws ClassNotFoundException if the class could not be found
+ */
+ private static Class<?> getSpecialClassForName(final String className) throws ClassNotFoundException {
+ if (PRIMITIVE_MAPPER.containsKey(className))
+ {
+ return PRIMITIVE_MAPPER.get(className);
+ }
+
+ if (missesPackageName(className))
+ {
+ return getStandardClassForName(className);
+ }
+
+ throw new ClassNotFoundException(className);
+ }
+
+ /**
+ * Gets a 'standard' java class for the given className.
+ *
+ * @param className the className
+ * @return the class for the given className (if any)
+ * @throws ClassNotFoundException of no 'standard' java class was found for the given className
+ */
+ private static Class<?> getStandardClassForName(String className) throws ClassNotFoundException {
+ try {
+ return Class.forName("java.lang." + className, false, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ try {
+ return Class.forName("java.util." + className, false, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e1) {
+ throw new ClassNotFoundException(className);
+ }
+ }
+ }
+
+ /**
+ * Tests if the given className possibly misses its package name.
+ *
+ * @param className the className
+ * @return true if the className might miss its package name, otherwise false
+ */
+ private static boolean missesPackageName(String className) {
+ if (className.contains("."))
+ {
+ return false;
+ }
+ if (className.startsWith(className.substring(0, 1).toUpperCase()))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the constructor for a given class with the given parameters.
+ *
+ * @param type the class to instantiate
+ * @param parameterTypes the types of the parameters
+ * @return the constructor
+ * @throws NoSuchMethodException if the method could not be found
+ */
+ private static <T> Constructor<T> getConstructor(final Class<T> type, final Class<?>[] parameterTypes) throws NoSuchMethodException {
+ Constructor<T> constructor = type.getDeclaredConstructor(parameterTypes);
+ constructor.setAccessible(true);
+ return constructor;
+ }
+
+ /**
+ * Return the named field from the given instance or class. Returns a static field if instanceOrClass is a class.
+ *
+ * @param instanceOrClass the instance or class to get the field from
+ * @param fieldName the name of the field to get
+ * @return the field
+ * @throws NoSuchFieldException if no such field can be found
+ * @throws InvalidParameterException if instanceOrClass was null
+ */
+ private static Field getField(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException,
+ InvalidParameterException {
+ if (instanceOrClass == null)
+ {
+ throw new InvalidParameterException("Can't get field on null object/class");
+ }
+
+ Class<?> type = getClass(instanceOrClass);
+
+ try {
+ Field field = type.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field;
+ } catch (NoSuchFieldException e) {
+ if (type.getSuperclass() == null)
+ {
+ throw e;
+ }
+ return getField(type.getSuperclass(), fieldName);
+ }
+ }
+
+ /**
+ * Gets the class of the given parameter. If the parameter is a class, it is returned, if it is an object, its class is returned
+ *
+ * @param instanceOrClass the instance or class to get the class of
+ * @return the class of the given parameter
+ */
+ private static Class<?> getClass(final Object instanceOrClass) {
+ if (instanceOrClass instanceof Class)
+ {
+ return (Class<?>) instanceOrClass;
+ }
+
+ return instanceOrClass.getClass();
+ }
+
+ /**
+ * Return the named method with a method signature matching classTypes from the given class.
+ *
+ * @param type the class to get the method from
+ * @param methodName the name of the method to get
+ * @param parameterTypes the parameter-types of the method to get
+ * @return the method
+ * @throws NoSuchMethodException if the method could not be found
+ */
+ private static Method getMethod(final Class<?> type, final String methodName, final Class<?>[] parameterTypes)
+ throws NoSuchMethodException {
+ try {
+ return type.getDeclaredMethod(methodName, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ if (type.getSuperclass() == null)
+ {
+ throw e;
+ }
+ return getMethod(type.getSuperclass(), methodName, parameterTypes);
+ }
+ }
+
+ /**
+ * Gets the method with the given name and parameters from the given instance or class. If instanceOrClass is a class, then we get a
+ * static method.
+ *
+ * @param instanceOrClass the instance or class to get the method of
+ * @param methodName the name of the method
+ * @param parameterTypes the parameter-types of the method to get
+ * @return the method
+ * @throws NoSuchMethodException if the method could not be found
+ */
+ private static Method getMethod(final Object instanceOrClass, final String methodName, final Class<?>[] parameterTypes)
+ throws NoSuchMethodException {
+ Class<?> type;
+
+ type = getClass(instanceOrClass);
+
+ Method accessMethod = getMethod(type, methodName, parameterTypes);
+ accessMethod.setAccessible(true);
+ return accessMethod;
+ }
+
+ /**
+ * Gets the name of a method.
+ *
+ * @param methodSignature the signature of the method
+ * @return the name of the method
+ */
+ private static String getMethodName(final String methodSignature) {
+ try {
+ return methodSignature.substring(0, methodSignature.indexOf('(')).trim();
+ } catch (StringIndexOutOfBoundsException e) {
+ assert false : "Signature must have been checked before this method was called";
+ return null;
+ }
+ }
+
+ /**
+ * Gets the types of the parameters.
+ *
+ * @param parameters the parameters
+ * @return the class-types of the arguments
+ */
+ private static Class<?>[] getParameterTypes(final Object[] parameters) {
+ if (parameters == null)
+ {
+ return new Class[0];
+ }
+
+ Class<?>[] typesOfParameters = new Class[parameters.length];
+
+ for (int i = 0; i < parameters.length; i++) {
+ typesOfParameters[i] = parameters[i].getClass();
+ }
+ return typesOfParameters;
+ }
+
+ /**
+ * Gets the types of the given parameters. If the parameters don't match the given methodSignature an IllegalArgumentException is
+ * thrown.
+ *
+ * @param methodSignature the signature of the method
+ * @return the parameter types as class[]
+ * @throws NoSuchMethodException if the method could not be found
+ * @throws IllegalArgumentException if one of the given parameters doesn't math the given methodSignature
+ */
+ private static Class<?>[] getParameterTypes(final String methodSignature) throws NoSuchMethodException, IllegalArgumentException {
+ String signature = getSignatureWithoutBraces(methodSignature);
+
+ StringTokenizer tokenizer = new StringTokenizer(signature, ", *");
+ Class<?>[] typesInSignature = new Class[tokenizer.countTokens()];
+
+ for (int x = 0; tokenizer.hasMoreTokens(); x++) {
+ String className = tokenizer.nextToken();
+ try {
+ typesInSignature[x] = getClassForName(className);
+ } catch (ClassNotFoundException e) {
+ NoSuchMethodException noSuchMethodException = new NoSuchMethodException(methodSignature);
+ noSuchMethodException.initCause(e);
+ throw noSuchMethodException;
+ }
+ }
+ return typesInSignature;
+ }
+
+ /**
+ * Gets the parameter types as a string.
+ *
+ * @param classTypes the types to get as names.
+ * @return the parameter types as a string
+ *
+ * @see java.lang.Class#argumentTypesToString(Class[])
+ */
+ private static String getParameterTypesAsString(final Class<?>[] classTypes) {
+ assert classTypes != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
+ if (classTypes.length == 0)
+ {
+ return "";
+ }
+
+ StringBuilder parameterTypes = new StringBuilder();
+ for (Class<?> clazz : classTypes) {
+ assert clazz != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
+ parameterTypes.append(clazz.getName()).append(", ");
+ }
+
+ return parameterTypes.substring(0, parameterTypes.length() - 2);
+ }
+
+ /**
+ * Removes the braces around the methods signature.
+ *
+ * @param methodSignature the signature with braces
+ * @return the signature without braces
+ */
+ private static String getSignatureWithoutBraces(final String methodSignature) {
+ try {
+ return methodSignature.substring(methodSignature.indexOf('(') + 1, methodSignature.indexOf(')'));
+ } catch (IndexOutOfBoundsException e) {
+ assert false : "signature must have been checked before this method";
+ return null;
+ }
+ }
+
+}