1. Project Clover database Fri Dec 6 2024 13:47:14 GMT
  2. Package jalview.appletgui

File FeatureRenderer.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

56
189
13
2
539
395
46
0.24
14.54
6.5
3.54

Classes

Class
Line #
Actions
FeatureRenderer 64 160 37
0.00%
FeatureRenderer.FeatureColourPanel 96 29 9
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.appletgui;
22   
23    import jalview.api.FeatureColourI;
24    import jalview.datamodel.SearchResults;
25    import jalview.datamodel.SearchResultsI;
26    import jalview.datamodel.SequenceFeature;
27    import jalview.datamodel.SequenceI;
28    import jalview.io.FeaturesFile;
29    import jalview.schemes.FeatureColour;
30    import jalview.util.ColorUtils;
31    import jalview.util.MessageManager;
32    import jalview.viewmodel.AlignmentViewport;
33   
34    import java.awt.BorderLayout;
35    import java.awt.Button;
36    import java.awt.Choice;
37    import java.awt.Color;
38    import java.awt.Dimension;
39    import java.awt.FlowLayout;
40    import java.awt.Font;
41    import java.awt.Frame;
42    import java.awt.Graphics;
43    import java.awt.GridLayout;
44    import java.awt.Label;
45    import java.awt.Panel;
46    import java.awt.ScrollPane;
47    import java.awt.TextArea;
48    import java.awt.TextField;
49    import java.awt.event.ActionEvent;
50    import java.awt.event.ActionListener;
51    import java.awt.event.MouseAdapter;
52    import java.awt.event.MouseEvent;
53    import java.awt.event.TextEvent;
54    import java.awt.event.TextListener;
55    import java.util.Hashtable;
56    import java.util.List;
57   
58    /**
59    * DOCUMENT ME!
60    *
61    * @author $author$
62    * @version $Revision$
63    */
 
