<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.merge_results = Merge Results
action.load_scheme = Load scheme
action.save_scheme = Save scheme
+label.scheme_changed = Changes to scheme ''{0}'' have not been saved.<br><br>Save changes, or continue without saving to make a new colour scheme.
+label.save_changes = Save Changes
+label.dont_save_changes = Don't Save
action.save_image = Save Image
action.paste = Paste
action.show_html_source = Show HTML Source
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.standard_databases = Standard Databases
label.fetch_embl_uniprot = Fetch from EMBL/EMBLCDS or Uniprot/PDB and any selected DAS sources
label.reset_min_max_colours_to_defaults = Reset min and max colours to defaults from user preferences.
-label.align_structures_using_linked_alignment_views = Superpose structures using selected alignment view
+label.align_structures_using_linked_alignment_views = Superpose structures using {0} selected alignment view(s)
label.connect_to_session = Connect to session {0}
label.threshold_feature_display_by_score = Threshold the feature display by score.
label.threshold_feature_no_threshold = No Threshold
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
label.colour_with_jmol = Colour with Jmol
label.colour_with_chimera = Colour with Chimera
label.superpose_structures = Superpose Structures
+error.superposition_failed = Superposition failed: {0}
+label.insufficient_residues = Not enough aligned residues ({0}) to perform superposition
label.jmol = Jmol
label.chimera = Chimera
label.create_chimera_attributes = Write Jalview features
label.create_chimera_attributes_tip = Set Chimera residue attributes for visible features
+label.attributes_set = {0} attribute values set on Chimera
label.sort_alignment_by_tree = Sort Alignment By Tree
label.mark_unlinked_leaves = Mark Unlinked Leaves
label.associate_leaves_with = Associate Leaves With
action.merge_results = Unificar resultados
action.load_scheme = Cargar esquema
action.save_scheme = Guardar esquema
+label.scheme_changed = Cambios en el esquema ''{0}'' no se han guardado.<br><br>Guardar cambios, o continuar sin guardar para hacer un nuevo esquema.
+label.save_changes = Guardar cambios
+label.dont_save_changes = No guardar
action.save_image = Guardar imagen
action.paste = Pegar
action.show_html_source = Mostrar código HTML
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.standard_databases = Bases de datos estándar
label.fetch_embl_uniprot = Recuperar de EMBL/EMBLCDS o Uniprot/PDB y de cualquier fuente DAS seleccionada
label.reset_min_max_colours_to_defaults = Reiniciar los colores min y max colours a los valores por defecto establecidos en las preferencias de usuario
-label.align_structures_using_linked_alignment_views = Alinear las estructuras utlizando las {0} vistas de alineamiento enlazadas
+label.align_structures_using_linked_alignment_views = Alinear las estructuras utilizando las {0} vista(s) de alineamiento enlazada(s)
label.connect_to_session = Conectar a la sesión {0}
label.threshold_feature_display_by_score = Filtrar la caracterÃstica mostrada por puntuación.
label.threshold_feature_no_threshold = Sin umbral
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}
label.nuc_alignment_colour=Color del Alineamiento NucleotÃdico
label.copy_format_from=Copiar formato de
label.chimera=Chimera
+label.create_chimera_attributes = Escribir caracterÃsticas de Jalview
+label.create_chimera_attributes_tip = Establecer atributos en Chimera para caracterÃsticas visibles
+label.attributes_set = {0} valores de atributos establecidos en Chimera
label.open_split_window=Abrir ventana dividida
label.open_split_window?=¿Quieres abrir ventana dividida, con cDNA y proteÃna vinculadas?
status.searching_for_pdb_structures=Buscando Estructuras PDB
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
info.change_threshold_mode_to_enable=Cambiar Modo de Umbral para Habilitar
label.separate_multiple_query_values=Introducir uno o mas {0}s separados por punto y coma ";"
label.let_chimera_manage_structure_colours=Deja que Chimera maneje colores de estructuras
+label.fetch_chimera_attributes = Buscar atributos desde Chimera
+label.fetch_chimera_attributes_tip = Copiar atributo de Chimera a caracterÃstica de Jalview
label.view_rna_structure=Estructura 2D VARNA
label.scale_protein_to_cdna_tip=Hacer a los residuos de proteÃnas de la misma anchura que los codones en ventanas divididas
label.colour_with_chimera=Colorear con Chimera
+label.superpose_structures = Superponer estructuras
+error.superposition_failed = Superposición fallido: {0}
+label.insufficient_residues = Residuos alineados ({0}) insuficentes para superponer
label.show_pdbstruct_dialog=Datos de Estructura 3D...
label.hide_all=Ocultar todos
label.invert=Invertir
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 jalview.datamodel.SequenceI;
import jalview.io.DataSourceType;
import jalview.io.StructureFile;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.AtomSpec;
import jalview.structure.StructureListener;
import jalview.structure.StructureMapping;
showFeatures = true;
}
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
+
PDBChain chain;
if (bysequence && pdb != null)
{
if (pos > 0)
{
pos = sequence[s].findIndex(pos);
- tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
- if (showFeatures)
- {
- tmp.startCol = fr.findFeatureColour(tmp.startCol,
- sequence[s], pos);
- }
+ tmp.startCol = sr.getResidueColour(sequence[s], pos,
+ finder);
}
pos = mapping[m].getSeqPos(tmp.at2.resNumber) - 1;
if (pos > 0)
{
pos = sequence[s].findIndex(pos);
- tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
- if (showFeatures)
- {
- tmp.endCol = fr.findFeatureColour(tmp.endCol,
- sequence[s], pos);
- }
+ tmp.endCol = sr
+ .getResidueColour(sequence[s], pos, finder);
}
-
}
}
}
import jalview.gui.SequenceRenderer;
import jalview.io.DataSourceType;
import jalview.io.StructureFile;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.AtomSpec;
import jalview.structure.StructureListener;
import jalview.structure.StructureMapping;
showFeatures = true;
}
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
PDBChain chain;
if (bysequence && pdb != null)
{
if (pos > 0)
{
pos = sequence[s].findIndex(pos);
- tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
- if (showFeatures)
- {
- tmp.startCol = fr.findFeatureColour(tmp.startCol,
- sequence[s], pos);
- }
+ tmp.startCol = sr.getResidueColour(sequence[s], pos,
+ finder);
}
pos = mapping[m].getSeqPos(tmp.at2.resNumber) - 1;
if (pos > 0)
{
pos = sequence[s].findIndex(pos);
- tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
- if (showFeatures)
- {
- tmp.endCol = fr.findFeatureColour(tmp.endCol,
- sequence[s], pos);
- }
+ tmp.endCol = sr
+ .getResidueColour(sequence[s], pos, finder);
}
}
/**
* Derive the gap count annotation row.
*
- * @param consensus
+ * @param gaprow
* the annotation row to add annotations to
* @param profiles
* the source consensus data
* @param endCol
* end column (exclusive)
*/
- public static void completeGapAnnot(AlignmentAnnotation consensus,
+ public static void completeGapAnnot(AlignmentAnnotation gaprow,
ProfilesI profiles, int startCol, int endCol, long nseq)
{
- if (consensus == null || consensus.annotations == null
- || consensus.annotations.length < endCol)
+ if (gaprow == null || gaprow.annotations == null
+ || gaprow.annotations.length < endCol)
{
/*
* called with a bad alignment annotation row
return;
}
// always set ranges again
- consensus.graphMax = nseq;
- consensus.graphMin = 0;
+ gaprow.graphMax = nseq;
+ gaprow.graphMin = 0;
for (int i = startCol; i < endCol; i++)
{
ProfileI profile = profiles.get(i);
* happens if sequences calculated over were
* shorter than alignment width
*/
- consensus.annotations[i] = null;
+ gaprow.annotations[i] = null;
return;
}
String description = String.valueOf(gapped);
- consensus.annotations[i] = new Annotation(description, description,
+ gaprow.annotations[i] = new Annotation(description, description,
'\0',
gapped);
}
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShaderI;
import jalview.schemes.ColourSchemeI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.util.Hashtable;
public interface AlignViewportI extends ViewStyleI
{
- int getEndRes();
+ /**
+ * Get the ranges object containing details of the start and end sequences and
+ * residues
+ *
+ * @return
+ */
+ public ViewportRanges getRanges();
/**
* calculate the height for visible annotation, revalidating bounds where
import jalview.datamodel.SequenceI;
import java.awt.Color;
+import java.awt.Graphics;
import java.util.List;
import java.util.Map;
{
/**
- * compute the perceived colour for a given column position in sequenceI,
- * taking transparency and feature visibility into account.
+ * Computes the feature colour for a given sequence and column position,
+ * taking into account sequence feature locations, feature colour schemes,
+ * render ordering, feature and feature group visibility, and transparency.
+ * <p>
+ * The graphics argument should be provided if transparency is applied
+ * (getTransparency() < 1). With feature transparency, visible features are
+ * written to the graphics context and the composite colour may be read off
+ * from it. In this case, the returned feature colour is not the composite
+ * colour but that of the last feature drawn.
+ * <p>
+ * If no transparency applies, then the graphics argument may be null, and the
+ * returned colour is the one that would be drawn for the feature.
+ * <p>
+ * Returns null if there is no visible feature at the position.
+ * <p>
+ * This is provided to support rendering of feature colours other than on the
+ * sequence alignment, including by structure viewers and the overview window.
+ * Note this method takes no account of whether the sequence or column is
+ * hidden.
*
- * @param col
- * - background colour (due to alignment/group shading schemes, etc).
- * @param sequenceI
- * - sequence providing features
- * @param r
- * - column position
+ * @param sequence
+ * @param column
+ * @param g
* @return
*/
- Color findFeatureColour(Color col, SequenceI sequenceI, int r);
+ Color findFeatureColour(SequenceI sequence, int column, Graphics g);
/**
* trigger the feature discovery process for a newly created feature renderer.
*/
void setVisible(String featureType);
+ /**
+ * Sets the transparency value, between 0 (full transparency) and 1 (no
+ * transparency)
+ *
+ * @param value
+ */
+ void setTransparency(float value);
+
+ /**
+ * Returns the transparency value, between 0 (full transparency) and 1 (no
+ * transparency)
+ *
+ * @return
+ */
+ float getTransparency();
}
package jalview.api;
import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import java.awt.Color;
public interface SequenceRenderer
{
- Color getResidueBoxColour(SequenceI sequenceI, int r);
-
- Color getResidueColour(SequenceI seq, int position, FeatureRenderer fr);
+ Color getResidueColour(SequenceI seq, int position,
+ FeatureColourFinder finder);
}
import jalview.util.MappingUtils;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Canvas;
@Override
public void keyPressed(KeyEvent evt)
{
+ ViewportRanges ranges = viewport.getRanges();
+
if (viewport.cursorMode
&& ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt
.getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
new String[] { (viewport.cursorMode ? "on" : "off") }));
if (viewport.cursorMode)
{
- alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
- alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
+ alignPanel.seqPanel.seqCanvas.cursorX = ranges.getStartRes();
+ alignPanel.seqPanel.seqCanvas.cursorY = ranges.getStartSeq();
}
break;
}
else
{
- alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
- - viewport.endSeq + viewport.startSeq);
+ alignPanel.setScrollValues(ranges.getStartRes(),
+ 2 * ranges.getStartSeq() - ranges.getEndSeq());
}
break;
}
else
{
- alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
- + viewport.endSeq - viewport.startSeq);
+ alignPanel
+ .setScrollValues(ranges.getStartRes(), ranges.getEndSeq());
}
break;
{
delete_actionPerformed();
}
+ else if (source == createGroup)
+ {
+ createGroup_actionPerformed();
+ }
+ else if (source == unGroup)
+ {
+ unGroup_actionPerformed();
+ }
else if (source == grpsFromSelection)
{
makeGrpsFromSelection_actionPerformed();
seqs, 0, viewport.getAlignment().getWidth(),
viewport.getAlignment()));
- viewport.setEndSeq(viewport.getAlignment().getHeight());
+ viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight());
viewport.getAlignment().getWidth();
viewport.firePropertyChange("alignment", null, viewport.getAlignment()
.getSequences());
void trimAlignment(boolean trimLeft)
{
+ AlignmentI al = viewport.getAlignment();
+ ViewportRanges ranges = viewport.getRanges();
ColumnSelection colSel = viewport.getColumnSelection();
int column;
}
else
{
- seqs = viewport.getAlignment().getSequencesArray();
+ seqs = al.getSequencesArray();
}
TrimRegionCommand trimRegion;
if (trimLeft)
{
trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
- column, viewport.getAlignment());
- viewport.setStartRes(0);
+ column, al);
+ ranges.setStartRes(0);
}
else
{
trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
- column, viewport.getAlignment());
+ column, al);
}
statusBar.setText(MessageManager.formatMessage(
.toString() }));
addHistoryItem(trimRegion);
- for (SequenceGroup sg : viewport.getAlignment().getGroups())
+ for (SequenceGroup sg : al.getGroups())
{
if ((trimLeft && !sg.adjustForRemoveLeft(column))
|| (!trimLeft && !sg.adjustForRemoveRight(column)))
{
- viewport.getAlignment().deleteGroup(sg);
+ al.deleteGroup(sg);
}
}
- viewport.firePropertyChange("alignment", null, viewport
- .getAlignment().getSequences());
+ viewport.firePropertyChange("alignment", null, al.getSequences());
}
}
public void removeGappedColumnMenuItem_actionPerformed()
{
- int start = 0, end = viewport.getAlignment().getWidth() - 1;
+ AlignmentI al = viewport.getAlignment();
+ ViewportRanges ranges = viewport.getRanges();
+ int start = 0;
+ int end = ranges.getAbsoluteAlignmentWidth() - 1;
SequenceI[] seqs;
if (viewport.getSelectionGroup() != null)
// This is to maintain viewport position on first residue
// of first sequence
- SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(viewport.startRes);
+ SequenceI seq = al.getSequenceAt(0);
+ int startRes = seq.findPosition(ranges.getStartRes());
// ShiftList shifts;
// viewport.getAlignment().removeGaps(shifts=new ShiftList());
// edit.alColumnChanges=shifts.getInverse();
// if (viewport.hasHiddenColumns)
// viewport.getColumnSelection().compensateForEdits(shifts);
- viewport.setStartRes(seq.findIndex(startRes) - 1);
- viewport.firePropertyChange("alignment", null, viewport.getAlignment()
- .getSequences());
+ ranges.setStartRes(seq.findIndex(startRes) - 1);
+ viewport.firePropertyChange("alignment", null, al.getSequences());
}
public void removeAllGapsMenuItem_actionPerformed()
{
- int start = 0, end = viewport.getAlignment().getWidth() - 1;
+ AlignmentI al = viewport.getAlignment();
+ ViewportRanges ranges = viewport.getRanges();
+ int start = 0;
+ int end = ranges.getAbsoluteAlignmentWidth() - 1;
SequenceI[] seqs;
if (viewport.getSelectionGroup() != null)
// This is to maintain viewport position on first residue
// of first sequence
- SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(viewport.startRes);
+ SequenceI seq = al.getSequenceAt(0);
+ int startRes = seq.findPosition(ranges.getStartRes());
addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
- viewport.getAlignment()));
+ al));
- viewport.setStartRes(seq.findIndex(startRes) - 1);
+ ranges.setStartRes(seq.findIndex(startRes) - 1);
- viewport.firePropertyChange("alignment", null, viewport.getAlignment()
- .getSequences());
+ viewport.firePropertyChange("alignment", null, al.getSequences());
}
boolean selected = conservationMenuItem.getState();
modifyConservation.setEnabled(selected);
viewport.setConservationSelected(selected);
-
- // viewport.setAbovePIDThreshold(false);
- // abovePIDThreshold.setState(false);
+ viewport.getResidueShading().setConservationApplied(selected);
changeColour(viewport.getGlobalColourScheme());
boolean selected = abovePIDThreshold.getState();
modifyPID.setEnabled(selected);
viewport.setAbovePIDThreshold(selected);
- // conservationMenuItem.setState(false);
- // viewport.setConservationSelected(false);
+ if (!selected)
+ {
+ viewport.getResidueShading().setThreshold(0,
+ viewport.isIgnoreGapsConsensus());
+ }
changeColour(viewport.getGlobalColourScheme());
.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 jalview.renderer.ResidueShader;
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.UserColourScheme;
-import jalview.structure.CommandListener;
import jalview.structure.SelectionSource;
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Font;
public class AlignViewport extends AlignmentViewport implements
- SelectionSource, VamsasSource, CommandListener
+ SelectionSource
{
boolean cursorMode = false;
calculator = new jalview.workers.AlignCalcManager();
this.applet = applet;
alignment = al;
+ ranges = new ViewportRanges(this.alignment);
// we always pad gaps
this.setPadGaps(true);
- this.startRes = 0;
- this.endRes = al.getWidth() - 1;
- this.startSeq = 0;
- this.endSeq = al.getHeight() - 1;
+
if (applet != null)
{
// get the width and height scaling factors if they were specified
public void resetSeqLimits(int height)
{
- setEndSeq(height / getCharHeight());
+ ranges.setEndSeq(height / getCharHeight());
}
public void setCurrentTree(NJTree tree)
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceI;
import jalview.structure.StructureSelectionManager;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Color;
AnnotationLabels alabels;
+ ViewportRanges vpRanges;
+
// this value is set false when selection area being dragged
boolean fastPaint = true;
{
alignFrame = null;
av = null;
+ vpRanges = null;
seqPanel = null;
seqPanelHolder = null;
sequenceHolderPanel = null;
alignFrame = af;
this.av = av;
+ vpRanges = av.getRanges();
seqPanel = new SeqPanel(av, this);
idPanel = new IdPanel(av, this);
scalePanel = new ScalePanel(av, this);
@Override
public void componentResized(ComponentEvent evt)
{
- setScrollValues(av.getStartRes(), av.getStartSeq());
+ setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
if (getSize().height > 0
&& annotationPanelHolder.getSize().height > 0)
{
*/
if (centre)
{
- int offset = (av.getEndRes() - av.getStartRes() + 1) / 2 - 1;
+ int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
start = Math.max(start - offset, 0);
end = Math.min(end + offset, seq.getEnd() - 1);
}
// setScrollValues(start, seqIndex);
// }
// logic copied from jalview.gui.AlignmentPanel:
- if ((startv = av.getStartRes()) >= start)
+ if ((startv = vpRanges.getStartRes()) >= start)
{
/*
* Scroll left to make start of search results visible
*/
setScrollValues(start - 1, seqIndex);
}
- else if ((endv = av.getEndRes()) <= end)
+ else if ((endv = vpRanges.getEndRes()) <= end)
{
/*
* Scroll right to make end of search results visible
*/
setScrollValues(startv + 1 + end - endv, seqIndex);
}
- else if ((starts = av.getStartSeq()) > seqIndex)
+ else if ((starts = vpRanges.getStartSeq()) > seqIndex)
{
/*
* Scroll up to make start of search results visible
*/
- setScrollValues(av.getStartRes(), seqIndex);
+ setScrollValues(vpRanges.getStartRes(), seqIndex);
}
- else if ((ends = av.getEndSeq()) <= seqIndex)
+ else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
{
/*
* Scroll down to make end of search results visible
*/
- setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
+ setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
+ + 1);
}
/*
* Else results are already visible - no need to scroll
{
int cwidth = seqPanel.seqCanvas
.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
- if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))
+ if (res <= vpRanges.getStartRes()
+ || res >= (vpRanges.getStartRes() + cwidth))
{
vscroll.setValue(res / cwidth);
- av.startRes = vscroll.getValue() * cwidth;
+ vpRanges.setStartRes(vscroll.getValue() * cwidth);
}
}
public void setWrapAlignment(boolean wrap)
{
- av.startSeq = 0;
- av.startRes = 0;
+ vpRanges.setStartSeq(0);
+ vpRanges.setStartRes(0);
scalePanelHolder.setVisible(!wrap);
hscroll.setVisible(!wrap);
{
x = 0;
}
- ;
+
hextent = seqPanel.seqCanvas.getSize().width / av.getCharWidth();
vextent = seqPanel.seqCanvas.getSize().height / av.getCharHeight();
x = 0;
}
- av.setStartSeq(y);
-
- int endSeq = y + vextent;
- if (endSeq > av.getAlignment().getHeight())
- {
- endSeq = av.getAlignment().getHeight();
- }
-
- av.setEndSeq(endSeq);
- av.setStartRes(x);
- av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av
+ vpRanges.setStartSeq(y);
+ vpRanges.setEndSeq(y + vextent);
+ vpRanges.setStartRes(x);
+ vpRanges.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av
.getCharWidth())) - 1);
hscroll.setValues(x, hextent, 0, width);
@Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
- int oldX = av.getStartRes();
- int oldY = av.getStartSeq();
+ int oldX = vpRanges.getStartRes();
+ int oldY = vpRanges.getStartSeq();
if (evt == null || evt.getSource() == apvscroll)
{
if (evt == null || evt.getSource() == hscroll)
{
int x = hscroll.getValue();
- av.setStartRes(x);
- av.setEndRes(x + seqPanel.seqCanvas.getSize().width
+ vpRanges.setStartRes(x);
+ vpRanges.setEndRes(x + seqPanel.seqCanvas.getSize().width
/ av.getCharWidth() - 1);
}
{
int rowSize = seqPanel.seqCanvas
.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
- av.setStartRes(vscroll.getValue() * rowSize);
- av.setEndRes((vscroll.getValue() + 1) * rowSize);
+ vpRanges.setStartRes(vscroll.getValue() * rowSize);
+ vpRanges.setEndRes((vscroll.getValue() + 1) * rowSize);
}
else
{
- av.setStartSeq(offy);
- av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
- / av.getCharHeight());
+ vpRanges.setStartSeq(offy);
+ vpRanges.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
+ / av.getCharHeight() - 1);
}
}
overviewPanel.setBoxPosition();
}
- int scrollX = av.startRes - oldX;
- int scrollY = av.startSeq - oldY;
+ int scrollX = vpRanges.getStartRes() - oldX;
+ int scrollY = vpRanges.getStartSeq() - oldY;
if (av.getWrapAlignment() || !fastPaint || av.MAC)
{
{
// Make sure we're not trying to draw a panel
// larger than the visible window
- if (scrollX > av.endRes - av.startRes)
+ if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
{
- scrollX = av.endRes - av.startRes;
+ scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
}
- else if (scrollX < av.startRes - av.endRes)
+ else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
{
- scrollX = av.startRes - av.endRes;
+ scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
}
idPanel.idCanvas.fastPaint(scrollY);
scalePanel.repaint();
if (av.isShowAnnotation())
{
- annotationPanel.fastPaint(av.getStartRes() - oldX);
+ annotationPanel.fastPaint(vpRanges.getStartRes() - oldX);
}
}
sendViewPosition();
private void sendViewPosition()
{
StructureSelectionManager.getStructureSelectionManager(av.applet)
- .sendViewPosition(this, av.startRes, av.endRes, av.startSeq,
- av.endSeq);
+ .sendViewPosition(this, vpRanges.getStartRes(),
+ vpRanges.getEndRes(), vpRanges.getStartSeq(),
+ vpRanges.getEndSeq());
}
/**
}
else
{
- setScrollValues(av.getStartRes(), av.getStartSeq());
+ setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
}
seqPanel.seqCanvas.repaint();
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
av.calcPanelHeight());
f.height += dif;
ap.seqPanelHolder.setPreferredSize(f);
- ap.setScrollValues(av.getStartRes(), av.getStartSeq());
+ ap.setScrollValues(av.getRanges().getStartRes(), av.getRanges()
+ .getStartSeq());
ap.validate();
// ap.paintAlignment(true);
ap.addNotify();
}
}
- int column = evt.getX() / av.getCharWidth() + av.getStartRes();
+ int column = evt.getX() / av.getCharWidth()
+ + av.getRanges().getStartRes();
if (av.hasHiddenColumns())
{
gg.setColor(Color.white);
gg.fillRect(0, 0, getSize().width, getSize().height);
- drawComponent(gg, av.startRes, av.endRes + 1);
+ drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
+ .getEndRes() + 1);
g.drawImage(image, 0, 0, this);
}
gg.copyArea(0, 0, imgWidth, getSize().height,
-horizontal * av.getCharWidth(), 0);
- int sr = av.startRes, er = av.endRes + 1, transX = 0;
+ int sr = av.getRanges().getStartRes(), er = av.getRanges().getEndRes() + 1, transX = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
{
public jalview.api.FeatureRenderer getFeatureRenderer(
AlignmentViewPanel alignment)
{
- AlignmentPanel ap = (AlignmentPanel) alignment;
- if (appletJmolBinding.ap.av.isShowSequenceFeatures())
- {
- if (appletJmolBinding.fr == null)
- {
- appletJmolBinding.fr = new jalview.appletgui.FeatureRenderer(
- appletJmolBinding.ap.av);
- }
-
- appletJmolBinding.fr
- .transferSettings(appletJmolBinding.ap.seqPanel.seqCanvas
- .getFeatureRenderer());
- }
-
- return appletJmolBinding.fr;
+ return appletJmolBinding.ap.getFeatureRenderer();
}
@Override
@Override
public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
{
- AlignmentPanel ap = (AlignmentPanel) alignment;
- if (ap.av.isShowSequenceFeatures())
+ AlignmentPanel alignPanel = (AlignmentPanel) alignment;
+ if (alignPanel.av.isShowSequenceFeatures())
{
- return ap.getFeatureRenderer();
+ return alignPanel.getFeatureRenderer();
}
else
{
if (dialog.accept)
{
- // This ensures that the last sequence
- // is refreshed and new features are rendered
- lastSeq = null;
lastFeatureAdded = name.getText().trim();
lastFeatureGroupAdded = source.getText().trim();
lastDescriptionAdded = description.getText().replace('\n', ' ');
public void adjustmentValueChanged(AdjustmentEvent evt)
{
fr.setTransparency((100 - transparency.getValue()) / 100f);
- ap.seqPanel.seqCanvas.repaint();
-
+ ap.paintAlignment(true);
}
class MyCheckbox extends Checkbox
package jalview.appletgui;
import jalview.datamodel.SequenceI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.awt.Font;
return;
}
+ ViewportRanges ranges = av.getRanges();
+
gg.copyArea(0, 0, getSize().width, imgHeight, 0,
-vertical * av.getCharHeight());
- int ss = av.startSeq, es = av.endSeq, transY = 0;
+ int ss = ranges.getStartSeq(), es = ranges.getEndSeq(), transY = 0;
if (vertical > 0) // scroll down
{
ss = es - vertical;
- if (ss < av.startSeq) // ie scrolling too fast, more than a page at a time
+ if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page
+ // at a
+ // time
{
- ss = av.startSeq;
+ ss = ranges.getStartSeq();
}
else
{
- transY = imgHeight - vertical * av.getCharHeight();
+ transY = imgHeight - ((vertical + 1) * av.getCharHeight());
}
}
else if (vertical < 0)
{
es = ss - vertical;
- if (es > av.endSeq)
+ if (es > ranges.getEndSeq())
{
- es = av.endSeq;
+ es = ranges.getEndSeq();
}
}
gg.setFont(italic);
gg.fillRect(0, 0, getSize().width, getSize().height);
- drawIds(av.startSeq, av.endSeq);
+ drawIds(av.getRanges().getStartSeq(), av.getRanges().getEndSeq());
g.drawImage(image, 0, 0, this);
}
int cHeight = alheight * avcharHeight + hgap + annotationHeight;
- int rowSize = av.getEndRes() - av.getStartRes();
+ int rowSize = av.getRanges().getEndRes()
+ - av.getRanges().getStartRes();
// Draw the rest of the panels
- for (int ypos = hgap, row = av.startRes; (ypos <= getSize().height)
+ for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getSize().height)
&& (row < maxwidth); ypos += cHeight, row += rowSize)
{
for (int i = starty; i < alheight; i++)
{
// Now draw the id strings
SequenceI seq;
- for (int i = starty; i < endy; i++)
+ for (int i = starty; i <= endy; i++)
{
seq = av.getAlignment().getSequenceAt(i);
return;
}
- if (mouseDragging && e.getY() < 0 && av.getStartSeq() > 0)
+ if (mouseDragging && e.getY() < 0 && av.getRanges().getStartSeq() > 0)
{
scrollThread = new ScrollThread(true);
}
if (mouseDragging && e.getY() >= getSize().height
- && av.getAlignment().getHeight() > av.getEndSeq())
+ && av.getAlignment().getHeight() > av.getRanges().getEndSeq())
{
scrollThread = new ScrollThread(false);
}
int index = av.getAlignment().findIndex(list.get(0));
// do we need to scroll the panel?
- if (av.getStartSeq() > index || av.getEndSeq() < index)
+ if (av.getRanges().getStartSeq() > index
+ || av.getRanges().getEndSeq() < index)
{
- alignPanel.setScrollValues(av.getStartRes(), index);
+ alignPanel.setScrollValues(av.getRanges().getStartRes(), index);
}
}
if (alignPanel.scrollUp(up))
{
// scroll was ok, so add new sequence to selection
- int seq = av.getStartSeq();
+ int seq = av.getRanges().getStartSeq();
if (!up)
{
- seq = av.getEndSeq();
+ seq = av.getRanges().getEndSeq();
}
if (seq < lastid)
*/
package jalview.appletgui;
-import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.viewmodel.OverviewDimensions;
import java.awt.Color;
import java.awt.Dimension;
public class OverviewPanel extends Panel implements Runnable,
MouseMotionListener, MouseListener
{
- Image miniMe;
+ private OverviewDimensions od;
- Image offscreen;
+ private Image miniMe;
- AlignViewport av;
+ private Image offscreen;
- AlignmentPanel ap;
+ private AlignViewport av;
- float scalew = 1f;
+ private AlignmentPanel ap;
- float scaleh = 1f;
+ private boolean resizing = false;
- public int width, sequencesHeight;
-
- int graphHeight = 20;
-
- int boxX = -1, boxY = -1, boxWidth = -1, boxHeight = -1;
-
- boolean resizing = false;
+ // This is set true if the user resizes whilst
+ // the overview is being calculated
+ private boolean resizeAgain = false;
// Can set different properties in this seqCanvas than
// main visible SeqCanvas
- SequenceRenderer sr;
+ private SequenceRenderer sr;
- FeatureRenderer fr;
+ private FeatureRenderer fr;
- Frame nullFrame;
+ private Frame nullFrame;
- public OverviewPanel(AlignmentPanel ap)
+ public OverviewPanel(AlignmentPanel alPanel)
{
- this.av = ap.av;
- this.ap = ap;
+ this.av = alPanel.av;
+ this.ap = alPanel;
setLayout(null);
nullFrame = new Frame();
nullFrame.addNotify();
sr.forOverview = true;
fr = new FeatureRenderer(av);
- // scale the initial size of overviewpanel to shape of alignment
- float initialScale = (float) av.getAlignment().getWidth()
- / (float) av.getAlignment().getHeight();
-
- if (av.getSequenceConsensusHash() == null)
- {
- graphHeight = 0;
- }
-
- if (av.getAlignment().getWidth() > av.getAlignment().getHeight())
- {
- // wider
- width = 400;
- sequencesHeight = (int) (400f / initialScale);
- if (sequencesHeight < 40)
- {
- sequencesHeight = 40;
- }
- }
- else
- {
- // taller
- width = (int) (400f * initialScale);
- sequencesHeight = 300;
- if (width < 120)
- {
- width = 120;
- }
- }
+ od = new OverviewDimensions(av.getRanges(),
+ (av.isShowAnnotation() && av.getSequenceConsensusHash() != null));
- setSize(new Dimension(width, sequencesHeight + graphHeight));
+ setSize(new Dimension(od.getWidth(), od.getHeight()));
addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent evt)
{
- if (getSize().width != width
- || getSize().height != sequencesHeight + graphHeight)
+ if ((getWidth() != od.getWidth())
+ || (getHeight() != (od.getHeight())))
{
updateOverviewImage();
}
@Override
public void mousePressed(MouseEvent evt)
{
- boxX = evt.getX();
- boxY = evt.getY();
- checkValid();
+ mouseAction(evt);
}
@Override
public void mouseReleased(MouseEvent evt)
{
- boxX = evt.getX();
- boxY = evt.getY();
- checkValid();
+ mouseAction(evt);
}
@Override
public void mouseDragged(MouseEvent evt)
{
- boxX = evt.getX();
- boxY = evt.getY();
- checkValid();
+ mouseAction(evt);
}
- void checkValid()
+ private void mouseAction(MouseEvent evt)
{
- if (boxY < 0)
- {
- boxY = 0;
- }
-
- if (boxY > (sequencesHeight - boxHeight))
- {
- boxY = sequencesHeight - boxHeight + 1;
- }
-
- if (boxX < 0)
- {
- boxX = 0;
- }
-
- if (boxX > (width - boxWidth))
- {
- if (av.hasHiddenColumns())
- {
- // Try smallest possible box
- boxWidth = (int) ((av.endRes - av.startRes + 1) * av.getCharWidth() * scalew);
- }
- boxX = width - boxWidth;
- }
-
- int col = (int) (boxX / scalew / av.getCharWidth());
- int row = (int) (boxY / scaleh / av.getCharHeight());
-
- if (av.hasHiddenColumns())
- {
- if (!av.getColumnSelection().isVisible(col))
- {
- return;
- }
-
- col = av.getColumnSelection().findColumnPosition(col);
- }
-
- if (av.hasHiddenRows())
- {
- row = av.getAlignment().getHiddenSequences()
- .findIndexWithoutHiddenSeqs(row);
- }
-
- ap.setScrollValues(col, row);
+ od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
+ .getHiddenSequences(), av.getColumnSelection(), av
+ .getRanges());
+ ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
ap.paintAlignment(false);
}
/**
- * DOCUMENT ME!
+ * Updates the overview image when the related alignment panel is updated
*/
public void updateOverviewImage()
{
if ((getSize().width > 0) && (getSize().height > 0))
{
- width = getSize().width;
- sequencesHeight = getSize().height - graphHeight;
+ od.setWidth(getSize().width);
+ od.setHeight(getSize().height);
}
- setSize(new Dimension(width, sequencesHeight + graphHeight));
+ setSize(new Dimension(od.getWidth(), od.getHeight()));
Thread thread = new Thread(this);
thread.start();
repaint();
}
- // This is set true if the user resizes whilst
- // the overview is being calculated
- boolean resizeAgain = false;
-
@Override
public void run()
{
miniMe = null;
- int alwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getHeight()
- + av.getAlignment().getHiddenSequences().getSize();
if (av.isShowSequenceFeatures())
{
if (getSize().width > 0 && getSize().height > 0)
{
- width = getSize().width;
- sequencesHeight = getSize().height - graphHeight;
+ od.setWidth(getSize().width);
+ od.setHeight(getSize().height);
}
- setSize(new Dimension(width, sequencesHeight + graphHeight));
-
- int fullsizeWidth = alwidth * av.getCharWidth();
- int fullsizeHeight = alheight * av.getCharHeight();
+ setSize(new Dimension(od.getWidth(), od.getHeight()));
- scalew = (float) width / (float) fullsizeWidth;
- scaleh = (float) sequencesHeight / (float) fullsizeHeight;
-
- miniMe = nullFrame.createImage(width, sequencesHeight + graphHeight);
- offscreen = nullFrame.createImage(width, sequencesHeight + graphHeight);
+ miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
+ offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
Graphics mg = miniMe.getGraphics();
- float sampleCol = (float) alwidth / (float) width;
- float sampleRow = (float) alheight / (float) sequencesHeight;
-
- int lastcol = 0, lastrow = 0;
- int xstart = 0, ystart = 0;
- Color color = Color.yellow;
- int row, col, sameRow = 0, sameCol = 0;
- jalview.datamodel.SequenceI seq;
- final boolean hasHiddenRows = av.hasHiddenRows(), hasHiddenCols = av
- .hasHiddenColumns();
- boolean hiddenRow = false;
- AlignmentI alignment = av.getAlignment();
- for (row = 0; row <= sequencesHeight; row++)
- {
- if (resizeAgain)
- {
- break;
- }
- if ((int) (row * sampleRow) == lastrow)
- {
- sameRow++;
- continue;
- }
-
- hiddenRow = false;
- if (hasHiddenRows)
- {
- seq = alignment.getHiddenSequences().getHiddenSequence(lastrow);
- if (seq == null)
- {
- int index = alignment.getHiddenSequences()
- .findIndexWithoutHiddenSeqs(lastrow);
-
- seq = alignment.getSequenceAt(index);
- }
- else
- {
- hiddenRow = true;
- }
- }
- else
- {
- seq = alignment.getSequenceAt(lastrow);
- }
-
- for (col = 0; col < width; col++)
- {
- if ((int) (col * sampleCol) == lastcol
- && (int) (row * sampleRow) == lastrow)
- {
- sameCol++;
- continue;
- }
-
- lastcol = (int) (col * sampleCol);
-
- if (seq.getLength() > lastcol)
- {
- color = sr.getResidueBoxColour(seq, lastcol);
-
- if (av.isShowSequenceFeatures())
- {
- color = fr.findFeatureColour(color, seq, lastcol);
- }
- }
- else
- {
- color = Color.white; // White
- }
-
- if (hiddenRow
- || (hasHiddenCols && !av.getColumnSelection().isVisible(
- lastcol)))
- {
- color = color.darker().darker();
- }
- mg.setColor(color);
- if (sameCol == 1 && sameRow == 1)
- {
- mg.drawLine(xstart, ystart, xstart, ystart);
- }
- else
- {
- mg.fillRect(xstart, ystart, sameCol, sameRow);
- }
+ int alwidth = av.getAlignment().getWidth();
+ int alheight = av.getAlignment().getAbsoluteHeight();
+ float sampleCol = alwidth / (float) od.getWidth();
+ float sampleRow = alheight / (float) od.getSequencesHeight();
- xstart = col;
- sameCol = 1;
- }
- lastrow = (int) (row * sampleRow);
- ystart = row;
- sameRow = 1;
- }
+ buildImage(sampleRow, sampleCol, mg);
- if (av.getAlignmentConservationAnnotation() != null)
+ // check for conservation annotation to make sure overview works for DNA too
+ if (av.isShowAnnotation()
+ && (av.getAlignmentConservationAnnotation() != null))
{
- for (col = 0; col < width; col++)
+ for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
{
- if (resizeAgain)
- {
- break;
- }
- lastcol = (int) (col * sampleCol);
- {
- mg.translate(col, sequencesHeight);
- ap.annotationPanel.renderer.drawGraph(mg,
- av.getAlignmentConservationAnnotation(),
- av.getAlignmentConservationAnnotation().annotations,
- (int) (sampleCol) + 1, graphHeight,
- (int) (col * sampleCol), (int) (col * sampleCol) + 1);
- mg.translate(-col, -sequencesHeight);
- }
+ mg.translate(col, od.getSequencesHeight());
+ ap.annotationPanel.renderer.drawGraph(mg,
+ av.getAlignmentConservationAnnotation(),
+ av.getAlignmentConservationAnnotation().annotations,
+ (int) (sampleCol) + 1, od.getGraphHeight(),
+ (int) (col * sampleCol), (int) (col * sampleCol) + 1);
+ mg.translate(-col, -od.getSequencesHeight());
}
}
System.gc();
}
}
- public void setBoxPosition()
+ /*
+ * Build the overview panel image
+ */
+ private void buildImage(float sampleRow, float sampleCol, Graphics mg)
{
- int fullsizeWidth = av.getAlignment().getWidth() * av.getCharWidth();
- int fullsizeHeight = (av.getAlignment().getHeight() + av.getAlignment()
- .getHiddenSequences().getSize())
- * av.getCharHeight();
-
- int startRes = av.getStartRes();
- int endRes = av.getEndRes();
+ int lastcol = 0;
+ int lastrow = 0;
+ int xstart = 0;
+ int ystart = 0;
+ Color color = Color.yellow;
+ int sameRow = 0;
+ int sameCol = 0;
- if (av.hasHiddenColumns())
- {
- startRes = av.getColumnSelection().adjustForHiddenColumns(startRes);
- endRes = av.getColumnSelection().adjustForHiddenColumns(endRes);
- }
+ SequenceI seq = null;
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
- int startSeq = av.startSeq;
- int endSeq = av.endSeq;
+ final boolean hasHiddenCols = av.hasHiddenColumns();
+ boolean hiddenRow = false;
- if (av.hasHiddenRows())
+ for (int row = 0; row <= od.getSequencesHeight() && !resizeAgain; row++)
{
- startSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(startSeq);
-
- endSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(endSeq);
+ if ((int) (row * sampleRow) == lastrow)
+ {
+ sameRow++;
+ }
+ else
+ {
+ // get the sequence which would be at alignment index 'lastrow' if no
+ // columns were hidden, and determine whether it is hidden or not
+ hiddenRow = av.getAlignment().isHidden(lastrow);
+ seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
+ for (int col = 0; col < od.getWidth(); col++)
+ {
+ if ((int) (col * sampleCol) == lastcol
+ && (int) (row * sampleRow) == lastrow)
+ {
+ sameCol++;
+ }
+ else
+ {
+ lastcol = (int) (col * sampleCol);
+
+ color = getColumnColourFromSequence(seq, hiddenRow,
+ hasHiddenCols, lastcol, finder);
+
+ mg.setColor(color);
+ if (sameCol == 1 && sameRow == 1)
+ {
+ mg.drawLine(xstart, ystart, xstart, ystart);
+ }
+ else
+ {
+ mg.fillRect(xstart, ystart, sameCol, sameRow);
+ }
+
+ xstart = col;
+ sameCol = 1;
+ }
+ }
+ lastrow = (int) (row * sampleRow);
+ ystart = row;
+ sameRow = 1;
+ }
}
+ }
- scalew = (float) width / (float) fullsizeWidth;
- scaleh = (float) sequencesHeight / (float) fullsizeHeight;
-
- boxX = (int) (startRes * av.getCharWidth() * scalew);
- boxY = (int) (startSeq * av.getCharHeight() * scaleh);
-
- if (av.hasHiddenColumns())
+ /*
+ * Find the colour of a sequence at a specified column position
+ */
+ private Color getColumnColourFromSequence(
+ jalview.datamodel.SequenceI seq, boolean hiddenRow,
+ boolean hasHiddenCols, int lastcol, FeatureColourFinder finder)
+ {
+ Color color = Color.white;
+ if (seq.getLength() > lastcol)
{
- boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
+ color = sr.getResidueColour(seq, lastcol, finder);
}
- else
+
+ if (hiddenRow
+ || (hasHiddenCols && !av.getColumnSelection()
+ .isVisible(lastcol)))
{
- boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
+ color = color.darker().darker();
}
+ return color;
+ }
- boxHeight = (int) ((endSeq - startSeq) * av.getCharHeight() * scaleh);
-
+ /**
+ * Update the overview panel box when the associated alignment panel is
+ * changed
+ *
+ */
+ public void setBoxPosition()
+ {
+ od.setBoxPosition(av.getAlignment()
+ .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
repaint();
}
{
og.drawImage(miniMe, 0, 0, this);
og.setColor(Color.red);
- og.drawRect(boxX, boxY, boxWidth, boxHeight);
- og.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
+ od.drawBox(og);
g.drawImage(offscreen, 0, 0, this);
}
}
@Override
public void mousePressed(MouseEvent evt)
{
- int x = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int x = (evt.getX() / av.getCharWidth()) + av.getRanges().getStartRes();
final int res;
if (av.hasHiddenColumns())
{
mouseDragging = false;
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
if (res > av.getAlignment().getWidth())
{
mouseDragging = true;
ColumnSelection cs = av.getColumnSelection();
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
res = Math.max(0, res);
res = cs.adjustForHiddenColumns(res);
res = Math.min(res, av.getAlignment().getWidth() - 1);
return;
}
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
res = av.getColumnSelection().adjustForHiddenColumns(res);
@Override
public void paint(Graphics g)
{
- drawScale(g, av.getStartRes(), av.getEndRes(), getSize().width,
+ drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
+ getSize().width,
getSize().height);
}
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.awt.FontMetrics;
return;
}
+ ViewportRanges ranges = av.getRanges();
+
updateViewport();
// Its possible on certain browsers that the call to fastpaint
// is faster than it can paint, so this check here catches
// this possibility
- if (lastsr + horizontal != av.startRes)
+ if (lastsr + horizontal != ranges.getStartRes())
{
- horizontal = av.startRes - lastsr;
+ horizontal = ranges.getStartRes() - lastsr;
}
- lastsr = av.startRes;
+ lastsr = ranges.getStartRes();
fastPaint = true;
gg.copyArea(horizontal * avcharWidth, vertical * avcharHeight, imgWidth
imgHeight - vertical * avcharHeight, -horizontal * avcharWidth,
-vertical * avcharHeight);
- int sr = av.startRes, er = av.endRes, ss = av.startSeq, es = av.endSeq, transX = 0, transY = 0;
+ int sr = ranges.getStartRes(), er = ranges.getEndRes(), ss = ranges
+ .getStartSeq(), es = ranges
+ .getEndSeq(), transX = 0, transY = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
{
else if (vertical > 0) // scroll down
{
ss = es - vertical;
- if (ss < av.startSeq) // ie scrolling too fast, more than a page at a time
+ if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page
+ // at a
+ // time
{
- ss = av.startSeq;
+ ss = ranges.getStartSeq();
}
else
{
- transY = imgHeight - vertical * avcharHeight;
+ transY = imgHeight - ((vertical + 1) * avcharHeight);
}
}
else if (vertical < 0)
{
es = ss - vertical;
- if (es > av.endSeq)
+ if (es > ranges.getEndSeq())
{
- es = av.endSeq;
+ es = ranges.getEndSeq();
}
}
gg.setColor(Color.white);
gg.fillRect(0, 0, imgWidth, imgHeight);
+ ViewportRanges ranges = av.getRanges();
+
if (av.getWrapAlignment())
{
- drawWrappedPanel(gg, imgWidth, imgHeight, av.startRes);
+ drawWrappedPanel(gg, imgWidth, imgHeight, ranges.getStartRes());
}
else
{
- drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq, 0);
+ drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
+ ranges.getStartSeq(), ranges.getEndSeq(), 0);
}
g.drawImage(img, 0, 0, this);
av.setWrappedWidth(cWidth);
- av.endRes = av.startRes + cWidth;
+ av.getRanges().setEndRes(av.getRanges().getStartRes() + cWidth);
int endx;
int ypos = hgap;
g.setClip(0, 0, cWidth * avcharWidth, canvasHeight);
}
- drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);
+ drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
g.setClip(null);
if (av.isShowAnnotation())
g1.setColor(Color.blue);
g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1,
0 + offset, (blockEnd - blockStart + 1) * avcharWidth
- - 1, (endSeq - startSeq) * avcharHeight
+ - 1, (endSeq - startSeq + 1) * avcharHeight
+ offset);
}
// / First draw the sequences
// ///////////////////////////
- for (int i = startSeq; i < endSeq; i++)
+ for (int i = startSeq; i <= endSeq; i++)
{
nextSeq = av.getAlignment().getSequenceAt(i);
if (av.isShowSequenceFeatures())
{
fr.drawSequence(g, nextSeq, startRes, endRes, offset
- + ((i - startSeq) * avcharHeight));
+ + ((i - startSeq) * avcharHeight), false);
}
// / Highlight search Results once all sequences have been drawn
int bottom = -1;
int alHeight = av.getAlignment().getHeight() - 1;
- for (i = startSeq; i < endSeq; i++)
+ for (i = startSeq; i <= endSeq; i++)
{
sx = (group.getStartRes() - startRes) * avcharWidth;
sy = offset + ((i - startSeq) * avcharHeight);
import jalview.util.MappingUtils;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Font;
}
else
{
- while (seqCanvas.cursorY < av.startSeq)
+ ViewportRanges ranges = av.getRanges();
+ while (seqCanvas.cursorY < ranges.getStartSeq())
{
ap.scrollUp(true);
}
- while (seqCanvas.cursorY + 1 > av.endSeq)
+ while (seqCanvas.cursorY + 1 > ranges.getEndSeq())
{
ap.scrollUp(false);
}
while (seqCanvas.cursorX < av.getColumnSelection()
- .adjustForHiddenColumns(av.startRes))
+ .adjustForHiddenColumns(ranges.getStartRes()))
{
if (!ap.scrollRight(false))
}
}
while (seqCanvas.cursorX > av.getColumnSelection()
- .adjustForHiddenColumns(av.endRes))
+ .adjustForHiddenColumns(ranges.getEndRes()))
{
if (!ap.scrollRight(true))
{
}
wrappedBlock = y / cHeight;
- wrappedBlock += av.getStartRes() / cwidth;
+ wrappedBlock += av.getRanges().getStartRes() / cwidth;
res = wrappedBlock * cwidth + x / av.getCharWidth();
}
else
{
- res = (x / av.getCharWidth()) + av.getStartRes();
+ res = (x / av.getCharWidth()) + av.getRanges().getStartRes();
}
if (av.hasHiddenColumns())
}
else
{
- seq = Math.min((y / av.getCharHeight()) + av.getStartSeq(), av
+ seq = Math.min((y / av.getCharHeight())
+ + av.getRanges().getStartSeq(),
+ av
.getAlignment().getHeight() - 1);
if (seq < 0)
{
oldSeq = -1;
}
- if (res > av.endRes || res < av.startRes || y < av.startSeq
- || y > av.endSeq)
+ if (res > av.getRanges().getEndRes()
+ || res < av.getRanges().getStartRes()
+ || y < av.getRanges().getStartSeq()
+ || y > av.getRanges().getEndSeq())
{
mouseExited(evt);
}
if (evt != null)
{
- if (mouseDragging && evt.getY() < 0 && av.getStartSeq() > 0)
+ if (mouseDragging && evt.getY() < 0
+ && av.getRanges().getStartSeq() > 0)
{
running = ap.scrollUp(true);
}
if (mouseDragging && evt.getY() >= getSize().height
- && av.getAlignment().getHeight() > av.getEndSeq())
+ && av.getAlignment().getHeight() > av.getRanges()
+ .getEndSeq())
{
running = ap.scrollUp(false);
}
public void scrollTo(int row, int column)
{
- row = row < 0 ? ap.av.startSeq : row;
- column = column < 0 ? ap.av.startRes : column;
+ row = row < 0 ? ap.av.getRanges().getStartSeq() : row;
+ column = column < 0 ? ap.av.getRanges().getStartRes() : column;
ap.scrollTo(column, column, row, true, true);
}
public void scrollToRow(int row)
{
- row = row < 0 ? ap.av.startSeq : row;
- ap.scrollTo(ap.av.startRes, ap.av.startRes, row, true, true);
+ row = row < 0 ? ap.av.getRanges().getStartSeq() : row;
+ ap.scrollTo(ap.av.getRanges().getStartRes(), ap.av.getRanges()
+ .getStartRes(), row, true, true);
}
/**
public void scrollToColumn(int column)
{
- column = column < 0 ? ap.av.startRes : column;
- ap.scrollTo(column, column, ap.av.startSeq, true, true);
+ column = column < 0 ? ap.av.getRanges().getStartRes() : column;
+ ap.scrollTo(column, column, ap.av.getRanges().getStartSeq(), true, true);
}
/**
*/
package jalview.appletgui;
-import jalview.api.FeatureRenderer;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShaderI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import java.awt.Color;
import java.awt.Font;
this.renderGaps = renderGaps;
}
- @Override
- public Color getResidueBoxColour(SequenceI seq, int i)
+ protected Color getResidueBoxColour(SequenceI seq, int i)
{
allGroups = av.getAlignment().findAllGroups(seq);
*
* @param seq
* @param position
- * @param fr
+ * @param finder
* @return
*/
@Override
public Color getResidueColour(final SequenceI seq, int position,
- FeatureRenderer fr)
+ FeatureColourFinder finder)
{
// TODO replace 8 or so code duplications with calls to this method
// (refactored as needed)
Color col = getResidueBoxColour(seq, position);
- if (fr != null)
+ if (finder != null)
{
- col = fr.findFeatureColour(col, seq, position);
+ col = finder.findFeatureColour(col, seq, position);
}
return col;
}
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)
return AlignmentUtils.getSequencesByName(this);
}
- /**
- * DOCUMENT ME!
- *
- * @param i
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
+
@Override
public SequenceI getSequenceAt(int i)
{
return null;
}
+ @Override
+ public SequenceI getSequenceAtAbsoluteIndex(int i)
+ {
+ SequenceI seq = null;
+ if (getHiddenSequences().getSize() > 0)
+ {
+ seq = getHiddenSequences().getHiddenSequence(i);
+ if (seq == null)
+ {
+ // didn't find the sequence in the hidden sequences, get it from the
+ // alignment
+ int index = getHiddenSequences().findIndexWithoutHiddenSeqs(i);
+ seq = getSequenceAt(index);
+ }
+ }
+ else
+ {
+ seq = getSequenceAt(i);
+ }
+ return seq;
+ }
+
/**
* Adds a sequence to the alignment. Recalculates maxLength and size. Note
* this currently does not recalculate whether or not the alignment is
}
}
- /**
- * DOCUMENT ME!
- *
- * @param s
- * DOCUMENT ME!
- */
@Override
public void deleteSequence(SequenceI s)
{
- deleteSequence(findIndex(s));
+ synchronized (sequences)
+ {
+ deleteSequence(findIndex(s));
+ }
}
- /**
- * DOCUMENT ME!
- *
- * @param i
- * DOCUMENT ME!
- */
@Override
public void deleteSequence(int i)
{
- if (i > -1 && i < getHeight())
+ synchronized (sequences)
{
- synchronized (sequences)
+ if (i > -1 && i < getHeight())
{
sequences.remove(i);
hiddenSequences.adjustHeightSequenceDeleted(i);
}
}
+ @Override
+ public void deleteHiddenSequence(int i)
+ {
+ synchronized (sequences)
+ {
+ if (i > -1 && i < getHeight())
+ {
+ sequences.remove(i);
+ }
+ }
+ }
+
/*
* (non-Javadoc)
*
return -1;
}
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
+
@Override
public int getHeight()
{
return sequences.size();
}
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
+ @Override
+ public int getAbsoluteHeight()
+ {
+ return sequences.size() + getHiddenSequences().getSize();
+ }
+
@Override
public int getWidth()
{
return true;
}
+ @Override
+ public boolean isHidden(int alignmentIndex)
+ {
+ return (getHiddenSequences().getHiddenSequence(alignmentIndex) != null);
+ }
+
/**
* Delete all annotations, including auto-calculated if the flag is set true.
* Returns true if at least one annotation was deleted, else false.
}
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++)
public interface AlignmentI extends AnnotatedCollectionI
{
/**
- * Calculates the number of sequences in an alignment
+ * Calculates the number of sequences in an alignment, excluding hidden
+ * sequences
*
* @return Number of sequences in alignment
*/
int getHeight();
/**
+ * Calculates the number of sequences in an alignment, including hidden
+ * sequences
+ *
+ * @return Number of sequences in alignment
+ */
+ int getAbsoluteHeight();
+
+ /**
*
* Calculates the maximum width of the alignment, including gaps.
*
boolean isAligned(boolean includeHidden);
/**
+ * Answers if the sequence at alignmentIndex is hidden
+ *
+ * @param alignmentIndex
+ * the index to check
+ * @return true if the sequence is hidden
+ */
+ boolean isHidden(int alignmentIndex);
+
+ /**
* Gets sequences as a Synchronized collection
*
* @return All sequences in alignment.
SequenceI getSequenceAt(int i);
/**
+ * Find a specific sequence in this alignment.
+ *
+ * @param i
+ * Index of required sequence in full alignment, i.e. if all columns
+ * were visible
+ *
+ * @return SequenceI at given index.
+ */
+ SequenceI getSequenceAtAbsoluteIndex(int i);
+
+ /**
* Returns a map of lists of sequences keyed by sequence name.
*
* @return
SequenceI replaceSequenceAt(int i, SequenceI seq);
/**
- * Deletes a sequence from the alignment
+ * Deletes a sequence from the alignment. Updates hidden sequences to account
+ * for the removed sequence. Do NOT use this method to delete sequences which
+ * are just hidden.
*
* @param s
* Sequence to be deleted.
void deleteSequence(SequenceI s);
/**
- * Deletes a sequence from the alignment.
+ * Deletes a sequence from the alignment. Updates hidden sequences to account
+ * for the removed sequence. Do NOT use this method to delete sequences which
+ * are just hidden.
*
* @param i
* Index of sequence to be deleted.
void deleteSequence(int i);
/**
+ * Deletes a sequence in the alignment which has been hidden.
+ *
+ * @param i
+ * Index of sequence to be deleted
+ */
+ void deleteHiddenSequence(int i);
+
+ /**
* Finds sequence in alignment using sequence name as query.
*
* @param name
* @return
*/
public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols);
+
}
* left-most visible column will always be returned.
*
* @param hiddenColumn
- * int
- * @return int
+ * the column index in the full alignment including hidden columns
+ * @return the position of the column in the visible alignment
*/
public int findColumnPosition(int hiddenColumn)
{
result -= region[1] + 1 - region[0];
}
} while ((hiddenColumn > region[1]) && (index < hiddenColumns.size()));
- if (hiddenColumn > region[0] && hiddenColumn < region[1])
- {
- return region[0] + hiddenColumn - result;
+
+ if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
+ {
+ // Here the hidden column is within a region, so
+ // we want to return the position of region[0]-1, adjusted for any
+ // earlier hidden columns.
+ // Calculate the difference between the actual hidden col position
+ // and region[0]-1, and then subtract from result to convert result from
+ // the adjusted hiddenColumn value to the adjusted region[0]-1 value
+
+ // However, if the region begins at 0 we cannot return region[0]-1
+ // just return 0
+ if (region[0] == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return result - (hiddenColumn - region[0] + 1);
+ }
}
}
return result; // return the shifted position after removing hidden columns.
}
/**
+ * Find the visible column which is a given visible number of columns to the
+ * left of another visible column. i.e. for a startColumn x, the column which
+ * is distance 1 away will be column x-1.
+ *
+ * @param visibleDistance
+ * the number of visible columns to offset by
+ * @param startColumn
+ * the column to start from
+ * @return the position of the column in the visible alignment
+ */
+ public int subtractVisibleColumns(int visibleDistance, int startColumn)
+ {
+ int distance = visibleDistance;
+
+ // in case startColumn is in a hidden region, move it to the left
+ int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+
+ // get index of hidden region to left of start
+ int index = getHiddenIndexLeft(start);
+ if (index == -1)
+ {
+ // no hidden regions to left of startColumn
+ return start - distance;
+ }
+
+ // walk backwards through the alignment subtracting the counts of visible
+ // columns from distance
+ int[] region;
+ int gap = 0;
+ int nextstart = start;
+
+ while ((index > -1) && (distance - gap > 0))
+ {
+ // subtract the gap to right of region from distance
+ distance -= gap;
+ start = nextstart;
+
+ // calculate the next gap
+ region = hiddenColumns.get(index);
+ gap = start - region[1];
+
+ // set start to just to left of current region
+ nextstart = region[0] - 1;
+ index--;
+ }
+
+ if (distance - gap > 0)
+ {
+ // fell out of loop because there are no more hidden regions
+ distance -= gap;
+ return nextstart - distance;
+ }
+ return start - distance;
+
+ }
+
+ /**
* Use this method to determine where the next hiddenRegion starts
*
* @param hiddenRegion
}
+ /**
+ * This method returns the index of the hidden region to the left of a column
+ * position. If the column is in a hidden region it returns the index of the
+ * region to the left. If there is no hidden region to the left it returns -1.
+ *
+ * @param pos
+ * int
+ */
+ private int getHiddenIndexLeft(int pos)
+ {
+ if (hiddenColumns != null)
+ {
+ int index = hiddenColumns.size() - 1;
+ do
+ {
+ int[] region = hiddenColumns.elementAt(index);
+ if (pos > region[1])
+ {
+ return index;
+ }
+
+ index--;
+ } while (index > -1);
+ }
+
+ return -1;
+
+ }
+
public void hideSelectedColumns()
{
synchronized (selection)
hiddenSequences = new SequenceI[alignment.getHeight()];
}
- int alignmentIndex = alignment.findIndex(sequence);
- alignmentIndex = adjustForHiddenSeqs(alignmentIndex);
+ int absAlignmentIndex = alignment.findIndex(sequence);
+ int alignmentIndex = adjustForHiddenSeqs(absAlignmentIndex);
if (hiddenSequences[alignmentIndex] != null)
{
hiddenSequences[alignmentIndex] = sequence;
- alignment.deleteSequence(sequence);
+ alignment.deleteHiddenSequence(absAlignmentIndex);
}
public List<SequenceI> showAll(
return hiddenSequences == null ? null : hiddenSequences[alignmentIndex];
}
+ /**
+ * Convert absolute alignment index to visible alignment index
+ *
+ * @param alignmentIndex
+ * @return
+ */
public int findIndexWithoutHiddenSeqs(int alignmentIndex)
{
if (hiddenSequences == null)
}
int index = 0;
int hiddenSeqs = 0;
+ int diff = 0;
if (hiddenSequences.length <= alignmentIndex)
{
+ // if the alignmentIndex runs past the end of hidden sequences
+ // and therefore actually past the end of the alignment
+ // store the difference to add back on at the end, so that behaviour
+ // is consistent with hidden columns behaviour (used by overview panel)
+ diff = alignmentIndex - hiddenSequences.length + 1;
alignmentIndex = hiddenSequences.length - 1;
}
index++;
}
- return (alignmentIndex - hiddenSeqs);
+ return (alignmentIndex - hiddenSeqs + diff);
+ }
+
+ /**
+ * Find the visible row which is a given visible number of rows above another
+ * visible row. i.e. for a startRow x, the row which is distance 1 away will
+ * be row x-1.
+ *
+ * @param visibleDistance
+ * the number of visible rows to offset by
+ * @param startRow
+ * the row to start from
+ * @return the position of the row in the visible alignment
+ */
+ public int subtractVisibleRows(int visibleDistance, int startRow)
+ {
+ // walk upwards through the alignment
+ // count all the non-null sequences until we have visibleDistance counted
+ // then return the next visible sequence
+ if (hiddenSequences == null)
+ {
+ return startRow - visibleDistance;
+ }
+
+ int index = startRow;
+ int count = 0;
+ while ((index > -1) && (count < visibleDistance))
+ {
+ if (hiddenSequences[index] == null)
+ {
+ // count visible sequences
+ count++;
+ }
+ index--;
+ }
+ return index;
}
+ /**
+ * Convert alignment index from visible alignment to absolute alignment
+ *
+ * @param alignmentIndex
+ * @return
+ */
public int adjustForHiddenSeqs(int alignmentIndex)
{
if (hiddenSequences == null)
AnnotatedCollectionI ref = ctx;
while (ref != null)
{
- if (ref == this)
+ if (ref == this || ref.getContext() == ctx)
{
throw new IllegalArgumentException(
"Circular reference in SequenceGroup.context");
*/
package jalview.ext.jmol;
+import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.MessageManager;
import java.awt.Color;
import java.awt.Container;
import java.net.URL;
import java.security.AccessControlException;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
}
/**
- * Construct and send a command to align structures against a reference
- * structure, based on one or more sequence alignments
- *
- * @param _alignment
- * an array of alignments to process
- * @param _refStructure
- * an array of corresponding reference structures (index into pdb
- * file array); if a negative value is passed, the first PDB file
- * mapped to an alignment sequence is used as the reference for
- * superposition
- * @param _hiddenCols
- * an array of corresponding hidden columns for each alignment
+ * {@inheritDoc}
*/
@Override
- public void superposeStructures(AlignmentI[] _alignment,
+ public String superposeStructures(AlignmentI[] _alignment,
int[] _refStructure, ColumnSelection[] _hiddenCols)
{
while (viewer.isScriptExecuting())
String[] files = getPdbFile();
if (!waitForFileLoad(files))
{
- return;
+ return null;
}
StringBuilder selectioncom = new StringBuilder(256);
nSeconds = " " + (2.0 / files.length) + " ";
// if (nSeconds).substring(0,5)+" ";
}
+
// see JAL-1345 - should really automatically turn off the animation for
// large numbers of structures, but Jmol doesn't seem to allow that.
// nSeconds = " ";
}
/*
- * 'matched' array will hold 'true' for visible alignment columns where
+ * 'matched' bit j will be set for visible alignment columns j where
* all sequences have a residue with a mapping to the PDB structure
*/
- // TODO could use a BitSet for matched
- boolean matched[] = new boolean[alignment.getWidth()];
- for (int m = 0; m < matched.length; m++)
+ BitSet matched = new BitSet();
+ for (int m = 0; m < alignment.getWidth(); m++)
{
- matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
+ if (hiddenCols == null || hiddenCols.isVisible(m))
+ {
+ matched.set(m);
+ }
}
SuperposeData[] structures = new SuperposeData[files.length];
}
String[] selcom = new String[files.length];
- int nmatched = 0;
- for (boolean b : matched)
- {
- if (b)
- {
- nmatched++;
- }
- }
+ int nmatched = matched.cardinality();
if (nmatched < 4)
{
- // TODO: bail out here because superposition illdefined?
+ return (MessageManager.formatMessage(
+"label.insufficient_residues",
+ nmatched));
}
/*
boolean run = false;
StringBuilder molsel = new StringBuilder();
molsel.append("{");
- for (int r = 0; r < matched.length; r++)
+
+ int nextColumnMatch = matched.nextSetBit(0);
+ while (nextColumnMatch != -1)
{
- if (matched[r])
+ int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
+ if (lpos != pdbResNo - 1)
{
- int pdbResNo = structures[pdbfnum].pdbResNo[r];
- if (lpos != pdbResNo - 1)
+ // discontinuity
+ if (lpos != -1)
{
- // discontinuity
- if (lpos != -1)
- {
- molsel.append(lpos);
- molsel.append(chainCd);
- molsel.append("|");
- }
- run = false;
+ molsel.append(lpos);
+ molsel.append(chainCd);
+ molsel.append("|");
}
- else
+ run = false;
+ }
+ else
+ {
+ // continuous run - and lpos >-1
+ if (!run)
{
- // continuous run - and lpos >-1
- if (!run)
- {
- // at the beginning, so add dash
- molsel.append(lpos);
- molsel.append("-");
- }
- run = true;
+ // at the beginning, so add dash
+ molsel.append(lpos);
+ molsel.append("-");
}
- lpos = pdbResNo;
+ run = true;
}
+ lpos = pdbResNo;
+ nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
}
/*
* add final selection phrase
+ selectioncom.toString() + "); cartoons; ");
// evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
}
+
+ return null;
}
public void evalStateCommand(String command)
/**
* @param files
* @param sr
- * @param fr
- * @param alignment
+ * @param viewPanel
* @return
*/
@Override
protected StructureMappingcommandSet[] getColourBySequenceCommands(
- String[] files, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
+ String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
{
return JmolCommands.getColourBySequenceCommand(getSsm(), files,
- getSequence(), sr, fr, alignment);
+ getSequence(), sr, viewPanel);
}
/**
*/
package jalview.ext.jmol;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
import java.awt.Color;
import java.util.ArrayList;
+import java.util.List;
/**
* Routines for generating Jmol commands for Jalview/Jmol binding another
*/
public static StructureMappingcommandSet[] getColourBySequenceCommand(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
+ SequenceI[][] sequence, SequenceRenderer sr,
+ AlignmentViewPanel viewPanel)
{
-
- ArrayList<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
+ FeatureRenderer fr = viewPanel.getFeatureRenderer();
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
+ AlignViewportI viewport = viewPanel.getAlignViewport();
+ ColumnSelection cs = viewport.getColumnSelection();
+ AlignmentI al = viewport.getAlignment();
+ List<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
for (int sp, m = 0; m < mapping.length; m++)
{
if (mapping[m].getSequence() == sequence[pdbfnum][s]
- && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
+ && (sp = al.findIndex(sequence[pdbfnum][s])) > -1)
{
- SequenceI asp = alignment.getSequenceAt(sp);
+ SequenceI asp = al.getSequenceAt(sp);
for (int r = 0; r < asp.getLength(); r++)
{
// no mapping to gaps in sequence
lastPos = pos;
- Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
+ Color col = sr.getResidueColour(sequence[pdbfnum][s], r,
+ finder);
- if (fr != null)
+ /*
+ * shade hidden regions darker
+ */
+ if (!cs.isVisible(r))
{
- col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
+ col = Color.GRAY;
}
+
String newSelcom = (mapping[m].getChain() != " " ? ":"
+ mapping[m].getChain() : "")
+ "/"
*/
package jalview.ext.rbvi.chimera;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
* @param sequence
* @param sr
* @param fr
- * @param alignment
+ * @param viewPanel
* @return
*/
public static StructureMappingcommandSet[] getColourBySequenceCommand(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
+ SequenceI[][] sequence, SequenceRenderer sr,
+ AlignmentViewPanel viewPanel)
{
Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, files,
- sequence, sr, fr, alignment);
+ sequence, sr, viewPanel);
List<String> colourCommands = buildColourCommands(colourMap);
/**
* <pre>
- * Build a data structure which maps contiguous subsequences for each colour.
- * This generates a data structure from which we can easily generate the
- * Chimera command for colour by sequence.
+ * Build a data structure which records contiguous subsequences for each colour.
+ * From this we can easily generate the Chimera command for colour by sequence.
* Color
* Model number
* Chain
*/
protected static Map<Object, AtomSpecModel> buildColoursMap(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
+ SequenceI[][] sequence, SequenceRenderer sr,
+ AlignmentViewPanel viewPanel)
{
+ FeatureRenderer fr = viewPanel.getFeatureRenderer();
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
+ AlignViewportI viewport = viewPanel.getAlignViewport();
+ ColumnSelection cs = viewport.getColumnSelection();
+ AlignmentI al = viewport.getAlignment();
Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<Object, AtomSpecModel>();
Color lastColour = null;
+
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
{
final SequenceI seq = sequence[pdbfnum][s];
if (mapping[m].getSequence() == seq
- && (sp = alignment.findIndex(seq)) > -1)
+ && (sp = al.findIndex(seq)) > -1)
{
- SequenceI asp = alignment.getSequenceAt(sp);
+ SequenceI asp = al.getSequenceAt(sp);
for (int r = 0; r < asp.getLength(); r++)
{
// no mapping to gaps in sequence
continue;
}
- Color colour = sr.getResidueColour(seq, r, fr);
+ Color colour = sr.getResidueColour(seq, r, finder);
+
+ /*
+ * darker colour for hidden regions
+ */
+ if (!cs.isVisible(r))
+ {
+ colour = Color.GRAY;
+ }
+
final String chain = mapping[m].getChain();
/*
* @param ssm
* @param files
* @param seqs
- * @param fr
- * @param alignment
+ * @param viewPanel
* @return
*/
public static StructureMappingcommandSet getSetAttributeCommandsForFeatures(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+ SequenceI[][] seqs, AlignmentViewPanel viewPanel)
{
Map<String, Map<Object, AtomSpecModel>> featureMap = buildFeaturesMap(
- ssm, files, seqs, fr, alignment);
+ ssm, files, seqs, viewPanel);
List<String> commands = buildSetAttributeCommands(featureMap);
* @param ssm
* @param files
* @param seqs
- * @param fr
- * @param alignment
+ * @param viewPanel
* @return
*/
protected static Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+ SequenceI[][] seqs, AlignmentViewPanel viewPanel)
{
Map<String, Map<Object, AtomSpecModel>> theMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
+ FeatureRenderer fr = viewPanel.getFeatureRenderer();
+ if (fr == null)
+ {
+ return theMap;
+ }
+
List<String> visibleFeatures = fr.getDisplayedFeatureTypes();
if (visibleFeatures.isEmpty())
{
return theMap;
}
+ AlignmentI alignment = viewPanel.getAlignment();
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
/*
* for each distinct value recorded for this feature type,
* add a command to set the attribute on the mapped residues
+ * Put values in single quotes, encoding any embedded single quotes
*/
StringBuilder sb = new StringBuilder(128);
- sb.append("setattr r ").append(attributeName).append(" \"")
- .append(value.toString()).append("\" ");
+ String featureValue = value.toString();
+ featureValue = featureValue.replaceAll("\\'", "'");
+ sb.append("setattr r ").append(attributeName).append(" '")
+ .append(featureValue).append("' ");
sb.append(values.get(value).getAtomSpec());
commands.add(sb.toString());
}
package jalview.ext.rbvi.chimera;
import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.api.structures.JalviewStructureDisplayI;
import jalview.bin.Cache;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResultMatchI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.httpserver.AbstractRequestHandler;
import java.io.PrintWriter;
import java.net.BindException;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collections;
import java.util.Hashtable;
import java.util.LinkedHashMap;
if (getSsm() != null)
{
getSsm().addStructureViewerListener(this);
- // ssm.addSelectionListener(this);
- FeatureRenderer fr = getFeatureRenderer(null);
- if (fr != null)
- {
- fr.featuresAdded();
- }
- refreshGUI();
}
return true;
} catch (Exception q)
}
/**
- * Construct and send a command to align structures against a reference
- * structure, based on one or more sequence alignments
- *
- * @param _alignment
- * an array of alignments to process
- * @param _refStructure
- * an array of corresponding reference structures (index into pdb
- * file array); if a negative value is passed, the first PDB file
- * mapped to an alignment sequence is used as the reference for
- * superposition
- * @param _hiddenCols
- * an array of corresponding hidden columns for each alignment
+ * {@inheritDoc}
*/
@Override
- public void superposeStructures(AlignmentI[] _alignment,
+ public String superposeStructures(AlignmentI[] _alignment,
int[] _refStructure, ColumnSelection[] _hiddenCols)
{
StringBuilder allComs = new StringBuilder(128);
if (!waitForFileLoad(files))
{
- return;
+ return null;
}
refreshPdbEntries();
}
/*
- * 'matched' array will hold 'true' for visible alignment columns where
+ * 'matched' bit i will be set for visible alignment columns i where
* all sequences have a residue with a mapping to the PDB structure
*/
- boolean matched[] = new boolean[alignment.getWidth()];
- for (int m = 0; m < matched.length; m++)
+ BitSet matched = new BitSet();
+ for (int m = 0; m < alignment.getWidth(); m++)
{
- matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
+ if (hiddenCols == null || hiddenCols.isVisible(m))
+ {
+ matched.set(m);
+ }
}
SuperposeData[] structures = new SuperposeData[files.length];
refStructure = candidateRefStructure;
}
- int nmatched = 0;
- for (boolean b : matched)
- {
- if (b)
- {
- nmatched++;
- }
- }
+ int nmatched = matched.cardinality();
if (nmatched < 4)
{
- // TODO: bail out here because superposition illdefined?
+ return MessageManager.formatMessage("label.insufficient_residues",
+ nmatched);
}
/*
int lpos = -1;
boolean run = false;
StringBuilder molsel = new StringBuilder();
- for (int r = 0; r < matched.length; r++)
+
+ int nextColumnMatch = matched.nextSetBit(0);
+ while (nextColumnMatch != -1)
{
- if (matched[r])
+ int pdbResNum = structures[pdbfnum].pdbResNo[nextColumnMatch];
+ if (lpos != pdbResNum - 1)
{
- int pdbResNum = structures[pdbfnum].pdbResNo[r];
- if (lpos != pdbResNum - 1)
+ /*
+ * discontiguous - append last residue now
+ */
+ if (lpos != -1)
{
- /*
- * discontiguous - append last residue now
- */
- if (lpos != -1)
- {
- molsel.append(String.valueOf(lpos));
- molsel.append(chainCd);
- molsel.append(",");
- }
- run = false;
+ molsel.append(String.valueOf(lpos));
+ molsel.append(chainCd);
+ molsel.append(",");
}
- else
+ run = false;
+ }
+ else
+ {
+ /*
+ * extending a contiguous run
+ */
+ if (!run)
{
/*
- * extending a contiguous run
+ * start the range selection
*/
- if (!run)
- {
- /*
- * start the range selection
- */
- molsel.append(String.valueOf(lpos));
- molsel.append("-");
- }
- run = true;
+ molsel.append(String.valueOf(lpos));
+ molsel.append("-");
}
- lpos = pdbResNum;
+ run = true;
}
+ lpos = pdbResNum;
+ nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
}
/*
.append(";" + command.toString());
}
}
+
+ String error = null;
if (selectioncom.length() > 0)
{
// TODO: visually distinguish regions that were superposed
}
allComs.append("; ~display all; chain @CA|P; ribbon ")
.append(selectioncom.toString()).append("; focus");
- sendChimeraCommand(allComs.toString(), false);
+ List<String> chimeraReplies = sendChimeraCommand(allComs.toString(),
+ true);
+ for (String reply : chimeraReplies)
+ {
+ if (reply.toLowerCase().contains("unequal numbers of atoms"))
+ {
+ error = reply;
+ }
+ }
}
-
+ return error;
}
/**
/**
* @param files
* @param sr
- * @param fr
- * @param alignment
+ * @param viewPanel
* @return
*/
@Override
protected StructureMappingcommandSet[] getColourBySequenceCommands(
- String[] files, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
+ String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
{
return ChimeraCommands.getColourBySequenceCommand(getSsm(), files,
- getSequence(), sr, fr, alignment);
+ getSequence(), sr, viewPanel);
}
/**
* features visible in Jalview
*
* @param avp
+ * @return
*/
- public void sendFeaturesToViewer(AlignmentViewPanel avp)
+ public int sendFeaturesToViewer(AlignmentViewPanel avp)
{
// TODO refactor as required to pull up to an interface
AlignmentI alignment = avp.getAlignment();
- FeatureRenderer fr = getFeatureRenderer(avp);
-
- /*
- * fr is null if feature display is turned off
- */
- if (fr == null)
- {
- return;
- }
String[] files = getPdbFile();
if (files == null)
{
- return;
+ return 0;
}
StructureMappingcommandSet commandSet = ChimeraCommands
.getSetAttributeCommandsForFeatures(getSsm(), files,
- getSequence(), fr, alignment);
+ getSequence(), avp);
String[] commands = commandSet.commands;
if (commands.length > 10)
{
sendAsynchronousCommand(command, null);
}
}
+ return commands.length;
}
/**
/*
* locate the mapped position in the alignment (if any)
*/
- SearchResults sr = getSsm()
+ SearchResultsI sr = getSsm()
.findAlignmentPositionsForStructurePositions(atoms);
/*
*/
package jalview.ext.varna;
-import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
import jalview.structure.StructureSelectionManager;
*/
public static String[] getColourBySequenceCommand(
StructureSelectionManager ssm, String[] files,
- SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
+ SequenceI[][] sequence, SequenceRenderer sr,
+ FeatureColourFinder finder,
AlignmentI alignment)
{
ArrayList<String> str = new ArrayList<String>();
StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
if (mapping == null || mapping.length < 1)
+ {
continue;
+ }
int lastPos = -1;
for (int s = 0; s < sequence[pdbfnum].length; s++)
int pos = mapping[m].getPDBResNum(asp.findPosition(r));
if (pos < 1 || pos == lastPos)
+ {
continue;
+ }
lastPos = pos;
- Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
+ Color col = sr.getResidueColour(sequence[pdbfnum][s], r,
+ finder);
- if (fr != null)
- col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
String newSelcom = (mapping[m].getChain() != " " ? ":"
+ mapping[m].getChain() : "")
+ "/"
if (foundDataRow != null && foundDataRow.length > 0)
{
result = new ArrayList<FTSData>();
- String titleRow = getDataColumnsFieldsAsTabDelimitedString(uniprotRestRequest
- .getWantedFields());
- // System.out.println(">>>>Title row : " + titleRow);
+ boolean firstRow = true;
for (String dataRow : foundDataRow)
{
- if (dataRow.equalsIgnoreCase(titleRow))
+ // The first data row is usually the header data. This should be
+ // filtered out from the rest of the data See: JAL-2485
+ if (firstRow)
{
- // System.out.println(">>>>>>>>>> matched!!!");
+ firstRow = false;
continue;
}
// System.out.println(dataRow);
import jalview.schemes.TCoffeeColourScheme;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import jalview.ws.DBRefFetcher;
import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
import jalview.ws.jws1.Discoverer;
AlignViewport viewport;
+ ViewportRanges vpRanges;
+
public AlignViewControllerI avc;
List<AlignmentPanel> alignPanels = new ArrayList<AlignmentPanel>();
progressBar = new ProgressBar(this.statusPanel, this.statusBar);
}
+ vpRanges = viewport.getRanges();
avc = new jalview.controller.AlignViewController(this, viewport,
alignPanel);
if (viewport.getAlignmentConservationAnnotation() == null)
new String[] { (viewport.cursorMode ? "on" : "off") }));
if (viewport.cursorMode)
{
- alignPanel.getSeqPanel().seqCanvas.cursorX = viewport.startRes;
- alignPanel.getSeqPanel().seqCanvas.cursorY = viewport.startSeq;
+ alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges
+ .getStartRes();
+ alignPanel.getSeqPanel().seqCanvas.cursorY = vpRanges
+ .getStartSeq();
}
alignPanel.getSeqPanel().seqCanvas.repaint();
break;
}
else
{
- alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
- - viewport.endSeq + viewport.startSeq);
+ alignPanel.setScrollValues(vpRanges.getStartRes(),
+ 2 * vpRanges.getStartSeq() - vpRanges.getEndSeq());
}
break;
case KeyEvent.VK_PAGE_DOWN:
}
else
{
- alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
- + viewport.endSeq - viewport.startSeq);
+ alignPanel.setScrollValues(vpRanges.getStartRes(),
+ vpRanges.getEndSeq());
}
break;
}
{
// propagate alignment changed.
- viewport.setEndSeq(alignment.getHeight());
+ vpRanges.setEndSeq(alignment.getHeight());
if (annotationAdded)
{
// Duplicate sequence annotation in all views.
{
trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
column, viewport.getAlignment());
- viewport.setStartRes(0);
+ vpRanges.setStartRes(0);
}
else
{
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(viewport.startRes);
+ int startRes = seq.findPosition(vpRanges.getStartRes());
// ShiftList shifts;
// viewport.getAlignment().removeGaps(shifts=new ShiftList());
// edit.alColumnChanges=shifts.getInverse();
// if (viewport.hasHiddenColumns)
// viewport.getColumnSelection().compensateForEdits(shifts);
- viewport.setStartRes(seq.findIndex(startRes) - 1);
+ vpRanges.setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null, viewport.getAlignment()
.getSequences());
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(viewport.startRes);
+ int startRes = seq.findPosition(vpRanges.getStartRes());
addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
viewport.getAlignment()));
- viewport.setStartRes(seq.findIndex(startRes) - 1);
+ vpRanges.setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null, viewport.getAlignment()
.getSequences());
*/
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);
*/
if (ResidueColourScheme.USER_DEFINED.equals(name))
{
- new UserDefinedColours(alignPanel, null);
+ new UserDefinedColours(alignPanel);
return;
}
public void changeColour(ColourSchemeI cs)
{
// TODO: pull up to controller method
- if (cs != null)
- {
- ColourMenuHelper.setColourSelected(colourMenu, cs.getSchemeName());
- }
+ ColourMenuHelper.setColourSelected(colourMenu, cs);
viewport.setGlobalColourScheme(cs);
colourMenu.add(annotationColour);
ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
- String schemeName = colourScheme == null ? null : colourScheme
- .getSchemeName();
-
- ColourMenuHelper.setColourSelected(colourMenu, schemeName);
+ ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
}
}
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.ResidueColourScheme;
import jalview.schemes.UserColourScheme;
-import jalview.structure.CommandListener;
import jalview.structure.SelectionSource;
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import jalview.ws.params.AutoCalcSetting;
import java.awt.Container;
* @version $Revision: 1.141 $
*/
public class AlignViewport extends AlignmentViewport implements
- SelectionSource, CommandListener
+ SelectionSource
{
Font font;
void init()
{
- this.startRes = 0;
- this.endRes = alignment.getWidth() - 1;
- this.startSeq = 0;
- this.endSeq = alignment.getHeight() - 1;
+ ranges = new ViewportRanges(this.alignment);
applyViewProperties();
String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
}
}
- setEndSeq(getAlignment().getHeight());
+ ranges.setEndSeq(getAlignment().getHeight());
firePropertyChange("alignment", null, getAlignment().getSequences());
}
import jalview.structure.StructureSelectionManager;
import jalview.util.MessageManager;
import jalview.util.Platform;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Color;
{
public AlignViewport av;
+ ViewportRanges vpRanges;
+
OverviewPanel overviewPanel;
private SeqPanel seqPanel;
// this value is set false when selection area being dragged
boolean fastPaint = true;
- int hextent = 0;
+ private int hextent = 0;
- int vextent = 0;
+ private int vextent = 0;
/*
* Flag set while scrolling to follow complementary cDNA/protein scroll. When
{
alignFrame = af;
this.av = av;
+ vpRanges = av.getRanges();
setSeqPanel(new SeqPanel(av, this));
setIdPanel(new IdPanel(av, this));
*/
if (centre)
{
- int offset = (av.getEndRes() - av.getStartRes() + 1) / 2 - 1;
+ int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
start = Math.max(start - offset, 0);
end = end + offset - 1;
}
// + av.getStartSeq() + ", ends=" + av.getEndSeq());
if (!av.getWrapAlignment())
{
- if ((startv = av.getStartRes()) >= start)
+ if ((startv = vpRanges.getStartRes()) >= start)
{
/*
* Scroll left to make start of search results visible
// setScrollValues(start - 1, seqIndex); // plus one residue
setScrollValues(start, seqIndex);
}
- else if ((endv = av.getEndRes()) <= end)
+ else if ((endv = vpRanges.getEndRes()) <= end)
{
/*
* Scroll right to make end of search results visible
// setScrollValues(startv + 1 + end - endv, seqIndex); // plus one
setScrollValues(startv + end - endv, seqIndex);
}
- else if ((starts = av.getStartSeq()) > seqIndex)
+ else if ((starts = vpRanges.getStartSeq()) > seqIndex)
{
/*
* Scroll up to make start of search results visible
*/
- setScrollValues(av.getStartRes(), seqIndex);
+ setScrollValues(vpRanges.getStartRes(), seqIndex);
}
- else if ((ends = av.getEndSeq()) <= seqIndex)
+ else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
{
/*
* Scroll down to make end of search results visible
*/
- setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
+ setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
+ + 1);
}
/*
* Else results are already visible - no need to scroll
{
int cwidth = getSeqPanel().seqCanvas
.getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
- if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
+ if (res < vpRanges.getStartRes()
+ || res >= (vpRanges.getStartRes() + cwidth))
{
vscroll.setValue((res / cwidth));
- av.startRes = vscroll.getValue() * cwidth;
+ vpRanges.setStartRes(vscroll.getValue() * cwidth);
}
}
fontChanged();
setAnnotationVisible(av.isShowAnnotation());
boolean wrap = av.getWrapAlignment();
- av.startSeq = 0;
+ vpRanges.setStartSeq(0);
scalePanelHolder.setVisible(!wrap);
hscroll.setVisible(!wrap);
idwidthAdjuster.setVisible(!wrap);
*/
public void setScrollValues(int x, int y)
{
- // System.err.println("Scroll " + this.av.viewName + " to " + x + "," + y);
if (av == null || av.getAlignment() == null)
{
return;
if (av.hasHiddenColumns())
{
+ // reset the width to exclude hidden columns
width = av.getColumnSelection().findColumnPosition(width);
}
- av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av
- .getCharWidth())) - 1);
-
hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
x = 0;
}
+ // update endRes after x has (possibly) been adjusted
+ vpRanges.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av
+ .getCharWidth())) - 1);
+
/*
* each scroll adjustment triggers adjustmentValueChanged, which resets the
* 'do not scroll complement' flag; ensure it is the same for both
@Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
- int oldX = av.getStartRes();
- int oldY = av.getStartSeq();
+ int oldX = vpRanges.getStartRes();
+ int oldY = vpRanges.getStartSeq();
if (evt.getSource() == hscroll)
{
int x = hscroll.getValue();
- av.setStartRes(x);
- av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av
+ vpRanges.setStartRes(x);
+ vpRanges.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av
.getCharWidth())) - 1);
}
{
int rowSize = getSeqPanel().seqCanvas
.getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
- av.setStartRes(offy * rowSize);
- av.setEndRes((offy + 1) * rowSize);
+ vpRanges.setStartRes(offy * rowSize);
+ vpRanges.setEndRes((offy + 1) * rowSize);
}
else
{
@Override
public void run()
{
- setScrollValues(av.getStartRes(), av.getStartSeq());
+ setScrollValues(vpRanges.getStartRes(),
+ vpRanges.getStartSeq());
}
});
}
}
else
{
- av.setStartSeq(offy);
- av.setEndSeq(offy
- + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight()));
+ vpRanges.setStartSeq(offy);
+ vpRanges.setEndSeq(offy
+ + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight())
+ - 1);
}
}
overviewPanel.setBoxPosition();
}
- int scrollX = av.startRes - oldX;
- int scrollY = av.startSeq - oldY;
+ int scrollX = vpRanges.getStartRes() - oldX;
+ int scrollY = vpRanges.getStartSeq() - oldY;
if (av.getWrapAlignment() || !fastPaint)
{
{
// Make sure we're not trying to draw a panel
// larger than the visible window
- if (scrollX > av.endRes - av.startRes)
+ if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
{
- scrollX = av.endRes - av.startRes;
+ scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
}
- else if (scrollX < av.startRes - av.endRes)
+ else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
{
- scrollX = av.startRes - av.endRes;
+ scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
}
if (scrollX != 0 || scrollY != 0)
}
else
{
- setScrollValues(av.getStartRes(), av.getStartSeq());
+ setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
}
}
{
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 javax.swing.JColorChooser;
import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.Scrollable;
return;
}
- int column = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int column = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
if (av.hasHiddenColumns())
{
return;
}
}
- imgWidth = (av.endRes - av.startRes + 1) * av.getCharWidth();
+ imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes() + 1)
+ * av.getCharWidth();
if (imgWidth < 1)
{
return;
imageFresh = true;
}
- drawComponent(gg, av.startRes, av.endRes + 1);
+ drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
+ .getEndRes() + 1);
imageFresh = false;
g.drawImage(image, 0, 0, this);
}
gg.copyArea(0, 0, imgWidth, getHeight(),
-horizontal * av.getCharWidth(), 0);
long mtime = System.currentTimeMillis();
- int sr = av.startRes;
- int er = av.endRes + 1;
+ int sr = av.getRanges().getStartRes();
+ int er = av.getRanges().getEndRes() + 1;
int transX = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
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;
+ }
}
{
private AppJmol appJmolWindow;
- private FeatureRenderer fr = null;
-
public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm,
PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol)
{
}
@Override
- public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
- {
- AlignmentPanel ap = (alignment == null) ? appJmolWindow
- .getAlignmentPanel() : (AlignmentPanel) alignment;
- if (ap.av.isShowSequenceFeatures())
- {
- if (fr == null)
- {
- fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer();
- }
- else
- {
- ap.updateFeatureRenderer(fr);
- }
- }
-
- return fr;
- }
-
- @Override
public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
{
return new SequenceRenderer(((AlignmentPanel) alignment).av);
{
return appJmolWindow;
}
+
+ @Override
+ public jalview.api.FeatureRenderer getFeatureRenderer(
+ AlignmentViewPanel alignment)
+ {
+ AlignmentPanel ap = (alignment == null) ? appJmolWindow
+ .getAlignmentPanel() : (AlignmentPanel) alignment;
+ if (ap.av.isShowSequenceFeatures())
+ {
+ return ap.av.getAlignPanel().getSeqPanel().seqCanvas.fr;
+ }
+
+ return null;
+ }
}
*/
package jalview.gui;
+import jalview.api.FeatureRenderer;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.PDBEntry;
private Random random = new Random();
+ private int myWidth = 500;
+
+ private int myHeight = 150;
+
/**
* Initialise menu options.
*/
*/
protected void sendFeaturesToChimera()
{
- jmb.sendFeaturesToViewer(getAlignmentPanel());
+ int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
+ statusBar.setText(MessageManager.formatMessage("label.attributes_set",
+ count));
}
/**
useAlignmentPanelForSuperposition(ap);
}
jmb.setColourBySequence(true);
- setSize(400, 400); // probably should be a configurable/dynamic default here
+ setSize(myWidth, myHeight);
initMenus();
addingStructures = false;
jmb.setFinishedInit(true);
jmb.setLoadingFromArchive(false);
+ /*
+ * ensure that any newly discovered features (e.g. RESNUM)
+ * are added to any open feature settings dialog
+ */
+ FeatureRenderer fr = getBinding().getFeatureRenderer(null);
+ if (fr != null)
+ {
+ fr.featuresAdded();
+ }
+
// refresh the sequence colours for the new structure(s)
for (AlignmentPanel ap : _colourwith)
{
}
/**
- * Override superclass method to make the 'Chimera' menu always visible, but
- * 'Superpose with...' only enabled if there is more than one structure shown
+ * Sends commands to align structures according to associated alignment(s).
+ *
+ * @return
*/
@Override
- public void updateTitleAndMenus()
+ protected String alignStructs_withAllAlignPanels()
{
- super.updateTitleAndMenus();
- viewerActionMenu.setVisible(true);
- viewSelectionMenu.setEnabled(false);
- if (getBinding().getPdbFile().length > 1
- && getBinding().getSequence().length > 1)
+ String reply = super.alignStructs_withAllAlignPanels();
+ if (reply != null)
{
- viewSelectionMenu.setEnabled(true);
+ statusBar.setText("Superposition failed: " + reply);
}
+ return reply;
}
}
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;
{
public interface ColourChangeListener
{
+ /**
+ * Change colour scheme to the selected scheme
+ *
+ * @param name
+ * the registered (unique) name of a colour scheme
+ */
void changeColour_actionPerformed(String name);
}
* <li>Clustal</li>
* <li>...other 'built-in' colours</li>
* <li>...any user-defined colours</li>
- * <li>User Defined..</li>
+ * <li>User Defined..(only for AlignFrame menu)</li>
* </ul>
*
* @param colourMenu
}
/*
- * scan registered colour schemes (built-in or user-defined
+ * scan registered colour schemes (built-in or user-defined)
* and add them to the menu (in the order they were registered)
*/
Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
/*
* user-defined colour scheme loaded on startup or during the
* Jalview session; right-click on this offers the option to
- * remove it as a colour choice
+ * remove it as a colour choice (unless currently selected)
*/
radioItem.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent evt)
{
- if (evt.isPopupTrigger()) // Mac
+ if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
{
offerRemoval();
}
@Override
public void mouseReleased(MouseEvent evt)
{
- if (evt.isPopupTrigger()) // Windows
+ if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
{
offerRemoval();
}
final String label = MessageManager.getString("action.user_defined");
JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
label);
+ userDefinedColour.setName(ResidueColourScheme.USER_DEFINED);
userDefinedColour.addActionListener(new ActionListener()
{
@Override
}
/**
- * Marks as selected the colour menu item matching the given name, or the
- * first item ('None') if no match is found
+ * Marks as selected the colour menu item matching the given colour scheme, or
+ * the first item ('None') if no match is found. If the colour scheme is a
+ * user defined scheme, but not in the menu (this arises if a new scheme is
+ * defined and applied but not saved to file), then menu option
+ * "User Defined.." is selected.
*
* @param colourMenu
- * @param colourName
+ * @param cs
*/
- public static void setColourSelected(JMenu colourMenu, String colourName)
+ public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
{
- if (colourName == null)
- {
- return;
- }
+ String colourName = cs == null ? ResidueColourScheme.NONE : cs
+ .getSchemeName();
JRadioButtonMenuItem none = null;
+ JRadioButtonMenuItem userDefined = null;
/*
* select the radio button whose name matches the colour name
{
if (menuItem instanceof JRadioButtonMenuItem)
{
- String buttonName = ((JRadioButtonMenuItem) menuItem).getName();
- if (colourName.equals(buttonName))
+ JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
+ String buttonName = radioButton.getName();
+ if (buttonName.equals(colourName))
{
- ((JRadioButtonMenuItem) menuItem).setSelected(true);
+ radioButton.setSelected(true);
return;
}
if (ResidueColourScheme.NONE.equals(buttonName))
{
- none = (JRadioButtonMenuItem) menuItem;
+ none = radioButton;
+ }
+ if (ResidueColourScheme.USER_DEFINED.equals(buttonName))
+ {
+ userDefined = radioButton;
}
}
}
- if (none != null)
+
+ /*
+ * no match by name; select User Defined.. if current scheme is a
+ * user defined one, else select None
+ */
+ if (cs instanceof UserColourScheme && userDefined != null)
+ {
+ userDefined.setSelected(true);
+ }
+ else if (none != null)
{
none.setSelected(true);
}
}
/**
- * Marks as selected the colour menu item matching the given colour scheme, or
- * the first item ('None') if no match is found
- *
- * @param colourMenu
- * @param cs
- */
- public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
- {
- setColourSelected(colourMenu, cs == null ? ResidueColourScheme.NONE
- : cs.getSchemeName());
- }
-
- /**
* Updates the USER_DEFINE_COLOURS preference to remove any de-registered
* colour scheme
*/
{
try
{
- UserColourScheme ucs = ColourSchemes.loadColourScheme(file);
+ UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
if (ucs != null
&& ColourSchemes.getInstance().nameExists(ucs.getName()))
{
if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
{
- if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
- {
- jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
- }
t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
changeSupport);
-
}
Thread t3 = null;
{
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
* @version $Revision$
*/
public class FeatureRenderer extends
- jalview.renderer.seqfeatures.FeatureRenderer implements
- jalview.api.FeatureRenderer
+ jalview.renderer.seqfeatures.FeatureRenderer
{
Color resBoxColour;
if (reply == JvOptionPane.OK_OPTION && name.getText().length() > 0)
{
- // This ensures that the last sequence
- // is refreshed and new features are rendered
- lastSeq = null;
lastFeatureAdded = name.getText().trim();
lastFeatureGroupAdded = source.getText().trim();
lastDescriptionAdded = description.getText().replaceAll("\n", " ");
package jalview.gui;
import jalview.datamodel.SequenceI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Color;
return;
}
+ ViewportRanges ranges = av.getRanges();
+
gg.copyArea(0, 0, getWidth(), imgHeight, 0,
-vertical * av.getCharHeight());
- int ss = av.startSeq;
- int es = av.endSeq;
+ int ss = ranges.getStartSeq();
+ int es = ranges.getEndSeq();
int transY = 0;
if (vertical > 0) // scroll down
{
ss = es - vertical;
- if (ss < av.startSeq)
+ if (ss < ranges.getStartSeq())
{ // ie scrolling too fast, more than a page at a time
- ss = av.startSeq;
+ ss = ranges.getStartSeq();
}
else
{
- transY = imgHeight - (vertical * av.getCharHeight());
+ transY = imgHeight - ((vertical + 1) * av.getCharHeight());
}
}
- else if (vertical < 0)
+ else if (vertical < 0) // scroll up
{
es = ss - vertical;
- if (es > av.endSeq)
+ if (es > ranges.getEndSeq())
{
- es = av.endSeq;
+ es = ranges.getEndSeq();
}
}
gg.setColor(Color.white);
gg.fillRect(0, 0, getWidth(), imgHeight);
- drawIds(av.getStartSeq(), av.endSeq);
+ drawIds(av.getRanges().getStartSeq(), av.getRanges().getEndSeq());
g.drawImage(image, 0, 0, this);
}
int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
- int rowSize = av.getEndRes() - av.getStartRes();
+ int rowSize = av.getRanges().getEndRes()
+ - av.getRanges().getStartRes();
// Draw the rest of the panels
- for (int ypos = hgap, row = av.startRes; (ypos <= getHeight())
+ for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getHeight())
&& (row < maxwidth); ypos += cHeight, row += rowSize)
{
for (int i = starty; i < alheight; i++)
SequenceI sequence;
// Now draw the id strings
- for (int i = starty; i < endy; i++)
+ for (int i = starty; i <= endy; i++)
{
sequence = av.getAlignment().getSequenceAt(i);
return;
}
- if (mouseDragging && (e.getY() < 0) && (av.getStartSeq() > 0))
+ if (mouseDragging && (e.getY() < 0)
+ && (av.getRanges().getStartSeq() > 0))
{
scrollThread = new ScrollThread(true);
}
if (mouseDragging && (e.getY() >= getHeight())
- && (av.getAlignment().getHeight() > av.getEndSeq()))
+ && (av.getAlignment().getHeight() > av.getRanges().getEndSeq()))
{
scrollThread = new ScrollThread(false);
}
int index = av.getAlignment().findIndex(list.get(0));
// do we need to scroll the panel?
- if ((av.getStartSeq() > index) || (av.getEndSeq() < index))
+ if ((av.getRanges().getStartSeq() > index)
+ || (av.getRanges().getEndSeq() < index))
{
- alignPanel.setScrollValues(av.getStartRes(), index);
+ alignPanel.setScrollValues(av.getRanges().getStartRes(), index);
}
}
if (alignPanel.scrollUp(up))
{
// scroll was ok, so add new sequence to selection
- int seq = av.getStartSeq();
+ int seq = av.getRanges().getStartSeq();
if (!up)
{
- seq = av.getEndSeq();
+ seq = av.getRanges().getEndSeq();
}
if (seq < lastid)
private JLabel dbstatus, dbstatex;
+ private JPanel mainPanel = new JPanel(new BorderLayout());
+
public JDatabaseTree(jalview.ws.SequenceFetcher sfetch)
{
- initDialogFrame(this, true, false,
+ mainPanel.add(this);
+ initDialogFrame(mainPanel, true, false,
MessageManager
.getString("label.select_database_retrieval_source"),
650, 490);
}
// and sort the tree
sortTreeNodes(root);
- svp = new JScrollPane();
- // svp.setAutoscrolls(true);
dbviews = new JTree(new DefaultTreeModel(root, false));
dbviews.setCellRenderer(new DbTreeRenderer(this));
dbviews.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
- svp.getViewport().setView(dbviews);
- // svp.getViewport().setMinimumSize(new Dimension(300,200));
- // svp.setSize(300,250);
- // JPanel panel=new JPanel();
- // panel.setSize(new Dimension(350,220));
- // panel.add(svp);
+ svp = new JScrollPane(dbviews);
+ svp.setMinimumSize(new Dimension(100, 200));
+ svp.setPreferredSize(new Dimension(200, 400));
+ svp.setMaximumSize(new Dimension(300, 600));
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setSize(new Dimension(350, 220));
+ panel.add(svp);
dbviews.addTreeSelectionListener(new TreeSelectionListener()
{
dbstat.add(dbstatex);
jc.add(dbstat, BorderLayout.SOUTH);
jc.validate();
- // j.setPreferredSize(new Dimension(300,50));
add(jc, BorderLayout.CENTER);
ok.setEnabled(false);
j.add(ok);
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;
import jalview.util.StringUtils;
import jalview.util.jarInputStreamProvider;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
import jalview.ws.jws2.Jws2Discoverer;
List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
AlignViewport av = ap.av;
+ ViewportRanges vpRanges = av.getRanges();
JalviewModel object = new JalviewModel();
object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
view.setWidth(size.width);
view.setHeight(size.height);
- view.setStartRes(av.startRes);
- view.setStartSeq(av.startSeq);
+ view.setStartRes(vpRanges.getStartRes());
+ view.setStartSeq(vpRanges.getStartSeq());
if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
{
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);
}
});
}
af.viewport.setThresholdTextColour(view.getTextColThreshold());
af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
.isShowUnconserved() : false);
- af.viewport.setStartRes(view.getStartRes());
- af.viewport.setStartSeq(view.getStartSeq());
+ af.viewport.getRanges().setStartRes(view.getStartRes());
+ af.viewport.getRanges().setStartSeq(view.getStartSeq());
af.alignPanel.updateLayout();
ColourSchemeI cs = null;
// apply colourschemes
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;
af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
view.getHeight());
- af.viewport.setStartRes(view.getStartRes());
- af.viewport.setStartSeq(view.getStartSeq());
+ af.viewport.getRanges().setStartRes(view.getStartRes());
+ af.viewport.getRanges().setStartSeq(view.getStartSeq());
af.viewport.setShowAnnotation(view.getShowAnnotation());
af.viewport.setAbovePIDThreshold(view.getPidSelected());
af.viewport.setColourText(view.getShowColourText());
{
private ChimeraViewFrame cvf;
- private FeatureRenderer fr = null;
-
-
public JalviewChimeraBindingModel(ChimeraViewFrame chimeraViewFrame,
StructureSelectionManager ssm, PDBEntry[] pdbentry,
SequenceI[][] sequenceIs, DataSourceType protocol)
: (AlignmentPanel) alignment;
if (ap.av.isShowSequenceFeatures())
{
- if (fr == null)
- {
- fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer();
- }
- else
- {
- ap.updateFeatureRenderer(fr);
- }
+ return ap.getSeqPanel().seqCanvas.fr;
}
- return fr;
+ return null;
}
@Override
*/
package jalview.gui;
+import jalview.datamodel.SequenceI;
import jalview.renderer.AnnotationRenderer;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.viewmodel.OverviewDimensions;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JPanel;
/**
- * DOCUMENT ME!
+ * Panel displaying an overview of the full alignment, with an interactive box
+ * representing the viewport onto the alignment.
*
* @author $author$
* @version $Revision$
*/
public class OverviewPanel extends JPanel implements Runnable
{
- BufferedImage miniMe;
+ private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
- AlignViewport av;
+ private final AnnotationRenderer renderer = new AnnotationRenderer();
- AlignmentPanel ap;
+ private OverviewDimensions od;
- final AnnotationRenderer renderer = new AnnotationRenderer();
+ private BufferedImage miniMe;
- float scalew = 1f;
-
- float scaleh = 1f;
-
- int width;
-
- int sequencesHeight;
-
- int graphHeight = 20;
-
- int boxX = -1;
+ private BufferedImage lastMiniMe = null;
- int boxY = -1;
+ private AlignViewport av;
- int boxWidth = -1;
+ private AlignmentPanel ap;
- int boxHeight = -1;
+ //
+ private boolean resizing = false;
- boolean resizing = false;
+ // This is set true if the user resizes whilst
+ // the overview is being calculated
+ private boolean resizeAgain = false;
// Can set different properties in this seqCanvas than
// main visible SeqCanvas
- SequenceRenderer sr;
+ private SequenceRenderer sr;
jalview.renderer.seqfeatures.FeatureRenderer fr;
/**
* Creates a new OverviewPanel object.
*
- * @param ap
- * DOCUMENT ME!
+ * @param alPanel
+ * The alignment panel which is shown in the overview panel
*/
- public OverviewPanel(AlignmentPanel ap)
+ public OverviewPanel(AlignmentPanel alPanel)
{
- this.av = ap.av;
- this.ap = ap;
+ this.av = alPanel.av;
+ this.ap = alPanel;
setLayout(null);
sr = new SequenceRenderer(av);
sr.forOverview = true;
fr = new FeatureRenderer(ap);
- // scale the initial size of overviewpanel to shape of alignment
- float initialScale = (float) av.getAlignment().getWidth()
- / (float) av.getAlignment().getHeight();
-
- if (av.getAlignmentConservationAnnotation() == null)
- {
- graphHeight = 0;
- }
-
- if (av.getAlignment().getWidth() > av.getAlignment().getHeight())
- {
- // wider
- width = 400;
- sequencesHeight = (int) (400f / initialScale);
- if (sequencesHeight < 40)
- {
- sequencesHeight = 40;
- }
- }
- else
- {
- // taller
- width = (int) (400f * initialScale);
- sequencesHeight = 300;
-
- if (width < 120)
- {
- width = 120;
- }
- }
+ od = new OverviewDimensions(av.getRanges(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null));
addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent evt)
{
- if ((getWidth() != width)
- || (getHeight() != (sequencesHeight + graphHeight)))
+ if ((getWidth() != od.getWidth())
+ || (getHeight() != (od.getHeight())))
{
updateOverviewImage();
}
{
if (!av.getWrapAlignment())
{
- // TODO: feature: jv2.5 detect shift drag and update selection from
- // it.
- boxX = evt.getX();
- boxY = evt.getY();
- checkValid();
+ od.updateViewportFromMouse(evt.getX(), evt.getY(), av
+ .getAlignment().getHiddenSequences(), av
+ .getColumnSelection(), av.getRanges());
+ ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
}
}
});
{
if (!av.getWrapAlignment())
{
- boxX = evt.getX();
- boxY = evt.getY();
- checkValid();
+ od.updateViewportFromMouse(evt.getX(), evt.getY(), av
+ .getAlignment().getHiddenSequences(), av
+ .getColumnSelection(), av.getRanges());
+ ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
}
}
});
}
/**
- * DOCUMENT ME!
- */
- void checkValid()
- {
- if (boxY < 0)
- {
- boxY = 0;
- }
-
- if (boxY > (sequencesHeight - boxHeight))
- {
- boxY = sequencesHeight - boxHeight + 1;
- }
-
- if (boxX < 0)
- {
- boxX = 0;
- }
-
- if (boxX > (width - boxWidth))
- {
- if (av.hasHiddenColumns())
- {
- // Try smallest possible box
- boxWidth = (int) ((av.endRes - av.startRes + 1) * av.getCharWidth() * scalew);
- }
- boxX = width - boxWidth;
- }
-
- int col = (int) (boxX / scalew / av.getCharWidth());
- int row = (int) (boxY / scaleh / av.getCharHeight());
-
- if (av.hasHiddenColumns())
- {
- if (!av.getColumnSelection().isVisible(col))
- {
- return;
- }
-
- col = av.getColumnSelection().findColumnPosition(col);
- }
-
- if (av.hasHiddenRows())
- {
- row = av.getAlignment().getHiddenSequences()
- .findIndexWithoutHiddenSeqs(row);
- }
-
- ap.setScrollValues(col, row);
-
- }
-
- /**
- * DOCUMENT ME!
+ * Updates the overview image when the related alignment panel is updated
*/
public void updateOverviewImage()
{
if ((getWidth() > 0) && (getHeight() > 0))
{
- width = getWidth();
- sequencesHeight = getHeight() - graphHeight;
+ od.setWidth(getWidth());
+ od.setHeight(getHeight());
}
- setPreferredSize(new Dimension(width, sequencesHeight + graphHeight));
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
Thread thread = new Thread(this);
thread.start();
repaint();
}
- // This is set true if the user resizes whilst
- // the overview is being calculated
- boolean resizeAgain = false;
-
- /**
- * DOCUMENT ME!
- */
@Override
public void run()
{
fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer());
}
- int alwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getHeight()
- + av.getAlignment().getHiddenSequences().getSize();
-
- setPreferredSize(new Dimension(width, sequencesHeight + graphHeight));
-
- int fullsizeWidth = alwidth * av.getCharWidth();
- int fullsizeHeight = alheight * av.getCharHeight();
+ // why do we need to set preferred size again? was set in
+ // updateOverviewImage
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- scalew = (float) width / (float) fullsizeWidth;
- scaleh = (float) sequencesHeight / (float) fullsizeHeight;
-
- miniMe = new BufferedImage(width, sequencesHeight + graphHeight,
+ miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics mg = miniMe.getGraphics();
mg.setColor(Color.orange);
- mg.fillRect(0, 0, width, miniMe.getHeight());
-
- float sampleCol = (float) alwidth / (float) width;
- float sampleRow = (float) alheight / (float) sequencesHeight;
+ mg.fillRect(0, 0, od.getWidth(), miniMe.getHeight());
- int lastcol = -1, lastrow = -1;
- int color = Color.white.getRGB();
- int row, col;
- jalview.datamodel.SequenceI seq;
- final boolean hasHiddenRows = av.hasHiddenRows(), hasHiddenCols = av
- .hasHiddenColumns();
- boolean hiddenRow = false;
- // get hidden row and hidden column map once at beginning.
- // clone featureRenderer settings to avoid race conditions... if state is
- // updated just need to refresh again
- for (row = 0; row < sequencesHeight; row++)
- {
- if (resizeAgain)
- {
- break;
- }
- if ((int) (row * sampleRow) == lastrow)
- {
- // No need to recalculate the colours,
- // Just copy from the row above
- for (col = 0; col < width; col++)
- {
- if (resizeAgain)
- {
- break;
- }
- miniMe.setRGB(col, row, miniMe.getRGB(col, row - 1));
- }
- continue;
- }
-
- lastrow = (int) (row * sampleRow);
-
- hiddenRow = false;
- if (hasHiddenRows)
- {
- seq = av.getAlignment().getHiddenSequences()
- .getHiddenSequence(lastrow);
- if (seq == null)
- {
- int index = av.getAlignment().getHiddenSequences()
- .findIndexWithoutHiddenSeqs(lastrow);
-
- seq = av.getAlignment().getSequenceAt(index);
- }
- else
- {
- hiddenRow = true;
- }
- }
- else
- {
- seq = av.getAlignment().getSequenceAt(lastrow);
- }
-
- if (seq == null)
- {
- System.out.println(lastrow + " null");
- continue;
- }
-
- for (col = 0; col < width; col++)
- {
- if (resizeAgain)
- {
- break;
- }
- if ((int) (col * sampleCol) == lastcol
- && (int) (row * sampleRow) == lastrow)
- {
- miniMe.setRGB(col, row, color);
- continue;
- }
-
- lastcol = (int) (col * sampleCol);
-
- if (seq.getLength() > lastcol)
- {
- color = sr.getResidueBoxColour(seq, lastcol).getRGB();
-
- if (av.isShowSequenceFeatures())
- {
- color = fr.findFeatureColour(color, seq, lastcol);
- }
- }
- else
- {
- color = -1; // White
- }
+ // calculate sampleCol and sampleRow
+ // alignment width is max number of residues/bases
+ // alignment height is number of sequences
+ int alwidth = av.getAlignment().getWidth();
+ int alheight = av.getAlignment().getAbsoluteHeight();
- if (hiddenRow
- || (hasHiddenCols && !av.getColumnSelection().isVisible(
- lastcol)))
- {
- color = new Color(color).darker().darker().getRGB();
- }
+ // sampleCol or sampleRow is the width/height allocated to each residue
+ // in particular, sometimes we may need more than one row/col of the
+ // BufferedImage allocated
+ // sampleCol is how much of a residue to assign to each pixel
+ // sampleRow is how many sequences to assign to each pixel
+ float sampleCol = alwidth / (float) od.getWidth();
+ float sampleRow = alheight / (float) od.getSequencesHeight();
- miniMe.setRGB(col, row, color);
+ buildImage(sampleRow, sampleCol);
- }
- }
-
- if (av.getAlignmentConservationAnnotation() != null)
+ // check for conservation annotation to make sure overview works for DNA too
+ if (av.isShowAnnotation()
+ && (av.getAlignmentConservationAnnotation() != null))
{
renderer.updateFromAlignViewport(av);
- for (col = 0; col < width; col++)
+ for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
{
- if (resizeAgain)
- {
- break;
- }
- lastcol = (int) (col * sampleCol);
- {
- mg.translate(col, sequencesHeight);
- renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(),
- av.getAlignmentConservationAnnotation().annotations,
- (int) (sampleCol) + 1, graphHeight,
- (int) (col * sampleCol), (int) (col * sampleCol) + 1);
- mg.translate(-col, -sequencesHeight);
- }
+ mg.translate(col, od.getSequencesHeight());
+ renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(),
+ av.getAlignmentConservationAnnotation().annotations,
+ (int) (sampleCol) + 1, od.getGraphHeight(),
+ (int) (col * sampleCol), (int) (col * sampleCol) + 1);
+ mg.translate(-col, -od.getSequencesHeight());
+
}
}
System.gc();
setBoxPosition();
}
- /**
- * DOCUMENT ME!
+ /*
+ * Build the overview panel image
*/
- public void setBoxPosition()
+ private void buildImage(float sampleRow, float sampleCol)
{
- int fullsizeWidth = av.getAlignment().getWidth() * av.getCharWidth();
- int fullsizeHeight = (av.getAlignment().getHeight() + av.getAlignment()
- .getHiddenSequences().getSize())
- * av.getCharHeight();
+ int lastcol = -1;
+ int lastrow = -1;
+ int rgbColour = Color.white.getRGB();
- int startRes = av.getStartRes();
- int endRes = av.getEndRes();
+ SequenceI seq = null;
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
- if (av.hasHiddenColumns())
+ final boolean hasHiddenCols = av.hasHiddenColumns();
+ boolean hiddenRow = false;
+ // get hidden row and hidden column map once at beginning.
+ // clone featureRenderer settings to avoid race conditions... if state is
+ // updated just need to refresh again
+ for (int row = 0; row < od.getSequencesHeight() && !resizeAgain; row++)
{
- startRes = av.getColumnSelection().adjustForHiddenColumns(startRes);
- endRes = av.getColumnSelection().adjustForHiddenColumns(endRes);
- }
+ boolean doCopy = true;
+ int currentrow = (int) (row * sampleRow);
+ if (currentrow != lastrow)
+ {
+ doCopy = false;
- int startSeq = av.startSeq;
- int endSeq = av.endSeq;
+ lastrow = currentrow;
- if (av.hasHiddenRows())
- {
- startSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(startSeq);
+ // get the sequence which would be at alignment index 'lastrow' if no
+ // rows were hidden, and determine whether it is hidden or not
+ hiddenRow = av.getAlignment().isHidden(lastrow);
+ seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
+ }
- endSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(endSeq);
+ for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
+ {
+ if (doCopy)
+ {
+ rgbColour = miniMe.getRGB(col, row - 1);
+ }
+ else if ((int) (col * sampleCol) != lastcol
+ || (int) (row * sampleRow) != lastrow)
+ {
+ lastcol = (int) (col * sampleCol);
+ rgbColour = getColumnColourFromSequence(seq, hiddenRow,
+ hasHiddenCols, lastcol, finder);
+ }
+ // else we just use the color we already have , so don't need to set it
+ miniMe.setRGB(col, row, rgbColour);
+ }
}
+ }
- scalew = (float) width / (float) fullsizeWidth;
- scaleh = (float) sequencesHeight / (float) fullsizeHeight;
-
- boxX = (int) (startRes * av.getCharWidth() * scalew);
- boxY = (int) (startSeq * av.getCharHeight() * scaleh);
+ /*
+ * Find the colour of a sequence at a specified column position
+ */
+ private int getColumnColourFromSequence(
+ jalview.datamodel.SequenceI seq,
+ boolean hiddenRow, boolean hasHiddenCols, int lastcol,
+ FeatureColourFinder finder)
+ {
+ Color color = Color.white;
- if (av.hasHiddenColumns())
+ if ((seq != null) && (seq.getLength() > lastcol))
{
- boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
+ color = sr.getResidueColour(seq, lastcol, finder);
}
- else
+
+ if (hiddenRow
+ || (hasHiddenCols && !av.getColumnSelection()
+ .isVisible(lastcol)))
{
- boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
+ color = color.darker().darker();
}
- boxHeight = (int) ((endSeq - startSeq) * av.getCharHeight() * scaleh);
-
- repaint();
+ return color.getRGB();
}
- private BufferedImage lastMiniMe = null;
-
/**
- * DOCUMENT ME!
+ * Update the overview panel box when the associated alignment panel is
+ * changed
*
- * @param g
- * DOCUMENT ME!
*/
+ public void setBoxPosition()
+ {
+ od.setBoxPosition(av.getAlignment()
+ .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
+ repaint();
+ }
+
+
@Override
public void paintComponent(Graphics g)
{
{
g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
}
- g.setColor(new Color(100, 100, 100, 25));
+ g.setColor(TRANS_GREY);
g.fillRect(0, 0, getWidth(), getHeight());
}
else if (lastMiniMe != null)
g.drawImage(lastMiniMe, 0, 0, this);
if (lastMiniMe != miniMe)
{
- g.setColor(new Color(100, 100, 100, 25));
+ g.setColor(TRANS_GREY);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
- // TODO: render selected regions
+
g.setColor(Color.red);
- g.drawRect(boxX, boxY, boxWidth, boxHeight);
- g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
+ od.drawBox(g);
}
}
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;
import jalview.schemes.PIDColourScheme;
-import jalview.schemes.ResidueColourScheme;
import jalview.util.GroupUrlLink;
import jalview.util.GroupUrlLink.UrlStringTooLongException;
import jalview.util.MessageManager;
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!
*
public void changeColour_actionPerformed(String colourSchemeName)
{
SequenceGroup sg = getGroup();
- if (ResidueColourScheme.USER_DEFINED.equals(colourSchemeName))
- {
- /*
- * open a panel to load or configure a user-defined colour scheme
- */
- new UserDefinedColours(ap, sg);
- }
- else
+ /*
+ * switch to the chosen colour scheme (or null for None)
+ */
+ ColourSchemeI colourScheme = ColourSchemes.getInstance()
+ .getColourScheme(colourSchemeName, sg,
+ ap.av.getHiddenRepSequences());
+ sg.setColourScheme(colourScheme);
+ if (colourScheme instanceof Blosum62ColourScheme
+ || colourScheme instanceof PIDColourScheme)
{
- /*
- * switch to the chosen colour scheme (or null for None)
- */
- ColourSchemeI colourScheme = ColourSchemes.getInstance().getColourScheme(
- colourSchemeName, sg, ap.av.getHiddenRepSequences());
- sg.setColourScheme(colourScheme);
- if (colourScheme instanceof Blosum62ColourScheme
- || colourScheme instanceof PIDColourScheme)
- {
- sg.cs.setConsensus(AAFrequency.calculate(
- sg.getSequences(ap.av.getHiddenRepSequences()),
- sg.getStartRes(), sg.getEndRes() + 1));
- }
+ sg.cs.setConsensus(AAFrequency.calculate(
+ sg.getSequences(ap.av.getHiddenRepSequences()),
+ sg.getStartRes(), sg.getEndRes() + 1));
}
refresh();
@Override
public void mousePressed(MouseEvent evt)
{
- int x = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int x = (evt.getX() / av.getCharWidth()) + av.getRanges().getStartRes();
final int res;
if (av.hasHiddenColumns())
{
mouseDragging = false;
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
if (av.hasHiddenColumns())
{
mouseDragging = true;
ColumnSelection cs = av.getColumnSelection();
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
res = Math.max(0, res);
res = cs.adjustForHiddenColumns(res);
res = Math.min(res, av.getAlignment().getWidth() - 1);
return;
}
- int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
+ int res = (evt.getX() / av.getCharWidth())
+ + av.getRanges().getStartRes();
res = av.getColumnSelection().adjustForHiddenColumns(res);
@Override
public void paintComponent(Graphics g)
{
- drawScale(g, av.getStartRes(), av.getEndRes(), getWidth(), getHeight());
+ drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
+ getWidth(), getHeight());
}
// scalewidth will normally be screenwidth,
import jalview.datamodel.SequenceI;
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
imgHeight, -horizontal * charWidth, -vertical * charHeight);
- int sr = av.startRes;
- int er = av.endRes;
- int ss = av.startSeq;
- int es = av.endSeq;
+ ViewportRanges ranges = av.getRanges();
+ int sr = ranges.getStartRes();
+ int er = ranges.getEndRes();
+ int ss = ranges.getStartSeq();
+ int es = ranges.getEndSeq();
int transX = 0;
int transY = 0;
{
ss = es - vertical;
- if (ss < av.startSeq)
+ if (ss < ranges.getStartSeq())
{ // ie scrolling too fast, more than a page at a time
- ss = av.startSeq;
+ ss = ranges.getStartSeq();
}
else
{
- transY = imgHeight - (vertical * charHeight);
+ transY = imgHeight - ((vertical + 1) * charHeight);
}
}
else if (vertical < 0)
{
es = ss - vertical;
- if (es > av.endSeq)
+ if (es > ranges.getEndSeq())
{
- es = av.endSeq;
+ es = ranges.getEndSeq();
}
}
gg.setColor(Color.white);
gg.fillRect(0, 0, imgWidth, imgHeight);
+ ViewportRanges ranges = av.getRanges();
if (av.getWrapAlignment())
{
- drawWrappedPanel(gg, getWidth(), getHeight(), av.startRes);
+ drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
}
else
{
- drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq, 0);
+ drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
+ ranges.getStartSeq(), ranges.getEndSeq(), 0);
}
g.drawImage(lcimg, 0, 0, this);
av.setWrappedWidth(cWidth);
- av.endRes = av.startRes + cWidth;
+ av.getRanges().setEndRes(av.getRanges().getStartRes() + cWidth);
int endx;
int ypos = hgap;
(int) clip.getBounds().getHeight());
}
- drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);
+ drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
if (av.isShowAnnotation())
{
g1.drawLine((blockEnd - blockStart + 1) * charWidth - 1,
0 + offset, (blockEnd - blockStart + 1) * charWidth - 1,
- (endSeq - startSeq) * charHeight + offset);
+ (endSeq - startSeq + 1) * charHeight + offset);
}
g1.translate(-screenY * charWidth, 0);
// / First draw the sequences
// ///////////////////////////
- for (int i = startSeq; i < endSeq; i++)
+ for (int i = startSeq; i <= endSeq; i++)
{
nextSeq = av.getAlignment().getSequenceAt(i);
if (nextSeq == null)
if (av.isShowSequenceFeatures())
{
fr.drawSequence(g, nextSeq, startRes, endRes, offset
- + ((i - startSeq) * charHeight));
+ + ((i - startSeq) * charHeight), false);
}
// / Highlight search Results once all sequences have been drawn
int top = -1;
int bottom = -1;
- for (i = startSeq; i < endSeq; i++)
+ for (i = startSeq; i <= endSeq; i++)
{
sx = (group.getStartRes() - startRes) * charWidth;
sy = offset + ((i - startSeq) * charHeight);
}
wrappedBlock = y / cHeight;
- wrappedBlock += av.getStartRes() / cwidth;
+ wrappedBlock += av.getRanges().getStartRes() / cwidth;
res = wrappedBlock * cwidth + x / av.getCharWidth();
// right-hand gutter
x = seqCanvas.getX() + seqCanvas.getWidth();
}
- res = (x / av.getCharWidth()) + av.getStartRes();
- if (res > av.getEndRes())
+ res = (x / av.getCharWidth()) + av.getRanges().getStartRes();
+ if (res > av.getRanges().getEndRes())
{
// moused off right
- res = av.getEndRes();
+ res = av.getRanges().getEndRes();
}
}
}
else
{
- seq = Math.min((y / av.getCharHeight()) + av.getStartSeq(), av
+ seq = Math.min((y / av.getCharHeight())
+ + av.getRanges().getStartSeq(),
+ av
.getAlignment().getHeight() - 1);
}
}
else
{
- while (seqCanvas.cursorY < av.startSeq)
+ while (seqCanvas.cursorY < av.getRanges().getStartSeq())
{
ap.scrollUp(true);
}
- while (seqCanvas.cursorY + 1 > av.endSeq)
+ while (seqCanvas.cursorY + 1 > av.getRanges().getEndSeq())
{
ap.scrollUp(false);
}
if (!av.getWrapAlignment())
{
while (seqCanvas.cursorX < av.getColumnSelection()
- .adjustForHiddenColumns(av.startRes))
+ .adjustForHiddenColumns(av.getRanges().getStartRes()))
{
if (!ap.scrollRight(false))
{
}
}
while (seqCanvas.cursorX > av.getColumnSelection()
- .adjustForHiddenColumns(av.endRes))
+ .adjustForHiddenColumns(av.getRanges().getEndRes()))
{
if (!ap.scrollRight(true))
{
changeStartRes = true;
}
- if (res < av.getStartRes())
+ if (res < av.getRanges().getStartRes())
{
- res = av.getStartRes();
+ res = av.getRanges().getStartRes();
}
if (changeEndRes)
{
if (evt != null)
{
- if (mouseDragging && (evt.getY() < 0) && (av.getStartSeq() > 0))
+ if (mouseDragging && (evt.getY() < 0)
+ && (av.getRanges().getStartSeq() > 0))
{
running = ap.scrollUp(true);
}
if (mouseDragging && (evt.getY() >= getHeight())
- && (av.getAlignment().getHeight() > av.getEndSeq()))
+ && (av.getAlignment().getHeight() > av.getRanges()
+ .getEndSeq()))
{
running = ap.scrollUp(false);
}
*/
package jalview.gui;
-import jalview.api.FeatureRenderer;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShaderI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.util.Comparison;
import java.awt.Color;
boolean forOverview = false;
/**
- * Creates a new SequenceRenderer object.
+ * Creates a new SequenceRenderer object
*
- * @param av
- * DOCUMENT ME!
+ * @param viewport
*/
- public SequenceRenderer(AlignViewport av)
+ public SequenceRenderer(AlignViewport viewport)
{
- this.av = av;
+ this.av = viewport;
}
/**
this.renderGaps = renderGaps;
}
- @Override
- public Color getResidueBoxColour(SequenceI seq, int i)
+ protected Color getResidueBoxColour(SequenceI seq, int i)
{
// rate limiting step when rendering overview for lots of groups
allGroups = av.getAlignment().findAllGroups(seq);
*
* @param seq
* @param position
- * @param fr
+ * @param finder
* @return
*/
@Override
public Color getResidueColour(final SequenceI seq, int position,
- FeatureRenderer fr)
+ FeatureColourFinder finder)
{
- // TODO replace 8 or so code duplications with calls to this method
- // (refactored as needed)
Color col = getResidueBoxColour(seq, position);
- if (fr != null)
+ if (finder != null)
{
- col = fr.findFeatureColour(col, seq, position);
+ col = finder.findFeatureColour(col, seq, position);
}
return col;
}
public void itemStateChanged(ItemEvent e)
{
alignStructs.setEnabled(!_alignwith.isEmpty());
- alignStructs
- .setToolTipText(MessageManager
- .getString("label.align_structures_using_linked_alignment_views"));
+ alignStructs.setToolTipText(MessageManager.formatMessage(
+ "label.align_structures_using_linked_alignment_views",
+ _alignwith.size()));
}
};
viewSelectionMenu = new ViewSelectionMenu(
public void setJalviewColourScheme(ColourSchemeI cs) {
getBinding().setJalviewColourScheme(cs);
}
+
+ /**
+ * Sends commands to the structure viewer to superimpose structures based on
+ * currently associated alignments. May optionally return an error message for
+ * the operation.
+ */
@Override
- protected void alignStructs_actionPerformed(ActionEvent actionEvent)
+ protected String alignStructs_actionPerformed(
+ ActionEvent actionEvent)
{
- alignStructs_withAllAlignPanels();
+ return alignStructs_withAllAlignPanels();
}
- protected void alignStructs_withAllAlignPanels()
+
+ protected String alignStructs_withAllAlignPanels()
{
if (getAlignmentPanel() == null)
{
- return;
+ return null;
}
if (_alignwith.size() == 0)
_alignwith.add(getAlignmentPanel());
}
+ String reply = null;
try
{
AlignmentI[] als = new Alignment[_alignwith.size()];
alm[a] = -1;
alc[a++] = ap.av.getColumnSelection();
}
- getBinding().superposeStructures(als, alm, alc);
+ reply = getBinding().superposeStructures(als, alm, alc);
+ if (reply != null)
+ {
+ String text = MessageManager.formatMessage(
+ "error.superposition_failed", reply);
+ statusBar.setText(text);
+ }
} catch (Exception e)
{
StringBuffer sp = new StringBuffer();
Cache.log.info("Couldn't align structures with the " + sp.toString()
+ "associated alignment panels.", e);
}
+ return reply;
}
+
@Override
public void background_actionPerformed(ActionEvent actionEvent)
{
}
protected abstract String getViewerName();
+
+ /**
+ * Configures the title and menu items of the viewer panel.
+ */
public void updateTitleAndMenus()
{
AAStructureBindingModel binding = getBinding();
setChainMenuItems(binding.getChainNames());
this.setTitle(binding.getViewerTitle(getViewerName(), true));
- if (binding.getPdbFile().length > 1 && binding.getSequence().length > 1)
+
+ /*
+ * enable 'Superpose with' if more than one mapped structure
+ */
+ viewSelectionMenu.setEnabled(false);
+ if (getBinding().getPdbFile().length > 1
+ && getBinding().getSequence().length > 1)
{
- viewerActionMenu.setVisible(true);
+ viewSelectionMenu.setEnabled(true);
}
+
+ /*
+ * Show action menu if it has any enabled items
+ */
+ viewerActionMenu.setVisible(false);
+ for (int i = 0; i < viewerActionMenu.getItemCount(); i++)
+ {
+ if (viewerActionMenu.getItem(i).isEnabled())
+ {
+ viewerActionMenu.setVisible(true);
+ break;
+ }
+ }
+
if (!binding.isLoadingFromArchive())
{
seqColour_actionPerformed(null);
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);
*/
package jalview.gui;
-import jalview.api.structures.JalviewStructureDisplayI;
import jalview.bin.Cache;
-import jalview.datamodel.SequenceGroup;
import jalview.io.JalviewFileChooser;
import jalview.io.JalviewFileView;
import jalview.jbgui.GUserDefinedColours;
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;
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
-import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
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;
AlignmentPanel ap;
- SequenceGroup seqGroup;
-
- List<JButton> selectedButtons;
-
+ /*
+ * the colour scheme when the dialog was opened, or
+ * the scheme last saved to file
+ */
ColourSchemeI oldColourScheme;
- JInternalFrame frame;
+ /*
+ * flag is true if the colour scheme has been changed since the
+ * dialog was opened, or the changes last saved to file
+ */
+ boolean changed;
- JalviewStructureDisplayI structureViewer;
+ JInternalFrame frame;
List<JButton> upperCaseButtons;
List<JButton> lowerCaseButtons;
/**
- * Creates a new UserDefinedColours object.
+ * Creates and displays a new UserDefinedColours panel
*
- * @param ap
- * @param sg
+ * @param alignPanel
*/
- public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
+ public UserDefinedColours(AlignmentPanel alignPanel)
{
this();
lcaseColour.setEnabled(false);
- this.ap = ap;
- seqGroup = sg;
+ this.ap = alignPanel;
- if (seqGroup != null)
- {
- oldColourScheme = seqGroup.getColourScheme();
- }
- else
- {
- oldColourScheme = ap.av.getGlobalColourScheme();
- }
+ oldColourScheme = alignPanel.av.getGlobalColourScheme();
if (oldColourScheme instanceof UserColourScheme)
{
showFrame();
}
- public UserDefinedColours(JalviewStructureDisplayI viewer,
- ColourSchemeI oldcs)
- {
- this();
- this.structureViewer = viewer;
-
- colorChooser.getSelectionModel().addChangeListener(this);
-
- oldColourScheme = oldcs;
-
- if (oldColourScheme instanceof UserColourScheme)
- {
- schemeName.setText(((UserColourScheme) oldColourScheme)
- .getSchemeName());
- }
-
- resetButtonPanel(false);
-
- showFrame();
-
- }
-
- public UserDefinedColours()
+ UserDefinedColours()
{
super();
selectedButtons = new ArrayList<JButton>();
Desktop.addInternalFrame(frame,
MessageManager.getString("label.user_defined_colours"),
MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
-
- if (seqGroup != null)
- {
- frame.setTitle(frame.getTitle() + " (" + seqGroup.getName() + ")");
- }
}
/**
{
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));
+ }
+
+ changed = true;
}
/**
}
else
{
+ /*
+ * OK is treated as 'apply colours and close'
+ */
applyButton_actionPerformed();
+ /*
+ * If editing a named colour scheme, warn if changes
+ * have not been saved
+ */
+ warnIfUnsavedChanges();
+
try
{
frame.setClosed(true);
}
/**
+ * If we have made changes to an existing user defined colour scheme but not
+ * saved them, show a dialog with the option to save. If the user chooses to
+ * save, do so, else clear the colour scheme name to indicate a new colour
+ * scheme.
+ */
+ protected void warnIfUnsavedChanges()
+ {
+ if (!changed)
+ {
+ return;
+ }
+
+ String name = schemeName.getText().trim();
+ if (oldColourScheme != null && !"".equals(name)
+ && name.equals(oldColourScheme.getSchemeName()))
+ {
+ String message = MessageManager.formatMessage("label.scheme_changed",
+ name);
+ String title = MessageManager.getString("label.save_changes");
+ String[] options = new String[] { title,
+ MessageManager.getString("label.dont_save_changes"), };
+ final String question = JvSwingUtils.wrapTooltip(true, message);
+ int response = JvOptionPane.showOptionDialog(Desktop.desktop,
+ question, title, JvOptionPane.DEFAULT_OPTION,
+ JvOptionPane.PLAIN_MESSAGE, null, options, options[0]);
+
+ boolean saved = false;
+ if (response == 0)
+ {
+ /*
+ * prompt to save changes to file
+ */
+ saved = savebutton_actionPerformed();
+ }
+
+ /*
+ * if user chooses not to save (either in this dialog or in the
+ * save as dialogs), treat this as a new user defined colour scheme
+ */
+ if (!saved)
+ {
+ /*
+ * clear scheme name and re-apply as an anonymous scheme
+ */
+ schemeName.setText("");
+ applyButton_actionPerformed();
+ }
+ }
+ }
+
+ /**
* Returns true if the user has not made any colour selection (including if
* 'case-sensitive' selected and no lower-case colour chosen).
*
}
/**
- * Applies the current colour scheme to the alignment, sequence group or
- * structure view.
+ * Applies the current colour scheme to the alignment or sequence group
*/
@Override
protected void applyButton_actionPerformed()
}
UserColourScheme ucs = getSchemeFromButtons();
- if (seqGroup != null)
- {
- seqGroup.setColourScheme(ucs);
- ap.paintAlignment(true);
- }
- else if (ap != null)
- {
- ap.alignFrame.changeColour(ucs);
- }
- else if (structureViewer != null)
- {
- structureViewer.setJalviewColourScheme(ucs);
- }
+ ap.alignFrame.changeColour(ucs);
}
+ /**
+ * Constructs an instance of UserColourScheme with the residue colours
+ * currently set on the buttons on the panel
+ *
+ * @return
+ */
UserColourScheme getSchemeFromButtons()
{
ucs.setLowerCaseColours(newColours);
}
- // if (ap != null)
- // {
- // ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
- // }
-
return ucs;
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Action on clicking Load scheme button.
+ * <ul>
+ * <li>Open a file chooser to browse for files with extension .jc</li>
+ * <li>Load in the colour scheme and transfer it to this panel's buttons</li>
+ * <li>Register the loaded colour scheme</li>
+ * </ul>
*/
@Override
- protected void loadbutton_actionPerformed(ActionEvent e)
+ protected void loadbutton_actionPerformed()
{
upperCaseButtons = new ArrayList<JButton>();
lowerCaseButtons = new ArrayList<JButton>();
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)
}
/**
- * DOCUMENT ME!
+ * Action on pressing the Save button.
+ * <ul>
+ * <li>Check a name has been entered</li>
+ * <li>Warn if the name already exists, remove any existing scheme of the same
+ * name if overwriting</li>
+ * <li>Do the standard file chooser thing to write with extension .jc</li>
+ * <li>If saving changes (possibly not yet applied) to the currently selected
+ * colour scheme, then apply the changes, as it is too late to back out now</li>
+ * <li>Don't apply the changes if the currently selected scheme is different,
+ * to allow a new scheme to be configured and saved but not applied</li>
+ * </ul>
+ * Returns true if the scheme is saved to file, false if it is not
*
- * @param e
- * DOCUMENT ME!
+ * @return
*/
@Override
- protected void savebutton_actionPerformed(ActionEvent e)
+ protected boolean savebutton_actionPerformed()
{
String name = schemeName.getText().trim();
if (name.length() < 1)
.getString("label.user_colour_scheme_must_have_name"),
MessageManager.getString("label.no_name_colour_scheme"),
JvOptionPane.WARNING_MESSAGE);
- return;
+ return false;
}
if (ColourSchemes.getInstance().nameExists(name))
JvOptionPane.YES_NO_OPTION);
if (reply != JvOptionPane.YES_OPTION)
{
- return;
+ return false;
}
- ColourSchemes.getInstance().removeColourScheme(name);
}
JalviewFileChooser chooser = new JalviewFileChooser("jc",
"Jalview User Colours");
int value = chooser.showSaveDialog(this);
- if (value == JalviewFileChooser.APPROVE_OPTION)
+ if (value != JalviewFileChooser.APPROVE_OPTION)
+ {
+ return false;
+ }
+
+ File file = chooser.getSelectedFile();
+ UserColourScheme updatedScheme = addNewColourScheme(file.getPath());
+ saveToFile(file);
+ changed = false;
+
+ /*
+ * changes saved - apply to alignment if we are changing
+ * the currently selected colour scheme; also make the updated
+ * colours the 'backout' scheme on Cancel
+ */
+ if (oldColourScheme != null
+ && name.equals(oldColourScheme.getSchemeName()))
{
- File file = chooser.getSelectedFile();
- addNewColourScheme(file.getPath());
- saveToFile(file);
+ oldColourScheme = updatedScheme;
+ applyButton_actionPerformed();
}
+ return true;
}
/**
* the colour scheme.
*
* @param filePath
+ * @return
*/
- protected void addNewColourScheme(String filePath)
+ protected UserColourScheme addNewColourScheme(String filePath)
{
/*
* update the delimited list of user defined colour files in
{
ap.alignFrame.buildColourMenu();
}
+
+ return ucs;
}
/**
* marshal to file
*/
JalviewUserColours ucs = new JalviewUserColours();
- ucs.setSchemeName(schemeName.getText());
+ String name = schemeName.getText();
+ ucs.setSchemeName(name);
try
{
PrintWriter out = new PrintWriter(new OutputStreamWriter(
}
/**
- * On cancel, restores the colour scheme before the dialogue was opened
- *
- * @param e
+ * On cancel, restores the colour scheme that was selected before the dialogue
+ * was opened
*/
@Override
- protected void cancelButton_actionPerformed(ActionEvent e)
+ protected void cancelButton_actionPerformed()
{
- if (ap != null)
- {
- if (seqGroup != null)
- {
- seqGroup.setColourScheme(oldColourScheme);
- }
- else
- {
- ap.alignFrame.changeColour(oldColourScheme);
- }
- ap.paintAlignment(true);
- }
-
- if (structureViewer != null)
- {
- structureViewer.setJalviewColourScheme(oldColourScheme);
- }
+ ap.alignFrame.changeColour(oldColourScheme);
+ ap.paintAlignment(true);
try
{
}
}
+ /**
+ * Action on selecting or deselecting the Case Sensitive option. When
+ * selected, separate buttons are shown for lower case residues, and the panel
+ * is resized to accommodate them. Also, the checkbox for 'apply colour to all
+ * lower case' is enabled.
+ */
@Override
- public void caseSensitive_actionPerformed(ActionEvent e)
+ public void caseSensitive_actionPerformed()
{
boolean selected = caseSensitive.isSelected();
resetButtonPanel(selected);
import jalview.json.binding.biojson.v1.SequenceFeaturesPojo;
import jalview.json.binding.biojson.v1.SequenceGrpPojo;
import jalview.json.binding.biojson.v1.SequencePojo;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.schemes.JalviewColourScheme;
import jalview.schemes.ResidueColourScheme;
import jalview.util.ColorUtils;
return sequenceFeaturesPojo;
}
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
+
for (SequenceI seq : sqs)
{
SequenceI dataSetSequence = seq.getDatasetSequence();
String.valueOf(seq.hashCode()));
String featureColour = (fr == null) ? null : jalview.util.Format
- .getHexString(fr.findFeatureColour(Color.white, seq,
+ .getHexString(finder.findFeatureColour(Color.white, seq,
seq.findIndex(sf.getBegin())));
jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
jsonFeature.setXend(seq.findIndex(sf.getEnd()));
}
}
}
- globalColourScheme = viewport.getGlobalColourScheme().getSchemeName();
+ globalColourScheme = (viewport.getGlobalColourScheme() == null) ? ResidueColourScheme.NONE
+ : viewport.getGlobalColourScheme().getSchemeName();
setDisplayedFeatures(viewport.getFeaturesDisplayed());
showSeqFeatures = viewport.isShowSequenceFeatures();
ArrayList<String[]> ccomands = new ArrayList<String[]>();
ArrayList<String> pdbfn = new ArrayList<String>();
StructureMappingcommandSet[] colcommands = JmolCommands
- .getColourBySequenceCommand(ssm, modelSet, sequence, sr, fr,
- ((AlignmentViewPanel) source).getAlignment());
+ .getColourBySequenceCommand(ssm, modelSet, sequence, sr,
+ (AlignmentViewPanel) source);
if (colcommands == null)
{
return;
return _listenerfn;
}
+ @Override
public void finalize() throws Throwable
{
jvlite = 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
{
}
- protected void alignStructs_actionPerformed(ActionEvent actionEvent)
- {
- }
+ protected abstract String alignStructs_actionPerformed(
+ ActionEvent actionEvent);
public void pdbFile_actionPerformed(ActionEvent actionEvent)
{
gridLayout.setRows(5);
okButton.setFont(new java.awt.Font("Verdana", 0, 11));
okButton.setText(MessageManager.getString("action.ok"));
- okButton.addActionListener(new java.awt.event.ActionListener()
+ okButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
});
loadbutton.setFont(new java.awt.Font("Verdana", 0, 11));
loadbutton.setText(MessageManager.getString("action.load_scheme"));
- loadbutton.addActionListener(new java.awt.event.ActionListener()
+ loadbutton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- loadbutton_actionPerformed(e);
+ loadbutton_actionPerformed();
}
});
savebutton.setFont(new java.awt.Font("Verdana", 0, 11));
savebutton.setText(MessageManager.getString("action.save_scheme"));
- savebutton.addActionListener(new java.awt.event.ActionListener()
+ savebutton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- savebutton_actionPerformed(e);
+ savebutton_actionPerformed();
}
});
cancelButton.setFont(JvSwingUtils.getLabelFont());
cancelButton.setText(MessageManager.getString("action.cancel"));
- cancelButton.addActionListener(new java.awt.event.ActionListener()
+ cancelButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- cancelButton_actionPerformed(e);
+ cancelButton_actionPerformed();
}
});
this.setBackground(new Color(212, 208, 223));
@Override
public void actionPerformed(ActionEvent e)
{
- caseSensitive_actionPerformed(e);
+ caseSensitive_actionPerformed();
}
});
lcaseColour
* @param e
* DOCUMENT ME!
*/
- protected void loadbutton_actionPerformed(ActionEvent e)
+ protected void loadbutton_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void savebutton_actionPerformed(ActionEvent e)
+ protected boolean savebutton_actionPerformed()
{
+ return false;
}
/**
* @param e
* DOCUMENT ME!
*/
- protected void cancelButton_actionPerformed(ActionEvent e)
+ protected void cancelButton_actionPerformed()
{
}
- public void caseSensitive_actionPerformed(ActionEvent e)
+ public void caseSensitive_actionPerformed()
{
}
- public void lcaseColour_actionPerformed(ActionEvent e)
+ public void lcaseColour_actionPerformed()
{
}
public void updateFromAlignViewport(AlignViewportI av)
{
charWidth = av.getCharWidth();
- endRes = av.getEndRes();
+ endRes = av.getRanges().getEndRes();
charHeight = av.getCharHeight();
hasHiddenColumns = av.hasHiddenColumns();
validCharWidth = av.isValidCharWidth();
--- /dev/null
+package jalview.renderer.seqfeatures;
+
+import jalview.api.FeatureRenderer;
+import jalview.api.FeaturesDisplayedI;
+import jalview.datamodel.SequenceI;
+import jalview.viewmodel.seqfeatures.FeatureRendererModel;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+/**
+ * A helper class to find feature colour using an associated FeatureRenderer
+ *
+ * @author gmcarstairs
+ *
+ */
+public class FeatureColourFinder
+{
+ /*
+ * the class we delegate feature finding to
+ */
+ private FeatureRenderer featureRenderer;
+
+ /*
+ * a 1-pixel image on which features can be drawn, for the case where
+ * transparency allows 'see-through' of multiple feature colours
+ */
+ private BufferedImage offscreenImage;
+
+ /**
+ * Constructor
+ *
+ * @param fr
+ */
+ public FeatureColourFinder(FeatureRenderer fr)
+ {
+ featureRenderer = fr;
+ offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * Answers the feature colour to show for the given sequence and column
+ * position. This delegates to the FeatureRenderer to find the colour, which
+ * will depend on feature location, visibility, ordering, colour scheme, and
+ * whether or not transparency is applied. For feature rendering with
+ * transparency, this class provides a dummy 'offscreen' graphics context
+ * where multiple feature colours can be overlaid and the combined colour read
+ * back.
+ * <p>
+ * This method is not thread-safe when transparency is applied, since a shared
+ * BufferedImage would be used by all threads to hold the composite colour at
+ * a position. Each thread should use a separate instance of this class.
+ *
+ * @param defaultColour
+ * @param seq
+ * @param column
+ * alignment column position (base zero)
+ * @return
+ */
+ public Color findFeatureColour(Color defaultColour, SequenceI seq,
+ int column)
+ {
+ if (noFeaturesDisplayed())
+ {
+ return defaultColour;
+ }
+
+ Graphics g = null;
+
+ /*
+ * if transparency applies, provide a notional 1x1 graphics context
+ * that has been primed with the default colour
+ */
+ if (featureRenderer.getTransparency() != 1f)
+ {
+ g = offscreenImage.getGraphics();
+ if (defaultColour != null)
+ {
+ offscreenImage.setRGB(0, 0, defaultColour.getRGB());
+ }
+ }
+
+ Color c = featureRenderer.findFeatureColour(seq, column, g);
+ if (c == null)
+ {
+ return defaultColour;
+ }
+
+ if (g != null)
+ {
+ c = new Color(offscreenImage.getRGB(0, 0));
+ }
+ return c;
+ }
+
+ /**
+ * Answers true if feature display is turned off, or there are no features
+ * configured to be visible
+ *
+ * @return
+ */
+ boolean noFeaturesDisplayed()
+ {
+ if (featureRenderer == null
+ || !featureRenderer.getViewport().isShowSequenceFeatures())
+ {
+ return true;
+ }
+
+ if (!((FeatureRendererModel) featureRenderer).hasRenderOrder())
+ {
+ return true;
+ }
+
+ FeaturesDisplayedI displayed = featureRenderer.getFeaturesDisplayed();
+ if (displayed == null || displayed.getVisibleFeatureCount() == 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
import jalview.api.AlignViewportI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
import jalview.viewmodel.seqfeatures.FeatureRendererModel;
import java.awt.AlphaComposite;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
public class FeatureRenderer extends FeatureRendererModel
{
-
- FontMetrics fm;
-
- int charOffset;
-
- boolean offscreenRender = false;
-
- protected SequenceI lastSeq;
-
- char s;
-
- int i;
-
- int av_charHeight, av_charWidth;
-
- boolean av_validCharWidth, av_isShowSeqFeatureHeight;
-
- private Integer currentColour;
+ private static final AlphaComposite NO_TRANSPARENCY = AlphaComposite
+ .getInstance(AlphaComposite.SRC_OVER, 1.0f);
/**
* Constructor given a viewport
this.av = viewport;
}
- protected void updateAvConfig()
+ /**
+ * Renders the sequence using the given feature colour between the given start
+ * and end columns. Returns true if at least one column is drawn, else false
+ * (the feature range does not overlap the start and end positions).
+ *
+ * @param g
+ * @param seq
+ * @param featureStart
+ * @param featureEnd
+ * @param featureColour
+ * @param start
+ * @param end
+ * @param y1
+ * @param colourOnly
+ * @return
+ */
+ boolean renderFeature(Graphics g, SequenceI seq, int featureStart,
+ int featureEnd, Color featureColour, int start, int end, int y1,
+ boolean colourOnly)
{
- av_charHeight = av.getCharHeight();
- av_charWidth = av.getCharWidth();
- av_validCharWidth = av.isValidCharWidth();
- av_isShowSeqFeatureHeight = av.isShowSequenceFeaturesHeight();
- }
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+ boolean validCharWidth = av.isValidCharWidth();
- void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
- Color featureColour, int start, int end, int y1)
- {
- updateAvConfig();
- if (((fstart <= end) && (fend >= start)))
+ if (featureStart > end || featureEnd < start)
{
- if (fstart < start)
- { // fix for if the feature we have starts before the sequence start,
- fstart = start; // but the feature end is still valid!!
- }
-
- if (fend >= end)
- {
- fend = end;
- }
- int pady = (y1 + av_charHeight) - av_charHeight / 5;
- for (i = fstart; i <= fend; i++)
- {
- s = seq.getCharAt(i);
-
- if (jalview.util.Comparison.isGap(s))
- {
- continue;
- }
-
- g.setColor(featureColour);
-
- g.fillRect((i - start) * av_charWidth, y1, av_charWidth,
- av_charHeight);
-
- if (offscreenRender || !av_validCharWidth)
- {
- continue;
- }
-
- g.setColor(Color.white);
- charOffset = (av_charWidth - fm.charWidth(s)) / 2;
- g.drawString(String.valueOf(s), charOffset
- + (av_charWidth * (i - start)), pady);
+ return false;
+ }
- }
+ if (featureStart < start)
+ {
+ featureStart = start;
}
- }
+ if (featureEnd >= end)
+ {
+ featureEnd = end;
+ }
+ int pady = (y1 + charHeight) - charHeight / 5;
- void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend,
- Color featureColour, int start, int end, int y1, byte[] bs)
- {
- updateAvConfig();
- if (((fstart <= end) && (fend >= start)))
+ FontMetrics fm = g.getFontMetrics();
+ for (int i = featureStart; i <= featureEnd; i++)
{
- if (fstart < start)
- { // fix for if the feature we have starts before the sequence start,
- fstart = start; // but the feature end is still valid!!
- }
+ char s = seq.getCharAt(i);
- if (fend >= end)
- {
- fend = end;
- }
- int pady = (y1 + av_charHeight) - av_charHeight / 5;
- int ystrt = 0, yend = av_charHeight;
- if (bs[0] != 0)
- {
- // signed - zero is always middle of residue line.
- if (bs[1] < 128)
- {
- yend = av_charHeight * (128 - bs[1]) / 512;
- ystrt = av_charHeight - yend / 2;
- }
- else
- {
- ystrt = av_charHeight / 2;
- yend = av_charHeight * (bs[1] - 128) / 512;
- }
- }
- else
+ if (Comparison.isGap(s))
{
- yend = av_charHeight * bs[1] / 255;
- ystrt = av_charHeight - yend;
-
+ continue;
}
- for (i = fstart; i <= fend; i++)
- {
- s = seq.getCharAt(i);
-
- if (jalview.util.Comparison.isGap(s))
- {
- continue;
- }
- g.setColor(featureColour);
- int x = (i - start) * av_charWidth;
- g.drawRect(x, y1, av_charWidth, av_charHeight);
- g.fillRect(x, y1 + ystrt, av_charWidth, yend);
+ g.setColor(featureColour);
- if (offscreenRender || !av_validCharWidth)
- {
- continue;
- }
+ g.fillRect((i - start) * charWidth, y1, charWidth,
+ charHeight);
- g.setColor(Color.black);
- charOffset = (av_charWidth - fm.charWidth(s)) / 2;
- g.drawString(String.valueOf(s), charOffset
- + (av_charWidth * (i - start)), pady);
+ if (colourOnly || !validCharWidth)
+ {
+ continue;
}
- }
- }
-
- BufferedImage offscreenImage;
- @Override
- public Color findFeatureColour(Color initialCol, SequenceI seq, int res)
- {
- return new Color(findFeatureColour(initialCol.getRGB(), seq, res));
+ g.setColor(Color.white);
+ int charOffset = (charWidth - fm.charWidth(s)) / 2;
+ g.drawString(String.valueOf(s), charOffset
+ + (charWidth * (i - start)), pady);
+ }
+ return true;
}
/**
- * This is used by Structure Viewers and the Overview Window to get the
- * feature colour of the rendered sequence, returned as an RGB value
+ * Renders the sequence using the given SCORE feature colour between the given
+ * start and end columns. Returns true if at least one column is drawn, else
+ * false (the feature range does not overlap the start and end positions).
*
- * @param defaultColour
+ * @param g
* @param seq
- * @param column
+ * @param fstart
+ * @param fend
+ * @param featureColour
+ * @param start
+ * @param end
+ * @param y1
+ * @param bs
+ * @param colourOnly
* @return
*/
- public synchronized int findFeatureColour(int defaultColour,
- final SequenceI seq, int column)
+ boolean renderScoreFeature(Graphics g, SequenceI seq, int fstart,
+ int fend, Color featureColour, int start, int end, int y1,
+ byte[] bs, boolean colourOnly)
{
- if (!av.isShowSequenceFeatures())
+ if (fstart > end || fend < start)
{
- return defaultColour;
+ return false;
}
- SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
- if (seq != lastSeq)
+ if (fstart < start)
+ { // fix for if the feature we have starts before the sequence start,
+ fstart = start; // but the feature end is still valid!!
+ }
+
+ if (fend >= end)
+ {
+ fend = end;
+ }
+ int charHeight = av.getCharHeight();
+ int pady = (y1 + charHeight) - charHeight / 5;
+ int ystrt = 0, yend = charHeight;
+ if (bs[0] != 0)
{
- lastSeq = seq;
- lastSequenceFeatures = sequenceFeatures;
- if (lastSequenceFeatures != null)
+ // signed - zero is always middle of residue line.
+ if (bs[1] < 128)
{
- sfSize = lastSequenceFeatures.length;
+ yend = charHeight * (128 - bs[1]) / 512;
+ ystrt = charHeight - yend / 2;
+ }
+ else
+ {
+ ystrt = charHeight / 2;
+ yend = charHeight * (bs[1] - 128) / 512;
}
}
else
{
- if (lastSequenceFeatures != sequenceFeatures)
+ yend = charHeight * bs[1] / 255;
+ ystrt = charHeight - yend;
+
+ }
+
+ FontMetrics fm = g.getFontMetrics();
+ int charWidth = av.getCharWidth();
+
+ for (int i = fstart; i <= fend; i++)
+ {
+ char s = seq.getCharAt(i);
+
+ if (Comparison.isGap(s))
{
- lastSequenceFeatures = sequenceFeatures;
- if (lastSequenceFeatures != null)
- {
- sfSize = lastSequenceFeatures.length;
- }
+ continue;
}
+
+ g.setColor(featureColour);
+ int x = (i - start) * charWidth;
+ g.drawRect(x, y1, charWidth, charHeight);
+ g.fillRect(x, y1 + ystrt, charWidth, yend);
+
+ if (colourOnly || !av.isValidCharWidth())
+ {
+ continue;
+ }
+
+ g.setColor(Color.black);
+ int charOffset = (charWidth - fm.charWidth(s)) / 2;
+ g.drawString(String.valueOf(s), charOffset
+ + (charWidth * (i - start)), pady);
}
+ return true;
+ }
- if (lastSequenceFeatures == null || sfSize == 0)
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Color findFeatureColour(SequenceI seq, int column, Graphics g)
+ {
+ if (!av.isShowSequenceFeatures())
{
- return defaultColour;
+ return null;
}
- if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))
+ SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
+
+ if (sequenceFeatures == null || sequenceFeatures.length == 0)
{
- return Color.white.getRGB();
+ return null;
}
- // Only bother making an offscreen image if transparency is applied
- if (transparency != 1.0f && offscreenImage == null)
+ if (Comparison.isGap(seq.getCharAt(column)))
{
- offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ return Color.white;
}
- currentColour = null;
- // TODO: non-threadsafe - each rendering thread needs its own instance of
- // the feature renderer - or this should be synchronized.
- offscreenRender = true;
-
- if (offscreenImage != null)
+ Color renderedColour = null;
+ if (transparency == 1.0f)
{
- offscreenImage.setRGB(0, 0, defaultColour);
- drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0);
-
- return offscreenImage.getRGB(0, 0);
+ /*
+ * simple case - just find the topmost rendered visible feature colour
+ */
+ renderedColour = findFeatureColour(seq, seq.findPosition(column));
}
else
{
- drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1);
-
- if (currentColour == null)
- {
- return defaultColour;
- }
- else
- {
- return currentColour.intValue();
- }
+ /*
+ * transparency case - draw all visible features in render order to
+ * build up a composite colour on the graphics context
+ */
+ renderedColour = drawSequence(g, seq, column, column, 0, true);
}
-
+ return renderedColour;
}
- private volatile SequenceFeature[] lastSequenceFeatures;
-
- int sfSize;
-
- int sfindex;
-
- int spos;
-
- int epos;
-
/**
- * Draws the sequence on the graphics context, or just determines the colour
- * that would be drawn (if flag offscreenrender is true).
+ * Draws the sequence features on the graphics context, or just determines the
+ * colour that would be drawn (if flag colourOnly is true). Returns the last
+ * colour drawn (which may not be the effective colour if transparency
+ * applies), or null if no feature is drawn in the range given.
*
* @param g
+ * the graphics context to draw on (may be null if colourOnly==true)
* @param seq
* @param start
- * start column (or sequence position in offscreenrender mode)
+ * start column
* @param end
- * end column (not used in offscreenrender mode)
+ * end column
* @param y1
* vertical offset at which to draw on the graphics
+ * @param colourOnly
+ * if true, only do enough to determine the colour for the position,
+ * do not draw the character
+ * @return
*/
- public synchronized void drawSequence(Graphics g, final SequenceI seq,
- int start, int end, int y1)
+ public synchronized Color drawSequence(final Graphics g,
+ final SequenceI seq, int start, int end, int y1,
+ boolean colourOnly)
{
SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
if (sequenceFeatures == null || sequenceFeatures.length == 0)
{
- return;
- }
-
- if (g != null)
- {
- fm = g.getFontMetrics();
+ return null;
}
updateFeatures();
- if (lastSeq == null || seq != lastSeq
- || sequenceFeatures != lastSequenceFeatures)
- {
- lastSeq = seq;
- lastSequenceFeatures = sequenceFeatures;
- }
-
- if (transparency != 1 && g != null)
+ if (transparency != 1f && g != null)
{
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
transparency));
}
- if (!offscreenRender)
- {
- spos = lastSeq.findPosition(start);
- epos = lastSeq.findPosition(end);
- }
+ int startPos = seq.findPosition(start);
+ int endPos = seq.findPosition(end);
+
+ int sfSize = sequenceFeatures.length;
+ Color drawnColour = null;
- sfSize = lastSequenceFeatures.length;
+ /*
+ * iterate over features in ordering of their rendering (last is on top)
+ */
for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
{
String type = renderOrder[renderIndex];
// loop through all features in sequence to find
// current feature to render
- for (sfindex = 0; sfindex < sfSize; sfindex++)
+ for (int sfindex = 0; sfindex < sfSize; sfindex++)
{
- final SequenceFeature sequenceFeature = lastSequenceFeatures[sfindex];
+ final SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
if (!sequenceFeature.type.equals(type))
{
continue;
}
+ /*
+ * a feature type may be flagged as shown but the group
+ * an instance of it belongs to may be hidden
+ */
if (featureGroupNotShown(sequenceFeature))
{
continue;
}
/*
- * check feature overlaps the visible part of the alignment,
- * unless doing offscreenRender (to the Overview window or a
- * structure viewer) which is not limited
+ * check feature overlaps the target range
+ * TODO: efficient retrieval of features overlapping a range
*/
- if (!offscreenRender
- && (sequenceFeature.getBegin() > epos || sequenceFeature
- .getEnd() < spos))
+ if (sequenceFeature.getBegin() > endPos
+ || sequenceFeature.getEnd() < startPos)
{
continue;
}
Color featureColour = getColour(sequenceFeature);
boolean isContactFeature = sequenceFeature.isContactFeature();
- if (offscreenRender && offscreenImage == null)
- {
- /*
- * offscreen mode with no image (image is only needed if transparency
- * is applied to feature colours) - just check feature is rendered at
- * the requested position (start == sequence position in this mode)
- */
- boolean featureIsAtPosition = sequenceFeature.begin <= start
- && sequenceFeature.end >= start;
- if (isContactFeature)
- {
- featureIsAtPosition = sequenceFeature.begin == start
- || sequenceFeature.end == start;
- }
- if (featureIsAtPosition)
- {
- // this is passed out to the overview and other sequence renderers
- // (e.g. molecule viewer) to get displayed colour for rendered
- // sequence
- currentColour = new Integer(featureColour.getRGB());
- // used to be retreived from av.featuresDisplayed
- // currentColour = av.featuresDisplayed
- // .get(sequenceFeatures[sfindex].type);
-
- }
- }
- else if (isContactFeature)
+ if (isContactFeature)
{
- renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
+ boolean drawn = renderFeature(g, seq,
+ seq.findIndex(sequenceFeature.begin) - 1,
seq.findIndex(sequenceFeature.begin) - 1, featureColour,
- start, end, y1);
- renderFeature(g, seq, seq.findIndex(sequenceFeature.end) - 1,
+ start, end, y1, colourOnly);
+ drawn |= renderFeature(g, seq,
+ seq.findIndex(sequenceFeature.end) - 1,
seq.findIndex(sequenceFeature.end) - 1, featureColour,
- start, end, y1);
-
+ start, end, y1, colourOnly);
+ if (drawn)
+ {
+ drawnColour = featureColour;
+ }
}
else if (showFeature(sequenceFeature))
{
- if (av_isShowSeqFeatureHeight
+ if (av.isShowSequenceFeaturesHeight()
&& !Float.isNaN(sequenceFeature.score))
{
- renderScoreFeature(g, seq,
+ boolean drawn = renderScoreFeature(g, seq,
seq.findIndex(sequenceFeature.begin) - 1,
- seq.findIndex(sequenceFeature.end) - 1,
- featureColour, start, end, y1,
- normaliseScore(sequenceFeature));
+ seq.findIndex(sequenceFeature.end) - 1, featureColour,
+ start, end, y1, normaliseScore(sequenceFeature),
+ colourOnly);
+ if (drawn)
+ {
+ drawnColour = featureColour;
+ }
}
else
{
- renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
- seq.findIndex(sequenceFeature.end) - 1,
- featureColour, start, end, y1);
+ boolean drawn = renderFeature(g, seq,
+ seq.findIndex(sequenceFeature.begin) - 1,
+ seq.findIndex(sequenceFeature.end) - 1, featureColour,
+ start, end, y1, colourOnly);
+ if (drawn)
+ {
+ drawnColour = featureColour;
+ }
}
}
}
if (transparency != 1.0f && g != null)
{
+ /*
+ * reset transparency
+ */
Graphics2D g2 = (Graphics2D) g;
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- 1.0f));
+ g2.setComposite(NO_TRANSPARENCY);
}
+
+ return drawnColour;
}
/**
@Override
public void featuresAdded()
{
- lastSeq = null;
findAllFeatures();
}
+
+ /**
+ * Returns the sequence feature colour rendered at the given sequence
+ * position, or null if none found. The feature of highest render order (i.e.
+ * on top) is found, subject to both feature type and feature group being
+ * visible, and its colour returned.
+ *
+ * @param seq
+ * @param pos
+ * @return
+ */
+ Color findFeatureColour(SequenceI seq, int pos)
+ {
+ SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
+ if (sequenceFeatures == null || sequenceFeatures.length == 0)
+ {
+ return null;
+ }
+
+ /*
+ * check for new feature added while processing
+ */
+ updateFeatures();
+
+ /*
+ * inspect features in reverse renderOrder (the last in the array is
+ * displayed on top) until we find one that is rendered at the position
+ */
+ for (int renderIndex = renderOrder.length - 1; renderIndex >= 0; renderIndex--)
+ {
+ String type = renderOrder[renderIndex];
+ if (!showFeatureOfType(type))
+ {
+ continue;
+ }
+
+ for (int sfindex = 0; sfindex < sequenceFeatures.length; sfindex++)
+ {
+ SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
+ if (!sequenceFeature.type.equals(type))
+ {
+ continue;
+ }
+
+ if (featureGroupNotShown(sequenceFeature))
+ {
+ continue;
+ }
+
+ /*
+ * check the column position is within the feature range
+ * (or is one of the two contact positions for a contact feature)
+ */
+ boolean featureIsAtPosition = sequenceFeature.begin <= pos
+ && sequenceFeature.end >= pos;
+ if (sequenceFeature.isContactFeature())
+ {
+ featureIsAtPosition = sequenceFeature.begin == pos
+ || sequenceFeature.end == pos;
+ }
+ if (featureIsAtPosition)
+ {
+ return getColour(sequenceFeature);
+ }
+ }
+ }
+
+ /*
+ * no displayed feature found at position
+ */
+ return null;
+ }
}
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;
private static ColourSchemes instance = new ColourSchemes();
/*
- * a map from scheme name to an instance of it
+ * a map from scheme name (lower-cased) to an instance of it
*/
private Map<String, ColourSchemeI> schemes;
*/
public void removeColourScheme(String name)
{
- schemes.remove(name);
+ if (name != null)
+ {
+ schemes.remove(name.toLowerCase());
+ }
}
/**
{
return false;
}
- name = name.toLowerCase();
- for (ColourSchemeI scheme : getColourSchemes())
- {
- if (name.equals(scheme.getSchemeName().toLowerCase()))
- {
- return true;
- }
- }
- 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;
+ return schemes.containsKey(name.toLowerCase());
}
}
return pdb;
}
- private boolean isCIFFile(String filename)
+ public void addStructureMapping(StructureMapping sm)
{
- String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
- filename.length());
- return "cif".equalsIgnoreCase(fileExt);
+ mappings.add(sm);
}
/**
* @param atoms
* @return
*/
- public SearchResults findAlignmentPositionsForStructurePositions(
+ public SearchResultsI findAlignmentPositionsForStructurePositions(
List<AtomSpec> atoms)
{
- SearchResults results = new SearchResults();
+ SearchResultsI results = new SearchResults();
for (AtomSpec atom : atoms)
{
SequenceI lastseq = null;
package jalview.structures.models;
import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.api.StructureSelectionManagerProvider;
import jalview.api.structures.JalviewStructureDisplayI;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.List;
/**
* the sequence alignment which is the basis of structure
* superposition
* @param matched
- * an array of booleans, indexed by alignment column, where true
- * indicates that every structure has a mapped residue present in the
- * column (so the column can participate in structure alignment)
+ * a BitSet, where bit j is set to indicate that every structure has
+ * a mapped residue present in column j (so the column can
+ * participate in structure alignment)
* @param structures
* an array of data beans corresponding to pdb file index
* @return
*/
protected int findSuperposableResidues(AlignmentI alignment,
- boolean[] matched, SuperposeData[] structures)
+ BitSet matched, SuperposeData[] structures)
{
int refStructure = -1;
String[] files = getPdbFile();
{
refStructure = pdbfnum;
}
- for (int r = 0; r < matched.length; r++)
+ for (int r = 0; r < alignment.getWidth(); r++)
{
- if (!matched[r])
+ if (!matched.get(r))
{
continue;
}
int pos = getMappedPosition(theSequence, r, mapping);
if (pos < 1 || pos == lastPos)
{
- matched[r] = false;
+ matched.clear(r);
continue;
}
lastPos = pos;
public abstract void setJalviewColourScheme(ColourSchemeI cs);
- public abstract void superposeStructures(AlignmentI[] als, int[] alm,
- ColumnSelection[] alc);
-
- public abstract void setBackgroundColour(Color col);
-
- protected abstract StructureMappingcommandSet[] getColourBySequenceCommands(
- String[] files, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment);
-
/**
- * returns the current featureRenderer that should be used to colour the
- * structures
- *
- * @param alignment
+ * Constructs and sends a command to align structures against a reference
+ * structure, based on one or more sequence alignments. May optionally return
+ * an error or warning message for the alignment command.
*
+ * @param alignments
+ * an array of alignments to process
+ * @param structureIndices
+ * an array of corresponding reference structures (index into pdb
+ * file array); if a negative value is passed, the first PDB file
+ * mapped to an alignment sequence is used as the reference for
+ * superposition
+ * @param hiddenCols
+ * an array of corresponding hidden columns for each alignment
* @return
*/
- public abstract FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment);
+ public abstract String superposeStructures(AlignmentI[] alignments, int[] structureIndices,
+ ColumnSelection[] hiddenCols);
+
+ public abstract void setBackgroundColour(Color col);
+
+ protected abstract StructureMappingcommandSet[] getColourBySequenceCommands(
+ String[] files, SequenceRenderer sr, AlignmentViewPanel avp);
/**
* returns the current sequenceRenderer that should be used to colour the
*/
public void colourBySequence(AlignmentViewPanel alignmentv)
{
- boolean showFeatures = alignmentv.getAlignViewport()
- .isShowSequenceFeatures();
if (!colourBySequence || !isLoadingFinished())
{
return;
SequenceRenderer sr = getSequenceRenderer(alignmentv);
- FeatureRenderer fr = null;
- if (showFeatures)
- {
- fr = getFeatureRenderer(alignmentv);
- }
- AlignmentI alignment = alignmentv.getAlignment();
-
StructureMappingcommandSet[] colourBySequenceCommands = getColourBySequenceCommands(
- files, sr, fr, alignment);
+ files, sr, alignmentv);
colourBySequence(colourBySequenceCommands);
}
{
return fileLoadingError != null && fileLoadingError.length() > 0;
}
+
+ public abstract jalview.api.FeatureRenderer getFeatureRenderer(
+ AlignmentViewPanel alignment);
}
public abstract class AlignmentViewport implements AlignViewportI,
CommandListener, VamsasSource
{
+ protected ViewportRanges ranges;
+
protected ViewStyleI viewStyle = new ViewStyle();
/**
*/
private boolean followHighlight = true;
- // TODO private with getters and setters?
- public int startRes;
-
- public int endRes;
-
- public int startSeq;
-
- public int endSeq;
-
/**
* Property change listener for changes in alignment
*
}
/**
- * 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)
this.followHighlight = b;
}
- public int getStartRes()
- {
- return startRes;
- }
-
@Override
- public int getEndRes()
- {
- return endRes;
- }
-
- public int getStartSeq()
- {
- return startSeq;
- }
-
- public void setStartRes(int res)
- {
- this.startRes = res;
- }
-
- public void setStartSeq(int seq)
- {
- this.startSeq = seq;
- }
-
- public void setEndRes(int res)
- {
- if (res > alignment.getWidth() - 1)
- {
- // log.System.out.println(" Corrected res from " + res + " to maximum " +
- // (alignment.getWidth()-1));
- res = alignment.getWidth() - 1;
- }
- if (res < 0)
- {
- res = 0;
- }
- this.endRes = res;
- }
-
- public void setEndSeq(int seq)
- {
- if (seq > alignment.getHeight())
- {
- seq = alignment.getHeight();
- }
- if (seq < 0)
- {
- seq = 0;
- }
- this.endSeq = seq;
- }
-
- public int getEndSeq()
+ public ViewportRanges getRanges()
{
- return endSeq;
+ return ranges;
}
/**
* locate 'middle' column (true middle if an odd number visible, left of
* middle if an even number visible)
*/
- int middleColumn = getStartRes() + (getEndRes() - getStartRes()) / 2;
+ int middleColumn = ranges.getStartRes()
+ + (ranges.getEndRes() - ranges.getStartRes()) / 2;
final HiddenSequences hiddenSequences = getAlignment()
.getHiddenSequences();
*/
int lastSeq = alignment.getHeight() - 1;
List<AlignedCodonFrame> seqMappings = null;
- for (int seqNo = getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
+ for (int seqNo = ranges.getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
{
sequence = getAlignment().getSequenceAt(seqNo);
if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenSequences;
+
+import java.awt.Graphics;
+
+public class OverviewDimensions
+{
+ // Default width and height values
+ private static final int DEFAULT_GRAPH_HEIGHT = 20;
+
+ private static final int MAX_WIDTH = 400;
+
+ private static final int MIN_WIDTH = 120;
+
+ private static final int MIN_SEQ_HEIGHT = 40;
+
+ private static final int MAX_SEQ_HEIGHT = 300;
+
+ // width of the overview panel
+ private int width;
+
+ // height of sequences part of the overview panel
+ private int sequencesHeight;
+
+ // height of the graphs part of the overview panel
+ private int graphHeight = DEFAULT_GRAPH_HEIGHT;
+
+ // dimensions of box outlining current extent of view in alignment panel
+ // location of left side of box
+ private int boxX = -1;
+
+ // location of bottom of box
+ private int boxY = -1;
+
+ // width of box
+ private int boxWidth = -1;
+
+ // height of box
+ private int boxHeight = -1;
+
+ // scroll position in viewport corresponding to boxX
+ private int scrollCol = -1;
+
+ // scroll position in viewport corresponding to boxY
+ private int scrollRow = -1;
+
+ /**
+ * Create an OverviewDimensions object
+ *
+ * @param ranges
+ * positional properties of the viewport
+ * @param showAnnotationPanel
+ * true if the annotation panel is to be shown, false otherwise
+ */
+ public OverviewDimensions(ViewportRanges ranges,
+ boolean showAnnotationPanel)
+ {
+ // scale the initial size of overviewpanel to shape of alignment
+ float initialScale = (float) ranges.getAbsoluteAlignmentWidth()
+ / (float) ranges.getAbsoluteAlignmentHeight();
+
+ if (!showAnnotationPanel)
+ {
+ graphHeight = 0;
+ }
+
+ if (ranges.getAbsoluteAlignmentWidth() > ranges
+ .getAbsoluteAlignmentHeight())
+ {
+ // wider
+ width = MAX_WIDTH;
+ sequencesHeight = Math.round(MAX_WIDTH / initialScale);
+ if (sequencesHeight < MIN_SEQ_HEIGHT)
+ {
+ sequencesHeight = MIN_SEQ_HEIGHT;
+ }
+ }
+ else
+ {
+ // taller
+ width = Math.round(MAX_WIDTH * initialScale);
+ sequencesHeight = MAX_SEQ_HEIGHT;
+
+ if (width < MIN_WIDTH)
+ {
+ width = MIN_WIDTH;
+ }
+ }
+ }
+
+ /**
+ * Check box dimensions and scroll positions and correct if necessary
+ *
+ * @param mousex
+ * x position in overview panel
+ * @param mousey
+ * y position in overview panel
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param ranges
+ * viewport position properties
+ */
+ public void updateViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
+ ViewportRanges ranges)
+ {
+ int x = mousex;
+ int y = mousey;
+
+ int alwidth = ranges.getAbsoluteAlignmentWidth();
+ int alheight = ranges.getAbsoluteAlignmentHeight();
+
+ if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ y = 0;
+ }
+
+ //
+ // Convert x value to residue position
+ //
+
+ // need to determine where scrollCol should be, given x
+ // to do this also need to know width of viewport, and some hidden column
+ // correction
+
+ // convert x to residues - this is an absolute position
+ int xAsRes = Math.round((float) x * alwidth / width);
+
+ // get viewport width in residues
+ int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
+
+ // get where x should be when accounting for hidden cols
+ // if x is in a hidden col region, shift to left - but we still need
+ // absolute position
+ // so convert back after getting visible region position
+ int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
+
+ // check in case we went off the edge of the alignment
+ int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
+ if (visXAsRes + vpwidth - 1 > visAlignWidth)
+ {
+ // went past the end of the alignment, adjust backwards
+
+ // if last position was before the end of the alignment, need to update
+ if ((scrollCol + vpwidth - 1) < visAlignWidth)
+ {
+ visXAsRes = hiddenCols.findColumnPosition(hiddenCols
+ .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
+ }
+ else
+ {
+ visXAsRes = scrollCol;
+ }
+ }
+
+ //
+ // Convert y value to sequence position
+ //
+
+ // convert y to residues
+ int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
+
+ // get viewport height in sequences
+ // add 1 because height includes both endSeq and startSeq
+ int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
+
+ // get where y should be when accounting for hidden rows
+ // if y is in a hidden row region, shift up - but we still need absolute
+ // position,
+ // so convert back after getting visible region position
+ yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
+ .findIndexWithoutHiddenSeqs(yAsSeq));
+
+ // check in case we went off the edge of the alignment
+ int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
+ int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
+ if (visYAsRes + vpheight - 1 > visAlignHeight)
+ {
+ // went past the end of the alignment, adjust backwards
+ if ((scrollRow + vpheight - 1) < visAlignHeight)
+ {
+ visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
+ .subtractVisibleRows(vpheight - 1, alheight - 1));
+ }
+ else
+ {
+ visYAsRes = scrollRow;
+ }
+ }
+
+ // update scroll values
+ scrollCol = visXAsRes;
+ scrollRow = visYAsRes;
+
+ }
+
+ /**
+ * Update the overview panel box when the associated alignment panel is
+ * changed
+ *
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param ranges
+ * viewport position properties
+ */
+ public void setBoxPosition(HiddenSequences hiddenSeqs,
+ ColumnSelection hiddenCols, ViewportRanges ranges)
+ {
+ int alwidth = ranges.getAbsoluteAlignmentWidth();
+ int alheight = ranges.getAbsoluteAlignmentHeight();
+
+ // work with absolute values of startRes and endRes
+ int startRes = hiddenCols.adjustForHiddenColumns(ranges.getStartRes());
+ int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
+
+ // work with absolute values of startSeq and endSeq
+ int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
+ int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
+
+ // boxX, boxY is the x,y location equivalent to startRes, startSeq
+ boxX = Math.round((float) startRes * width / alwidth);
+ boxY = Math.round((float) startSeq * sequencesHeight / alheight);
+
+ // boxWidth is the width in residues translated to pixels
+ // since the box includes both the start and end residues, add 1 to the
+ // difference
+ boxWidth = Math
+ .round((float) (endRes - startRes + 1) * width / alwidth);
+ // boxHeight is the height in sequences translated to pixels
+ boxHeight = Math.round((float) (endSeq - startSeq + 1)
+ * sequencesHeight
+ / alheight);
+ }
+
+ /**
+ * Draw the overview panel's viewport box on a graphics object
+ *
+ * @param g
+ * the graphics object to draw on
+ */
+ public void drawBox(Graphics g)
+ {
+ g.drawRect(boxX, boxY, boxWidth, boxHeight);
+ g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
+ }
+
+ public int getScrollCol()
+ {
+ return scrollCol;
+ }
+
+ public int getScrollRow()
+ {
+ return scrollRow;
+ }
+
+ // TODO should be removed, when unit test has mock Graphics object available
+ // to check boxX/boxY
+ public int getBoxX()
+ {
+ return boxX;
+ }
+
+ // TODO should be removed, when unit test has mock Graphics object available
+ // to check boxX/boxY
+ public int getBoxY()
+ {
+ return boxY;
+ }
+
+ // TODO should be removed, when unit test has mock Graphics object available
+ public int getBoxWidth()
+ {
+ return boxWidth;
+ }
+
+ // TODO should be removed, when unit test has mock Graphics object available
+ public int getBoxHeight()
+ {
+ return boxHeight;
+ }
+
+ public void setWidth(int w)
+ {
+ width = w;
+ }
+
+ public void setHeight(int h)
+ {
+ sequencesHeight = h - graphHeight;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public int getHeight()
+ {
+ return sequencesHeight + graphHeight;
+ }
+
+ public int getSequencesHeight()
+ {
+ return sequencesHeight;
+ }
+
+ public int getGraphHeight()
+ {
+ return graphHeight;
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+public abstract class ViewportProperties
+{
+
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+import jalview.datamodel.AlignmentI;
+
+/**
+ * Embryonic class which: Supplies and updates viewport properties relating to
+ * position such as: start and end residues and sequences; ideally will serve
+ * hidden columns/rows too. Intention also to support calculations for
+ * positioning, scrolling etc. such as finding the middle of the viewport,
+ * checking for scrolls off screen
+ */
+public class ViewportRanges extends ViewportProperties
+{
+ // start residue of viewport
+ private int startRes;
+
+ // end residue of viewport
+ private int endRes;
+
+ // start sequence of viewport
+ private int startSeq;
+
+ // end sequence of viewport
+ private int endSeq;
+
+ // alignment
+ private AlignmentI al;
+
+ /**
+ * Constructor
+ *
+ * @param alignment
+ * the viewport's alignment
+ */
+ public ViewportRanges(AlignmentI alignment)
+ {
+ // initial values of viewport settings
+ this.startRes = 0;
+ this.endRes = alignment.getWidth() - 1;
+ this.startSeq = 0;
+ this.endSeq = alignment.getHeight() - 1;
+ this.al = alignment;
+ }
+
+ /**
+ * Get alignment width in cols, including hidden cols
+ */
+ public int getAbsoluteAlignmentWidth()
+ {
+ return al.getWidth();
+ }
+
+ /**
+ * Get alignment height in rows, including hidden rows
+ */
+ public int getAbsoluteAlignmentHeight()
+ {
+ return al.getHeight() + al.getHiddenSequences().getSize();
+ }
+
+ /**
+ * Set first residue visible in the viewport
+ *
+ * @param res
+ * residue position
+ */
+ public void setStartRes(int res)
+ {
+ if (res > al.getWidth() - 1)
+ {
+ res = al.getWidth() - 1;
+ }
+ else if (res < 0)
+ {
+ res = 0;
+ }
+ this.startRes = res;
+ }
+
+ /**
+ * Set last residue visible in the viewport
+ *
+ * @param res
+ * residue position
+ */
+ public void setEndRes(int res)
+ {
+ if (res >= al.getWidth())
+ {
+ res = al.getWidth() - 1;
+ }
+ else if (res < 0)
+ {
+ res = 0;
+ }
+ this.endRes = res;
+ }
+
+ /**
+ * Set the first sequence visible in the viewport
+ *
+ * @param seq
+ * sequence position
+ */
+ public void setStartSeq(int seq)
+ {
+ if (seq > al.getHeight() - 1)
+ {
+ seq = al.getHeight() - 1;
+ }
+ else if (seq < 0)
+ {
+ seq = 0;
+ }
+ this.startSeq = seq;
+ }
+
+ /**
+ * Set the last sequence visible in the viewport
+ *
+ * @param seq
+ * sequence position
+ */
+ public void setEndSeq(int seq)
+ {
+ if (seq >= al.getHeight())
+ {
+ seq = al.getHeight() - 1;
+ }
+ else if (seq < 0)
+ {
+ seq = 0;
+ }
+ this.endSeq = seq;
+ }
+
+ /**
+ * Get start residue of viewport
+ */
+ public int getStartRes()
+ {
+ return startRes;
+ }
+
+ /**
+ * Get end residue of viewport
+ */
+ public int getEndRes()
+ {
+ return endRes;
+ }
+
+ /**
+ * Get start sequence of viewport
+ */
+ public int getStartSeq()
+ {
+ return startSeq;
+ }
+
+ /**
+ * Get end sequence of viewport
+ */
+ public int getEndSeq()
+ {
+ return endSeq;
+ }
+}
}
/**
- * calculate the render colour for a specific feature using current feature
- * settings.
+ * Returns the configured colour for a particular feature instance. This
+ * includes calculation of 'colour by label', or of a graduated score colour,
+ * if applicable. It does not take into account feature visibility or colour
+ * transparency.
*
* @param feature
- * @return render colour for the given feature
+ * @return
*/
public Color getColour(SequenceFeature feature)
{
featureColours.put(featureType, col);
}
+ @Override
public void setTransparency(float value)
{
transparency = value;
}
+ @Override
public float getTransparency()
{
return transparency;
* @return list of groups
*/
@Override
- public List getGroups(boolean visible)
+ public List<String> getGroups(boolean visible)
{
if (featureGroups != null)
{
{
calcMan.notifyStart(this); // updatingConservation = true;
- while (!calcMan.notifyWorking(this))
+ while ((calcMan != null) && (!calcMan.notifyWorking(this)))
{
try
{
ex.printStackTrace();
}
}
- if (alignViewport.isClosed())
+ if ((alignViewport == null) || (calcMan == null)
+ || (alignViewport.isClosed()))
{
abortAndDestroy();
return;
}
calcMan.workerComplete(this);
+ if ((alignViewport == null) || (calcMan == null)
+ || (alignViewport.isClosed()))
+ {
+ abortAndDestroy();
+ return;
+ }
if (ap != null)
{
ap.paintAlignment(true);
}
af.getFeatureRenderer().featuresAdded();
- int start = af.getViewport().getStartSeq();
- int end = af.getViewport().getEndSeq();
+ int start = af.getViewport().getRanges().getStartSeq();
+ int end = af.getViewport().getRanges().getEndSeq();
int index;
for (index = start; index < end; index++)
{
return loadingDasSources;
}
+ @Override
public String getDasRegistryURL()
{
String registry = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",
return dsrc;
} catch (Exception ex)
{
- System.err.println("Failed to contact DAS1 registry at "
- + registryURL);
- ex.printStackTrace();
+ System.out.println("DAS1 registry at " + registryURL
+ + " no longer exists");
return new ArrayList<jalviewSourceI>();
}
}
/*
* the .jalview_properties entry for JWS2 URLS
*/
- final static String JWS2HOSTURLS = "JWS2HOSTURLS";
+ private final static String JWS2HOSTURLS = "JWS2HOSTURLS";
/*
* Singleton instance
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
this);
- Vector<String> invalidServiceUrls = null, urlsWithoutServices = null,
- validServiceUrls = null;
+ private Vector<String> invalidServiceUrls = null;
- boolean running = false, aborted = false;
+ private Vector<String> urlsWithoutServices = null;
- Thread oldthread = null;
+ private Vector<String> validServiceUrls = null;
+
+ private volatile boolean running = false;
+
+ private volatile boolean aborted = false;
+
+ private Thread oldthread = null;
/**
* holds list of services.
public void setAborted(boolean aborted)
{
this.aborted = aborted;
-
}
+ @Override
public void run()
{
{
}
}
+ aborted = false;
Cache.log.debug("Old discovery thread has finished.");
}
running = true;
ignoredServices.add(ignored);
}
- changeSupport.firePropertyChange("services", services, new Vector());
+ changeSupport.firePropertyChange("services", services,
+ new Vector<Jws2Instance>());
oldthread = Thread.currentThread();
try
{
if (!aborted)
{
// resort services according to order found in jabaws service list
- // also ensure servics for each host are ordered in same way.
+ // also ensure services for each host are ordered in same way.
if (services != null && services.size() > 0)
{
}
oldthread = null;
running = false;
- changeSupport.firePropertyChange("services", new Vector(), services);
+ changeSupport.firePropertyChange("services",
+ new Vector<Jws2Instance>(), services);
}
/**
service.hasParameters();
if (validServiceUrls == null)
{
- validServiceUrls = new Vector();
+ validServiceUrls = new Vector<String>();
}
validServiceUrls.add(jwsservers);
}
* attach all available web services to the appropriate submenu in the given
* JMenu
*/
+ @Override
public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
{
// dynamically regenerate service list.
{
return;
}
- boolean byhost = Cache.getDefault("WSMENU_BYHOST", false), bytype = Cache
- .getDefault("WSMENU_BYTYPE", false);
+
/**
* eventually, JWS2 services will appear under the same align/etc submenus.
* for moment we keep them separate.
{
new Thread(new Runnable()
{
+ @Override
public void run()
{
setPreferredServiceFor(alignFrame, sv.serviceType,
sv.action, sv);
changeSupport.firePropertyChange("services",
- new Vector(), services);
+ new Vector<Jws2Instance>(), services);
};
}).start();
}
});
}
- /*
- * hitm.addActionListener(new ActionListener() {
- *
- * @Override public void actionPerformed(ActionEvent arg0) { new
- * Thread(new Runnable() {
- *
- * @Override public void run() { new SetPreferredServer(alignFrame,
- * service.serviceType, service.action); } }).start(); } });
- */
}
}
}
* for moment we keep them separate.
*/
JMenu atpoint;
- MsaWSClient msacl = new MsaWSClient();
+
List<String> hostLabels = new ArrayList<String>();
Hashtable<String, String> lasthostFor = new Hashtable<String, String>();
Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<String, ArrayList<Jws2Instance>>();
new PropertyChangeListener()
{
+ @Override
public void propertyChange(PropertyChangeEvent evt)
{
if (getDiscoverer().services != null)
return true;
}
+ public boolean restart()
+ {
+ synchronized (this)
+ {
+ if (running)
+ {
+ aborted = true;
+ }
+ else
+ {
+ running = true;
+ }
+ return aborted;
+ }
+ }
+
/**
* Start a fresh discovery thread and notify the given object when we're
* finished. Any known existing threads will be killed before this one is
*/
public Thread startDiscoverer(PropertyChangeListener changeSupport2)
{
+ /* if (restart())
+ {
+ return;
+ }
+ else
+ {
+ Thread thr = new Thread(this);
+ thr.start();
+ }
+ */
if (isRunning())
{
setAborted(true);
.getDbResNum());
} catch (NumberFormatException nfe)
{
- resNum = (pdbRefDb == null) ? Integer.valueOf(residue
- .getDbResNum()) : Integer.valueOf(pdbRefDb
+ if (pdbRefDb == null || pdbRefDb.getDbResNum().equals("null"))
+ {
+ resNum = UNASSIGNED;
+ continue;
+ }
+ resNum = Integer.valueOf(pdbRefDb
.getDbResNum().split("[a-zA-Z]")[0]);
continue;
}
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
+import jalview.analysis.AlignmentGenerator;
import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
import jalview.gui.JvOptionPane;
import jalview.io.DataSourceType;
assertNull(a.findGroup(seq2, 8));
}
+ @Test(groups = { "Functional" })
+ public void testDeleteSequenceByIndex()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI a = gen.generate(20, 15, 123, 5, 5);
+
+ // delete sequence 10, alignment reduced by 1
+ int height = a.getAbsoluteHeight();
+ a.deleteSequence(10);
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+
+ // try to delete -ve index, nothing happens
+ a.deleteSequence(-1);
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+
+ // try to delete beyond end of alignment, nothing happens
+ a.deleteSequence(14);
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testDeleteSequenceBySeq()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI a = gen.generate(20, 15, 123, 5, 5);
+
+ // delete sequence 10, alignment reduced by 1
+ int height = a.getAbsoluteHeight();
+ SequenceI seq = a.getSequenceAt(10);
+ a.deleteSequence(seq);
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+
+ // try to delete non-existent sequence, nothing happens
+ seq = new Sequence("cds", "GCCTCGGAT");
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testDeleteHiddenSequence()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI a = gen.generate(20, 15, 123, 5, 5);
+
+ // delete a sequence which is hidden, check it is NOT removed from hidden
+ // sequences
+ int height = a.getAbsoluteHeight();
+ SequenceI seq = a.getSequenceAt(2);
+ a.getHiddenSequences().hideSequence(seq);
+ assertEquals(a.getHiddenSequences().getSize(), 1);
+ a.deleteSequence(2);
+ assertEquals(a.getAbsoluteHeight(), height - 1);
+ assertEquals(a.getHiddenSequences().getSize(), 1);
+
+ // delete a sequence which is not hidden, check hiddenSequences are not
+ // affected
+ a.deleteSequence(10);
+ assertEquals(a.getAbsoluteHeight(), height - 2);
+ 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);
+ }
}
cs.hideColumns(4, 4);
assertEquals(4, cs.findColumnPosition(5));
+ // hiding column 4 moves column 4 to position 3
+ assertEquals(3, cs.findColumnPosition(4));
+
// hiding columns 1 and 2 moves column 5 to column 2
cs.hideColumns(1, 2);
assertEquals(2, cs.findColumnPosition(5));
+
+ // check with > 1 hidden column regions
+ // where some columns are in the hidden regions
+ ColumnSelection cs2 = new ColumnSelection();
+ cs2.hideColumns(5, 10);
+ cs2.hideColumns(20, 27);
+ cs2.hideColumns(40, 44);
+
+ // hiding columns 5-10 and 20-27 moves column 8 to column 4
+ assertEquals(4, cs2.findColumnPosition(8));
+
+ // and moves column 24 to 13
+ assertEquals(13, cs2.findColumnPosition(24));
+
+ // and moves column 28 to 14
+ assertEquals(14, cs2.findColumnPosition(28));
+
+ // and moves column 40 to 25
+ assertEquals(25, cs2.findColumnPosition(40));
+
+ // check when hidden columns start at 0 that the visible column
+ // is returned as 0
+ ColumnSelection cs3 = new ColumnSelection();
+ cs3.hideColumns(0, 4);
+ assertEquals(0, cs3.findColumnPosition(2));
+
+ }
+
+ /**
+ * Test the method that finds the visible column position a given distance
+ * before another column
+ */
+ @Test(groups = { "Functional" })
+ public void testFindColumnNToLeft()
+ {
+ ColumnSelection cs = new ColumnSelection();
+
+ // test that without hidden columns, findColumnNToLeft returns
+ // position n to left of provided position
+ int pos = cs.subtractVisibleColumns(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = cs.subtractVisibleColumns(0, 10);
+ assertEquals(10, pos);
+
+ // overflow to left returns negative number
+ pos = cs.subtractVisibleColumns(3, 0);
+ assertEquals(-3, pos);
+
+ // test that with hidden columns to left of result column
+ // behaviour is the same as above
+ cs.hideColumns(1, 3);
+
+ // position n to left of provided position
+ pos = cs.subtractVisibleColumns(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = cs.subtractVisibleColumns(0, 10);
+ assertEquals(10, pos);
+
+ // test with one set of hidden columns between start and required position
+ cs.hideColumns(12, 15);
+ pos = cs.subtractVisibleColumns(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden columns between start and required position
+ cs.hideColumns(20, 21);
+ pos = cs.subtractVisibleColumns(8, 23);
+ assertEquals(9, pos);
+
+ // repeat last 2 tests with no hidden columns to left of required position
+ cs.revealAllHiddenColumns();
+
+ // test with one set of hidden columns between start and required position
+ cs.hideColumns(12, 15);
+ pos = cs.subtractVisibleColumns(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden columns between start and required position
+ cs.hideColumns(20, 21);
+ pos = cs.subtractVisibleColumns(8, 23);
+ assertEquals(9, pos);
+
}
/**
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- static int SEQ_COUNT = 10;
+ static int SEQ_COUNT = 25;
SequenceI[] seqs;
seqs = new SequenceI[SEQ_COUNT];
for (int i = 0; i < SEQ_COUNT; i++)
{
- // sequence lengths are 1, 2, ... 10
- seqs[i] = new Sequence("Seq" + i, "abcdefghijk".substring(0, i + 1));
+ // sequence lengths are 1, 2, ... 25
+ seqs[i] = new Sequence("Seq" + i,
+ "abcdefghijklmnopqrstuvwxy".substring(0, i + 1));
}
}
/*
* alignment is now seq0/2/3/4/7/8/9
*/
- assertEquals(7, al.getHeight());
+ assertEquals(SEQ_COUNT - 3, al.getHeight());
assertEquals(0, hs.adjustForHiddenSeqs(0));
assertEquals(2, hs.adjustForHiddenSeqs(1));
assertEquals(3, hs.adjustForHiddenSeqs(2));
/*
* alignment is now seq0/2/3/4/7/8/9
*/
- assertEquals(7, al.getHeight());
+ assertEquals(SEQ_COUNT - 3, al.getHeight());
assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
}
/**
+ * Test the method that finds the visible row position a given distance before
+ * another row
+ */
+ @Test(groups = { "Functional" })
+ public void testFindIndexNFromRow()
+ {
+ AlignmentI al = new Alignment(seqs);
+ HiddenSequences hs = new HiddenSequences(al);
+
+ // test that without hidden rows, findIndexNFromRow returns
+ // position n above provided position
+ int pos = hs.subtractVisibleRows(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = hs.subtractVisibleRows(0, 10);
+ assertEquals(10, pos);
+
+ // overflow to top returns negative number
+ pos = hs.subtractVisibleRows(3, 0);
+ assertEquals(-3, pos);
+
+ // test that with hidden rows above result row
+ // behaviour is the same as above
+ hs.hideSequence(seqs[1]);
+ hs.hideSequence(seqs[2]);
+ hs.hideSequence(seqs[3]);
+
+ // position n above provided position
+ pos = hs.subtractVisibleRows(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = hs.subtractVisibleRows(0, 10);
+ assertEquals(10, pos);
+
+ // test with one set of hidden rows between start and required position
+ hs.hideSequence(seqs[12]);
+ hs.hideSequence(seqs[13]);
+ hs.hideSequence(seqs[14]);
+ hs.hideSequence(seqs[15]);
+ pos = hs.subtractVisibleRows(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden rows between start and required position
+ hs.hideSequence(seqs[20]);
+ hs.hideSequence(seqs[21]);
+ pos = hs.subtractVisibleRows(8, 23);
+ assertEquals(9, pos);
+
+ // repeat last 2 tests with no hidden columns to left of required position
+ hs.showAll(null);
+
+ // test with one set of hidden rows between start and required position
+ hs.hideSequence(seqs[12]);
+ hs.hideSequence(seqs[13]);
+ hs.hideSequence(seqs[14]);
+ hs.hideSequence(seqs[15]);
+ pos = hs.subtractVisibleRows(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden rows between start and required position
+ hs.hideSequence(seqs[20]);
+ hs.hideSequence(seqs[21]);
+ pos = hs.subtractVisibleRows(8, 23);
+ assertEquals(9, pos);
+
+ }
+
+ /**
* Test the method that reconstructs (sort of) the full alignment including
* hidden sequences
*/
assertTrue(al.getSequences().contains(seqs[1]));
HiddenSequences hs = al.getHiddenSequences();
assertEquals(0, hs.getSize());
- assertEquals(10, al.getHeight());
+ assertEquals(SEQ_COUNT, al.getHeight());
/*
* hide the second sequence in the alignment
assertTrue(hs.isHidden(seqs[1]));
assertFalse(al.getSequences().contains(seqs[1]));
assertEquals(1, hs.getSize());
- assertEquals(9, al.getHeight());
+ assertEquals(SEQ_COUNT - 1, al.getHeight());
assertSame(seqs[2], al.getSequenceAt(1));
/*
assertFalse(al.getSequences().contains(seqs[1]));
assertFalse(al.getSequences().contains(seqs[2]));
assertEquals(2, hs.getSize());
- assertEquals(8, al.getHeight());
+ assertEquals(SEQ_COUNT - 2, al.getHeight());
/*
* perform 'reveal' on what is now the second sequence in the alignment
assertTrue(revealed.contains(seqs[1]));
assertTrue(revealed.contains(seqs[2]));
assertEquals(0, hs.getSize());
- assertEquals(10, al.getHeight());
+ assertEquals(SEQ_COUNT, al.getHeight());
+ }
+
+ /**
+ * Test the method that adds a sequence to the hidden sequences and deletes it
+ * from the alignment, and its converse, where the first hidden sequences are
+ * at the bottom of the alignment (JAL-2437)
+ */
+ @Test(groups = "Functional")
+ public void testHideShowLastSequences()
+ {
+ AlignmentI al = new Alignment(seqs);
+ assertTrue(al.getSequences().contains(seqs[1]));
+ HiddenSequences hs = al.getHiddenSequences();
+ assertEquals(0, hs.getSize());
+ assertEquals(SEQ_COUNT, al.getHeight());
+
+ /*
+ * hide the last sequence in the alignment
+ */
+ hs.hideSequence(seqs[SEQ_COUNT - 1]);
+ assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
+ assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1]));
+ assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1]));
+ assertEquals(1, hs.getSize());
+ assertEquals(SEQ_COUNT - 1, al.getHeight());
+
+ /*
+ * hide the third last sequence in the alignment
+ */
+ hs.hideSequence(seqs[SEQ_COUNT - 3]);
+ assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
+ assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3]));
+ assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3]));
+ assertEquals(2, hs.getSize());
+ assertEquals(SEQ_COUNT - 2, al.getHeight());
+
+ /*
+ * reveal all the sequences, which should be reinstated in the same order as they started in
+ */
+ hs.showAll(null);
+ assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3]));
+ assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1]));
+ assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3));
+ assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2));
+ assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1));
+ assertEquals(0, hs.getSize());
+ assertEquals(SEQ_COUNT, al.getHeight());
}
@Test(groups = "Functional")
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;
// need some mappings!
StructureMappingcommandSet[] commands = JmolCommands
- .getColourBySequenceCommand(ssm, files, seqs, sr, null, al);
+ .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]"));
}
}
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.awt.Color;
import java.util.HashMap;
* feature name gets a jv_ namespace prefix
* feature value is quoted in case it contains spaces
*/
- assertEquals(commands.get(0), "setattr r jv_chain \"X\" #0:8-20.A");
+ assertEquals(commands.get(0), "setattr r jv_chain 'X' #0:8-20.A");
// add same feature value, overlapping range
ChimeraCommands.addColourRange(featureValues, "X", 0, 3, 9, "A");
ChimeraCommands.addColourRange(featureValues, "X", 0, 21, 25, "A");
commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
assertEquals(1, commands.size());
- assertEquals(commands.get(0), "setattr r jv_chain \"X\" #0:3-25.A");
+ assertEquals(commands.get(0), "setattr r jv_chain 'X' #0:3-25.A");
// same feature value and model, different chain
ChimeraCommands.addColourRange(featureValues, "X", 0, 21, 25, "B");
commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
assertEquals(1, commands.size());
assertEquals(commands.get(0),
- "setattr r jv_chain \"X\" #0:3-25.A,21-25.B|#1:26-30.A");
+ "setattr r jv_chain 'X' #0:3-25.A,21-25.B|#1:26-30.A");
// same feature, different value
ChimeraCommands.addColourRange(featureValues, "Y", 0, 40, 50, "A");
// commands are ordered by feature type but not by value
// so use contains to test for the expected command:
assertTrue(commands
- .contains("setattr r jv_chain \"X\" #0:3-25.A,21-25.B|#1:26-30.A"));
- assertTrue(commands.contains("setattr r jv_chain \"Y\" #0:40-50.A"));
+ .contains("setattr r jv_chain 'X' #0:3-25.A,21-25.B|#1:26-30.A"));
+ assertTrue(commands.contains("setattr r jv_chain 'Y' #0:40-50.A"));
featuresMap.clear();
featureValues.clear();
featuresMap.put("side-chain binding!", featureValues);
- ChimeraCommands.addColourRange(featureValues, "metal ion!", 0, 7, 15,
+ ChimeraCommands.addColourRange(featureValues,
+ "<html>metal <a href=\"http:a.b.c/x\"> 'ion!", 0, 7, 15,
"A");
- // feature names are sanitised to change space or hyphen to underscore
+ // feature names are sanitised to change non-alphanumeric to underscore
+ // feature values are sanitised to encode single quote characters
commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
assertTrue(commands
- .contains("setattr r jv_side_chain_binding_ \"metal ion!\" #0:7-15.A"));
+ .contains("setattr r jv_side_chain_binding_ '<html>metal <a href=\"http:a.b.c/x\"> 'ion!' #0:7-15.A"));
}
/**
assertEquals(ChimeraCommands.makeAttributeName("helixColor"),
"jv_helixColor_");
}
+
+ @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 = ChimeraCommands
+ .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
+ assertEquals(1, commands.length);
+ assertEquals(1, commands[0].commands.length);
+ String theCommand = commands[0].commands[0];
+ // M colour is #82827d (see strand.html help page)
+ 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
+ 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"));
+ // S and G are both coloured #4949b6
+ assertTrue(theCommand.contains("color #4949b6 #0:26-30.A|#1:26-30.B"));
+ }
}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.viewmodel.ViewportRanges;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class AlignmentPanelTest
+{
+ SequenceI seq1 = new Sequence(
+ "Seq1",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq2 = new Sequence(
+ "Seq2",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq3 = new Sequence(
+ "Seq3",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq4 = new Sequence(
+ "Seq4",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq5 = new Sequence(
+ "Seq5",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq6 = new Sequence(
+ "Seq6",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq7 = new Sequence(
+ "Seq7",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq8 = new Sequence(
+ "Seq8",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq9 = new Sequence(
+ "Seq9",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq10 = new Sequence(
+ "Seq10",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq11 = new Sequence(
+ "Seq11",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq12 = new Sequence(
+ "Seq12",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq13 = new Sequence(
+ "Seq13",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq14 = new Sequence(
+ "Seq14",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq15 = new Sequence(
+ "Seq15",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq16 = new Sequence(
+ "Seq16",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq17 = new Sequence(
+ "Seq17",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq18 = new Sequence(
+ "Seq18",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq19 = new Sequence(
+ "Seq19",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq20 = new Sequence(
+ "Seq20",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq21 = new Sequence(
+ "Seq21",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq22 = new Sequence(
+ "Seq22",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ SequenceI seq23 = new Sequence(
+ "Seq23",
+ "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ AlignFrame af;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp()
+ {
+ Jalview.main(new String[] { "-nonews", "-props",
+ "test/jalview/testProps.jvprops" });
+
+ Cache.applicationProperties.setProperty("SHOW_IDENTITY",
+ Boolean.TRUE.toString());
+ af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
+ DataSourceType.FILE);
+
+ /*
+ * wait for Consensus thread to complete
+ */
+ synchronized (this)
+ {
+ while (af.getViewport().getConsensusSeq() == null)
+ {
+ try
+ {
+ wait(50);
+ } catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Test side effect that end residue is set correctly by setScrollValues, with
+ * or without hidden columns
+ */
+ @Test(groups = "Functional")
+ public void TestSetScrollValues()
+ {
+ ViewportRanges ranges = af.getViewport().getRanges();
+ af.alignPanel.setScrollValues(0, 0);
+
+ int oldres = ranges.getEndRes();
+ af.alignPanel.setScrollValues(-1, 5);
+
+ // setting -ve x value does not change residue
+ assertEquals(ranges.getEndRes(), oldres);
+
+ af.alignPanel.setScrollValues(0, 5);
+
+ // setting 0 as x value does not change residue
+ assertEquals(ranges.getEndRes(), oldres);
+
+ af.alignPanel.setScrollValues(5, 5);
+ // setting x value to 5 extends endRes by 5 residues
+ assertEquals(ranges.getEndRes(), oldres + 5);
+
+ // scroll to position after hidden columns sets endres to oldres (width) +
+ // position
+ int scrollpos = 60;
+ af.getViewport().hideColumns(30, 50);
+ af.alignPanel.setScrollValues(scrollpos, 5);
+ assertEquals(ranges.getEndRes(), oldres + scrollpos);
+
+ // scroll to position within hidden columns, still sets endres to oldres +
+ // position
+ // not sure if this is actually correct behaviour but this is what Jalview
+ // currently does
+ scrollpos = 40;
+ af.getViewport().showAllHiddenColumns();
+ af.getViewport().hideColumns(30, 50);
+ af.alignPanel.setScrollValues(scrollpos, 5);
+ assertEquals(ranges.getEndRes(), oldres + scrollpos);
+
+ // scroll to position within <width> distance of the end of the alignment
+ // endRes should be set to width of alignment - 1
+ scrollpos = 130;
+ af.getViewport().showAllHiddenColumns();
+ af.alignPanel.setScrollValues(scrollpos, 5);
+ assertEquals(ranges.getEndRes(), af.getViewport()
+ .getAlignment().getWidth() - 1);
+
+ // now hide some columns, and scroll to position within <width>
+ // distance of the end of the alignment
+ // endRes should be set to width of alignment - 1 - the number of hidden
+ // columns
+ af.getViewport().hideColumns(30, 50);
+ af.alignPanel.setScrollValues(scrollpos, 5);
+ assertEquals(ranges.getEndRes(), af.getViewport()
+ .getAlignment().getWidth() - 1 - 21); // 21 is the number of hidden
+ // columns
+ }
+}
--- /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");
+ }
+}
av.setGlobalColourScheme(new ZappoColourScheme());
// @see ResidueProperties.zappo
- assertEquals(Color.pink, sr.getResidueColour(seq, 0, null)); // M
- assertEquals(Color.green, sr.getResidueColour(seq, 2, null)); // T
- assertEquals(Color.magenta, sr.getResidueColour(seq, 5, null)); // G
- assertEquals(Color.orange, sr.getResidueColour(seq, 12, null)); // F
+ assertEquals(Color.pink, sr.getResidueBoxColour(seq, 0)); // M
+ assertEquals(Color.green, sr.getResidueBoxColour(seq, 2)); // T
+ assertEquals(Color.magenta, sr.getResidueBoxColour(seq, 5)); // G
+ assertEquals(Color.orange, sr.getResidueBoxColour(seq, 12)); // F
}
// TODO more tests for getResidueBoxColour covering groups, feature rendering,
// gaps, overview...
import jalview.gui.JvOptionPane;
import jalview.json.binding.biojson.v1.ColourSchemeMapper;
import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ResidueColourScheme;
import java.io.IOException;
import java.util.ArrayList;
private JSONFile jf;
+ private AlignExportSettingI exportSettings;
+
@BeforeTest(alwaysRun = true)
public void setup() throws Exception
{
TEST_ANOT_HEIGHT = expectedAnnots.size();
TEST_CS_HEIGHT = expectedColSel.getHiddenColumns().size();
- AlignExportSettingI exportSettings = new AlignExportSettingI()
+ exportSettings = new AlignExportSettingI()
{
@Override
public boolean isExportHiddenSequences()
}
@Test(groups = { "Functional" })
+ /**
+ * Test for bug JAL-2489, NPE when exporting BioJSON with global colour scheme set as 'None'
+ */
+ public void testBioJSONRoundTripWithGlobalColourSchemeSetAsNone()
+ {
+ AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
+
+ Alignment _alignment;
+ try
+ {
+ // load example BioJSON file
+ _alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
+ DataSourceType.FILE, FileFormat.Json);
+ JSONFile bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+ AlignFrame alignFrame = new AlignFrame(_alignment,
+ bioJsonFile.getHiddenSequences(),
+ bioJsonFile.getColumnSelection(), AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ // Change colour scheme to 'None' and perform round trip
+ ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+ ResidueColourScheme.NONE, _alignment);
+ alignFrame.changeColour(cs);
+ alignFrame.getViewport().setFeaturesDisplayed(
+ bioJsonFile.getDisplayedFeatures());
+ formatAdapter = new AppletFormatAdapter(alignFrame.alignPanel,
+ exportSettings);
+ // export BioJSON string
+ String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+ alignFrame.alignPanel.getAlignment(), false);
+ // read back Alignment from BioJSON string
+ formatAdapter = new AppletFormatAdapter();
+ formatAdapter.readFile(jsonOutput, DataSourceType.PASTE,
+ FileFormat.Json);
+ // assert 'None' colour scheme is retained after round trip
+ JSONFile _bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+ Assert.assertEquals(_bioJsonFile.getGlobalColourScheme(),
+ ResidueColourScheme.NONE);
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Test(groups = { "Functional" })
public void isShowSeqFeaturesSet()
{
Assert.assertTrue(testJsonFile.isShowSeqFeatures(),
--- /dev/null
+package jalview.renderer.seqfeatures;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import jalview.api.FeatureColourI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.gui.FeatureRenderer;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.schemes.FeatureColour;
+
+import java.awt.Color;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for feature colour determination, including but not limited to
+ * <ul>
+ * <li>gap position</li>
+ * <li>no features present</li>
+ * <li>features present but show features turned off</li>
+ * <li>features displayed but selected feature turned off</li>
+ * <li>features displayed but feature group turned off</li>
+ * <li>feature displayed but none at the specified position</li>
+ * <li>multiple features at position, with no transparency</li>
+ * <li>multiple features at position, with transparency</li>
+ * <li>score graduated feature colour</li>
+ * <li>contact feature start at the selected position</li>
+ * <li>contact feature end at the selected position</li>
+ * <li>contact feature straddling the selected position (not shown)</li>
+ * </ul>
+ */
+public class FeatureColourFinderTest
+{
+ private AlignViewport av;
+
+ private SequenceI seq;
+
+ private FeatureColourFinder finder;
+
+ private AlignFrame af;
+
+ private FeatureRenderer fr;
+
+ @BeforeTest(alwaysRun = true)
+ public void setUp()
+ {
+ // aligned column 8 is sequence position 6
+ String s = ">s1\nABCDE---FGHIJKLMNOPQRSTUVWXYZ\n";
+ af = new FileLoader().LoadFileWaitTillLoaded(s,
+ DataSourceType.PASTE);
+ av = af.getViewport();
+ seq = av.getAlignment().getSequenceAt(0);
+ fr = af.getFeatureRenderer();
+ finder = new FeatureColourFinder(fr);
+ }
+
+ /**
+ * Clear down any sequence features before each test (not as easy as it
+ * sounds...)
+ */
+ @BeforeMethod(alwaysRun = true)
+ public void setUpBeforeTest()
+ {
+ SequenceFeature[] sfs = seq.getSequenceFeatures();
+ if (sfs != null)
+ {
+ for (SequenceFeature sf : sfs)
+ {
+ seq.deleteFeature(sf);
+ }
+ }
+ fr.findAllFeatures(true);
+
+ /*
+ * reset all feature groups to visible
+ */
+ for (String group : fr.getGroups(false))
+ {
+ fr.setGroupVisibility(group, true);
+ }
+
+ fr.clearRenderOrder();
+ av.setShowSequenceFeatures(true);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_noFeatures()
+ {
+ av.setShowSequenceFeatures(false);
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+
+ av.setShowSequenceFeatures(true);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_noFeaturesShown()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(false);
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_singleFeatureAtPosition()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ fr.setColour("Metal", new FeatureColour(Color.red));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_gapPosition()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, 0f,
+ null));
+ fr.setColour("Metal", new FeatureColour(Color.red));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+ Color c = finder.findFeatureColour(null, seq, 6);
+ assertEquals(c, Color.white);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_multipleFeaturesAtPositionNoTransparency()
+ {
+ /*
+ * featuresAdded -> FeatureRendererModel.updateRenderOrder which adds any
+ * new features 'on top' (but reverses the order of any added features)
+ */
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
+ Float.NaN, "DomainGroup"));
+ FeatureColour green = new FeatureColour(Color.green);
+ fr.setColour("Domain", green);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * expect Domain (green) to be rendered above Metal (red)
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.green);
+
+ /*
+ * now promote Metal above Domain
+ * - currently no way other than mimicking reordering of
+ * table in Feature Settings
+ */
+ Object[][] data = new Object[2][];
+ data[0] = new Object[] { "Metal", red, true };
+ data[1] = new Object[] { "Domain", green, true };
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+
+ /*
+ * ..and turn off display of Metal
+ */
+ data[0][2] = false;
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.green);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_singleFeatureNotAtPosition()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 8, 12,
+ Float.NaN, "MetalGroup"));
+ fr.setColour("Metal", new FeatureColour(Color.red));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+ // column 2 = sequence position 3
+ Color c = finder.findFeatureColour(Color.blue, seq, 2);
+ assertEquals(c, Color.blue);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_featureTypeNotDisplayed()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+
+ /*
+ * turn off display of Metal - is this the easiest way to do it??
+ */
+ Object[][] data = new Object[1][];
+ data[0] = new Object[] { "Metal", red, false };
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+
+ /*
+ * turn display of Metal back on
+ */
+ data[0] = new Object[] { "Metal", red, true };
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_featureGroupNotDisplayed()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+
+ /*
+ * turn off display of MetalGroup
+ */
+ fr.setGroupVisibility("MetalGroup", false);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+
+ /*
+ * turn display of MetalGroup back on
+ */
+ fr.setGroupVisibility("MetalGroup", true);
+ c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.red);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_contactFeature()
+ {
+ /*
+ * currently contact feature == type "Disulphide Bond" or "Disulfide Bond" !!
+ */
+ seq.addSequenceFeature(new SequenceFeature("Disulphide Bond",
+ "Contact", 2, 12, Float.NaN, "Disulphide"));
+ fr.setColour("Disulphide Bond", new FeatureColour(Color.red));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * Contact positions are residues 2 and 12
+ * which are columns 1 and 14
+ * positions in between don't count for a contact feature!
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq, 10);
+ assertEquals(c, Color.blue);
+ c = finder.findFeatureColour(Color.blue, seq, 8);
+ assertEquals(c, Color.blue);
+ c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, Color.red);
+ c = finder.findFeatureColour(Color.blue, seq, 14);
+ assertEquals(c, Color.red);
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_graduatedFeatureColour()
+ {
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+ 2, 0f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+ 4, 5f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+ 7, 10f, "KdGroup"));
+
+ /*
+ * graduated colour from 0 to 10
+ */
+ Color min = new Color(100, 50, 150);
+ Color max = new Color(200, 0, 100);
+ FeatureColourI fc = new FeatureColour(min, max, 0, 10);
+ fr.setColour("kd", fc);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * position 2, column 1, score 0 - minimum colour in range
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, min);
+
+ /*
+ * position 7, column 9, score 10 - maximum colour in range
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, max);
+
+ /*
+ * position 4, column 3, score 5 - half way from min to max
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, new Color(150, 25, 125));
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_transparencySingleFeature()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * the FeatureSettings transparency slider has range 0-70 which
+ * corresponds to a transparency value of 1 - 0.3
+ * A value of 0.4 gives a combination of
+ * 0.4 * red(255, 0, 0) + 0.6 * cyan(0, 255, 255) = (102, 153, 153)
+ */
+ fr.setTransparency(0.4f);
+ Color c = finder.findFeatureColour(Color.cyan, seq, 10);
+ assertEquals(c, new Color(102, 153, 153));
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_transparencyTwoFeatures()
+ {
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
+ Float.NaN, "DomainGroup"));
+ FeatureColour green = new FeatureColour(Color.green);
+ fr.setColour("Domain", green);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * Domain (green) rendered above Metal (red) above background (cyan)
+ * 1) 0.6 * red(255, 0, 0) + 0.4 * cyan(0, 255, 255) = (153, 102, 102)
+ * 2) 0.6* green(0, 255, 0) + 0.4 * (153, 102, 102) = (61, 194, 41) rounded
+ */
+ fr.setTransparency(0.6f);
+ Color c = finder.findFeatureColour(Color.cyan, seq, 10);
+ assertEquals(c, new Color(61, 194, 41));
+
+ /*
+ * now promote Metal above Domain
+ * - currently no way other than mimicking reordering of
+ * table in Feature Settings
+ * Metal (red) rendered above Domain (green) above background (cyan)
+ * 1) 0.6 * green(0, 255, 0) + 0.4 * cyan(0, 255, 255) = (0, 255, 102)
+ * 2) 0.6* red(255, 0, 0) + 0.4 * (0, 255, 102) = (153, 102, 41) rounded
+ */
+ Object[][] data = new Object[2][];
+ data[0] = new Object[] { "Metal", red, true };
+ data[1] = new Object[] { "Domain", green, true };
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.cyan, seq, 10);
+ assertEquals(c, new Color(153, 102, 41));
+
+ /*
+ * ..and turn off display of Metal
+ * Domain (green) above background (pink)
+ * 0.6 * green(0, 255, 0) + 0.4 * pink(255, 175, 175) = (102, 223, 70)
+ */
+ data[0][2] = false;
+ fr.setFeaturePriority(data);
+ c = finder.findFeatureColour(Color.pink, seq, 10);
+ assertEquals(c, new Color(102, 223, 70));
+ }
+
+ @Test(groups = "Functional")
+ public void testNoFeaturesDisplayed()
+ {
+ /*
+ * no features on alignment to render
+ */
+ assertTrue(finder.noFeaturesDisplayed());
+
+ /*
+ * add a feature
+ * it will be automatically set visible but we leave
+ * the viewport configured not to show features
+ */
+ av.setShowSequenceFeatures(false);
+ seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
+ Float.NaN, "MetalGroup"));
+ FeatureColour red = new FeatureColour(Color.red);
+ fr.setColour("Metal", red);
+ fr.featuresAdded();
+ assertTrue(finder.noFeaturesDisplayed());
+
+ /*
+ * turn on feature display
+ */
+ av.setShowSequenceFeatures(true);
+ assertFalse(finder.noFeaturesDisplayed());
+
+ /*
+ * turn off display of Metal
+ */
+ Object[][] data = new Object[1][];
+ data[0] = new Object[] { "Metal", red, false };
+ fr.setFeaturePriority(data);
+ assertTrue(finder.noFeaturesDisplayed());
+
+ /*
+ * turn display of Metal back on
+ */
+ fr.setVisible("Metal");
+ assertFalse(finder.noFeaturesDisplayed());
+
+ /*
+ * turn off MetalGroup - has no effect here since the group of a
+ * sequence feature instance is independent of its type
+ */
+ fr.setGroupVisibility("MetalGroup", false);
+ assertFalse(finder.noFeaturesDisplayed());
+
+ /*
+ * a finder with no feature renderer
+ */
+ FeatureColourFinder finder2 = new FeatureColourFinder(null);
+ assertTrue(finder2.noFeaturesDisplayed());
+ }
+}
--- /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);
+ }
+ }
+}
* set and check Taylor colours
*/
af.changeColour_actionPerformed(JalviewColourScheme.Taylor.toString());
- Color taylor1 = sr.getResidueBoxColour(seq, 88); // E 255,0,102
- Color taylor2 = sr.getResidueBoxColour(seq, 89); // A 204,255,0
- Color taylor3 = sr.getResidueBoxColour(seq, 90); // G 255,153,0
+ Color taylor1 = sr.getResidueColour(seq, 88, null); // E 255,0,102
+ Color taylor2 = sr.getResidueColour(seq, 89, null); // A 204,255,0
+ Color taylor3 = sr.getResidueColour(seq, 90, null); // G 255,153,0
assertEquals(taylor1, new Color(255, 0, 102));
assertEquals(taylor2, new Color(204, 255, 0));
assertEquals(taylor3, new Color(255, 153, 0));
* set and check Zappo colours
*/
af.changeColour_actionPerformed(JalviewColourScheme.Zappo.toString());
- Color zappo1 = sr.getResidueBoxColour(seq, 88); // E red
- Color zappo2 = sr.getResidueBoxColour(seq, 89); // A pink
- Color zappo3 = sr.getResidueBoxColour(seq, 90); // G magenta
+ Color zappo1 = sr.getResidueColour(seq, 88, null); // E red
+ Color zappo2 = sr.getResidueColour(seq, 89, null); // A pink
+ Color zappo3 = sr.getResidueColour(seq, 90, null); // G magenta
assertEquals(zappo1, Color.red);
assertEquals(zappo2, Color.pink);
assertEquals(zappo3, Color.magenta);
* set 'stripy' colours - odd columns are Taylor and even are Zappo
*/
af.changeColour_actionPerformed("stripy");
- Color stripy1 = sr.getResidueBoxColour(seq, 88);
- Color stripy2 = sr.getResidueBoxColour(seq, 89);
- Color stripy3 = sr.getResidueBoxColour(seq, 90);
+ Color stripy1 = sr.getResidueColour(seq, 88, null);
+ Color stripy2 = sr.getResidueColour(seq, 89, null);
+ Color stripy3 = sr.getResidueColour(seq, 90, null);
assertEquals(stripy1, zappo1);
assertEquals(stripy2, taylor2);
assertEquals(stripy3, zappo3);
* set and check Clustal colours
*/
af.changeColour_actionPerformed(JalviewColourScheme.Clustal.toString());
- Color clustal1 = sr.getResidueBoxColour(seq, 88);
- Color clustal2 = sr.getResidueBoxColour(seq, 89);
- Color clustal3 = sr.getResidueBoxColour(seq, 90);
+ Color clustal1 = sr.getResidueColour(seq, 88, null);
+ Color clustal2 = sr.getResidueColour(seq, 89, null);
+ Color clustal3 = sr.getResidueColour(seq, 90, null);
assertEquals(clustal1, ClustalColour.MAGENTA.colour);
assertEquals(clustal2, ClustalColour.BLUE.colour);
assertEquals(clustal3, ClustalColour.ORANGE.colour);
* set 'MyClustal' colours - uses AWT colour equivalents
*/
af.changeColour_actionPerformed("MyClustal");
- Color myclustal1 = sr.getResidueBoxColour(seq, 88);
- Color myclustal2 = sr.getResidueBoxColour(seq, 89);
- Color myclustal3 = sr.getResidueBoxColour(seq, 90);
+ Color myclustal1 = sr.getResidueColour(seq, 88, null);
+ Color myclustal2 = sr.getResidueColour(seq, 89, null);
+ Color myclustal3 = sr.getResidueColour(seq, 90, null);
assertEquals(myclustal1, Color.MAGENTA);
assertEquals(myclustal2, Color.BLUE);
assertEquals(myclustal3, Color.ORANGE);
import java.awt.Color;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.List;
import org.testng.annotations.BeforeClass;
}
@Override
- public void superposeStructures(AlignmentI[] als, int[] alm,
+ public String superposeStructures(AlignmentI[] als, int[] alm,
ColumnSelection[] alc)
{
+ return null;
}
@Override
@Override
protected StructureMappingcommandSet[] getColourBySequenceCommands(
- String[] files, SequenceRenderer sr, FeatureRenderer fr,
- AlignmentI alignment)
- {
- return null;
- }
-
- @Override
- public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+ String[] files, SequenceRenderer sr, AlignmentViewPanel avp)
{
return null;
}
public void colourByCharge()
{
}
+
+ @Override
+ public FeatureRenderer getFeatureRenderer(
+ AlignmentViewPanel alignment)
+ {
+ return null;
+ }
};
}
structs[i] = testee.new SuperposeData(al.getWidth());
}
/*
- * initialise array of 'superposable columns' to true (would be false for
+ * initialise BitSet of 'superposable columns' to true (would be false for
* hidden columns)
*/
- boolean[] matched = new boolean[al.getWidth()];
- Arrays.fill(matched, true);
+ BitSet matched = new BitSet();
+ for (int i = 0; i < al.getWidth(); i++)
+ {
+ matched.set(i);
+ }
int refStructure = testee
.findSuperposableResidues(al, matched, structs);
/*
* only ungapped, structure-mapped columns are superposable
*/
- assertFalse(matched[0]); // gap in first sequence
- assertTrue(matched[1]);
- assertFalse(matched[2]); // gap in third sequence
- assertFalse(matched[3]); // gap in fourth sequence
- assertTrue(matched[4]);
- assertTrue(matched[5]); // gap in second sequence
+ assertFalse(matched.get(0)); // gap in first sequence
+ assertTrue(matched.get(1));
+ assertFalse(matched.get(2)); // gap in third sequence
+ assertFalse(matched.get(3)); // gap in fourth sequence
+ assertTrue(matched.get(4));
+ assertTrue(matched.get(5)); // gap in second sequence
assertEquals("1YCS", structs[0].pdbId);
assertEquals("3A6S", structs[1].pdbId);
structs[i] = testee.new SuperposeData(al.getWidth());
}
/*
- * initialise array of 'superposable columns' to true (would be false for
+ * initialise BitSet of 'superposable columns' to true (would be false for
* hidden columns)
*/
- boolean[] matched = new boolean[al.getWidth()];
- Arrays.fill(matched, true);
+ BitSet matched = new BitSet();
+ for (int i = 0; i < al.getWidth(); i++)
+ {
+ matched.set(i);
+ }
+
// treat column 5 of the alignment as hidden
- matched[4] = false;
+ matched.clear(4);
int refStructure = testee
.findSuperposableResidues(al, matched, structs);
assertEquals(0, refStructure);
// only ungapped, structure-mapped columns are not superposable
- assertFalse(matched[0]);
- assertTrue(matched[1]);
- assertFalse(matched[2]);
- assertFalse(matched[3]);
- assertFalse(matched[4]); // superposable, but hidden, column
- assertTrue(matched[5]);
- }
-
- public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
- {
- return null;
- }
-
- public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
- {
- return null;
+ assertFalse(matched.get(0));
+ assertTrue(matched.get(1));
+ assertFalse(matched.get(2));
+ assertFalse(matched.get(3));
+ assertFalse(matched.get(4)); // superposable, but hidden, column
+ assertTrue(matched.get(5));
}
}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+
+import java.util.Hashtable;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+@Test(singleThreaded = true)
+public class OverviewDimensionsTest
+{
+ AlignmentI al;
+ OverviewDimensions od;
+
+ // cached widths and heights
+ int boxWidth;
+ int boxHeight;
+ int viewHeight;
+ int viewWidth;
+ int alheight;
+ int alwidth;
+
+ ViewportRanges vpranges;
+
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
+
+ ColumnSelection hiddenCols = new ColumnSelection();
+
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ al = gen.generate(157, 525, 123, 5, 5);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp()
+ {
+ if (!hiddenRepSequences.isEmpty())
+ {
+ al.getHiddenSequences().showAll(hiddenRepSequences);
+ }
+ hiddenCols.revealAllHiddenColumns();
+
+ vpranges = new ViewportRanges(al);
+ vpranges.setStartRes(0);
+ vpranges.setEndRes(62);
+ vpranges.setStartSeq(0);
+ vpranges.setEndSeq(17);
+
+ viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
+ viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
+
+ ColumnSelection hiddenCols = new ColumnSelection();
+
+ od = new OverviewDimensions(vpranges, true);
+ // Initial box sizing - default path through code
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+
+ mouseClick(od, 0, 0);
+ moveViewport(0, 0);
+
+ // calculate before hidden columns so we get absolute values
+ alheight = vpranges.getAbsoluteAlignmentHeight();
+ alwidth = vpranges.getAbsoluteAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void cleanUp()
+ {
+ al = null;
+ }
+
+ /**
+ * Test that the OverviewDimensions constructor sets width and height
+ * correctly
+ */
+ @Test(groups = { "Functional" })
+ public void testConstructor()
+ {
+ SequenceI seqa = new Sequence("Seq1", "ABC");
+ SequenceI seqb = new Sequence("Seq2", "ABC");
+ SequenceI seqc = new Sequence("Seq3", "ABC");
+ SequenceI seqd = new Sequence("Seq4", "ABC");
+ SequenceI seqe = new Sequence("Seq5",
+ "ABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ int defaultGraphHeight = 20;
+ int maxWidth = 400;
+ int minWidth = 120;
+ int maxSeqHeight = 300;
+ int minSeqHeight = 40;
+
+ // test for alignment with width > height
+ SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
+ Alignment al1 = new Alignment(seqs1);
+ ViewportRanges props = new ViewportRanges(al1);
+
+ OverviewDimensions od = new OverviewDimensions(props, true);
+ int scaledHeight = 267;
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), scaledHeight);
+ assertEquals(od.getWidth(), maxWidth);
+ assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
+
+ // test for alignment with width < height
+ SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
+ Alignment al2 = new Alignment(seqs2);
+ props = new ViewportRanges(al2);
+
+ od = new OverviewDimensions(props, true);
+ int scaledWidth = 300;
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), scaledWidth);
+ assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
+
+ // test for alignment with width > height and sequence height scaled below
+ // min value
+ SequenceI[] seqs3 = new SequenceI[] { seqe };
+ Alignment al3 = new Alignment(seqs3);
+ props = new ViewportRanges(al3);
+
+ od = new OverviewDimensions(props, true);
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), minSeqHeight);
+ assertEquals(od.getWidth(), maxWidth);
+ assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
+
+ // test for alignment with width < height and width scaled below min value
+ SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
+ seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
+ Alignment al4 = new Alignment(seqs4);
+ props = new ViewportRanges(al4);
+
+ od = new OverviewDimensions(props, true);
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), minWidth);
+ assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
+
+ Alignment al5 = new Alignment(seqs4);
+ props = new ViewportRanges(al5);
+
+ od = new OverviewDimensions(props, false);
+ assertEquals(od.getGraphHeight(), 0);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), minWidth);
+ assertEquals(od.getHeight(), maxSeqHeight);
+ }
+
+ /**
+ * Test that validation after mouse adjustments to boxX and boxY sets box
+ * dimensions and scroll values correctly, when there are no hidden rows or
+ * columns.
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromMouseClick()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // negative boxX value reset to 0
+ mouseClick(od, -5, 10);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollRow(),
+ Math.round((float) 10 * alheight / od.getSequencesHeight()));
+ assertEquals(od.getScrollCol(), 0);
+
+ // negative boxY value reset to 0
+ mouseClick(od, 6, -2);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) 6 * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // overly large boxX value reset to width-boxWidth
+ mouseClick(od, 100, 6);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxY(), 6);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // overly large boxY value reset to sequenceHeight - boxHeight
+ mouseClick(od, 10, 520);
+ assertEquals(od.getBoxX(), 10);
+ assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight());
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+
+ // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
+ // and round rounds to 508; however we get 507 working with row values
+ // hence the subtraction of 1
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()) - 1);
+
+ // click past end of alignment, as above
+ mouseClick(od, 3000, 5);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // move viewport so startRes non-zero and then mouseclick
+ moveViewportH(50);
+
+ // click at viewport position
+ int oldboxx = od.getBoxX();
+ int oldboxy = od.getBoxY();
+ mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
+ assertEquals(od.getBoxX(), oldboxx + 5);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getBoxY(), oldboxy + 2);
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // click at top corner
+ mouseClick(od, 0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols at the start
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsAtStart()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide cols at start and check updated box position is correct
+ // changes boxX but not boxwidth
+ int lastHiddenCol = 30;
+ hiddenCols.hideColumns(0, lastHiddenCol);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (lastHiddenCol + 1) * od.getWidth()
+ / alwidth));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // try to click in hidden cols, check box does not move
+ int xpos = 10;
+ mouseClick(od, xpos, 0);
+ assertEquals(
+ od.getBoxX(),
+ Math.round((float) (lastHiddenCol + 1) * od.getWidth()
+ / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(), 0);
+
+ // click to right of hidden columns, box moves to click point
+ testBoxIsAtClickPoint(40, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) 40 * alwidth / od.getWidth())
+ - (lastHiddenCol + 1));
+
+ // click to right of hidden columns such that box runs over right hand side
+ // of alignment
+ // box position is adjusted away from the edge
+ // overly large boxX value reset to width-boxWidth
+ xpos = 100;
+ mouseClick(od, xpos, 5);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxY(), 5);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth())
+ - (lastHiddenCol + 1));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols in the middle
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsInMiddle()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide columns 63-73, no change to box position or dimensions
+ int firstHidden = 63;
+ int lastHidden = 73;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so that it overlaps with hidden cols on one side
+ // box width changes, boxX and scrollCol as for unhidden case
+ int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
+ // between cols 60 and 70
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(), xpos);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(
+ od.getBoxWidth(),
+ Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round(xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so that it completely covers hidden cols
+ // box width changes, boxX and scrollCol as for hidden case
+ xpos = 33;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(), xpos);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(
+ od.getBoxWidth(),
+ Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so boxX is in hidden cols, box overhangs at right
+ // boxX and scrollCol at left of hidden area, box width extends across
+ // hidden region
+ xpos = 50;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(
+ od.getBoxWidth(),
+ boxWidth
+ + Math.round((float) (lastHidden - firstHidden + 1)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(), firstHidden - 1);
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so boxX is to right of hidden cols, but does not go beyond full
+ // width of alignment
+ // box width, boxX and scrollCol all as for non-hidden case
+ xpos = 75;
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round(xpos * alwidth / od.getWidth())
+ - (lastHidden - firstHidden + 1));
+
+ // move box so it goes beyond full width of alignment
+ // boxX, scrollCol adjusted back, box width normal
+ xpos = 3000;
+ mouseClick(od, xpos, 5);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxY(), 5);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round(((float) od.getBoxX() * alwidth / od.getWidth())
+ - (lastHidden - firstHidden + 1)));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols at the end of
+ * the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsAtEnd()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide columns 140-164, no change to box position or dimensions
+ int firstHidden = 140;
+ int lastHidden = 164;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // click to left of hidden cols, without overlapping
+ // boxX, scrollCol and width as normal
+ int xpos = 5;
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+
+ // click to left of hidden cols, with overlap
+ // boxX and scrollCol adjusted for hidden cols, width normal
+ xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
+ - boxWidth + 1);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // click in hidden cols
+ // boxX and scrollCol adjusted for hidden cols, width normal
+ xpos = 115;
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
+ - boxWidth + 1);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // click off end of alignment
+ // boxX and scrollCol adjusted for hidden cols, width normal
+ xpos = 3000;
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
+ - boxWidth + 1);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+ }
+
+ /**
+ * Test that the box position is set correctly when set from the viewport,
+ * with no hidden rows or columns
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewport()
+ {
+ // move viewport to start of alignment
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to right
+ moveViewportH(70);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 70 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport down
+ moveViewportV(100);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 70 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(),
+ Math.round(100 * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to bottom right
+ moveViewport(98, 508);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 98 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(),
+ Math.round((float) 508 * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * at the start
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsAtStart()
+ {
+ int firstHidden = 0;
+ int lastHidden = 20;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport to start of alignment
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment - need to make startRes by removing
+ // hidden cols because of how viewport/overview are implemented
+ moveViewport(98 - lastHidden - 1, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 98 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * in the middle
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsInMiddle()
+ {
+ int firstHidden = 68;
+ int lastHidden = 78;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport before hidden columns
+ moveViewport(3, 0);
+
+ assertEquals(od.getBoxX(),
+ Math.round((float) 3 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ System.out.println(od.getBoxWidth());
+ assertEquals(od.getBoxWidth(), boxWidth);
+ System.out.println(od.getBoxWidth());
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to left of hidden columns with overlap
+ moveViewport(10, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 10 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(
+ od.getBoxWidth(),
+ boxWidth
+ + Math.round((float) (lastHidden - firstHidden + 1)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to straddle hidden columns
+ moveViewport(63, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 63 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(
+ od.getBoxWidth(),
+ boxWidth
+ + Math.round((lastHidden - firstHidden + 1)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to right of hidden columns, no overlap
+ moveViewport(80 - (lastHidden - firstHidden + 1), 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 80 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * at the end
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsAtEnd()
+ {
+ int firstHidden = 152;
+ int lastHidden = 164;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport before hidden columns
+ moveViewport(3, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 3 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to hidden columns
+ // viewport can't actually extend into hidden cols,
+ // so move to the far right edge of the viewport
+ moveViewport(firstHidden - viewWidth, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - viewWidth)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows at
+ * the start
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsAtStart()
+ {
+ int firstHidden = 0;
+ int lastHidden = 20;
+ hideSequences(firstHidden, lastHidden);
+
+ // move viewport to start of alignment:
+ // box moves to below hidden rows, height remains same
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) (lastHidden + 1) * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment
+ moveViewport(0, 525 - viewHeight - lastHidden - 1);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (525 - viewHeight) * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows in
+ * the middle
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsInMiddle()
+ {
+ int firstHidden = 200;
+ int lastHidden = 210;
+ hideSequences(firstHidden, lastHidden);
+
+ // move viewport to start of alignment:
+ // box, height etc as in non-hidden case
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to straddle hidden rows
+ moveViewport(0, 198);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(
+ od.getBoxHeight(),
+ Math.round((float) (viewHeight + lastHidden - firstHidden + 1)
+ * od.getSequencesHeight() / alheight));
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows at
+ * the bottom
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsAtEnd()
+ {
+ int firstHidden = 500;
+ int lastHidden = 524;
+ hideSequences(firstHidden, lastHidden);
+
+ // move viewport to start of alignment:
+ // box, height etc as in non-hidden case
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment
+ // viewport sits above hidden rows and does not include them
+ moveViewport(0, firstHidden - viewHeight - 1);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (firstHidden - viewHeight - 1)
+ * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the start
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsAtStart()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows at start and check updated box position is correct
+ // changes boxY but not boxheight
+ int lastHiddenRow = 30;
+ hideSequences(0, lastHiddenRow);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) (lastHiddenRow + 1)
+ * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click in hidden rows - same result
+ mouseClick(od, 0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (lastHiddenRow + 1)
+ * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click below hidden rows
+ mouseClick(od, 0, 150);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 150);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the middle
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsInMiddle()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows in middle and check updated box position is correct
+ // no changes
+ int firstHiddenRow = 50;
+ int lastHiddenRow = 54;
+ hideSequences(firstHiddenRow, lastHiddenRow);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows, so that box overlaps
+ int ypos = 35; // column value in residues
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(
+ od.getBoxHeight(),
+ boxHeight
+ + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
+ * od.getSequencesHeight() / alheight));
+
+ // click so that box straddles hidden rows
+ ypos = 44; // column value in residues
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(
+ od.getBoxHeight(),
+ boxHeight
+ + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
+ * od.getSequencesHeight() / alheight));
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the end of
+ * the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsAtEnd()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows at end and check updated box position is correct
+ // no changes
+ int firstHidden = 500;
+ int lastHidden = 524;
+ hideSequences(firstHidden, lastHidden);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows
+ int ypos = 40; // row 40
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows so box overlaps
+ // boxY moved upwards, boxHeight remains same
+ ypos = 497; // row 497
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (firstHidden - viewHeight)
+ * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click within hidden rows
+ ypos = 505;
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((firstHidden - viewHeight) * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /*
+ * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
+ */
+ private void moveViewportH(int startRes)
+ {
+ vpranges.setStartRes(startRes);
+ vpranges.setEndRes(startRes + viewWidth - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ }
+
+ /*
+ * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
+ */
+ private void moveViewportV(int startSeq)
+ {
+ vpranges.setStartSeq(startSeq);
+ vpranges.setEndSeq(startSeq + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ }
+
+ /*
+ * Move viewport horizontally and vertically.
+ */
+ private void moveViewport(int startRes, int startSeq)
+ {
+ vpranges.setStartRes(startRes);
+ vpranges.setEndRes(startRes + viewWidth - 1);
+ vpranges.setStartSeq(startSeq);
+ vpranges.setEndSeq(startSeq + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ }
+
+ /*
+ * Mouse click as position x,y in overview window
+ */
+ private void mouseClick(OverviewDimensions od, int x, int y)
+ {
+ od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols,
+ vpranges);
+
+ // updates require an OverviewPanel to exist which it doesn't here
+ // so call setBoxPosition() as it would be called by the AlignmentPanel
+ // normally
+
+ vpranges.setStartRes(od.getScrollCol());
+ vpranges.setEndRes(od.getScrollCol() + viewWidth - 1);
+ vpranges.setStartSeq(od.getScrollRow());
+ vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ }
+
+ /*
+ * Test that the box is positioned with the top left corner at xpos, ypos
+ * and with the original width and height
+ */
+ private void testBoxIsAtClickPoint(int xpos, int ypos)
+ {
+ mouseClick(od, xpos, ypos);
+ assertEquals(od.getBoxX(), xpos);
+ assertEquals(od.getBoxY(), ypos);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /*
+ * Hide sequences between start and end
+ */
+ private void hideSequences(int start, int end)
+ {
+ SequenceI[] allseqs = al.getSequencesArray();
+ SequenceGroup theseSeqs = new SequenceGroup();
+
+ for (int i = start; i <= end; i++)
+ {
+ theseSeqs.addSequence(allseqs[i], false);
+ al.getHiddenSequences().hideSequence(allseqs[i]);
+ }
+
+ hiddenRepSequences.put(allseqs[start], theseSeqs);
+ }
+}
--- /dev/null
+package jalview.viewmodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.datamodel.AlignmentI;
+
+import org.testng.annotations.Test;
+
+public class ViewportRangesTest {
+
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+
+ AlignmentI al = gen.generate(20, 30, 1, 5, 5);
+
+ @Test
+ public void testViewportRanges()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+
+ assertEquals(vr.getStartRes(),0);
+ assertEquals(vr.getEndRes(), al.getWidth()-1);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), al.getHeight() - 1);
+ }
+
+ @Test
+ public void testGetAbsoluteAlignmentHeight()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+
+ assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight());
+
+ al.getHiddenSequences().hideSequence(al.getSequenceAt(3));
+ assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight() + 1);
+ }
+
+ @Test
+ public void testGetAbsoluteAlignmentWidth()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ assertEquals(vr.getAbsoluteAlignmentWidth(), al.getWidth());
+ }
+
+ @Test
+ public void testSetEndRes()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setEndRes(-1);
+ assertEquals(vr.getEndRes(), 0);
+
+ vr.setEndRes(al.getWidth());
+ assertEquals(vr.getEndRes(), al.getWidth() - 1);
+
+ vr.setEndRes(al.getWidth() - 1);
+ assertEquals(vr.getEndRes(), al.getWidth() - 1);
+ }
+
+ @Test
+ public void testSetEndSeq()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setEndSeq(-1);
+ assertEquals(vr.getEndSeq(), 0);
+
+ vr.setEndSeq(al.getHeight());
+ assertEquals(vr.getEndSeq(), al.getHeight() - 1);
+
+ vr.setEndRes(al.getHeight() - 1);
+ assertEquals(vr.getEndSeq(), al.getHeight() - 1);
+ }
+
+ @Test
+ public void testSetStartRes()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setStartRes(-1);
+ assertEquals(vr.getStartRes(), 0);
+
+ vr.setStartRes(al.getWidth());
+ assertEquals(vr.getStartRes(), al.getWidth() - 1);
+
+ vr.setStartRes(al.getWidth() - 1);
+ assertEquals(vr.getStartRes(), al.getWidth() - 1);
+ }
+
+ @Test
+ public void testSetStartSeq()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setStartSeq(-1);
+ assertEquals(vr.getStartSeq(), 0);
+
+ vr.setStartSeq(al.getHeight());
+ assertEquals(vr.getStartSeq(), al.getHeight() - 1);
+
+ vr.setStartSeq(al.getHeight() - 1);
+ assertEquals(vr.getStartSeq(), al.getHeight() - 1);
+ }
+}
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-@Test(groups = { "External" })
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class DisorderAnnotExportImport
{
public static jalview.gui.AlignFrame af = null;
- @BeforeClass(inheritGroups = true)
+ @BeforeClass(alwaysRun = true)
public static void setUpBeforeClass() throws Exception
{
Cache.loadProperties("test/jalview/io/testProps.jvprops");
Cache.initLogger();
disc = JalviewJabawsTestUtils.getJabawsDiscoverer();
+
+ while (disc.isRunning())
+ {
+ // don't get services until discoverer has finished
+ Thread.sleep(100);
+ }
+
iupreds = new ArrayList<Jws2Instance>();
for (Jws2Instance svc : disc.getServices())
{
/**
* test for patches to JAL-1294
*/
- @Test
+ @Test(groups = { "External", "Network" })
public void testDisorderAnnotExport()
{
disorderClient = new AADisorderClient(iupreds.get(0), af, null, null);
import compbio.metadata.Argument;
import compbio.metadata.WrongParameterException;
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class RNAStructExportImport
{
Cache.initLogger();
disc = JalviewJabawsTestUtils.getJabawsDiscoverer(false);
+ while (disc.isRunning())
+ {
+ // don't get services until discoverer has finished
+ Thread.sleep(100);
+ }
+
for (Jws2Instance svc : disc.getServices())
{
}
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRNAAliFoldValidStructure()
{
}
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRNAStructExport()
{
AlignmentI orig_alig = af.getViewport().getAlignment();
- testAnnotationFileIO("Testing RNAalifold Annotation IO", orig_alig);
+ verifyAnnotationFileIO("Testing RNAalifold Annotation IO", orig_alig);
}
- public static void testAnnotationFileIO(String testname, AlignmentI al)
+ static void verifyAnnotationFileIO(String testname, AlignmentI al)
{
try
{
+ "\nCouldn't complete Annotation file roundtrip input/output/input test.");
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRnaalifoldSettingsRecovery()
{
List<Argument> opts = new ArrayList<Argument>();
import compbio.metadata.PresetManager;
import compbio.metadata.WrongParameterException;
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class ParameterUtilsTest
{
|| serviceTests.contains(service.serviceType.toLowerCase());
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testCopyOption()
{
for (Jws2Instance service : disc.getServices())
/**
*/
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testCopyParameter()
{
for (Jws2Instance service : disc.getServices())
*/
package jalview.ws.seqfetcher;
+import static org.testng.Assert.assertTrue;
+
+import jalview.bin.Cache;
import jalview.gui.JvOptionPane;
-import org.testng.AssertJUnit;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testDasRegistryContact()
{
- jalview.bin.Cache.getDasSourceRegistry().refreshSources();
- AssertJUnit
- .assertTrue(
- "Expected to find at least one DAS source at the registry. Check config.",
- jalview.bin.Cache.getDasSourceRegistry().getSources()
- .size() > 0);
+ Cache.getDasSourceRegistry().refreshSources();
+ assertTrue(Cache.getDasSourceRegistry().getSources().isEmpty(),
+ "Expected to find no DAS sources at the registry. Check config.");
}
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import org.testng.Assert;
import org.testng.FileAssert;
"A", testSeq, null);
Assert.assertEquals(testSeq.getStart(), 1);
Assert.assertEquals(testSeq.getEnd(), 147);
- Assert.assertEquals(actualMapping, expectedMapping);
+ // Can't do Assert.assertEquals(actualMapping, expectedMapping);
+ // because this fails in our version of TestNG
+ Assert.assertEquals(actualMapping.size(), expectedMapping.size());
+ Iterator<Map.Entry<Integer, int[]>> it = expectedMapping.entrySet()
+ .iterator();
+ while (it.hasNext())
+ {
+ Map.Entry<Integer, int[]> pair = it.next();
+ Assert.assertTrue(actualMapping.containsKey(pair.getKey()));
+ Assert.assertEquals(actualMapping.get(pair.getKey()),
+ pair.getValue());
+ }
+
} catch (Exception e)
{
e.printStackTrace();
Assert.assertEquals(strucMapping.getMappingDetailsOutput(),
expectedMappingOutput);
- Assert.assertEquals(strucMapping.getMapping(), expectedMapping);
+
+ // Can't do Assert.assertEquals(strucMapping.getMapping(), expectedMapping);
+ // because this fails in our version of TestNG
+ Assert.assertEquals(strucMapping.getMapping().size(),
+ expectedMapping.size());
+ Iterator<Map.Entry<Integer, int[]>> it = expectedMapping.entrySet()
+ .iterator();
+ while (it.hasNext())
+ {
+ Map.Entry<Integer, int[]> pair = it.next();
+ Assert.assertTrue(strucMapping.getMapping()
+ .containsKey(pair.getKey()));
+ Assert.assertEquals(strucMapping.getMapping().get(pair.getKey()),
+ pair.getValue());
+ }
}
@Test(groups = { "Network" })
--- /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;
+ }
+ }
+
+}