JAL-1807 update
[jalviewjs.git] / unused / appletgui / FeatureRenderer.java
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.datamodel.SearchResults;
24 import jalview.datamodel.SequenceFeature;
25 import jalview.datamodel.SequenceI;
26 import jalview.io.FeaturesFile;
27 import jalview.schemes.AnnotationColourGradient;
28 import jalview.schemes.GraduatedColor;
29 import jalview.schemes.UserColourScheme;
30 import jalview.util.MessageManager;
31 import jalview.viewmodel.AlignmentViewport;
32
33 import java.awt.BorderLayout;
34 import javax.swing.JButton;
35 import java.awt.Color;
36 import java.awt.Dimension;
37 import java.awt.Font;
38 import java.awt.Graphics;
39 import java.awt.GridLayout;
40 import javax.swing.JLabel;
41 import javax.swing.JPanel;
42 import javax.swing.JScrollPane;
43 import javax.swing.JTextArea;
44 import javax.swing.JTextField;
45 import java.awt.event.ActionEvent;
46 import java.awt.event.ActionListener;
47 import java.util.Hashtable;
48
49 /**
50  * DOCUMENT ME!
51  * 
52  * @author $author$
53  * @version $Revision$
54  */
55 public class FeatureRenderer extends
56         jalview.renderer.seqfeatures.FeatureRenderer
57 {
58
59   // Holds web links for feature groups and feature types
60   // in the form label|link
61   Hashtable featureLinks = null;
62
63   /**
64    * Creates a new FeatureRenderer object.
65    * 
66    * @param av
67    *          DOCUMENT ME!
68    */
69   public FeatureRenderer(AlignmentViewport av)
70   {
71     super();
72     this.av = av;
73
74     setTransparencyAvailable(!System.getProperty("java.version")
75             .startsWith("1.1"));
76   }
77
78   static String lastFeatureAdded;
79
80   static String lastFeatureGroupAdded;
81
82   static String lastDescriptionAdded;
83
84   int featureIndex = 0;
85
86   boolean deleteFeature = false;
87
88   FeatureColourPanel colourPanel;
89
90   class FeatureColourPanel extends JPanel
91   {
92     String label = "";
93
94     private Color maxCol;
95
96     private boolean isColourByLabel, isGcol;
97
98     /**
99      * render a feature style in the amend feature dialog box
100      */
101     public void updateColor(Object newcol)
102     {
103
104       Color bg, col = null;
105       GraduatedColor gcol = null;
106       String vlabel = "";
107       if (newcol instanceof Color)
108       {
109         isGcol = false;
110         col = (Color) newcol;
111         gcol = null;
112       }
113       else if (newcol instanceof GraduatedColor)
114       {
115         isGcol = true;
116         gcol = (GraduatedColor) newcol;
117         col = null;
118       }
119       else
120       {
121         throw new Error(
122                 MessageManager
123                         .getString("error.invalid_colour_for_mycheckbox"));
124       }
125       if (col != null)
126       {
127         setBackground(bg = col);
128       }
129       else
130       {
131         if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
132         {
133           vlabel += " "
134                   + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
135                           : "(<)");
136         }
137         if (isColourByLabel = gcol.isColourByLabel())
138         {
139           setBackground(bg = Color.white);
140           vlabel += " (by Label)";
141         }
142         else
143         {
144           setBackground(bg = gcol.getMinColor());
145           maxCol = gcol.getMaxColor();
146         }
147       }
148       label = vlabel;
149       setBackground(bg);
150       repaint();
151     }
152
153     FeatureColourPanel()
154     {
155       super(null);
156     }
157
158     public void paint(Graphics g)
159     {
160       Dimension d = getSize();
161       if (isGcol)
162       {
163         if (isColourByLabel)
164         {
165           g.setColor(Color.white);
166           g.fillRect(d.width / 2, 0, d.width / 2, d.height);
167           g.setColor(Color.black);
168           Font f = new Font("Verdana", Font.PLAIN, 10);
169           g.setFont(f);
170           g.drawString(MessageManager.getString("label.label"), 0, 0);
171         }
172         else
173         {
174           g.setColor(maxCol);
175           g.fillRect(d.width / 2, 0, d.width / 2, d.height);
176
177         }
178       }
179     }
180
181   }
182
183   boolean amendFeatures(final SequenceI[] sequences,
184           final SequenceFeature[] features, boolean newFeatures,
185           final AlignmentPanel ap)
186   {
187     JPanel bigPanel = new JPanel(new BorderLayout());
188     final JTextField name = new JTextField(16);
189     final JTextField source = new JTextField(16);
190     final JTextArea description = new JTextArea(3, 35);
191     final JTextField start = new JTextField(8);
192     final JTextField end = new JTextField(8);
193     final Choice overlaps;
194     JButton deleteButton = new JButton("Delete");
195     deleteFeature = false;
196
197     colourPanel = new FeatureColourPanel();
198     colourPanel.setSize(110, 15);
199     final FeatureRenderer fr = this;
200
201     JPanel panel = new JPanel(new GridLayout(3, 1));
202
203     featureIndex = 0; // feature to be amended.
204     JPanel tmp;
205
206     // /////////////////////////////////////
207     // /MULTIPLE FEATURES AT SELECTED RESIDUE
208     if (!newFeatures && features.length > 1)
209     {
210       panel = new JPanel(new GridLayout(4, 1));
211       tmp = new JPanel();
212       tmp.add(new JLabel("Select Feature: "));
213       overlaps = new Choice();
214       for (int i = 0; i < features.length; i++)
215       {
216         String item = features[i].getType() + "/" + features[i].getBegin()
217                 + "-" + features[i].getEnd();
218
219         if (features[i].getFeatureGroup() != null)
220         {
221           item += " (" + features[i].getFeatureGroup() + ")";
222         }
223
224         overlaps.addItem(item);
225       }
226
227       tmp.add(overlaps);
228
229       overlaps.addItemListener(new java.awt.event.ItemListener()
230       {
231         public void itemStateChanged(java.awt.event.ItemEvent e)
232         {
233           int index = overlaps.getSelectedIndex();
234           if (index != -1)
235           {
236             featureIndex = index;
237             name.setText(features[index].getType());
238             description.setText(features[index].getDescription());
239             source.setText(features[index].getFeatureGroup());
240             start.setText(features[index].getBegin() + "");
241             end.setText(features[index].getEnd() + "");
242
243             SearchResults highlight = new SearchResults();
244             highlight.addResult(sequences[0], features[index].getBegin(),
245                     features[index].getEnd());
246
247             ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
248
249           }
250           Object col = getFeatureStyle(name.getText());
251           if (col == null)
252           {
253             col = new UserColourScheme().createColourFromName(name
254                     .getText());
255           }
256
257           colourPanel.updateColor(col);
258         }
259       });
260
261       panel.add(tmp);
262     }
263     // ////////
264     // ////////////////////////////////////
265
266     tmp = new JPanel();
267     panel.add(tmp);
268     tmp.add(new JLabel("Name: ", JLabel.RIGHT));
269     tmp.add(name);
270
271     tmp = new JPanel();
272     panel.add(tmp);
273     tmp.add(new JLabel("Group: ", JLabel.RIGHT));
274     tmp.add(source);
275
276     tmp = new JPanel();
277     panel.add(tmp);
278     tmp.add(new JLabel("Colour: ", JLabel.RIGHT));
279     tmp.add(colourPanel);
280
281     bigPanel.add(panel, BorderLayout.NORTH);
282
283     panel = new JPanel();
284     panel.add(new JLabel("Description: ", JLabel.RIGHT));
285     panel.add(new JScrollPane().add(description));
286
287     if (!newFeatures)
288     {
289       bigPanel.add(panel, BorderLayout.SOUTH);
290
291       panel = new JPanel();
292       panel.add(new JLabel(" Start:", JLabel.RIGHT));
293       panel.add(start);
294       panel.add(new JLabel("  End:", JLabel.RIGHT));
295       panel.add(end);
296       bigPanel.add(panel, BorderLayout.CENTER);
297     }
298     else
299     {
300       bigPanel.add(panel, BorderLayout.CENTER);
301     }
302
303     if (lastFeatureAdded == null)
304     {
305       if (features[0].type != null)
306       {
307         lastFeatureAdded = features[0].type;
308       }
309       else
310       {
311         lastFeatureAdded = "feature_1";
312       }
313     }
314
315     if (lastFeatureGroupAdded == null)
316     {
317       if (features[0].featureGroup != null)
318       {
319         lastFeatureGroupAdded = features[0].featureGroup;
320       }
321       else
322       {
323         lastFeatureAdded = "Jalview";
324       }
325     }
326
327     String title = newFeatures ? MessageManager
328             .getString("label.create_new_sequence_features")
329             : MessageManager.formatMessage("label.amend_delete_features",
330                     new String[]
331                     { sequences[0].getName() });
332
333     final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
334             240);
335
336     dialog.setMainPanel(bigPanel);
337
338     if (newFeatures)
339     {
340       name.setText(lastFeatureAdded);
341       source.setText(lastFeatureGroupAdded);
342     }
343     else
344     {
345       dialog.ok.setLabel(MessageManager.getString("label.amend"));
346       dialog.buttonPanel.add(deleteButton, 1);
347       deleteButton.addActionListener(new ActionListener()
348       {
349         public void actionPerformed(ActionEvent evt)
350         {
351           deleteFeature = true;
352           dialog.setVisible(false);
353         }
354       });
355       name.setText(features[0].getType());
356       source.setText(features[0].getFeatureGroup());
357     }
358
359     start.setText(features[0].getBegin() + "");
360     end.setText(features[0].getEnd() + "");
361     description.setText(features[0].getDescription());
362     Color col = getColour(name.getText());
363     if (col == null)
364     {
365       col = new UserColourScheme()
366               .createColourFromName(name.getText());
367     }
368     Object fcol = getFeatureStyle(name.getText());
369     // simply display the feature color in a box
370     colourPanel.updateColor(fcol);
371     dialog.setResizable(true);
372     // TODO: render the graduated color in the box.
373     colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
374     {
375       public void mousePressed(java.awt.event.MouseEvent evt)
376       {
377         if (!colourPanel.isGcol)
378         {
379           new UserDefinedColours(fr, ap.alignFrame);
380         }
381         else
382         {
383           FeatureColourChooser fcc = new FeatureColourChooser(
384                   ap.alignFrame, name.getText());
385           dialog.transferFocus();
386         }
387       }
388     });
389     dialog.setVisible(true);
390
391     FeaturesFile ffile = new FeaturesFile();
392
393     if (dialog.accept)
394     {
395       // This ensures that the last sequence
396       // is refreshed and new features are rendered
397       lastSeq = null;
398       lastFeatureAdded = name.getText().trim();
399       lastFeatureGroupAdded = source.getText().trim();
400       lastDescriptionAdded = description.getText().replace('\n', ' ');
401     }
402
403     if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
404     {
405       lastFeatureGroupAdded = null;
406     }
407
408     if (!newFeatures)
409     {
410
411       SequenceFeature sf = features[featureIndex];
412       if (dialog.accept)
413       {
414         sf.type = lastFeatureAdded;
415         sf.featureGroup = lastFeatureGroupAdded;
416         sf.description = lastDescriptionAdded;
417         if (!colourPanel.isGcol)
418         {
419           // update colour - otherwise its already done.
420           setColour(sf.type, colourPanel.getBackground());
421         }
422         try
423         {
424           sf.begin = Integer.parseInt(start.getText());
425           sf.end = Integer.parseInt(end.getText());
426         } catch (NumberFormatException ex)
427         {
428         }
429
430         ffile.parseDescriptionHTML(sf, false);
431         setVisible(lastFeatureAdded); // if user edited name then make sure new
432                                       // type is visible
433       }
434       if (deleteFeature)
435       {
436         sequences[0].deleteFeature(sf);
437       }
438
439     }
440     else
441     {
442       if (dialog.accept && name.getText().length() > 0)
443       {
444         for (int i = 0; i < sequences.length; i++)
445         {
446           features[i].type = lastFeatureAdded;
447           features[i].featureGroup = lastFeatureGroupAdded;
448           features[i].description = lastDescriptionAdded;
449           sequences[i].addSequenceFeature(features[i]);
450           ffile.parseDescriptionHTML(features[i], false);
451         }
452
453         Color newColour = colourPanel.getBackground();
454         // setColour(lastFeatureAdded, fcol);
455
456         if (lastFeatureGroupAdded != null)
457         {
458           setGroupVisibility(lastFeatureGroupAdded, true);
459         }
460         setColour(lastFeatureAdded, newColour); // was fcol
461         setVisible(lastFeatureAdded);
462         findAllFeatures(false); // different to original applet behaviour ?
463         // findAllFeatures();
464       }
465       else
466       {
467         // no update to the alignment
468         return false;
469       }
470     }
471     // refresh the alignment and the feature settings dialog
472     if (((AlignViewport) av).featureSettings != null)
473     {
474       ((AlignViewport) av).featureSettings.refreshTable();
475     }
476     // findAllFeatures();
477
478     ap.paintAlignment(true);
479
480     return true;
481   }
482 }