64    public class FeatureRenderer
65    extends jalview.renderer.seqfeatures.FeatureRenderer
66    {
67    /*
68    * creating a new feature defaults to the type and group as
69    * the last one created
70    */
71    static String lastFeatureAdded = "feature_1";
72   
73    static String lastFeatureGroupAdded = "Jalview";
74   
75    // Holds web links for feature groups and feature types
76    // in the form label|link
77    Hashtable featureLinks = null;
78   
79    /**
80    * Creates a new FeatureRenderer object.
81    *
82    * @param av
83    */
 
84  0 toggle public FeatureRenderer(AlignmentViewport av)
85    {
86  0 super(av);
87   
88    }
89   
90    int featureIndex = 0;
91   
92    boolean deleteFeature = false;
93   
94    FeatureColourPanel colourPanel;
95   
 
96    class FeatureColourPanel extends Panel
97    {
98    String label = "";
99   
100    private Color maxCol;
101   
102    private boolean isColourByLabel, isGcol;
103   
104    /**
105    * render a feature style in the amend feature dialog box
106    */
 
107  0 toggle public void updateColor(FeatureColourI newcol)
108    {
109  0 Color bg = null;
110  0 String vlabel = "";
111  0 if (newcol.isSimpleColour())
112    {
113  0 bg = newcol.getColour();
114  0 setBackground(bg);
115    }
116    else
117    {
118  0 if (newcol.isAboveThreshold())
119    {
120  0 vlabel += " (>)";
121    }
122  0 else if (newcol.isBelowThreshold())
123    {
124  0 vlabel += " (<)";
125    }
126   
127  0 if (isColourByLabel = newcol.isColourByLabel())
128    {
129  0 setBackground(bg = Color.white);
130  0 vlabel += " (by Label)";
131    }
132    else
133    {
134  0 setBackground(bg = newcol.getMinColour());
135  0 maxCol = newcol.getMaxColour();
136    }
137    }
138  0 label = vlabel;
139  0 setBackground(bg);
140  0 repaint();
141    }
142   
 
143  0 toggle FeatureColourPanel()
144    {
145  0 super(null);
146    }
147   
 
148  0 toggle @Override
149    public void paint(Graphics g)
150    {
151  0 Dimension d = getSize();
152  0 if (isGcol)
153    {
154  0 if (isColourByLabel)
155    {
156  0 g.setColor(Color.white);
157  0 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
158  0 g.setColor(Color.black);
159  0 Font f = new Font("Verdana", Font.PLAIN, 10);
160  0 g.setFont(f);
161  0 g.drawString(MessageManager.getString("label.label"), 0, 0);
162    }
163    else
164    {
165  0 g.setColor(maxCol);
166  0 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
167   
168    }
169    }
170    }
171   
172    }
173   
174    /**
175    * Shows a dialog allowing the user to create, or amend or delete, sequence
176    * features. If null in the supplied feature(s), feature type and group
177    * default to those for the last feature created (with initial defaults of
178    * "feature_1" and "Jalview").
179    *
180    * @param sequences
181    * @param features
182    * @param create
183    * @param ap
184    * @return
185    */
 
186  0 toggle boolean amendFeatures(final List<SequenceI> sequences,
187    final List<SequenceFeature> features, boolean create,
188    final AlignmentPanel ap)
189    {
190  0 final Panel bigPanel = new Panel(new BorderLayout());
191  0 final TextField name = new TextField(16);
192  0 final TextField group = new TextField(16);
193  0 final TextArea description = new TextArea(3, 35);
194  0 final TextField start = new TextField(8);
195  0 final TextField end = new TextField(8);
196  0 final Choice overlaps;
197  0 Button deleteButton = new Button("Delete");
198  0 deleteFeature = false;
199   
200  0 name.addTextListener(new TextListener()
201    {
 
202  0 toggle @Override
203    public void textValueChanged(TextEvent e)
204    {
205  0 warnIfTypeHidden(ap.alignFrame, name.getText());
206    }
207    });
208  0 group.addTextListener(new TextListener()
209    {
 
210  0 toggle @Override
211    public void textValueChanged(TextEvent e)
212    {
213  0 warnIfGroupHidden(ap.alignFrame, group.getText());
214    }
215    });
216  0 colourPanel = new FeatureColourPanel();
217  0 colourPanel.setSize(110, 15);
218  0 final FeatureRenderer fr = this;
219   
220  0 Panel panel = new Panel(new GridLayout(3, 1));
221   
222  0 featureIndex = 0; // feature to be amended.
223  0 Panel tmp;
224   
225    // /////////////////////////////////////
226    // /MULTIPLE FEATURES AT SELECTED RESIDUE
227  0 if (!create && features.size() > 1)
228    {
229  0 panel = new Panel(new GridLayout(4, 1));
230  0 tmp = new Panel();
231  0 tmp.add(new Label("Select Feature: "));
232  0 overlaps = new Choice();
233  0 for (SequenceFeature sf : features)
234    {
235  0 String item = sf.getType() + "/" + sf.getBegin() + "-"
236    + sf.getEnd();
237  0 if (sf.getFeatureGroup() != null)
238    {
239  0 item += " (" + sf.getFeatureGroup() + ")";
240    }
241  0 overlaps.addItem(item);
242    }
243   
244  0 tmp.add(overlaps);
245   
246  0 overlaps.addItemListener(new java.awt.event.ItemListener()
247    {
 
248  0 toggle @Override
249    public void itemStateChanged(java.awt.event.ItemEvent e)
250    {
251  0 int index = overlaps.getSelectedIndex();
252  0 if (index != -1)
253    {
254  0 featureIndex = index;
255  0 SequenceFeature sf = features.get(index);
256  0 name.setText(sf.getType());
257  0 description.setText(sf.getDescription());
258  0 group.setText(sf.getFeatureGroup());
259  0 start.setText(sf.getBegin() + "");
260  0 end.setText(sf.getEnd() + "");
261   
262  0 SearchResultsI highlight = new SearchResults();
263  0 highlight.addResult(sequences.get(0), sf.getBegin(),
264    sf.getEnd());
265   
266  0 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
267   
268    }
269  0 FeatureColourI col = getFeatureStyle(name.getText());
270  0 if (col == null)
271    {
272  0 Color generatedColour = ColorUtils
273    .createColourFromName(name.getText());
274  0 col = new FeatureColour(generatedColour);
275    }
276   
277  0 colourPanel.updateColor(col);
278    }
279    });
280   
281  0 panel.add(tmp);
282    }
283    // ////////
284    // ////////////////////////////////////
285   
286  0 tmp = new Panel();
287  0 panel.add(tmp);
288  0 tmp.add(new Label(MessageManager.getString("label.name:"),
289    Label.RIGHT));
290  0 tmp.add(name);
291   
292  0 tmp = new Panel();
293  0 panel.add(tmp);
294  0 tmp.add(new Label(MessageManager.getString("label.group:"),
295    Label.RIGHT));
296  0 tmp.add(group);
297   
298  0 tmp = new Panel();
299  0 panel.add(tmp);
300  0 tmp.add(new Label(MessageManager.getString("label.colour"),
301    Label.RIGHT));
302  0 tmp.add(colourPanel);
303   
304  0 bigPanel.add(panel, BorderLayout.NORTH);
305   
306  0 panel = new Panel();
307  0 panel.add(new Label(MessageManager.getString("label.description:"),
308    Label.RIGHT));
309  0 panel.add(new ScrollPane().add(description));
310   
311  0 if (!create)
312    {
313  0 bigPanel.add(panel, BorderLayout.SOUTH);
314   
315  0 panel = new Panel();
316  0 panel.add(new Label(MessageManager.getString("label.start"),
317    Label.RIGHT));
318  0 panel.add(start);
319  0 panel.add(new Label(MessageManager.getString("label.end"),
320    Label.RIGHT));
321  0 panel.add(end);
322  0 bigPanel.add(panel, BorderLayout.CENTER);
323    }
324    else
325    {
326  0 bigPanel.add(panel, BorderLayout.CENTER);
327    }
328   
329    /*
330    * use defaults for type and group (and update them on Confirm) only
331    * if feature type has not been supplied by the caller
332    * (e.g. for Amend, or create features from Find)
333    */
334  0 SequenceFeature firstFeature = features.get(0);
335  0 boolean useLastDefaults = firstFeature.getType() == null;
336  0 String featureType = useLastDefaults ? lastFeatureAdded
337    : firstFeature.getType();
338  0 String featureGroup = useLastDefaults ? lastFeatureGroupAdded
339    : firstFeature.getFeatureGroup();
340   
341  0 String title = create
342    ? MessageManager.getString("label.create_new_sequence_features")
343    : MessageManager.formatMessage("label.amend_delete_features",
344    new String[]
345    { sequences.get(0).getName() });
346   
347  0 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
348    240);
349   
350  0 dialog.setMainPanel(bigPanel);
351   
352  0 name.setText(featureType);
353  0 group.setText(featureGroup);
354   
355  0 if (!create)
356    {
357  0 dialog.ok.setLabel(MessageManager.getString("label.amend"));
358  0 dialog.buttonPanel.add(deleteButton, 1);
359  0 deleteButton.addActionListener(new ActionListener()
360    {
 
361  0 toggle @Override
362    public void actionPerformed(ActionEvent evt)
363    {
364  0 deleteFeature = true;
365  0 dialog.setVisible(false);
366    }
367    });
368    }
369   
370  0 start.setText(firstFeature.getBegin() + "");
371  0 end.setText(firstFeature.getEnd() + "");
372  0 description.setText(firstFeature.getDescription());
373    // lookup (or generate) the feature colour
374  0 FeatureColourI fcol = getFeatureStyle(name.getText());
375    // simply display the feature color in a box
376  0 colourPanel.updateColor(fcol);
377  0 dialog.setResizable(true);
378    // TODO: render the graduated color in the box.
379  0 colourPanel.addMouseListener(new MouseAdapter()
380    {
 
381  0 toggle @Override
382    public void mousePressed(MouseEvent evt)
383    {
384  0 if (!colourPanel.isGcol)
385    {
386  0 new UserDefinedColours(fr, ap.alignFrame);
387    }
388    else
389    {
390  0 new FeatureColourChooser(ap.alignFrame, name.getText());
391  0 dialog.transferFocus();
392    }
393    }
394    });
395  0 dialog.setVisible(true);
396   
397  0 FeaturesFile ffile = new FeaturesFile();
398   
399    /*
400    * only update default type and group if we used defaults
401    */
402  0 final String enteredType = name.getText().trim();
403  0 final String enteredGroup = group.getText().trim();
404  0 final String enteredDesc = description.getText().replace('\n', ' ');
405   
406  0 if (dialog.accept && useLastDefaults)
407    {
408  0 lastFeatureAdded = enteredType;
409  0 lastFeatureGroupAdded = enteredGroup;
410    }
411   
412  0 if (!create)
413    {
414  0 SequenceFeature sf = features.get(featureIndex);
415  0 if (dialog.accept)
416    {
417  0 if (!colourPanel.isGcol)
418    {
419    // update colour - otherwise its already done.
420  0 setColour(enteredType,
421    new FeatureColour(colourPanel.getBackground()));
422    }
423  0 int newBegin = sf.begin;
424  0 int newEnd = sf.end;
425  0 try
426    {
427  0 newBegin = Integer.parseInt(start.getText());
428  0 newEnd = Integer.parseInt(end.getText());
429    } catch (NumberFormatException ex)
430    {
431    //
432    }
433   
434    /*
435    * replace the feature by deleting it and adding a new one
436    * (to ensure integrity of SequenceFeatures data store)
437    */
438  0 sequences.get(0).deleteFeature(sf);
439  0 SequenceFeature newSf = new SequenceFeature(sf, enteredType,
440    newBegin, newEnd, enteredGroup, sf.getScore());
441  0 newSf.setDescription(enteredDesc);
442  0 ffile.parseDescriptionHTML(newSf, false);
443    // amend features dialog only updates one sequence at a time
444  0 sequences.get(0).addSequenceFeature(newSf);
445  0 boolean typeOrGroupChanged = (!featureType.equals(newSf.getType())
446    || !featureGroup.equals(newSf.getFeatureGroup()));
447   
448  0 ffile.parseDescriptionHTML(sf, false);
449  0 if (typeOrGroupChanged)
450    {
451  0 featuresAdded();
452    }
453    }
454  0 if (deleteFeature)
455    {
456  0 sequences.get(0).deleteFeature(sf);
457    // ensure Feature Settings reflects removal of feature / group
458  0 featuresAdded();
459    }
460    }
461    else
462    {
463    /*
464    * adding feature(s)
465    */
466  0 if (dialog.accept && name.getText().length() > 0)
467    {
468  0 for (int i = 0; i < sequences.size(); i++)
469    {
470  0 SequenceFeature sf = features.get(i);
471  0 SequenceFeature sf2 = new SequenceFeature(enteredType,
472    enteredDesc, sf.getBegin(), sf.getEnd(), enteredGroup);
473  0 ffile.parseDescriptionHTML(sf2, false);
474  0 sequences.get(i).addSequenceFeature(sf2);
475    }
476   
477  0 Color newColour = colourPanel.getBackground();
478    // setColour(lastFeatureAdded, fcol);
479   
480  0 setColour(enteredType, new FeatureColour(newColour)); // was fcol
481  0 featuresAdded();
482    }
483    else
484    {
485    // no update to the alignment
486  0 return false;
487    }
488    }
489    // refresh the alignment and the feature settings dialog
490  0 if (((jalview.appletgui.AlignViewport) av).featureSettings != null)
491    {
492  0 ((jalview.appletgui.AlignViewport) av).featureSettings.refreshTable();
493    }
494    // findAllFeatures();
495   
496  0 ap.paintAlignment(true, true);
497   
498  0 return true;
499    }
500   
 
