From: gmungoc Date: Wed, 24 Feb 2016 16:51:31 +0000 (+0000) Subject: JAL-2015 JAL-1956 rollout of FeatureColourI in place of X-Git-Tag: Release_2_10_0~161^2~1^2~2 X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=commitdiff_plain;h=refs%2Fheads%2FJAL-1956_featureStyles JAL-2015 JAL-1956 rollout of FeatureColourI in place of Color/GraduatedColour --- diff --git a/src/jalview/api/FeatureColourI.java b/src/jalview/api/FeatureColourI.java index d8363f4..0a333ca 100644 --- a/src/jalview/api/FeatureColourI.java +++ b/src/jalview/api/FeatureColourI.java @@ -1,18 +1,21 @@ package jalview.api; +import jalview.datamodel.SequenceFeature; + import java.awt.Color; public interface FeatureColourI { /** - * Answers true when either isColourByLabel, isAboveThreshold or - * isBelowThreshold answers true + * Answers true when the feature colour varies across the score range * * @return */ boolean isGraduatedColour(); + void setGraduatedColour(boolean b); + /** * Returns the feature colour (when isGraduatedColour answers false) * @@ -35,13 +38,22 @@ public interface FeatureColourI Color getMaxColour(); /** - * Answers true if the feature is coloured by label (description); only - * applicable when isGraduatedColour answers true + * Answers true if the feature has a single colour, i.e. if isColourByLabel() + * and isGraduatedColour() both answer false + * + * @return + */ + boolean isSimpleColour(); + + /** + * Answers true if the feature is coloured by label (description) * * @return */ boolean isColourByLabel(); + void setColourByLabel(boolean b); + /** * Answers true if the feature is coloured below a threshold value; only * applicable when isGraduatedColour answers true @@ -50,6 +62,8 @@ public interface FeatureColourI */ boolean isBelowThreshold(); + void setBelowThreshold(boolean b); + /** * Answers true if the feature is coloured above a threshold value; only * applicable when isGraduatedColour answers true @@ -58,14 +72,20 @@ public interface FeatureColourI */ boolean isAboveThreshold(); + void setAboveThreshold(boolean b); + /** - * Answers true if the threshold is the min (or max) of the colour range; only - * applicable when isGraduatedColour answers true + * Answers true if the threshold is the minimum value (when + * isAboveThreshold()) or maximum value (when isBelowThreshold()) of the + * colour range; only applicable when isGraduatedColour and either + * isAboveThreshold() or isBelowThreshold() answers true * * @return */ boolean isThresholdMinMax(); + void setThresholdMinMax(boolean b); + /** * Returns the threshold value (if any), else zero * @@ -73,10 +93,57 @@ public interface FeatureColourI */ float getThreshold(); + void setThreshold(float f); + + boolean isAutoScaled(); + + void setAutoScaled(boolean b); + + /** + * Returns the maximum score of the graduated colour range + * + * @return + */ + float getMax(); + + /** + * Returns the minimum score of the graduated colour range + * + * @return + */ + float getMin(); + + /** + * Answers true if either isAboveThreshold or isBelowThreshold answers true + * + * @return + */ + boolean hasThreshold(); + + /** + * Returns the computed colour for the given sequence feature + * + * @param feature + * @return + */ + Color getColor(SequenceFeature feature); + /** - * Answers true if ? + * Answers true if the feature has a simple colour, or is coloured by label, + * or has a graduated colour and the score of this feature instance is within + * the range to render (if any), i.e. does not lie below or above any + * threshold set. * + * @param feature * @return */ - boolean isLowToHigh(); + boolean isColored(SequenceFeature feature); + + /** + * Update the min-max range for a graduated colour scheme + * + * @param min + * @param max + */ + void updateBounds(float min, float max); } diff --git a/src/jalview/api/FeatureRenderer.java b/src/jalview/api/FeatureRenderer.java index 0d0adaa..21319fd 100644 --- a/src/jalview/api/FeatureRenderer.java +++ b/src/jalview/api/FeatureRenderer.java @@ -60,17 +60,15 @@ public interface FeatureRenderer * @param ft * @return display style for a feature */ - Object getFeatureStyle(String ft); + FeatureColourI getFeatureStyle(String ft); /** * update the feature style for a particular feature * * @param ft * @param ggc - * - currently allows java.awt.Color and - * jalview.schemes.GraduatedColor */ - void setColour(String ft, Object ggc); + void setColour(String ft, FeatureColourI ggc); AlignViewportI getViewport(); @@ -85,7 +83,7 @@ public interface FeatureRenderer * * @return */ - Map getFeatureColours(); + Map getFeatureColours(); /** * query the alignment view to find all features @@ -100,7 +98,7 @@ public interface FeatureRenderer * * @return */ - Map getDisplayedFeatureCols(); + Map getDisplayedFeatureCols(); /** * get all registered groups diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index b7e7899..40fbd6d 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -25,6 +25,7 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; import jalview.api.AlignViewportI; +import jalview.api.FeatureColourI; import jalview.api.FeatureRenderer; import jalview.api.FeatureSettingsControllerI; import jalview.api.SequenceStructureBinding; @@ -1406,7 +1407,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, return annotation; } - private Map getDisplayedFeatureCols() + private Map getDisplayedFeatureCols() { if (alignPanel.getFeatureRenderer() != null && viewport.getFeaturesDisplayed() != null) diff --git a/src/jalview/appletgui/FeatureColourChooser.java b/src/jalview/appletgui/FeatureColourChooser.java index 46a67c4..3c04ccd 100644 --- a/src/jalview/appletgui/FeatureColourChooser.java +++ b/src/jalview/appletgui/FeatureColourChooser.java @@ -20,9 +20,10 @@ */ package jalview.appletgui; +import jalview.api.FeatureColourI; import jalview.datamodel.GraphLine; import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.util.MessageManager; import java.awt.Checkbox; @@ -60,9 +61,9 @@ public class FeatureColourChooser extends Panel implements ActionListener, // AlignmentPanel ap; - GraduatedColor cs; + FeatureColourI cs; - Object oldcs; + FeatureColourI oldcs; Hashtable oldgroupColours; @@ -91,29 +92,29 @@ public class FeatureColourChooser extends Panel implements ActionListener, { this.type = type; fr = frenderer; - float mm[] = ((float[][]) fr.getMinMax().get(type))[0]; + float mm[] = fr.getMinMax().get(type)[0]; min = mm[0]; max = mm[1]; oldcs = fr.getFeatureColours().get(type); - if (oldcs instanceof GraduatedColor) + if (oldcs.isGraduatedColour()) { - cs = new GraduatedColor((GraduatedColor) oldcs, min, max); + cs = new FeatureColour((FeatureColour) oldcs, min, max); } else { // promote original color to a graduated color Color bl = Color.black; - if (oldcs instanceof Color) + if (oldcs.isSimpleColour()) { - bl = (Color) oldcs; + bl = oldcs.getColour(); } // original colour becomes the maximum colour - cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]); + cs = new FeatureColour(Color.white, bl, mm[0], mm[1]); } - minColour.setBackground(cs.getMinColor()); - maxColour.setBackground(cs.getMaxColor()); - minColour.setForeground(cs.getMinColor()); - maxColour.setForeground(cs.getMaxColor()); + minColour.setBackground(cs.getMinColour()); + maxColour.setBackground(cs.getMaxColour()); + minColour.setForeground(cs.getMinColour()); + maxColour.setForeground(cs.getMaxColour()); colourFromLabel.setState(cs.isColourByLabel()); adjusting = true; @@ -123,10 +124,8 @@ public class FeatureColourChooser extends Panel implements ActionListener, } catch (Exception ex) { } - threshold - .select(cs.getThreshType() == AnnotationColourGradient.NO_THRESHOLD ? 0 - : cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1 - : 2); + threshold.select(cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2 + : 0)); adjusting = false; changeColour(); @@ -259,6 +258,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, private GraphLine threshline; + @Override public void actionPerformed(ActionEvent evt) { if (evt.getSource() == thresholdValue) @@ -286,6 +286,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, } } + @Override public void itemStateChanged(ItemEvent evt) { maxColour.setEnabled(!colourFromLabel.getState()); @@ -293,19 +294,20 @@ public class FeatureColourChooser extends Panel implements ActionListener, changeColour(); } + @Override public void adjustmentValueChanged(AdjustmentEvent evt) { if (!adjusting) { - thresholdValue.setText(((float) slider.getValue() / 1000f) + ""); + thresholdValue.setText((slider.getValue() / 1000f) + ""); valueChanged(); } } protected void valueChanged() { - threshline.value = (float) slider.getValue() / 1000f; - cs.setThresh(threshline.value); + threshline.value = slider.getValue() / 1000f; + cs.setThreshold(threshline.value); changeColour(); PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); // ap.paintAlignment(false); @@ -369,7 +371,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, slider.setEnabled(true); thresholdValue.setEnabled(true); - GraduatedColor acg = new GraduatedColor(minColour.getBackground(), + FeatureColour acg = new FeatureColour(minColour.getBackground(), maxColour.getBackground(), min, max); acg.setColourByLabel(colourFromLabel.getState()); @@ -393,7 +395,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD) { adjusting = true; - acg.setThresh(threshline.value); + acg.setThreshold(threshline.value); float range = max * 1000f - min * 1000f; @@ -406,17 +408,17 @@ public class FeatureColourChooser extends Panel implements ActionListener, adjusting = false; } - acg.setThreshType(aboveThreshold); + acg.setAboveThreshold(true); if (thresholdIsMin.getState() && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD) { if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD) { - acg = new GraduatedColor(acg, threshline.value, max); + acg = new FeatureColour(acg, threshline.value, max); } else { - acg = new GraduatedColor(acg, min, threshline.value); + acg = new FeatureColour(acg, min, threshline.value); } } @@ -434,14 +436,17 @@ public class FeatureColourChooser extends Panel implements ActionListener, } + @Override public void mouseClicked(MouseEvent evt) { } + @Override public void mousePressed(MouseEvent evt) { } + @Override public void mouseReleased(MouseEvent evt) { if (evt.getSource() == minColour || evt.getSource() == maxColour) @@ -456,10 +461,12 @@ public class FeatureColourChooser extends Panel implements ActionListener, // ap.paintAlignment(true); } + @Override public void mouseEntered(MouseEvent evt) { } + @Override public void mouseExited(MouseEvent evt) { } diff --git a/src/jalview/appletgui/FeatureRenderer.java b/src/jalview/appletgui/FeatureRenderer.java index 4655ba5..b90b8d3 100644 --- a/src/jalview/appletgui/FeatureRenderer.java +++ b/src/jalview/appletgui/FeatureRenderer.java @@ -20,11 +20,13 @@ */ package jalview.appletgui; +import jalview.api.FeatureColourI; import jalview.datamodel.SearchResults; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; +import jalview.io.FeaturesFile; +import jalview.schemes.FeatureColour; +import jalview.schemes.UserColourScheme; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; @@ -43,6 +45,8 @@ import java.awt.TextArea; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.Hashtable; /** @@ -63,7 +67,6 @@ public class FeatureRenderer extends * Creates a new FeatureRenderer object. * * @param av - * DOCUMENT ME! */ public FeatureRenderer(AlignmentViewport av) { @@ -97,51 +100,35 @@ public class FeatureRenderer extends /** * render a feature style in the amend feature dialog box */ - public void updateColor(Object newcol) + public void updateColor(FeatureColourI newcol) { - - Color bg, col = null; - GraduatedColor gcol = null; + Color bg = null; String vlabel = ""; - if (newcol instanceof Color) - { - isGcol = false; - col = (Color) newcol; - gcol = null; - } - else if (newcol instanceof GraduatedColor) + if (newcol.isSimpleColour()) { - isGcol = true; - gcol = (GraduatedColor) newcol; - col = null; + bg = newcol.getColour(); + setBackground(bg); } else { - throw new Error( - MessageManager - .getString("error.invalid_colour_for_mycheckbox")); - } - if (col != null) - { - setBackground(bg = col); - } - else - { - if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD) + if (newcol.isAboveThreshold()) + { + vlabel += " (>)"; + } + else if (newcol.isBelowThreshold()) { - vlabel += " " - + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)" - : "(<)"); + vlabel += " (<)"; } - if (isColourByLabel = gcol.isColourByLabel()) + + if (isColourByLabel = newcol.isColourByLabel()) { setBackground(bg = Color.white); vlabel += " (by Label)"; } else { - setBackground(bg = gcol.getMinColor()); - maxCol = gcol.getMaxColor(); + setBackground(bg = newcol.getMinColour()); + maxCol = newcol.getMaxColour(); } } label = vlabel; @@ -154,6 +141,7 @@ public class FeatureRenderer extends super(null); } + @Override public void paint(Graphics g) { Dimension d = getSize(); @@ -227,6 +215,7 @@ public class FeatureRenderer extends overlaps.addItemListener(new java.awt.event.ItemListener() { + @Override public void itemStateChanged(java.awt.event.ItemEvent e) { int index = overlaps.getSelectedIndex(); @@ -246,11 +235,12 @@ public class FeatureRenderer extends ap.seqPanel.seqCanvas.highlightSearchResults(highlight); } - Object col = getFeatureStyle(name.getText()); + FeatureColourI col = getFeatureStyle(name.getText()); if (col == null) { - col = new jalview.schemes.UserColourScheme() + Color generatedColour = UserColourScheme .createColourFromName(name.getText()); + col = new FeatureColour(generatedColour); } colourPanel.updateColor(col); @@ -344,6 +334,7 @@ public class FeatureRenderer extends dialog.buttonPanel.add(deleteButton, 1); deleteButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent evt) { deleteFeature = true; @@ -357,20 +348,16 @@ public class FeatureRenderer extends start.setText(features[0].getBegin() + ""); end.setText(features[0].getEnd() + ""); description.setText(features[0].getDescription()); - Color col = getColour(name.getText()); - if (col == null) - { - col = new jalview.schemes.UserColourScheme() - .createColourFromName(name.getText()); - } - Object fcol = getFeatureStyle(name.getText()); + // lookup (or generate) the feature colour + FeatureColourI fcol = getFeatureStyle(name.getText()); // simply display the feature color in a box colourPanel.updateColor(fcol); dialog.setResizable(true); // TODO: render the graduated color in the box. - colourPanel.addMouseListener(new java.awt.event.MouseAdapter() + colourPanel.addMouseListener(new MouseAdapter() { - public void mousePressed(java.awt.event.MouseEvent evt) + @Override + public void mousePressed(MouseEvent evt) { if (!colourPanel.isGcol) { @@ -378,15 +365,14 @@ public class FeatureRenderer extends } else { - FeatureColourChooser fcc = new FeatureColourChooser( - ap.alignFrame, name.getText()); + new FeatureColourChooser(ap.alignFrame, name.getText()); dialog.transferFocus(); } } }); dialog.setVisible(true); - jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile(); + FeaturesFile ffile = new FeaturesFile(); if (dialog.accept) { @@ -415,7 +401,7 @@ public class FeatureRenderer extends if (!colourPanel.isGcol) { // update colour - otherwise its already done. - setColour(sf.type, colourPanel.getBackground()); + setColour(sf.type, new FeatureColour(colourPanel.getBackground())); } try { @@ -455,7 +441,7 @@ public class FeatureRenderer extends { setGroupVisibility(lastFeatureGroupAdded, true); } - setColour(lastFeatureAdded, newColour); // was fcol + setColour(lastFeatureAdded, new FeatureColour(newColour)); // was fcol setVisible(lastFeatureAdded); findAllFeatures(false); // different to original applet behaviour ? // findAllFeatures(); diff --git a/src/jalview/appletgui/FeatureSettings.java b/src/jalview/appletgui/FeatureSettings.java index 1c156dc..203605b 100755 --- a/src/jalview/appletgui/FeatureSettings.java +++ b/src/jalview/appletgui/FeatureSettings.java @@ -20,11 +20,10 @@ */ package jalview.appletgui; +import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; import jalview.util.MessageManager; import java.awt.BorderLayout; @@ -58,8 +57,8 @@ import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Enumeration; -import java.util.Hashtable; import java.util.List; +import java.util.Map; import java.util.Vector; public class FeatureSettings extends Panel implements ItemListener, @@ -165,6 +164,7 @@ public class FeatureSettings extends Panel implements ItemListener, final FeatureSettings me = this; frame.addWindowListener(new WindowAdapter() { + @Override public void windowClosing(WindowEvent e) { if (me.av.featureSettings == me) @@ -185,6 +185,7 @@ public class FeatureSettings extends Panel implements ItemListener, width, height); } + @Override public void paint(Graphics g) { g.setColor(Color.black); @@ -198,20 +199,22 @@ public class FeatureSettings extends Panel implements ItemListener, 60); } - protected void popupSort(final MyCheckbox check, final Hashtable minmax, + protected void popupSort(final MyCheckbox check, + final Map minmax, int x, int y) { final String type = check.type; - final Object typeCol = fr.getFeatureStyle(type); - java.awt.PopupMenu men = new PopupMenu(MessageManager.formatMessage( + final FeatureColourI typeCol = fr.getFeatureStyle(type); + PopupMenu men = new PopupMenu(MessageManager.formatMessage( "label.settings_for_type", new String[] { type })); - java.awt.MenuItem scr = new MenuItem( + MenuItem scr = new MenuItem( MessageManager.getString("label.sort_by_score")); men.add(scr); final FeatureSettings me = this; scr.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { me.ap.alignFrame.avc @@ -224,6 +227,7 @@ public class FeatureSettings extends Panel implements ItemListener, dens.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { me.ap.alignFrame.avc @@ -234,7 +238,7 @@ public class FeatureSettings extends Panel implements ItemListener, men.add(dens); if (minmax != null) { - final Object typeMinMax = minmax.get(type); + final float[][] typeMinMax = minmax.get(type); /* * final java.awt.CheckboxMenuItem chb = new * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the @@ -247,20 +251,21 @@ public class FeatureSettings extends Panel implements ItemListener, * * }); men.add(chb); */ - if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null) + if (typeMinMax != null && typeMinMax[0] != null) { // graduated colourschemes for those where minmax exists for the // positional features MenuItem mxcol = new MenuItem( - (typeCol instanceof Color) ? "Graduated Colour" + (typeCol.isSimpleColour()) ? "Graduated Colour" : "Single Colour"); men.add(mxcol); mxcol.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - if (typeCol instanceof Color) + if (typeCol.isSimpleColour()) { new FeatureColourChooser(me, type); // write back the current colour object to update the table @@ -268,8 +273,7 @@ public class FeatureSettings extends Panel implements ItemListener, } else { - new UserDefinedColours(me, check.type, - ((GraduatedColor) typeCol)); + new UserDefinedColours(me, check.type, typeCol); } } @@ -334,7 +338,7 @@ public class FeatureSettings extends Panel implements ItemListener, { SequenceFeature[] tmpfeatures; String group = null, type; - Vector visibleChecks = new Vector(); + Vector visibleChecks = new Vector(); AlignmentI alignment = av.getAlignment(); for (int i = 0; i < alignment.getHeight(); i++) { @@ -400,7 +404,7 @@ public class FeatureSettings extends Panel implements ItemListener, // now add checkboxes which should be visible, // if they have not already been added - Enumeration en = visibleChecks.elements(); + Enumeration en = visibleChecks.elements(); while (en.hasMoreElements()) { @@ -474,6 +478,7 @@ public class FeatureSettings extends Panel implements ItemListener, } } + @Override public void actionPerformed(ActionEvent evt) { for (int i = 0; i < featurePanel.getComponentCount(); i++) @@ -486,6 +491,7 @@ public class FeatureSettings extends Panel implements ItemListener, private ItemListener groupItemListener = new ItemListener() { + @Override public void itemStateChanged(ItemEvent evt) { Checkbox source = (Checkbox) evt.getSource(); @@ -500,6 +506,7 @@ public class FeatureSettings extends Panel implements ItemListener, }; }; + @Override public void itemStateChanged(ItemEvent evt) { selectionChanged(); @@ -533,6 +540,7 @@ public class FeatureSettings extends Panel implements ItemListener, boolean dragging = false; + @Override public void mousePressed(MouseEvent evt) { @@ -549,6 +557,7 @@ public class FeatureSettings extends Panel implements ItemListener, } + @Override public void mouseDragged(MouseEvent evt) { if (((Component) evt.getSource()).getParent() != featurePanel) @@ -558,6 +567,7 @@ public class FeatureSettings extends Panel implements ItemListener, dragging = true; } + @Override public void mouseReleased(MouseEvent evt) { if (((Component) evt.getSource()).getParent() != featurePanel) @@ -610,19 +620,9 @@ public class FeatureSettings extends Panel implements ItemListener, } } - public void setUserColour(String feature, Object originalColour) + public void setUserColour(String feature, FeatureColourI originalColour) { - if (originalColour instanceof Color - || originalColour instanceof GraduatedColor) - { - fr.setColour(feature, originalColour); - } - else - { - throw new Error( - MessageManager - .getString("error.implementation_error_unsupported_feature_colour_object")); - } + fr.setColour(feature, originalColour); refreshTable(); } @@ -633,14 +633,17 @@ public class FeatureSettings extends Panel implements ItemListener, ap.paintAlignment(true); } + @Override public void mouseEntered(MouseEvent evt) { } + @Override public void mouseExited(MouseEvent evt) { } + @Override public void mouseClicked(MouseEvent evt) { MyCheckbox check = (MyCheckbox) evt.getSource(); @@ -666,10 +669,10 @@ public class FeatureSettings extends Panel implements ItemListener, if (evt.getClickCount() > 1) { - Object fcol = fr.getFeatureStyle(check.type); - if (fcol instanceof Color) + FeatureColourI fcol = fr.getFeatureStyle(check.type); + if (fcol.isSimpleColour()) { - new UserDefinedColours(this, check.type, (Color) fcol); + new UserDefinedColours(this, check.type, fcol.getColour()); } else { @@ -680,10 +683,12 @@ public class FeatureSettings extends Panel implements ItemListener, } } + @Override public void mouseMoved(MouseEvent evt) { } + @Override public void adjustmentValueChanged(AdjustmentEvent evt) { fr.setTransparency((100 - transparency.getValue()) / 100f); @@ -699,49 +704,34 @@ public class FeatureSettings extends Panel implements ItemListener, boolean hasLink; - GraduatedColor gcol; - - Color col; + FeatureColourI col; - public void updateColor(Object newcol) + public void updateColor(FeatureColourI newcol) { - if (newcol instanceof Color) + col = newcol; + if (col.isSimpleColour()) { - col = (Color) newcol; - gcol = null; - } - else if (newcol instanceof GraduatedColor) - { - gcol = (GraduatedColor) newcol; - col = null; - } - else - { - throw new Error( - MessageManager - .getString("error.invalid_colour_for_mycheckbox")); - } - if (col != null) - { - setBackground(col); + setBackground(col.getColour()); } else { String vlabel = type; - if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD) + if (col.isAboveThreshold()) + { + vlabel += " (>)"; + } + else if (col.isBelowThreshold()) { - vlabel += " " - + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)" - : "(<)"); + vlabel += " (<)"; } - if (gcol.isColourByLabel()) + if (col.isColourByLabel()) { setBackground(Color.white); vlabel += " (by Label)"; } else { - setBackground(gcol.getMinColor()); + setBackground(col.getMinColour()); } this.setLabel(vlabel); } @@ -758,40 +748,38 @@ public class FeatureSettings extends Panel implements ItemListener, } public MyCheckbox(String type, boolean selected, boolean b, - Object featureStyle) + FeatureColourI featureStyle) { this(type, selected, b); updateColor(featureStyle); } + @Override public void paint(Graphics g) { Dimension d = getSize(); - if (gcol != null) + if (col.isColourByLabel()) { - if (gcol.isColourByLabel()) - { - g.setColor(Color.white); - g.fillRect(d.width / 2, 0, d.width / 2, d.height); - /* - * g.setColor(Color.black); Font f=g.getFont().deriveFont(9); - * g.setFont(f); - * - * // g.setFont(g.getFont().deriveFont( // - * AffineTransform.getScaleInstance( // - * width/g.getFontMetrics().stringWidth("Label"), // - * height/g.getFontMetrics().getHeight()))); g.drawString("Label", - * width/2, 0); - */ + g.setColor(Color.white); + g.fillRect(d.width / 2, 0, d.width / 2, d.height); + /* + * g.setColor(Color.black); Font f=g.getFont().deriveFont(9); + * g.setFont(f); + * + * // g.setFont(g.getFont().deriveFont( // + * AffineTransform.getScaleInstance( // + * width/g.getFontMetrics().stringWidth("Label"), // + * height/g.getFontMetrics().getHeight()))); g.drawString("Label", + * width/2, 0); + */ - } - else - { - Color maxCol = gcol.getMaxColor(); - g.setColor(maxCol); - g.fillRect(d.width / 2, 0, d.width / 2, d.height); + } + else if (col.isGraduatedColour()) + { + Color maxCol = col.getMaxColour(); + g.setColor(maxCol); + g.fillRect(d.width / 2, 0, d.width / 2, d.height); - } } if (hasLink) diff --git a/src/jalview/appletgui/UserDefinedColours.java b/src/jalview/appletgui/UserDefinedColours.java index 57cf669..88098a9 100644 --- a/src/jalview/appletgui/UserDefinedColours.java +++ b/src/jalview/appletgui/UserDefinedColours.java @@ -20,9 +20,10 @@ */ package jalview.appletgui; +import jalview.api.FeatureColourI; import jalview.datamodel.SequenceGroup; import jalview.schemes.ColourSchemeI; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.schemes.ResidueProperties; import jalview.schemes.UserColourScheme; import jalview.util.MessageManager; @@ -59,7 +60,7 @@ public class UserDefinedColours extends Panel implements ActionListener, Button selectedButton; - Vector oldColours = new Vector(); + Vector oldColours = new Vector(); ColourSchemeI oldColourScheme; @@ -75,7 +76,7 @@ public class UserDefinedColours extends Panel implements ActionListener, String originalLabel; - Object originalColour; + FeatureColourI originalColour; int R = 0, G = 0, B = 0; @@ -117,7 +118,7 @@ public class UserDefinedColours extends Panel implements ActionListener, public UserDefinedColours(FeatureRenderer fr, Frame alignframe) { caller = fr; - originalColour = fr.colourPanel.getBackground(); + originalColour = new FeatureColour(fr.colourPanel.getBackground()); originalLabel = "Feature Colour"; setForDialog("Select Feature Colour", alignframe); setTargetColour(fr.colourPanel.getBackground()); @@ -134,21 +135,21 @@ public class UserDefinedColours extends Panel implements ActionListener, * * @param caller * - handles events - * @param col1 + * @param col * - original colour * @param alignframe * - the parent Frame for the dialog * @param title * - window title */ - public UserDefinedColours(Component caller, Color col1, Frame alignframe, + public UserDefinedColours(Component caller, Color col, Frame alignframe, String title) { this.caller = caller; - originalColour = col1; + originalColour = new FeatureColour(col); originalLabel = title; setForDialog(title, alignframe); - setTargetColour(col1); + setTargetColour(col); dialog.setVisible(true); } @@ -161,7 +162,7 @@ public class UserDefinedColours extends Panel implements ActionListener, */ public UserDefinedColours(Object caller, String label, Color colour) { - this(caller, label, colour, colour); + this(caller, label, new FeatureColour(colour), colour); } /** @@ -172,13 +173,13 @@ public class UserDefinedColours extends Panel implements ActionListener, * @param graduatedColor */ public UserDefinedColours(FeatureSettings me, String type, - GraduatedColor graduatedColor) + FeatureColourI graduatedColor) { - this(me, type, graduatedColor, graduatedColor.getMaxColor()); + this(me, type, graduatedColor, graduatedColor.getMaxColour()); } - private UserDefinedColours(Object caller, String label, Object ocolour, - Color colour) + private UserDefinedColours(Object caller, String label, + FeatureColourI ocolour, Color colour) { this.caller = caller; originalColour = ocolour; @@ -228,6 +229,7 @@ public class UserDefinedColours extends Panel implements ActionListener, } + @Override public void actionPerformed(ActionEvent evt) { final Object source = evt.getSource(); @@ -257,6 +259,7 @@ public class UserDefinedColours extends Panel implements ActionListener, } } + @Override public void adjustmentValueChanged(AdjustmentEvent evt) { if (evt.getSource() == rScroller) @@ -420,6 +423,7 @@ public class UserDefinedColours extends Panel implements ActionListener, button.setFont(new java.awt.Font("Verdana", 1, 10)); button.addMouseListener(new java.awt.event.MouseAdapter() { + @Override public void mousePressed(MouseEvent e) { colourButtonPressed(e); @@ -451,7 +455,8 @@ public class UserDefinedColours extends Panel implements ActionListener, { if (caller instanceof FeatureSettings) { - ((FeatureSettings) caller).setUserColour(originalLabel, getColor()); + ((FeatureSettings) caller).setUserColour(originalLabel, + new FeatureColour(getColor())); } else if (caller instanceof AnnotationColourChooser) { @@ -468,7 +473,8 @@ public class UserDefinedColours extends Panel implements ActionListener, } else if (caller instanceof FeatureRenderer) { - ((FeatureRenderer) caller).colourPanel.updateColor(getColor()); + ((FeatureRenderer) caller).colourPanel + .updateColor(new FeatureColour(getColor())); } else if (caller instanceof FeatureColourChooser) { @@ -537,12 +543,12 @@ public class UserDefinedColours extends Panel implements ActionListener, if (originalLabel.equals("Min Colour")) { ((AnnotationColourChooser) caller) - .minColour_actionPerformed((Color) originalColour); + .minColour_actionPerformed(originalColour.getColour()); } else { ((AnnotationColourChooser) caller) - .maxColour_actionPerformed((Color) originalColour); + .maxColour_actionPerformed(originalColour.getColour()); } } else if (caller instanceof FeatureRenderer) @@ -556,12 +562,12 @@ public class UserDefinedColours extends Panel implements ActionListener, if (originalLabel.indexOf("inimum") > -1) { ((FeatureColourChooser) caller) - .minColour_actionPerformed((Color) originalColour); + .minColour_actionPerformed(originalColour.getColour()); } else { ((FeatureColourChooser) caller) - .maxColour_actionPerformed((Color) originalColour); + .maxColour_actionPerformed(originalColour.getColour()); } } if (dialog != null) @@ -576,7 +582,7 @@ public class UserDefinedColours extends Panel implements ActionListener, Color[] newColours = new Color[24]; for (int i = 0; i < 24; i++) { - newColours[i] = (Color) oldColours.elementAt(i); + newColours[i] = oldColours.elementAt(i); buttonPanel.getComponent(i).setBackground(newColours[i]); } diff --git a/src/jalview/gui/AnnotationExporter.java b/src/jalview/gui/AnnotationExporter.java index 643d8a0..383dd1b 100644 --- a/src/jalview/gui/AnnotationExporter.java +++ b/src/jalview/gui/AnnotationExporter.java @@ -20,6 +20,7 @@ */ package jalview.gui; +import jalview.api.FeatureColourI; import jalview.datamodel.AlignmentAnnotation; import jalview.io.AnnotationFile; import jalview.io.FeaturesFile; @@ -32,6 +33,7 @@ import java.awt.Color; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Map; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; @@ -153,17 +155,17 @@ public class AnnotationExporter extends JPanel .getString("label.no_features_on_alignment"); if (features) { + Map displayedFeatureColours = ap + .getFeatureRenderer().getDisplayedFeatureCols(); if (GFFFormat.isSelected()) { text = new FeaturesFile().printGFFFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), ap.getFeatureRenderer() - .getDisplayedFeatureCols(), true, ap.av.isShowNPFeats());// ap.av.featuresDisplayed//); + .getDataset().getSequencesArray(), displayedFeatureColours, true, ap.av.isShowNPFeats());// ap.av.featuresDisplayed//); } else { text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), ap.getFeatureRenderer() - .getDisplayedFeatureCols(), true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed); + .getDataset().getSequencesArray(), displayedFeatureColours, true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed); } } else @@ -236,6 +238,7 @@ public class AnnotationExporter extends JPanel toFile.setText(MessageManager.getString("label.to_file")); toFile.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { toFile_actionPerformed(e); @@ -244,6 +247,7 @@ public class AnnotationExporter extends JPanel toTextbox.setText(MessageManager.getString("label.to_textbox")); toTextbox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { toTextbox_actionPerformed(e); @@ -252,6 +256,7 @@ public class AnnotationExporter extends JPanel close.setText(MessageManager.getString("action.close")); close.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { close_actionPerformed(e); diff --git a/src/jalview/gui/FeatureColourChooser.java b/src/jalview/gui/FeatureColourChooser.java index 064d58b..79217ea 100644 --- a/src/jalview/gui/FeatureColourChooser.java +++ b/src/jalview/gui/FeatureColourChooser.java @@ -20,9 +20,9 @@ */ package jalview.gui; +import jalview.api.FeatureColourI; import jalview.datamodel.GraphLine; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.util.MessageManager; import java.awt.BorderLayout; @@ -33,7 +33,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.Hashtable; import javax.swing.BorderFactory; import javax.swing.JCheckBox; @@ -52,16 +51,16 @@ public class FeatureColourChooser extends JalviewDialog // FeatureSettings fs; FeatureRenderer fr; - private GraduatedColor cs; + private FeatureColourI cs; - private Object oldcs; + private FeatureColourI oldcs; /** * * @return the last colour setting selected by user - either oldcs (which may * be a java.awt.Color) or the new GraduatedColor */ - public Object getLastColour() + public FeatureColourI getLastColour() { if (cs == null) { @@ -70,8 +69,6 @@ public class FeatureColourChooser extends JalviewDialog return cs; } - Hashtable oldgroupColours; - AlignmentPanel ap; boolean adjusting = false; @@ -127,7 +124,7 @@ public class FeatureColourChooser extends JalviewDialog } }); - float mm[] = ((float[][]) fr.getMinMax().get(type))[0]; + float mm[] = fr.getMinMax().get(type)[0]; min = mm[0]; max = mm[1]; @@ -139,32 +136,32 @@ public class FeatureColourChooser extends JalviewDialog scaleFactor = (max == min) ? 1f : 100f / (max - min); oldcs = fr.getFeatureColours().get(type); - if (oldcs instanceof GraduatedColor) + if (!oldcs.isSimpleColour()) { - if (((GraduatedColor) oldcs).isAutoScale()) + if (oldcs.isAutoScaled()) { // update the scale - cs = new GraduatedColor((GraduatedColor) oldcs, min, max); + cs = new FeatureColour((FeatureColour) oldcs, min, max); } else { - cs = new GraduatedColor((GraduatedColor) oldcs); + cs = new FeatureColour((FeatureColour) oldcs); } } else { // promote original color to a graduated color - Color bl = Color.black; - if (oldcs instanceof Color) + Color bl = oldcs.getColour(); + if (bl == null) { - bl = (Color) oldcs; + bl = Color.BLACK; } // original colour becomes the maximum colour - cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]); + cs = new FeatureColour(Color.white, bl, mm[0], mm[1]); cs.setColourByLabel(false); } - minColour.setBackground(oldminColour = cs.getMinColor()); - maxColour.setBackground(oldmaxColour = cs.getMaxColor()); + minColour.setBackground(oldminColour = cs.getMinColour()); + maxColour.setBackground(oldmaxColour = cs.getMaxColour()); adjusting = true; try @@ -174,18 +171,15 @@ public class FeatureColourChooser extends JalviewDialog { } // update the gui from threshold state - thresholdIsMin.setSelected(!cs.isAutoScale()); + thresholdIsMin.setSelected(!cs.isAutoScaled()); colourByLabel.setSelected(cs.isColourByLabel()); - if (cs.getThreshType() != AnnotationColourGradient.NO_THRESHOLD) + if (cs.hasThreshold()) { // initialise threshold slider and selector - threshold - .setSelectedIndex(cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1 - : 2); + threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2); slider.setEnabled(true); thresholdValue.setEnabled(true); - threshline = new jalview.datamodel.GraphLine((max - min) / 2f, - "Threshold", Color.black); + threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black); } @@ -395,50 +389,50 @@ public class FeatureColourChooser extends JalviewDialog return; } - int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD; + boolean aboveThreshold = false; + boolean belowThreshold = false; if (threshold.getSelectedIndex() == 1) { - aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD; + aboveThreshold = true; } else if (threshold.getSelectedIndex() == 2) { - aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD; + belowThreshold = true; } + boolean hasThreshold = aboveThreshold || belowThreshold; slider.setEnabled(true); thresholdValue.setEnabled(true); - GraduatedColor acg; + FeatureColourI acg; if (cs.isColourByLabel()) { - acg = new GraduatedColor(oldminColour, oldmaxColour, min, max); + acg = new FeatureColour(oldminColour, oldmaxColour, min, max); } else { - acg = new GraduatedColor(oldminColour = minColour.getBackground(), + acg = new FeatureColour(oldminColour = minColour.getBackground(), oldmaxColour = maxColour.getBackground(), min, max); } - if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD) + if (!hasThreshold) { slider.setEnabled(false); thresholdValue.setEnabled(false); thresholdValue.setText(""); thresholdIsMin.setEnabled(false); } - else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD - && threshline == null) + else if (threshline == null) { // todo visual indication of feature threshold - threshline = new jalview.datamodel.GraphLine((max - min) / 2f, - "Threshold", Color.black); + threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black); } - if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD) + if (hasThreshold) { adjusting = true; - acg.setThresh(threshline.value); + acg.setThreshold(threshline.value); float range = (max - min) * scaleFactor; @@ -453,18 +447,18 @@ public class FeatureColourChooser extends JalviewDialog adjusting = false; } - acg.setThreshType(aboveThreshold); - if (thresholdIsMin.isSelected() - && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD) + acg.setAboveThreshold(aboveThreshold); + acg.setBelowThreshold(belowThreshold); + if (thresholdIsMin.isSelected() && hasThreshold) { acg.setAutoScaled(false); - if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD) + if (aboveThreshold) { - acg = new GraduatedColor(acg, threshline.value, max); + acg = new FeatureColour((FeatureColour) acg, threshline.value, max); } else { - acg = new GraduatedColor(acg, min, threshline.value); + acg = new FeatureColour((FeatureColour) acg, min, threshline.value); } } else @@ -554,7 +548,7 @@ public class FeatureColourChooser extends JalviewDialog public void valueChanged() { threshline.value = slider.getValue() / scaleFactor; - cs.setThresh(threshline.value); + cs.setThreshold(threshline.value); changeColour(); ap.paintAlignment(false); } diff --git a/src/jalview/gui/FeatureRenderer.java b/src/jalview/gui/FeatureRenderer.java index a0f1b80..46bcdab 100644 --- a/src/jalview/gui/FeatureRenderer.java +++ b/src/jalview/gui/FeatureRenderer.java @@ -20,10 +20,12 @@ */ package jalview.gui; +import jalview.api.FeatureColourI; import jalview.datamodel.SearchResults; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; +import jalview.schemes.UserColourScheme; import jalview.util.MessageManager; import java.awt.BorderLayout; @@ -92,7 +94,7 @@ public class FeatureRenderer extends static String lastDescriptionAdded; - Object oldcol, fcol; + FeatureColourI oldcol, fcol; int featureIndex = 0; @@ -121,22 +123,22 @@ public class FeatureRenderer extends { FeatureColourChooser fcc = null; + @Override public void mousePressed(MouseEvent evt) { - if (fcol instanceof Color) + if (fcol.isSimpleColour()) { Color col = JColorChooser.showDialog(Desktop.desktop, MessageManager.getString("label.select_feature_colour"), - ((Color) fcol)); + fcol.getColour()); if (col != null) { - fcol = col; - updateColourButton(bigPanel, colour, col); + fcol = new FeatureColour(col); + updateColourButton(bigPanel, colour, new FeatureColour(col)); } } else { - if (fcc == null) { final String type = features[featureIndex].getType(); @@ -147,6 +149,7 @@ public class FeatureRenderer extends fcc.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { fcol = fcc.getLastColour(); @@ -182,6 +185,7 @@ public class FeatureRenderer extends overlaps.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent e) { int index = overlaps.getSelectedIndex(); @@ -201,11 +205,11 @@ public class FeatureRenderer extends ap.getSeqPanel().seqCanvas.highlightSearchResults(highlight); } - Object col = getFeatureStyle(name.getText()); + FeatureColourI col = getFeatureStyle(name.getText()); if (col == null) { - col = new jalview.schemes.UserColourScheme() - .createColourFromName(name.getText()); + col = new FeatureColour(UserColourScheme + .createColourFromName(name.getText())); } oldcol = fcol = col; updateColourButton(bigPanel, colour, col); @@ -416,26 +420,25 @@ public class FeatureRenderer extends * * @param bigPanel * @param col - * @param col2 + * @param col */ protected void updateColourButton(JPanel bigPanel, JLabel colour, - Object col2) + FeatureColourI col) { colour.removeAll(); colour.setIcon(null); colour.setToolTipText(null); colour.setText(""); - if (col2 instanceof Color) + if (col.isSimpleColour()) { - colour.setBackground((Color) col2); + colour.setBackground(col.getColour()); } else { colour.setBackground(bigPanel.getBackground()); colour.setForeground(Color.black); - FeatureSettings.renderGraduatedColor(colour, (GraduatedColor) col2); - // colour.setForeground(colour.getBackground()); + FeatureSettings.renderGraduatedColor(colour, col); } } } diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 6b58b51..cf7bdb3 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -20,15 +20,19 @@ */ package jalview.gui; +import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; import jalview.bin.Cache; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.gui.Help.HelpId; import jalview.io.JalviewFileChooser; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; +import jalview.schemabinding.version2.JalviewUserColours; +import jalview.schemes.FeatureColour; +import jalview.util.Format; import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.util.QuickSort; import jalview.viewmodel.AlignmentViewport; import jalview.ws.dbsources.das.api.jalviewSourceI; @@ -57,6 +61,7 @@ import java.io.PrintWriter; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Vector; @@ -158,12 +163,13 @@ public class FeatureSettings extends JPanel implements table.setDefaultEditor(Color.class, new ColorEditor(this)); - table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this)); - table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer()); + table.setDefaultEditor(FeatureColour.class, new ColorEditor(this)); + table.setDefaultRenderer(FeatureColour.class, new ColorRenderer()); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.addMouseListener(new MouseAdapter() { + @Override public void mousePressed(MouseEvent evt) { selectedRow = table.rowAtPoint(evt.getPoint()); @@ -198,6 +204,7 @@ public class FeatureSettings extends JPanel implements table.addMouseMotionListener(new MouseMotionAdapter() { + @Override public void mouseDragged(MouseEvent evt) { int newRow = table.rowAtPoint(evt.getPoint()); @@ -237,6 +244,7 @@ public class FeatureSettings extends JPanel implements final FeatureSettings fs = this; fr.addPropertyChangeListener(change = new PropertyChangeListener() { + @Override public void propertyChange(PropertyChangeEvent evt) { if (!fs.resettingTable && !fs.handlingUpdate) @@ -252,7 +260,7 @@ public class FeatureSettings extends JPanel implements frame = new JInternalFrame(); frame.setContentPane(this); - if (new jalview.util.Platform().isAMac()) + if (Platform.isAMac()) { Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), @@ -267,6 +275,7 @@ public class FeatureSettings extends JPanel implements frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() { + @Override public void internalFrameClosed( javax.swing.event.InternalFrameEvent evt) { @@ -277,9 +286,12 @@ public class FeatureSettings extends JPanel implements frame.setLayer(JLayeredPane.PALETTE_LAYER); } - protected void popupSort(final int selectedRow, final String type, - final Object typeCol, final Hashtable minmax, int x, int y) + protected void popupSort(final int row, final String type, + final Object typeCol, final Map minmax, int x, + int y) { + final FeatureColourI featureColour = (FeatureColourI) typeCol; + JPopupMenu men = new JPopupMenu(MessageManager.formatMessage( "label.settings_for_param", new String[] { type })); JMenuItem scr = new JMenuItem( @@ -289,6 +301,7 @@ public class FeatureSettings extends JPanel implements scr.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { me.af.avc.sortAlignmentByFeatureScore(new String[] { type }); @@ -300,6 +313,7 @@ public class FeatureSettings extends JPanel implements dens.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { me.af.avc.sortAlignmentByFeatureDensity(new String[] { type }); @@ -309,7 +323,7 @@ public class FeatureSettings extends JPanel implements men.add(dens); if (minmax != null) { - final Object typeMinMax = minmax.get(type); + final float[][] typeMinMax = minmax.get(type); /* * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); // * this is broken at the moment and isn't that useful anyway! @@ -324,24 +338,25 @@ public class FeatureSettings extends JPanel implements * * men.add(chb); */ - if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null) + if (typeMinMax != null && typeMinMax[0] != null) { // if (table.getValueAt(row, column)); // graduated colourschemes for those where minmax exists for the // positional features final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem( "Graduated Colour"); - mxcol.setSelected(!(typeCol instanceof Color)); + mxcol.setSelected(!featureColour.isSimpleColour()); men.add(mxcol); mxcol.addActionListener(new ActionListener() { JColorChooser colorChooser; + @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == mxcol) { - if (typeCol instanceof Color) + if (featureColour.isSimpleColour()) { FeatureColourChooser fc = new FeatureColourChooser(me.fr, type); @@ -355,8 +370,7 @@ public class FeatureSettings extends JPanel implements "Select new Colour", true, // modal colorChooser, this, // OK button handler null); // no CANCEL button handler - colorChooser.setColor(((GraduatedColor) typeCol) - .getMaxColor()); + colorChooser.setColor(featureColour.getMaxColour()); dialog.setVisible(true); } } @@ -366,13 +380,13 @@ public class FeatureSettings extends JPanel implements { FeatureColourChooser fc = (FeatureColourChooser) e .getSource(); - table.setValueAt(fc.getLastColour(), selectedRow, 1); + table.setValueAt(fc.getLastColour(), row, 1); table.validate(); } else { // probably the color chooser! - table.setValueAt(colorChooser.getColor(), selectedRow, 1); + table.setValueAt(colorChooser.getColor(), row, 1); table.validate(); me.updateFeatureRenderer( ((FeatureTableModel) table.getModel()).getData(), @@ -421,13 +435,13 @@ public class FeatureSettings extends JPanel implements /** * contains a float[3] for each feature type string. created by setTableData */ - Hashtable typeWidth = null; + Map typeWidth = null; @Override synchronized public void discoverAllFeatureData() { - Vector allFeatures = new Vector(); - Vector allGroups = new Vector(); + Vector allFeatures = new Vector(); + Vector allGroups = new Vector(); SequenceFeature[] tmpfeatures; String group; for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++) @@ -507,6 +521,7 @@ public class FeatureSettings extends JPanel implements check.setFont(new Font("Serif", Font.BOLD, 12)); check.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent evt) { fr.setGroupVisibility(check.getText(), check.isSelected()); @@ -532,13 +547,13 @@ public class FeatureSettings extends JPanel implements return; } resettingTable = true; - typeWidth = new Hashtable(); + typeWidth = new Hashtable(); // TODO: change avWidth calculation to 'per-sequence' average and use long // rather than float float[] avWidth = null; SequenceFeature[] tmpfeatures; String group = null, type; - Vector visibleChecks = new Vector(); + Vector visibleChecks = new Vector(); // Find out which features should be visible depending on which groups // are selected / deselected @@ -579,7 +594,7 @@ public class FeatureSettings extends JPanel implements } else { - avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType()); + avWidth = typeWidth.get(tmpfeatures[index].getType()); } avWidth[0]++; if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd()) @@ -724,8 +739,7 @@ public class FeatureSettings extends JPanel implements InputStreamReader in = new InputStreamReader(new FileInputStream( file), "UTF-8"); - jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours(); - jucs = jucs.unmarshal(in); + JalviewUserColours jucs = JalviewUserColours.unmarshal(in); for (int i = jucs.getColourCount() - 1; i >= 0; i--) { @@ -744,7 +758,7 @@ public class FeatureSettings extends JPanel implements Cache.log.warn("Couldn't parse out graduated feature color.", e); } - GraduatedColor gcol = new GraduatedColor(mincol, maxcol, + FeatureColourI gcol = new FeatureColour(mincol, maxcol, newcol.getMin(), newcol.getMax()); if (newcol.hasAutoScale()) { @@ -756,31 +770,28 @@ public class FeatureSettings extends JPanel implements } if (newcol.hasThreshold()) { - gcol.setThresh(newcol.getThreshold()); - gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default + gcol.setThreshold(newcol.getThreshold()); } if (newcol.getThreshType().length() > 0) { String ttyp = newcol.getThreshType(); - if (ttyp.equalsIgnoreCase("NONE")) - { - gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); - } if (ttyp.equalsIgnoreCase("ABOVE")) { - gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD); + gcol.setAboveThreshold(true); } if (ttyp.equalsIgnoreCase("BELOW")) { - gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD); + gcol.setBelowThreshold(true); } } fr.setColour(name = newcol.getName(), gcol); } else { - fr.setColour(name = jucs.getColour(i).getName(), new Color( - Integer.parseInt(jucs.getColour(i).getRGB(), 16))); + Color color = new Color( + Integer.parseInt(jucs.getColour(i).getRGB(), 16)); + fr.setColour(name = jucs.getColour(i).getName(), + new FeatureColour(color)); } fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount()); } @@ -824,50 +835,40 @@ public class FeatureSettings extends JPanel implements PrintWriter out = new PrintWriter(new OutputStreamWriter( new FileOutputStream(choice), "UTF-8")); - Set fr_colours = fr.getAllFeatureColours(); - Iterator e = fr_colours.iterator(); + Set fr_colours = fr.getAllFeatureColours(); + Iterator e = fr_colours.iterator(); float[] sortOrder = new float[fr_colours.size()]; String[] sortTypes = new String[fr_colours.size()]; int i = 0; while (e.hasNext()) { - sortTypes[i] = e.next().toString(); + sortTypes[i] = e.next(); sortOrder[i] = fr.getOrder(sortTypes[i]); i++; } - jalview.util.QuickSort.sort(sortOrder, sortTypes); + QuickSort.sort(sortOrder, sortTypes); sortOrder = null; - Object fcol; - GraduatedColor gcol; for (i = 0; i < sortTypes.length; i++) { jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour(); col.setName(sortTypes[i]); - col.setRGB(jalview.util.Format.getHexString(fr.getColour(col - .getName()))); - fcol = fr.getFeatureStyle(sortTypes[i]); - if (fcol instanceof GraduatedColor) + FeatureColourI fcol = fr.getFeatureStyle(sortTypes[i]); + if (fcol.isSimpleColour()) { - gcol = (GraduatedColor) fcol; - col.setMin(gcol.getMin()); - col.setMax(gcol.getMax()); - col.setMinRGB(jalview.util.Format.getHexString(gcol - .getMinColor())); - col.setAutoScale(gcol.isAutoScale()); - col.setThreshold(gcol.getThresh()); - col.setColourByLabel(gcol.isColourByLabel()); - switch (gcol.getThreshType()) - { - case AnnotationColourGradient.NO_THRESHOLD: - col.setThreshType("NONE"); - break; - case AnnotationColourGradient.ABOVE_THRESHOLD: - col.setThreshType("ABOVE"); - break; - case AnnotationColourGradient.BELOW_THRESHOLD: - col.setThreshType("BELOW"); - break; - } + col.setRGB(Format.getHexString(fcol.getColour())); + } + else + { + col.setRGB(Format.getHexString(fcol.getMaxColour())); + col.setMin(fcol.getMin()); + col.setMax(fcol.getMax()); + col.setMinRGB(jalview.util.Format.getHexString(fcol + .getMinColour())); + col.setAutoScale(fcol.isAutoScaled()); + col.setThreshold(fcol.getThreshold()); + col.setColourByLabel(fcol.isColourByLabel()); + col.setThreshType(fcol.isAboveThreshold() ? "ABOVE" : (fcol + .isBelowThreshold() ? "BELOW" : "NONE")); } ucs.addColour(col); } @@ -903,7 +904,7 @@ public class FeatureSettings extends JPanel implements int num = 0; for (int i = 0; i < data.length; i++) { - awidth = (float[]) typeWidth.get(data[i][0]); + awidth = typeWidth.get(data[i][0]); if (awidth[0] > 0) { width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better @@ -1029,6 +1030,7 @@ public class FeatureSettings extends JPanel implements invert.setText(MessageManager.getString("label.invert_selection")); invert.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { invertSelection(); @@ -1038,6 +1040,7 @@ public class FeatureSettings extends JPanel implements optimizeOrder.setText(MessageManager.getString("label.optimise_order")); optimizeOrder.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { orderByAvWidth(); @@ -1048,6 +1051,7 @@ public class FeatureSettings extends JPanel implements .setText(MessageManager.getString("label.seq_sort_by_score")); sortByScore.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { af.avc.sortAlignmentByFeatureScore(null); @@ -1058,6 +1062,7 @@ public class FeatureSettings extends JPanel implements .getString("label.sequence_sort_by_density")); sortByDens.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { af.avc.sortAlignmentByFeatureDensity(null); @@ -1067,6 +1072,7 @@ public class FeatureSettings extends JPanel implements help.setText(MessageManager.getString("action.help")); help.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { try @@ -1082,6 +1088,7 @@ public class FeatureSettings extends JPanel implements help.setText(MessageManager.getString("action.help")); help.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { try @@ -1097,6 +1104,7 @@ public class FeatureSettings extends JPanel implements cancel.setText(MessageManager.getString("action.cancel")); cancel.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { fr.setTransparency(originalTransparency); @@ -1108,6 +1116,7 @@ public class FeatureSettings extends JPanel implements ok.setText(MessageManager.getString("action.ok")); ok.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { close(); @@ -1117,6 +1126,7 @@ public class FeatureSettings extends JPanel implements loadColours.setText(MessageManager.getString("label.load_colours")); loadColours.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { load(); @@ -1126,6 +1136,7 @@ public class FeatureSettings extends JPanel implements saveColours.setText(MessageManager.getString("label.save_colours")); saveColours.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { save(); @@ -1133,6 +1144,7 @@ public class FeatureSettings extends JPanel implements }); transparency.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent evt) { fr.setTransparency((100 - transparency.getValue()) / 100f); @@ -1146,6 +1158,7 @@ public class FeatureSettings extends JPanel implements fetchDAS.setText(MessageManager.getString("label.fetch_das_features")); fetchDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { fetchDAS_actionPerformed(e); @@ -1154,6 +1167,7 @@ public class FeatureSettings extends JPanel implements saveDAS.setText(MessageManager.getString("action.save_as_default")); saveDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { saveDAS_actionPerformed(e); @@ -1165,6 +1179,7 @@ public class FeatureSettings extends JPanel implements cancelDAS.setText(MessageManager.getString("action.cancel_fetch")); cancelDAS.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { cancelDAS_actionPerformed(e); @@ -1203,7 +1218,8 @@ public class FeatureSettings extends JPanel implements fetchDAS.setEnabled(false); cancelDAS.setEnabled(true); dassourceBrowser.setGuiEnabled(false); - Vector selectedSources = dassourceBrowser.getSelectedSources(); + Vector selectedSources = dassourceBrowser + .getSelectedSources(); doDasFeatureFetch(selectedSources, true, true); } @@ -1262,7 +1278,7 @@ public class FeatureSettings extends JPanel implements * Vector of Strings to resolve to DAS source nicknames. * @return sources that are present in source list. */ - public List resolveSourceNicknames(Vector sources) + public List resolveSourceNicknames(Vector sources) { return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources); } @@ -1273,7 +1289,7 @@ public class FeatureSettings extends JPanel implements * * @return vector of selected das source nicknames */ - public Vector getSelectedSources() + public Vector getSelectedSources() { return dassourceBrowser.getSelectedSources(); } @@ -1287,7 +1303,7 @@ public class FeatureSettings extends JPanel implements * if true then runs in same thread, otherwise passes to the Swing * executor */ - public void fetchDasFeatures(Vector sources, boolean block) + public void fetchDasFeatures(Vector sources, boolean block) { initDasSources(); List resolved = dassourceBrowser.sourceRegistry @@ -1304,6 +1320,7 @@ public class FeatureSettings extends JPanel implements Runnable fetcher = new Runnable() { + @Override public void run() { doDasFeatureFetch(dassources, true, false); @@ -1385,6 +1402,7 @@ public class FeatureSettings extends JPanel implements this.data = data; } + @Override public int getColumnCount() { return columnNames.length; @@ -1395,31 +1413,37 @@ public class FeatureSettings extends JPanel implements return data[row]; } + @Override public int getRowCount() { return data.length; } + @Override public String getColumnName(int col) { return columnNames[col]; } + @Override public Object getValueAt(int row, int col) { return data[row][col]; } + @Override public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } + @Override public boolean isCellEditable(int row, int col) { return col == 0 ? false : true; } + @Override public void setValueAt(Object value, int row, int col) { data[row][col] = value; @@ -1444,10 +1468,12 @@ public class FeatureSettings extends JPanel implements setVerticalTextPosition(SwingConstants.CENTER); } - public Component getTableCellRendererComponent(JTable table, + @Override + public Component getTableCellRendererComponent(JTable tbl, Object color, boolean isSelected, boolean hasFocus, int row, int column) { + FeatureColourI cellColour = (FeatureColourI) color; // JLabel comp = new JLabel(); // comp. setOpaque(true); @@ -1455,11 +1481,11 @@ public class FeatureSettings extends JPanel implements // setBounds(getBounds()); Color newColor; setToolTipText(baseTT); - setBackground(table.getBackground()); - if (color instanceof GraduatedColor) + setBackground(tbl.getBackground()); + if (!cellColour.isSimpleColour()) { - Rectangle cr = table.getCellRect(row, column, false); - FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color, + Rectangle cr = tbl.getCellRect(row, column, false); + FeatureSettings.renderGraduatedColor(this, cellColour, (int) cr.getWidth(), (int) cr.getHeight()); } @@ -1467,20 +1493,16 @@ public class FeatureSettings extends JPanel implements { this.setText(""); this.setIcon(null); - newColor = (Color) color; - // comp. + newColor = cellColour.getColour(); setBackground(newColor); - // comp.setToolTipText("RGB value: " + newColor.getRed() + ", " - // + newColor.getGreen() + ", " + newColor.getBlue()); } if (isSelected) { if (selectedBorder == null) { selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, - table.getSelectionBackground()); + tbl.getSelectionBackground()); } - // comp. setBorder(selectedBorder); } else @@ -1488,9 +1510,8 @@ public class FeatureSettings extends JPanel implements if (unselectedBorder == null) { unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, - table.getBackground()); + tbl.getBackground()); } - // comp. setBorder(unselectedBorder); } @@ -1504,7 +1525,7 @@ public class FeatureSettings extends JPanel implements * @param comp * @param gcol */ - public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol) + public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol) { int w = comp.getWidth(), h = comp.getHeight(); if (w < 20) @@ -1520,23 +1541,23 @@ public class FeatureSettings extends JPanel implements renderGraduatedColor(comp, gcol, w, h); } - public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol, + public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol, int w, int h) { boolean thr = false; String tt = ""; String tx = ""; - if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) + if (gcol.isAboveThreshold()) { thr = true; tx += ">"; - tt += "Thresholded (Above " + gcol.getThresh() + ") "; + tt += "Thresholded (Above " + gcol.getThreshold() + ") "; } - if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD) + if (gcol.isBelowThreshold()) { thr = true; tx += "<"; - tt += "Thresholded (Below " + gcol.getThresh() + ") "; + tt += "Thresholded (Below " + gcol.getThreshold() + ") "; } if (gcol.isColourByLabel()) { @@ -1550,7 +1571,7 @@ public class FeatureSettings extends JPanel implements } else { - Color newColor = gcol.getMaxColor(); + Color newColor = gcol.getMaxColour(); comp.setBackground(newColor); // System.err.println("Width is " + w / 2); Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr); @@ -1578,7 +1599,7 @@ public class FeatureSettings extends JPanel implements class FeatureIcon implements Icon { - GraduatedColor gcol; + FeatureColourI gcol; Color backg; @@ -1590,7 +1611,7 @@ class FeatureIcon implements Icon Color mpcolour = Color.white; - FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace) + FeatureIcon(FeatureColourI gfc, Color bg, int w, int h, boolean mspace) { gcol = gfc; backg = bg; @@ -1609,16 +1630,19 @@ class FeatureIcon implements Icon } } + @Override public int getIconWidth() { return width; } + @Override public int getIconHeight() { return height; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { @@ -1627,7 +1651,7 @@ class FeatureIcon implements Icon g.setColor(backg); g.fillRect(0, 0, width, height); // need an icon here. - g.setColor(gcol.getMaxColor()); + g.setColor(gcol.getMaxColour()); g.setFont(new Font("Verdana", Font.PLAIN, 9)); @@ -1641,7 +1665,7 @@ class FeatureIcon implements Icon } else { - Color minCol = gcol.getMinColor(); + Color minCol = gcol.getMinColour(); g.setColor(minCol); g.fillRect(0, 0, s1, height); if (midspace) @@ -1649,7 +1673,7 @@ class FeatureIcon implements Icon g.setColor(Color.white); g.fillRect(s1, 0, e1 - s1, height); } - g.setColor(gcol.getMaxColor()); + g.setColor(gcol.getMaxColour()); g.fillRect(0, e1, width - e1, height); } } @@ -1660,14 +1684,12 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, { FeatureSettings me; - GraduatedColor currentGColor; + FeatureColourI currentColor; FeatureColourChooser chooser; String type; - Color currentColor; - JButton button; JColorChooser colorChooser; @@ -1699,6 +1721,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, /** * Handles events from the editor button and from the dialog's OK button. */ + @Override public void actionPerformed(ActionEvent e) { @@ -1706,11 +1729,11 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, { // The user has clicked the cell, so // bring up the dialog. - if (currentColor != null) + if (currentColor.isSimpleColour()) { // bring up simple color chooser - button.setBackground(currentColor); - colorChooser.setColor(currentColor); + button.setBackground(currentColor.getColour()); + colorChooser.setColor(currentColor.getColour()); dialog.setVisible(true); } else @@ -1727,15 +1750,13 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, } else { // User pressed dialog's "OK" button. - if (currentColor != null) + if (currentColor.isSimpleColour()) { - currentColor = colorChooser.getColor(); + currentColor = new FeatureColour(colorChooser.getColor()); } else { - // class cast exceptions may be raised if the chooser created on a - // non-graduated color - currentGColor = (GraduatedColor) chooser.getLastColour(); + currentColor = chooser.getLastColour(); } me.table.setValueAt(getCellEditorValue(), selectedRow, 1); fireEditingStopped(); @@ -1744,31 +1765,27 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, } // Implement the one CellEditor method that AbstractCellEditor doesn't. + @Override public Object getCellEditorValue() { - if (currentColor == null) - { - return currentGColor; - } return currentColor; } // Implement the one method defined by TableCellEditor. + @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - currentGColor = null; - currentColor = null; + currentColor = (FeatureColourI) value; this.selectedRow = row; type = me.table.getValueAt(row, 0).toString(); button.setOpaque(true); button.setBackground(me.getBackground()); - if (value instanceof GraduatedColor) + if (!currentColor.isSimpleColour()) { - currentGColor = (GraduatedColor) value; JLabel btn = new JLabel(); btn.setSize(button.getSize()); - FeatureSettings.renderGraduatedColor(btn, currentGColor); + FeatureSettings.renderGraduatedColor(btn, currentColor); button.setBackground(btn.getBackground()); button.setIcon(btn.getIcon()); button.setText(btn.getText()); @@ -1777,8 +1794,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor, { button.setText(""); button.setIcon(null); - currentColor = (Color) value; - button.setBackground(currentColor); + button.setBackground(currentColor.getColour()); } return button; } diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index fc96edc..9a9c7b3 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -20,6 +20,7 @@ */ package jalview.gui; +import jalview.api.FeatureColourI; import jalview.api.ViewStyleI; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; @@ -71,7 +72,7 @@ import jalview.schemabinding.version2.Viewport; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.schemes.ResidueColourScheme; import jalview.schemes.ResidueProperties; import jalview.schemes.UserColourScheme; @@ -90,6 +91,7 @@ import jalview.ws.params.ArgumentI; import jalview.ws.params.AutoCalcSetting; import jalview.ws.params.WsParamSetI; +import java.awt.Color; import java.awt.Rectangle; import java.io.BufferedReader; import java.io.DataInputStream; @@ -1193,34 +1195,32 @@ public class Jalview2XML .getFeatureRenderer().getRenderOrder() .toArray(new String[0]); - Vector settingsAdded = new Vector(); - Object gstyle = null; - GraduatedColor gcol = null; + Vector settingsAdded = new Vector(); if (renderOrder != null) { for (int ro = 0; ro < renderOrder.length; ro++) { - gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer() + FeatureColourI gstyle = ap.getSeqPanel().seqCanvas + .getFeatureRenderer() .getFeatureStyle(renderOrder[ro]); Setting setting = new Setting(); setting.setType(renderOrder[ro]); - if (gstyle instanceof GraduatedColor) + if (!gstyle.isSimpleColour()) { - gcol = (GraduatedColor) gstyle; - setting.setColour(gcol.getMaxColor().getRGB()); - setting.setMincolour(gcol.getMinColor().getRGB()); - setting.setMin(gcol.getMin()); - setting.setMax(gcol.getMax()); - setting.setColourByLabel(gcol.isColourByLabel()); - setting.setAutoScale(gcol.isAutoScale()); - setting.setThreshold(gcol.getThresh()); - setting.setThreshstate(gcol.getThreshType()); + setting.setColour(gstyle.getMaxColour().getRGB()); + setting.setMincolour(gstyle.getMinColour().getRGB()); + setting.setMin(gstyle.getMin()); + setting.setMax(gstyle.getMax()); + setting.setColourByLabel(gstyle.isColourByLabel()); + setting.setAutoScale(gstyle.isAutoScaled()); + setting.setThreshold(gstyle.getThreshold()); + // -1 = No threshold, 0 = Below, 1 = Above + setting.setThreshstate(gstyle.isAboveThreshold() ? 1 + : (gstyle.isBelowThreshold() ? 0 : -1)); } else { - setting.setColour(ap.getSeqPanel().seqCanvas - .getFeatureRenderer().getColour(renderOrder[ro]) - .getRGB()); + setting.setColour(gstyle.getColour().getRGB()); } setting.setDisplay(av.getFeaturesDisplayed().isVisible( @@ -1236,36 +1236,11 @@ public class Jalview2XML } } - // Make sure we save none displayed feature settings - Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getFeatureColours().keySet().iterator(); - while (en.hasNext()) - { - String key = en.next().toString(); - if (settingsAdded.contains(key)) - { - continue; - } - - Setting setting = new Setting(); - setting.setType(key); - setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getColour(key).getRGB()); - - setting.setDisplay(false); - float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getOrder(key); - if (rorder > -1) - { - setting.setOrder(rorder); - } - fs.addSetting(setting); - settingsAdded.addElement(key); - } // is groups actually supposed to be a map here ? - en = ap.getSeqPanel().seqCanvas.getFeatureRenderer() + Iterator en = ap.getSeqPanel().seqCanvas + .getFeatureRenderer() .getFeatureGroups().iterator(); - Vector groupsAdded = new Vector(); + Vector groupsAdded = new Vector(); while (en.hasNext()) { String grp = en.next().toString(); @@ -1282,7 +1257,6 @@ public class Jalview2XML groupsAdded.addElement(grp); } jms.setFeatureSettings(fs); - } if (av.hasHiddenColumns()) @@ -2178,6 +2152,7 @@ public class Jalview2XML { SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { setLoadingFinishedForNewStructureViewers(); @@ -4352,25 +4327,33 @@ public class Jalview2XML af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed()); String[] renderOrder = new String[jms.getFeatureSettings() .getSettingCount()]; - Hashtable featureGroups = new Hashtable(); - Hashtable featureColours = new Hashtable(); - Hashtable featureOrder = new Hashtable(); + Map featureColours = new Hashtable(); + Map featureOrder = new Hashtable(); for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++) { Setting setting = jms.getFeatureSettings().getSetting(fs); if (setting.hasMincolour()) { - GraduatedColor gc = setting.hasMin() ? new GraduatedColor( - new java.awt.Color(setting.getMincolour()), - new java.awt.Color(setting.getColour()), - setting.getMin(), setting.getMax()) : new GraduatedColor( - new java.awt.Color(setting.getMincolour()), - new java.awt.Color(setting.getColour()), 0, 1); + FeatureColourI gc = setting.hasMin() ? new FeatureColour( + new Color(setting.getMincolour()), new Color( + setting.getColour()), setting.getMin(), + setting.getMax()) : new FeatureColour(new Color( + setting.getMincolour()), new Color(setting.getColour()), + 0, 1); if (setting.hasThreshold()) { - gc.setThresh(setting.getThreshold()); - gc.setThreshType(setting.getThreshstate()); + gc.setThreshold(setting.getThreshold()); + int threshstate = setting.getThreshstate(); + // -1 = None, 0 = Below, 1 = Above threshold + if (threshstate == 0) + { + gc.setBelowThreshold(true); + } + else if (threshstate == 1) + { + gc.setAboveThreshold(true); + } } gc.setAutoScaled(true); // default if (setting.hasAutoScale()) @@ -4386,8 +4369,8 @@ public class Jalview2XML } else { - featureColours.put(setting.getType(), - new java.awt.Color(setting.getColour())); + featureColours.put(setting.getType(), new FeatureColour( + new Color(setting.getColour()))); } renderOrder[fs] = setting.getType(); if (setting.hasOrder()) @@ -4404,7 +4387,7 @@ public class Jalview2XML fdi.setVisible(setting.getType()); } } - Hashtable fgtable = new Hashtable(); + Map fgtable = new Hashtable(); for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++) { Group grp = jms.getFeatureSettings().getGroup(gs); diff --git a/src/jalview/io/FeaturesFile.java b/src/jalview/io/FeaturesFile.java index aa5583c..6bc0374 100755 --- a/src/jalview/io/FeaturesFile.java +++ b/src/jalview/io/FeaturesFile.java @@ -21,13 +21,14 @@ package jalview.io; import jalview.analysis.SequenceIdMatcher; +import jalview.api.FeatureColourI; import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceDummy; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.schemes.UserColourScheme; import jalview.util.Format; import jalview.util.MapList; @@ -277,7 +278,7 @@ public class FeaturesFile extends AlignFile } else { - Object colour = null; + FeatureColourI colour = null; String colscheme = st.nextToken(); if (colscheme.indexOf("|") > -1 || colscheme.trim().equalsIgnoreCase("label")) @@ -393,7 +394,7 @@ public class FeaturesFile extends AlignFile } try { - colour = new jalview.schemes.GraduatedColor( + colour = new FeatureColour( new UserColourScheme(mincol).findColour('A'), new UserColourScheme(maxcol).findColour('A'), min, max); @@ -406,10 +407,8 @@ public class FeaturesFile extends AlignFile } if (colour != null) { - ((jalview.schemes.GraduatedColor) colour) - .setColourByLabel(labelCol); - ((jalview.schemes.GraduatedColor) colour) - .setAutoScaled(abso == null); + colour.setColourByLabel(labelCol); + colour.setAutoScaled(abso == null); // add in any additional parameters String ttype = null, tval = null; if (gcol.hasMoreTokens()) @@ -418,18 +417,14 @@ public class FeaturesFile extends AlignFile ttype = gcol.nextToken(); if (ttype.toLowerCase().startsWith("below")) { - ((jalview.schemes.GraduatedColor) colour) - .setThreshType(AnnotationColourGradient.BELOW_THRESHOLD); + colour.setBelowThreshold(true); } else if (ttype.toLowerCase().startsWith("above")) { - ((jalview.schemes.GraduatedColor) colour) - .setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD); + colour.setAboveThreshold(true); } else { - ((jalview.schemes.GraduatedColor) colour) - .setThreshType(AnnotationColourGradient.NO_THRESHOLD); if (!ttype.toLowerCase().startsWith("no")) { System.err @@ -438,14 +433,13 @@ public class FeaturesFile extends AlignFile } } } - if (((GraduatedColor) colour).getThreshType() != AnnotationColourGradient.NO_THRESHOLD) + if (colour.hasThreshold()) { try { gcol.nextToken(); tval = gcol.nextToken(); - ((jalview.schemes.GraduatedColor) colour) - .setThresh(new Float(tval).floatValue()); + colour.setThreshold(new Float(tval).floatValue()); } catch (Exception e) { System.err @@ -470,7 +464,7 @@ public class FeaturesFile extends AlignFile else { UserColourScheme ucs = new UserColourScheme(colscheme); - colour = ucs.findColour('A'); + colour = new FeatureColour(ucs.findColour('A')); } if (colour != null) { @@ -1176,20 +1170,20 @@ public class FeaturesFile extends AlignFile * * @param seqs * source of sequence features - * @param visible + * @param map * hash of feature types and colours * @return features file contents */ public String printJalviewFormat(SequenceI[] seqs, - Map visible) + Map map) { - return printJalviewFormat(seqs, visible, true, true); + return printJalviewFormat(seqs, map, true, true); } /** * generate a features file for seqs with colours from visible (if any) * - * @param seqs + * @param sequences * source of features * @param visible * hash of Colours for each feature type @@ -1200,7 +1194,8 @@ public class FeaturesFile extends AlignFile * of group or type) * @return features file contents */ - public String printJalviewFormat(SequenceI[] seqs, Map visible, + public String printJalviewFormat(SequenceI[] sequences, + Map visible, boolean visOnly, boolean nonpos) { StringBuffer out = new StringBuffer(); @@ -1217,54 +1212,46 @@ public class FeaturesFile extends AlignFile // write feature colours only if we're given them and we are generating // viewed features // TODO: decide if feature links should also be written here ? - Iterator en = visible.keySet().iterator(); - String type, color; + Iterator en = visible.keySet().iterator(); + String feature, color; while (en.hasNext()) { - type = en.next().toString(); + feature = en.next(); - if (visible.get(type) instanceof GraduatedColor) + FeatureColourI gc = visible.get(feature); + if (!gc.isSimpleColour()) { - GraduatedColor gc = (GraduatedColor) visible.get(type); color = (gc.isColourByLabel() ? "label|" : "") - + Format.getHexString(gc.getMinColor()) + "|" - + Format.getHexString(gc.getMaxColor()) - + (gc.isAutoScale() ? "|" : "|abso|") + gc.getMin() + "|" + + Format.getHexString(gc.getMinColour()) + "|" + + Format.getHexString(gc.getMaxColour()) + + (gc.isAutoScaled() ? "|" : "|abso|") + gc.getMin() + + "|" + gc.getMax() + "|"; - if (gc.getThreshType() != AnnotationColourGradient.NO_THRESHOLD) + if (gc.isBelowThreshold()) { - if (gc.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD) - { - color += "below"; - } - else - { - if (gc.getThreshType() != AnnotationColourGradient.ABOVE_THRESHOLD) - { - System.err.println("WARNING: Unsupported threshold type (" - + gc.getThreshType() + ") : Assuming 'above'"); - } - color += "above"; - } - // add the value - color += "|" + gc.getThresh(); + color += "below|" + gc.getThreshold(); + } + else if (gc.isAboveThreshold()) + { + color += "above|" + gc.getThreshold(); } else { color += "none"; } } - else if (visible.get(type) instanceof java.awt.Color) - { - color = Format.getHexString((java.awt.Color) visible.get(type)); - } else { - // legacy support for integer objects containing colour triplet values - color = Format.getHexString(new java.awt.Color(Integer - .parseInt(visible.get(type).toString()))); + color = Format.getHexString(gc.getColour()); } - out.append(type); + // else + // { + // // legacy support for integer objects containing colour triplet + // values + // color = Format.getHexString(new java.awt.Color(Integer + // .parseInt(visible.get(type).toString()))); + // } + out.append(feature); out.append("\t"); out.append(color); out.append(newline); @@ -1275,9 +1262,9 @@ public class FeaturesFile extends AlignFile int groupIndex = 0; boolean isnonpos = false; - for (int i = 0; i < seqs.length; i++) + for (int i = 0; i < sequences.length; i++) { - next = seqs[i].getSequenceFeatures(); + next = sequences[i].getSequenceFeatures(); if (next != null) { for (int j = 0; j < next.length; j++) @@ -1316,9 +1303,9 @@ public class FeaturesFile extends AlignFile group = null; } - for (int i = 0; i < seqs.length; i++) + for (int i = 0; i < sequences.length; i++) { - next = seqs[i].getSequenceFeatures(); + next = sequences[i].getSequenceFeatures(); if (next != null) { for (int j = 0; j < next.length; j++) @@ -1382,7 +1369,7 @@ public class FeaturesFile extends AlignFile out.append("\t"); } - out.append(seqs[i].getName()); + out.append(sequences[i].getName()); out.append("\t-1\t"); out.append(next[j].begin); out.append("\t"); @@ -1426,16 +1413,17 @@ public class FeaturesFile extends AlignFile * default. * * @param seqs - * @param visible + * @param map * @return */ - public String printGFFFormat(SequenceI[] seqs, Map visible) + public String printGFFFormat(SequenceI[] seqs, + Map map) { - return printGFFFormat(seqs, visible, true, true); + return printGFFFormat(seqs, map, true, true); } public String printGFFFormat(SequenceI[] seqs, - Map visible, boolean visOnly, boolean nonpos) + Map map, boolean visOnly, boolean nonpos) { StringBuffer out = new StringBuffer(); SequenceFeature[] next; @@ -1450,7 +1438,7 @@ public class FeaturesFile extends AlignFile { isnonpos = next[j].begin == 0 && next[j].end == 0; if ((!nonpos && isnonpos) - || (!isnonpos && visOnly && !visible + || (!isnonpos && visOnly && !map .containsKey(next[j].type))) { continue; @@ -1513,6 +1501,7 @@ public class FeaturesFile extends AlignFile /** * this is only for the benefit of object polymorphism - method does nothing. */ + @Override public void parse() { // IGNORED @@ -1523,6 +1512,7 @@ public class FeaturesFile extends AlignFile * * @return error message */ + @Override public String print() { return "USE printGFFFormat() or printJalviewFormat()"; diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index d3a1d09..6573a7f 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -26,8 +26,8 @@ import jalview.datamodel.SequenceI; import jalview.util.UrlLink; import java.util.ArrayList; -import java.util.Hashtable; import java.util.List; +import java.util.Map; /** * generate HTML reports for a sequence @@ -60,7 +60,7 @@ public class SequenceAnnotationReport } public void appendFeatures(final StringBuffer tooltipText2, int rpos, - List features, Hashtable minmax) + List features, Map map) { String tmpString; if (features != null) @@ -150,8 +150,8 @@ public class SequenceAnnotationReport // check score should be shown if (!Float.isNaN(feature.getScore())) { - float[][] rng = (minmax == null) ? null : ((float[][]) minmax - .get(feature.getType())); + float[][] rng = (map == null) ? null : (map.get(feature + .getType())); if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) { tooltipText2.append(" Score=" + feature.getScore()); @@ -321,7 +321,7 @@ public class SequenceAnnotationReport public void createSequenceAnnotationReport(final StringBuffer tip, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, - Hashtable minmax) + Map minmax) { createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats, true, minmax); @@ -329,7 +329,7 @@ public class SequenceAnnotationReport public void createSequenceAnnotationReport(final StringBuffer tip, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, - boolean tableWrap, Hashtable minmax) + boolean tableWrap, Map map) { String tmp; tip.append(""); @@ -369,7 +369,7 @@ public class SequenceAnnotationReport int sz = -tip.length(); List tfeat = new ArrayList(); tfeat.add(features[i]); - appendFeatures(tip, 0, tfeat, minmax); + appendFeatures(tip, 0, tfeat, map); sz += tip.length(); maxWidth = Math.max(maxWidth, sz); } diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java index 26bc895..bc00cc4 100644 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -50,6 +50,8 @@ public class FeatureRenderer extends boolean av_validCharWidth, av_isShowSeqFeatureHeight; + private Integer currentColour; + protected void updateAvConfig() { av_charHeight = av.getCharHeight(); @@ -168,14 +170,15 @@ public class FeatureRenderer extends BufferedImage offscreenImage; + @Override public Color findFeatureColour(Color initialCol, SequenceI seq, int res) { return new Color(findFeatureColour(initialCol.getRGB(), seq, res)); } /** - * This is used by the Molecule Viewer and Overview to get the accurate - * colourof the rendered sequence + * This is used by the Molecule Viewer and Overview to get the accurate colour + * of the rendered sequence */ public synchronized int findFeatureColour(int initialCol, final SequenceI seq, int column) @@ -245,7 +248,7 @@ public class FeatureRenderer extends } else { - return ((Integer) currentColour).intValue(); + return currentColour.intValue(); } } @@ -415,6 +418,7 @@ public class FeatureRenderer extends * discover and display. * */ + @Override public void featuresAdded() { lastSeq = null; diff --git a/src/jalview/schemes/FeatureColour.java b/src/jalview/schemes/FeatureColour.java new file mode 100644 index 0000000..ce382c3 --- /dev/null +++ b/src/jalview/schemes/FeatureColour.java @@ -0,0 +1,421 @@ +package jalview.schemes; + +import jalview.api.FeatureColourI; +import jalview.datamodel.SequenceFeature; + +import java.awt.Color; + +/** + * A class that wraps either a simple colour or a graduated colour + */ +public class FeatureColour implements FeatureColourI +{ + final private Color colour; + + final private Color minColour; + + final private Color maxColour; + + private boolean graduatedColour; + + private boolean colourByLabel; + + private float threshold; + + private float base; + + private float range; + + private boolean belowThreshold; + + private boolean aboveThreshold; + + private boolean thresholdIsMinOrMax; + + private boolean isHighToLow; + + private boolean autoScaled; + + final private float minRed; + + final private float minGreen; + + final private float minBlue; + + final private float deltaRed; + + final private float deltaGreen; + + final private float deltaBlue; + + /** + * Default constructor + */ + public FeatureColour() + { + this((Color) null); + } + + /** + * Constructor given a simple colour + * + * @param c + */ + public FeatureColour(Color c) + { + minColour = null; + maxColour = null; + minRed = 0f; + minGreen = 0f; + minBlue = 0f; + deltaRed = 0f; + deltaGreen = 0f; + deltaBlue = 0f; + colour = c; + } + + /** + * Constructor given a colour range and a score range + * + * @param low + * @param high + * @param min + * @param max + */ + public FeatureColour(Color low, Color high, float min, float max) + { + graduatedColour = true; + colour = null; + minColour = low; + maxColour = high; + threshold = Float.NaN; + isHighToLow = min >= max; + minRed = low.getRed() / 255f; + minGreen = low.getGreen() / 255f; + minBlue = low.getBlue() / 255f; + deltaRed = (high.getRed() / 255f) - minRed; + deltaGreen = (high.getGreen() / 255f) - minGreen; + deltaBlue = (high.getBlue() / 255f) - minBlue; + if (isHighToLow) + { + base = max; + range = min - max; + } + else + { + base = min; + range = max - min; + } + } + + /** + * Copy constructor + * + * @param fc + */ + public FeatureColour(FeatureColour fc) + { + colour = fc.colour; + minColour = fc.minColour; + maxColour = fc.maxColour; + minRed = fc.minRed; + minGreen = fc.minGreen; + minBlue = fc.minBlue; + deltaRed = fc.deltaRed; + deltaGreen = fc.deltaGreen; + deltaBlue = fc.deltaBlue; + base = fc.base; + range = fc.range; + isHighToLow = fc.isHighToLow; + setAboveThreshold(fc.isAboveThreshold()); + setBelowThreshold(fc.isBelowThreshold()); + setThreshold(fc.getThreshold()); + setAutoScaled(fc.isAutoScaled()); + setColourByLabel(fc.isColourByLabel()); + } + + /** + * Copy constructor with new min/max ranges + * @param fc + * @param min + * @param max + */ + public FeatureColour(FeatureColour fc, float min, float max) + { + this(fc); + graduatedColour = true; + updateBounds(min, max); + } + + @Override + public boolean isGraduatedColour() + { + return graduatedColour; + } + + /** + * Sets the 'graduated colour' flag. If true, also sets 'colour by label' to + * false. + */ + @Override + public void setGraduatedColour(boolean b) + { + graduatedColour = b; + if (b) + { + setColourByLabel(false); + } + } + + @Override + public Color getColour() + { + return colour; + } + + @Override + public Color getMinColour() + { + return minColour; + } + + @Override + public Color getMaxColour() + { + return maxColour; + } + + @Override + public boolean isColourByLabel() + { + return colourByLabel; + } + + /** + * Sets the 'colour by label' flag. If true, also sets 'graduated colour' to + * false. + */ + @Override + public void setColourByLabel(boolean b) + { + colourByLabel = b; + if (b) + { + setGraduatedColour(false); + } + } + @Override + public boolean isBelowThreshold() + { + return belowThreshold; + } + + @Override + public void setBelowThreshold(boolean b) + { + belowThreshold = b; + if (b) + { + setAboveThreshold(false); + } + } + + @Override + public boolean isAboveThreshold() + { + return aboveThreshold; + } + + @Override + public void setAboveThreshold(boolean b) + { + aboveThreshold = b; + if (b) + { + setBelowThreshold(false); + } + } + + @Override + public boolean isThresholdMinMax() + { + return thresholdIsMinOrMax; + } + + @Override + public void setThresholdMinMax(boolean b) + { + thresholdIsMinOrMax = b; + } + + @Override + public float getThreshold() + { + return threshold; + } + + @Override + public void setThreshold(float f) + { + threshold = f; + } + + @Override + public boolean isAutoScaled() + { + return autoScaled; + } + + @Override + public void setAutoScaled(boolean b) + { + this.autoScaled = b; + } + + /** + * Updates the base and range appropriately for the given minmax range + * + * @param min + * @param max + */ + @Override + public void updateBounds(float min, float max) + { + if (max < min) + { + base = max; + range = min - max; + isHighToLow = true; + } + else + { + base = min; + range = max - min; + isHighToLow = false; + } + } + + /** + * Returns the colour for the given instance of the feature. This may be a + * simple colour, a colour generated from the feature description (if + * isColourByLabel()), or a colour derived from the feature score (if + * isGraduatedColour()). + * + * @param feature + * @return + */ + @Override + public Color getColor(SequenceFeature feature) + { + if (isColourByLabel()) + { + return UserColourScheme + .createColourFromName(feature.getDescription()); + } + + if (!isGraduatedColour()) + { + return getColour(); + } + + // todo should we check for above/below threshold here? + if (range == 0.0) + { + return getMaxColour(); + } + float scr = feature.getScore(); + if (Float.isNaN(scr)) + { + return getMinColour(); + } + float scl = (scr - base) / range; + if (isHighToLow) + { + scl = -scl; + } + if (scl < 0f) + { + scl = 0f; + } + if (scl > 1f) + { + scl = 1f; + } + return new Color(minRed + scl * deltaRed, minGreen + scl * deltaGreen, minBlue + scl * deltaBlue); + } + + /** + * Returns the maximum score of the graduated colour range + * + * @return + */ + @Override + public float getMax() + { + // regenerate the original values passed in to the constructor + return (isHighToLow) ? base : (base + range); + } + + /** + * Returns the minimum score of the graduated colour range + * + * @return + */ + @Override + public float getMin() + { + // regenerate the original value passed in to the constructor + return (isHighToLow) ? (base + range) : base; + } + + /** + * Answers true if the feature has a simple colour, or is coloured by label, + * or has a graduated colour and the score of this feature instance is within + * the range to render (if any), i.e. does not lie below or above any + * threshold set. + * + * @param feature + * @return + */ + @Override + public boolean isColored(SequenceFeature feature) + { + if (isColourByLabel() || !isGraduatedColour()) + { + return true; + } + + float val = feature.getScore(); + if (Float.isNaN(val)) + { + return true; + } + if (Float.isNaN(this.threshold)) + { + return true; + } + + if (isAboveThreshold() && val <= threshold) + { + return false; + } + if (isBelowThreshold() && val >= threshold) + { + return false; + } + return true; + } + + @Override + public boolean isSimpleColour() + { + return (!isColourByLabel() && !isGraduatedColour()); + } + + @Override + public boolean hasThreshold() + { + return isAboveThreshold() || isBelowThreshold(); + } + +} diff --git a/src/jalview/schemes/FeatureColourAdapter.java b/src/jalview/schemes/FeatureColourAdapter.java deleted file mode 100644 index a86bee4..0000000 --- a/src/jalview/schemes/FeatureColourAdapter.java +++ /dev/null @@ -1,73 +0,0 @@ -package jalview.schemes; - -import jalview.api.FeatureColourI; - -import java.awt.Color; - -/** - * A convenience class with implementations of FeatureColourI methods. Override - * methods as required in subclasses. - */ -public class FeatureColourAdapter implements FeatureColourI -{ - @Override - public boolean isGraduatedColour() - { - return isColourByLabel() || isAboveThreshold() || isBelowThreshold(); - } - - @Override - public Color getColour() - { - return Color.BLACK; - } - - @Override - public Color getMinColour() - { - return Color.WHITE; - } - - @Override - public Color getMaxColour() - { - return Color.BLACK; - } - - @Override - public boolean isColourByLabel() - { - return false; - } - - @Override - public boolean isBelowThreshold() - { - return false; - } - - @Override - public boolean isAboveThreshold() - { - return false; - } - - @Override - public boolean isThresholdMinMax() - { - return false; - } - - @Override - public float getThreshold() - { - return 0f; - } - - @Override - public boolean isLowToHigh() - { - return true; - } - -} diff --git a/src/jalview/schemes/FeatureColourScheme.java b/src/jalview/schemes/FeatureColourScheme.java index 4a90b84..628b514 100644 --- a/src/jalview/schemes/FeatureColourScheme.java +++ b/src/jalview/schemes/FeatureColourScheme.java @@ -38,7 +38,7 @@ public enum FeatureColourScheme implements FeatureSettingsI { if (EXON.equals(type)) { - return new FeatureColourAdapter() + return new FeatureColour() { @Override public boolean isColourByLabel() @@ -49,15 +49,7 @@ public enum FeatureColourScheme implements FeatureSettingsI } if (SEQUENCE_VARIANT.equals(type)) { - return new FeatureColourAdapter() - { - - @Override - public Color getColour() - { - return Color.RED; - } - }; + return new FeatureColour(Color.RED); } return null; } diff --git a/src/jalview/schemes/UserColourScheme.java b/src/jalview/schemes/UserColourScheme.java index 7aff05a..2498208 100755 --- a/src/jalview/schemes/UserColourScheme.java +++ b/src/jalview/schemes/UserColourScheme.java @@ -136,7 +136,7 @@ public class UserColourScheme extends ResidueColourScheme } - public Color createColourFromName(String name) + public static Color createColourFromName(String name) { int r, g, b; diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 8db907c..b299624 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -21,12 +21,14 @@ package jalview.viewmodel.seqfeatures; import jalview.api.AlignViewportI; +import jalview.api.FeatureColourI; import jalview.api.FeaturesDisplayedI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.renderer.seqfeatures.FeatureRenderer; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; +import jalview.schemes.UserColourScheme; import jalview.viewmodel.AlignmentViewport; import java.awt.Color; @@ -50,19 +52,20 @@ public abstract class FeatureRendererModel implements */ protected float transparency = 1.0f; - protected Map featureColours = new ConcurrentHashMap(); + protected Map featureColours = new ConcurrentHashMap(); protected Map featureGroups = new ConcurrentHashMap(); - protected Object currentColour; - protected String[] renderOrder; + Map featureOrder = null; + protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( this); protected AlignmentViewport av; + @Override public AlignViewportI getViewport() { return av; @@ -188,9 +191,9 @@ public abstract class FeatureRendererModel implements renderOrder = neworder; } - protected Hashtable minmax = new Hashtable(); + protected Map minmax = new Hashtable(); - public Hashtable getMinMax() + public Map getMinMax() { return minmax; } @@ -204,7 +207,7 @@ public abstract class FeatureRendererModel implements */ protected final byte[] normaliseScore(SequenceFeature sequenceFeature) { - float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0]; + float[] mm = minmax.get(sequenceFeature.type)[0]; final byte[] r = new byte[] { 0, (byte) 255 }; if (mm != null) { @@ -335,7 +338,7 @@ public abstract class FeatureRendererModel implements } if (minmax == null) { - minmax = new Hashtable(); + minmax = new Hashtable(); } AlignmentI alignment = av.getAlignment(); for (int i = 0; i < alignment.getHeight(); i++) @@ -390,7 +393,7 @@ public abstract class FeatureRendererModel implements if (!Float.isNaN(features[index].score)) { int nonpos = features[index].getBegin() >= 1 ? 0 : 1; - float[][] mm = (float[][]) minmax.get(features[index].getType()); + float[][] mm = minmax.get(features[index].getType()); if (mm == null) { mm = new float[][] { null, null }; @@ -439,7 +442,6 @@ public abstract class FeatureRendererModel implements List allfeatures = new ArrayList(allFeatures); String[] oldRender = renderOrder; renderOrder = new String[allfeatures.size()]; - Object mmrange, fc = null; boolean initOrders = (featureOrder == null); int opos = 0; if (oldRender != null && oldRender.length > 0) @@ -459,16 +461,13 @@ public abstract class FeatureRendererModel implements allfeatures.remove(oldRender[j]); if (minmax != null) { - mmrange = minmax.get(oldRender[j]); + float[][] mmrange = minmax.get(oldRender[j]); if (mmrange != null) { - fc = featureColours.get(oldRender[j]); - if (fc != null && fc instanceof GraduatedColor - && ((GraduatedColor) fc).isAutoScale()) + FeatureColourI fc = featureColours.get(oldRender[j]); + if (fc != null && !fc.isSimpleColour() && fc.isAutoScaled()) { - ((GraduatedColor) fc).updateBounds( - ((float[][]) mmrange)[0][0], - ((float[][]) mmrange)[0][1]); + fc.updateBounds(mmrange[0][0], mmrange[0][1]); } } } @@ -492,15 +491,13 @@ public abstract class FeatureRendererModel implements if (minmax != null) { // update from new features minmax if necessary - mmrange = minmax.get(newf[i]); + float[][] mmrange = minmax.get(newf[i]); if (mmrange != null) { - fc = featureColours.get(newf[i]); - if (fc != null && fc instanceof GraduatedColor - && ((GraduatedColor) fc).isAutoScale()) + FeatureColourI fc = featureColours.get(newf[i]); + if (fc != null && !fc.isSimpleColour() && fc.isAutoScaled()) { - ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0], - ((float[][]) mmrange)[0][1]); + fc.updateBounds(mmrange[0][0], mmrange[0][1]); } } } @@ -512,7 +509,7 @@ public abstract class FeatureRendererModel implements setOrder(newf[i], i / (float) denom); } // set order from newly found feature from persisted ordering. - sortOrder[i] = 2 - ((Float) featureOrder.get(newf[i])).floatValue(); + sortOrder[i] = 2 - featureOrder.get(newf[i]).floatValue(); if (i < iSize) { // only sort if we need to @@ -530,51 +527,25 @@ public abstract class FeatureRendererModel implements /** * get a feature style object for the given type string. Creates a - * java.awt.Color for a featureType with no existing colourscheme. TODO: - * replace return type with object implementing standard abstract colour/style - * interface + * java.awt.Color for a featureType with no existing colourscheme. * * @param featureType - * @return java.awt.Color or GraduatedColor + * @return */ - public Object getFeatureStyle(String featureType) + @Override + public FeatureColourI getFeatureStyle(String featureType) { - Object fc = featureColours.get(featureType); + FeatureColourI fc = featureColours.get(featureType); if (fc == null) { - jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(); - Color col = ucs.createColourFromName(featureType); - featureColours.put(featureType, fc = col); + Color col = UserColourScheme.createColourFromName(featureType); + fc = new FeatureColour(col); + featureColours.put(featureType, fc); } return fc; } /** - * return a nominal colour for this feature - * - * @param featureType - * @return standard color, or maximum colour for graduated colourscheme - */ - public Color getColour(String featureType) - { - Object fc = getFeatureStyle(featureType); - - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).getMaxColor(); - } - } - throw new Error("Implementation Error: Unrecognised render object " - + fc.getClass() + " for features of type " + featureType); - } - - /** * calculate the render colour for a specific feature using current feature * settings. * @@ -583,33 +554,14 @@ public abstract class FeatureRendererModel implements */ public Color getColour(SequenceFeature feature) { - Object fc = getFeatureStyle(feature.getType()); - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).findColor(feature); - } - } - throw new Error("Implementation Error: Unrecognised render object " - + fc.getClass() + " for features of type " + feature.getType()); + FeatureColourI fc = getFeatureStyle(feature.getType()); + return fc.getColor(feature); } protected boolean showFeature(SequenceFeature sequenceFeature) { - Object fc = getFeatureStyle(sequenceFeature.type); - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).isColored(sequenceFeature); - } - else - { - return true; - } + FeatureColourI fc = getFeatureStyle(sequenceFeature.type); + return fc.isColored(sequenceFeature); } protected boolean showFeatureOfType(String type) @@ -617,14 +569,9 @@ public abstract class FeatureRendererModel implements return av.getFeaturesDisplayed().isVisible(type); } - public void setColour(String featureType, Object col) + @Override + public void setColour(String featureType, FeatureColourI col) { - // overwrite - // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof - // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null; - // Object c = featureColours.get(featureType); - // if (c == null || c instanceof Color || (c instanceof GraduatedColor && - // !((GraduatedColor)c).getMaxColor().equals(_col))) { featureColours.put(featureType, col); } @@ -640,8 +587,6 @@ public abstract class FeatureRendererModel implements return transparency; } - Map featureOrder = null; - /** * analogous to colour - store a normalized ordering for all feature types in * this rendering context. @@ -656,7 +601,7 @@ public abstract class FeatureRendererModel implements { if (featureOrder == null) { - featureOrder = new Hashtable(); + featureOrder = new Hashtable(); } featureOrder.put(type, new Float(position)); return position; @@ -674,14 +619,14 @@ public abstract class FeatureRendererModel implements { if (featureOrder.containsKey(type)) { - return ((Float) featureOrder.get(type)).floatValue(); + return featureOrder.get(type).floatValue(); } } return -1; } @Override - public Map getFeatureColours() + public Map getFeatureColours() { return featureColours; } @@ -736,8 +681,7 @@ public abstract class FeatureRendererModel implements for (int i = 0; i < data.length; i++) { String type = data[i][0].toString(); - setColour(type, data[i][1]); // todo : typesafety - feature color - // interface object + setColour(type, (FeatureColourI) data[i][1]); if (((Boolean) data[i][2]).booleanValue()) { av_featuresdisplayed.setVisible(type); @@ -767,7 +711,7 @@ public abstract class FeatureRendererModel implements changeSupport.removePropertyChangeListener(listener); } - public Set getAllFeatureColours() + public Set getAllFeatureColours() { return featureColours.keySet(); } @@ -831,13 +775,13 @@ public abstract class FeatureRendererModel implements * @return list of groups */ @Override - public List getGroups(boolean visible) + public List getGroups(boolean visible) { if (featureGroups != null) { - ArrayList gp = new ArrayList(); + List gp = new ArrayList(); - for (Object grp : featureGroups.keySet()) + for (String grp : featureGroups.keySet()) { Boolean state = featureGroups.get(grp); if (state.booleanValue() == visible) @@ -879,19 +823,19 @@ public abstract class FeatureRendererModel implements } @Override - public Hashtable getDisplayedFeatureCols() + public Map getDisplayedFeatureCols() { - Hashtable fcols = new Hashtable(); + Map fcols = new Hashtable(); if (getViewport().getFeaturesDisplayed() == null) { return fcols; } - Iterator en = getViewport().getFeaturesDisplayed() + Iterator features = getViewport().getFeaturesDisplayed() .getVisibleFeatures(); - while (en.hasNext()) + while (features.hasNext()) { - String col = en.next(); - fcols.put(col, getColour(col)); + String feature = features.next(); + fcols.put(feature, getFeatureStyle(feature)); } return fcols; } diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java index 1985b6d..dc2ae11 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java @@ -20,10 +20,10 @@ */ package jalview.viewmodel.seqfeatures; -import jalview.schemes.GraduatedColor; +import jalview.api.FeatureColourI; +import jalview.schemes.FeatureColour; import java.util.Arrays; -import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -32,24 +32,33 @@ public class FeatureRendererSettings implements Cloneable { String[] renderOrder; - Map featureGroups; + /* + * map of {groupName, isDisplayed} + */ + Map featureGroups; - Map featureColours; + /* + * map of {featureType, colourScheme} + */ + Map featureColours; float transparency; - Map featureOrder; + Map featureOrder; public FeatureRendererSettings(String[] renderOrder, - Hashtable featureGroups, Hashtable featureColours, - float transparency, Hashtable featureOrder) + Map featureGroups, + Map featureColours, float transparency, + Map featureOrder) { super(); this.renderOrder = Arrays.copyOf(renderOrder, renderOrder.length); - this.featureGroups = new ConcurrentHashMap(featureGroups); - this.featureColours = new ConcurrentHashMap(featureColours); + this.featureGroups = new ConcurrentHashMap( + featureGroups); + this.featureColours = new ConcurrentHashMap( + featureColours); this.transparency = transparency; - this.featureOrder = new ConcurrentHashMap(featureOrder); + this.featureOrder = new ConcurrentHashMap(featureOrder); } /** @@ -61,9 +70,9 @@ public class FeatureRendererSettings implements Cloneable jalview.viewmodel.seqfeatures.FeatureRendererModel fr) { renderOrder = null; - featureGroups = new ConcurrentHashMap(); - featureColours = new ConcurrentHashMap(); - featureOrder = new ConcurrentHashMap(); + featureGroups = new ConcurrentHashMap(); + featureColours = new ConcurrentHashMap(); + featureOrder = new ConcurrentHashMap(); if (fr.renderOrder != null) { this.renderOrder = new String[fr.renderOrder.length]; @@ -72,26 +81,30 @@ public class FeatureRendererSettings implements Cloneable } if (fr.featureGroups != null) { - this.featureGroups = new ConcurrentHashMap(fr.featureGroups); + this.featureGroups = new ConcurrentHashMap( + fr.featureGroups); } if (fr.featureColours != null) { - this.featureColours = new ConcurrentHashMap(fr.featureColours); + this.featureColours = new ConcurrentHashMap( + fr.featureColours); } - Iterator en = fr.featureColours.keySet().iterator(); + Iterator en = fr.featureColours.keySet().iterator(); while (en.hasNext()) { - Object next = en.next(); - Object val = featureColours.get(next); - if (val instanceof GraduatedColor) + String next = en.next(); + FeatureColourI val = featureColours.get(next); + // if (val instanceof GraduatedColor) + if (val.isGraduatedColour() || val.isColourByLabel()) // why this test? { - featureColours.put(next, new GraduatedColor((GraduatedColor) val)); + featureColours.put(next, new FeatureColour((FeatureColour) val)); } } this.transparency = fr.transparency; if (fr.featureOrder != null) { - this.featureOrder = new ConcurrentHashMap(fr.featureOrder); + this.featureOrder = new ConcurrentHashMap( + fr.featureOrder); } } } diff --git a/src/jalview/ws/jws2/AADisorderClient.java b/src/jalview/ws/jws2/AADisorderClient.java index f929b1e..71b6c91 100644 --- a/src/jalview/ws/jws2/AADisorderClient.java +++ b/src/jalview/ws/jws2/AADisorderClient.java @@ -21,13 +21,14 @@ package jalview.ws.jws2; import jalview.api.AlignCalcWorkerI; +import jalview.api.FeatureColourI; import jalview.bin.Cache; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.GraphLine; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.schemes.UserColourScheme; import jalview.ws.jws2.jabaws2.Jws2Instance; import jalview.ws.params.WsParamSetI; @@ -308,8 +309,8 @@ public class AADisorderClient extends JabawsCalcWorker implements annot.description += "
" + threshNote; } annot.description += ""; - Color col = new UserColourScheme(typeName) - .createColourFromName(typeName + scr.getMethod()); + Color col = UserColourScheme.createColourFromName(typeName + + scr.getMethod()); for (int p = 0, ps = annot.annotations.length; p < ps; p++) { if (annot.annotations[p] != null) @@ -337,13 +338,13 @@ public class AADisorderClient extends JabawsCalcWorker implements .cloneFeatureRenderer(); for (String ft : fc.keySet()) { - Object gc = fr.getFeatureStyle(ft); - if (gc instanceof Color) + FeatureColourI gc = fr.getFeatureStyle(ft); + if (gc.isSimpleColour()) { // set graduated color as fading to white for minimum, and // autoscaling to values on alignment - GraduatedColor ggc = new GraduatedColor(Color.white, - (Color) gc, Float.MIN_VALUE, Float.MAX_VALUE); + FeatureColourI ggc = new FeatureColour(Color.white, + gc.getColour(), Float.MIN_VALUE, Float.MAX_VALUE); ggc.setAutoScaled(true); fr.setColour(ft, ggc); } diff --git a/test/jalview/io/FeaturesFileTest.java b/test/jalview/io/FeaturesFileTest.java index 520d1bb..d65f9df 100644 --- a/test/jalview/io/FeaturesFileTest.java +++ b/test/jalview/io/FeaturesFileTest.java @@ -24,6 +24,7 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertTrue; +import jalview.api.FeatureColourI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; import jalview.gui.AlignFrame; @@ -76,7 +77,7 @@ public class FeaturesFileTest File f = new File("examples/uniref50.fa"); AlignmentI al = readAlignmentFile(f); AlignFrame af = new AlignFrame(al, 500, 500); - Map colours = af.getFeatureRenderer() + Map colours = af.getFeatureRenderer() .getFeatureColours(); FeaturesFile featuresFile = new FeaturesFile( "examples/exampleFeatures.txt", FormatAdapter.FILE); @@ -89,8 +90,8 @@ public class FeaturesFileTest */ colours = af.getFeatureRenderer().getFeatureColours(); assertEquals("26 feature group colours not found", 26, colours.size()); - assertEquals(colours.get("Cath"), new Color(0x93b1d1)); - assertEquals(colours.get("ASX-MOTIF"), new Color(0x6addbb)); + assertEquals(colours.get("Cath").getColour(), new Color(0x93b1d1)); + assertEquals(colours.get("ASX-MOTIF").getColour(), new Color(0x6addbb)); /* * verify (some) features on sequences diff --git a/test/jalview/schemes/FeatureColourTest.java b/test/jalview/schemes/FeatureColourTest.java new file mode 100644 index 0000000..81357fa --- /dev/null +++ b/test/jalview/schemes/FeatureColourTest.java @@ -0,0 +1,115 @@ +package jalview.schemes; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +import jalview.datamodel.SequenceFeature; + +import java.awt.Color; + +import org.testng.annotations.Test; + +public class FeatureColourTest +{ + @Test(groups = { "Functional" }) + public void testIsColored_simpleColour() + { + FeatureColour fc = new FeatureColour(Color.RED); + assertTrue(fc.isColored(new SequenceFeature())); + } + + @Test(groups = { "Functional" }) + public void testIsColored_colourByLabel() + { + FeatureColour fc = new FeatureColour(); + fc.setColourByLabel(true); + assertTrue(fc.isColored(new SequenceFeature())); + } + + @Test(groups = { "Functional" }) + public void testIsColored_aboveThreshold() + { + // graduated colour range from score 20 to 100 + FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f, + 100f); + + // score 0 is adjusted to bottom of range + SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f, + null); + assertTrue(fc.isColored(sf)); + assertEquals(Color.WHITE, fc.getColor(sf)); + + // score 120 is adjusted to top of range + sf.setScore(120f); + assertEquals(Color.BLACK, fc.getColor(sf)); + + // value below threshold is still rendered + // setting threshold has no effect yet... + fc.setThreshold(60f); + sf.setScore(36f); + assertTrue(fc.isColored(sf)); + assertEquals(new Color(204, 204, 204), fc.getColor(sf)); + + // now apply threshold: + fc.setAboveThreshold(true); + assertFalse(fc.isColored(sf)); + // colour is still returned though ?!? + assertEquals(new Color(204, 204, 204), fc.getColor(sf)); + + sf.setScore(84); // above threshold now + assertTrue(fc.isColored(sf)); + assertEquals(new Color(51, 51, 51), fc.getColor(sf)); + } + + @Test(groups = { "Functional" }) + public void testGetColor_simpleColour() + { + FeatureColour fc = new FeatureColour(Color.RED); + assertEquals(Color.RED, fc.getColor(new SequenceFeature())); + } + + @Test(groups = { "Functional" }) + public void testGetColor_colourByLabel() + { + FeatureColour fc = new FeatureColour(); + fc.setColourByLabel(true); + SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f, + null); + Color expected = UserColourScheme.createColourFromName("desc"); + assertEquals(expected, fc.getColor(sf)); + } + + @Test(groups = { "Functional" }) + public void testGetColor_Graduated() + { + // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0, 0) + FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f); + // feature score is 75 which is 3/4 of the way from GRAY to RED + SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f, + null); + // the colour gradient is computed in float values from 0-1 (where 1 == 255) + float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f; + float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f; + float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f; + Color expected = new Color(red, green, blue); + assertEquals(expected, fc.getColor(sf)); + } + + @Test(groups = { "Functional" }) + public void testGetColor_belowThreshold() + { + // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0) + FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f, + 150f); + SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f, + null); + fc.setThreshold(100f); // ignore for now + assertTrue(fc.isColored(sf)); + assertEquals(new Color(204, 204, 204), fc.getColor(sf)); + + fc.setAboveThreshold(true); // feature lies below threshold + assertFalse(fc.isColored(sf)); + assertEquals(new Color(204, 204, 204), fc.getColor(sf)); + } +}