501  0 toggle protected void warnIfGroupHidden(Frame frame, String group)
502    {
503  0 if (featureGroups.containsKey(group) && !featureGroups.get(group))
504    {
505  0 String msg = MessageManager.formatMessage("label.warning_hidden",
506    MessageManager.getString("label.group"), group);
507  0 showWarning(frame, msg);
508    }
509    }
510   
 
511  0 toggle protected void warnIfTypeHidden(Frame frame, String type)
512    {
513  0 if (getRenderOrder().contains(type))
514    {
515  0 if (!showFeatureOfType(type))
516    {
517  0 String msg = MessageManager.formatMessage("label.warning_hidden",
518    MessageManager.getString("label.feature_type"), type);
519  0 showWarning(frame, msg);
520    }
521    }
522    }
523   
524    /**
525    * @param frame
526    * @param msg
527    */
 
528  0 toggle protected void showWarning(Frame frame, String msg)
529    {
530  0 JVDialog d = new JVDialog(frame, "", true, 350, 200);
531  0 Panel mp = new Panel();
532  0 d.ok.setLabel(MessageManager.getString("action.ok"));
533  0 d.cancel.setVisible(false);
534  0 mp.setLayout(new FlowLayout());
535  0 mp.add(new Label(msg));
536  0 d.setMainPanel(mp);
537  0 d.setVisible(true);
538    }
539    }