Merge branch 'develop' into features/JAL-2094_colourInterface
[jalview.git] / src / jalview / appletgui / UserDefinedColours.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.api.FeatureColourI;
24 import jalview.datamodel.SequenceGroup;
25 import jalview.schemes.Colour;
26 import jalview.schemes.ColourSchemeI;
27 import jalview.schemes.FeatureColour;
28 import jalview.schemes.ResidueProperties;
29 import jalview.schemes.UserColourScheme;
30 import jalview.util.ColorUtils;
31 import jalview.util.MessageManager;
32
33 import java.awt.Button;
34 import java.awt.Color;
35 import java.awt.Component;
36 import java.awt.Container;
37 import java.awt.Dialog;
38 import java.awt.Font;
39 import java.awt.Frame;
40 import java.awt.GridLayout;
41 import java.awt.Label;
42 import java.awt.Panel;
43 import java.awt.Rectangle;
44 import java.awt.Scrollbar;
45 import java.awt.TextField;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.AdjustmentEvent;
49 import java.awt.event.AdjustmentListener;
50 import java.awt.event.FocusEvent;
51 import java.awt.event.FocusListener;
52 import java.awt.event.MouseEvent;
53 import java.util.Vector;
54
55 public class UserDefinedColours extends Panel implements ActionListener,
56         AdjustmentListener, FocusListener
57 {
58
59   AlignmentPanel ap;
60
61   SequenceGroup seqGroup;
62
63   Button selectedButton;
64
65   Vector<Color> oldColours = new Vector<Color>();
66
67   ColourSchemeI oldColourScheme;
68
69   Frame frame;
70
71   MCview.AppletPDBCanvas pdbcanvas;
72
73   AppletJmol jmol;
74
75   Dialog dialog;
76
77   Object caller;
78
79   String originalLabel;
80
81   FeatureColourI originalColour;
82
83   int R = 0, G = 0, B = 0;
84
85   public ColourSchemeI loadDefaultColours()
86   {
87     // NOT IMPLEMENTED YET IN APPLET VERSION
88     return null;
89   }
90
91   public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
92   {
93     this.ap = ap;
94     seqGroup = sg;
95
96     if (seqGroup != null)
97     {
98       oldColourScheme = seqGroup.cs;
99     }
100     else
101     {
102       oldColourScheme = ap.av.getGlobalColourScheme();
103     }
104
105     init();
106   }
107
108   public UserDefinedColours(MCview.AppletPDBCanvas pdb)
109   {
110     this.pdbcanvas = pdb;
111     init();
112   }
113
114   public UserDefinedColours(AppletJmol jmol)
115   {
116     this.jmol = jmol;
117     init();
118   }
119
120   public UserDefinedColours(FeatureRenderer fr, Frame alignframe)
121   {
122     caller = fr;
123     originalColour = new FeatureColour(new Colour(
124             fr.colourPanel.getBackground()));
125     originalLabel = "Feature Colour";
126     setForDialog("Select Feature Colour", alignframe);
127     setTargetColour(fr.colourPanel.getBackground());
128     dialog.setVisible(true);
129   }
130
131   public UserDefinedColours(Component caller, Color col1, Frame alignframe)
132   {
133     this(caller, col1, alignframe, "Select Colour");
134   }
135
136   /**
137    * Makes a dialog to choose the colour
138    * 
139    * @param caller
140    *          - handles events
141    * @param col
142    *          - original colour
143    * @param alignframe
144    *          - the parent Frame for the dialog
145    * @param title
146    *          - window title
147    */
148   public UserDefinedColours(Component caller, Color col, Frame alignframe,
149           String title)
150   {
151     this.caller = caller;
152     originalColour = new FeatureColour(new Colour(col));
153     originalLabel = title;
154     setForDialog(title, alignframe);
155     setTargetColour(col);
156     dialog.setVisible(true);
157   }
158
159   /**
160    * feature colour chooser
161    * 
162    * @param caller
163    * @param label
164    * @param colour
165    */
166   public UserDefinedColours(Object caller, String label, Color colour)
167   {
168     this(caller, label, new FeatureColour(new Colour(colour)), colour);
169   }
170
171   /**
172    * feature colour chooser when changing style to single color
173    * 
174    * @param me
175    * @param type
176    * @param graduatedColor
177    */
178   public UserDefinedColours(FeatureSettings me, String type,
179           FeatureColourI graduatedColor)
180   {
181     this(me, type, graduatedColor, ColorUtils.getColor(graduatedColor
182             .getMaxColour()));
183   }
184
185   private UserDefinedColours(Object caller, String label,
186           FeatureColourI ocolour, Color colour)
187   {
188     this.caller = caller;
189     originalColour = ocolour;
190     originalLabel = label;
191     init();
192     remove(buttonPanel);
193
194     setTargetColour(colour);
195
196     okcancelPanel.setBounds(new Rectangle(0, 113, 400, 35));
197     frame.setTitle(MessageManager.getString("label.user_defined_colours")
198             + " - " + label);
199     frame.setSize(420, 200);
200   }
201
202   void setForDialog(String title, Container alignframe)
203   {
204     init();
205     frame.setVisible(false);
206     remove(buttonPanel);
207     if (alignframe instanceof Frame)
208     {
209       dialog = new Dialog((Frame) alignframe, title, true);
210     }
211     else
212     {
213       // if (alignframe instanceof JVDialog){
214       // // not 1.1 compatible!
215       // dialog = new Dialog(((JVDialog)alignframe), title, true);
216       // } else {
217       throw new Error(
218               MessageManager
219                       .getString("label.error_unsupported_owwner_user_colour_scheme"));
220     }
221
222     dialog.add(this);
223     this.setSize(400, 123);
224     okcancelPanel.setBounds(new Rectangle(0, 123, 400, 35));
225     int height = 160 + alignframe.getInsets().top + getInsets().bottom;
226     int width = 400;
227
228     dialog.setBounds(alignframe.getBounds().x
229             + (alignframe.getSize().width - width) / 2,
230             alignframe.getBounds().y
231                     + (alignframe.getSize().height - height) / 2, width,
232             height);
233
234   }
235
236   @Override
237   public void actionPerformed(ActionEvent evt)
238   {
239     final Object source = evt.getSource();
240     if (source == okButton)
241     {
242       okButton_actionPerformed();
243     }
244     else if (source == applyButton)
245     {
246       applyButton_actionPerformed();
247     }
248     else if (source == cancelButton)
249     {
250       cancelButton_actionPerformed();
251     }
252     else if (source == rText)
253     {
254       rText_actionPerformed();
255     }
256     else if (source == gText)
257     {
258       gText_actionPerformed();
259     }
260     else if (source == bText)
261     {
262       bText_actionPerformed();
263     }
264   }
265
266   @Override
267   public void adjustmentValueChanged(AdjustmentEvent evt)
268   {
269     if (evt.getSource() == rScroller)
270     {
271       rScroller_adjustmentValueChanged();
272     }
273     else if (evt.getSource() == gScroller)
274     {
275       gScroller_adjustmentValueChanged();
276     }
277     else if (evt.getSource() == bScroller)
278     {
279       bScroller_adjustmentValueChanged();
280     }
281   }
282
283   void init()
284   {
285     try
286     {
287       jbInit();
288     } catch (Exception e)
289     {
290       e.printStackTrace();
291     }
292     frame = new Frame();
293     frame.add(this);
294     jalview.bin.JalviewLite.addFrame(frame,
295             MessageManager.getString("label.user_defined_colours"), 420,
296             345);
297
298     if (seqGroup != null)
299     {
300       frame.setTitle(frame.getTitle() + " (" + seqGroup.getName() + ")");
301     }
302
303     for (int i = 0; i < 20; i++)
304     {
305       makeButton(ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i])
306               + "", ResidueProperties.aa[i]);
307     }
308
309     makeButton("B", "B");
310     makeButton("Z", "Z");
311     makeButton("X", "X");
312     makeButton("Gap", "'.','-',' '");
313
314     validate();
315   }
316
317   protected void rText_actionPerformed()
318   {
319     try
320     {
321       int i = Integer.parseInt(rText.getText());
322       rScroller.setValue(i);
323       rScroller_adjustmentValueChanged();
324     } catch (NumberFormatException ex)
325     {
326     }
327   }
328
329   protected void gText_actionPerformed()
330   {
331     try
332     {
333       int i = Integer.parseInt(gText.getText());
334       gScroller.setValue(i);
335       gScroller_adjustmentValueChanged();
336     } catch (NumberFormatException ex)
337     {
338     }
339
340   }
341
342   protected void bText_actionPerformed()
343   {
344     try
345     {
346       int i = Integer.parseInt(bText.getText());
347       bScroller.setValue(i);
348       bScroller_adjustmentValueChanged();
349     } catch (NumberFormatException ex)
350     {
351     }
352
353   }
354
355   protected void rScroller_adjustmentValueChanged()
356   {
357     R = rScroller.getValue();
358     rText.setText(R + "");
359     colourChanged();
360   }
361
362   protected void gScroller_adjustmentValueChanged()
363   {
364     G = gScroller.getValue();
365     gText.setText(G + "");
366     colourChanged();
367   }
368
369   protected void bScroller_adjustmentValueChanged()
370   {
371     B = bScroller.getValue();
372     bText.setText(B + "");
373     colourChanged();
374   }
375
376   public void colourChanged()
377   {
378     Color col = new Color(R, G, B);
379     target.setBackground(col);
380     target.repaint();
381
382     if (selectedButton != null)
383     {
384       selectedButton.setBackground(col);
385       selectedButton.repaint();
386     }
387   }
388
389   void setTargetColour(Color col)
390   {
391     R = col.getRed();
392     G = col.getGreen();
393     B = col.getBlue();
394
395     rScroller.setValue(R);
396     gScroller.setValue(G);
397     bScroller.setValue(B);
398     rText.setText(R + "");
399     gText.setText(G + "");
400     bText.setText(B + "");
401     colourChanged();
402   }
403
404   public void colourButtonPressed(MouseEvent e)
405   {
406     selectedButton = (Button) e.getSource();
407     setTargetColour(selectedButton.getBackground());
408   }
409
410   void makeButton(String label, String aa)
411   {
412     final Button button = new Button();
413     Color col = Color.white;
414     if (oldColourScheme != null)
415     {
416       try
417       {
418         col = oldColourScheme.findColour(aa.charAt(0), -1, null);
419       } catch (Exception ex)
420       {
421       }
422     }
423     button.setBackground(col);
424     oldColours.addElement(col);
425     button.setLabel(label);
426     button.setForeground(col.darker().darker().darker());
427     button.setFont(new java.awt.Font("Verdana", 1, 10));
428     button.addMouseListener(new java.awt.event.MouseAdapter()
429     {
430       @Override
431       public void mousePressed(MouseEvent e)
432       {
433         colourButtonPressed(e);
434       }
435     });
436
437     buttonPanel.add(button, null);
438   }
439
440   protected void okButton_actionPerformed()
441   {
442     applyButton_actionPerformed();
443     if (dialog != null)
444     {
445       dialog.setVisible(false);
446     }
447
448     frame.setVisible(false);
449   }
450
451   public Color getColor()
452   {
453     return new Color(R, G, B);
454   }
455
456   protected void applyButton_actionPerformed()
457   {
458     if (caller != null)
459     {
460       if (caller instanceof FeatureSettings)
461       {
462         ((FeatureSettings) caller).setUserColour(originalLabel,
463                 new FeatureColour(new Colour(getColor())));
464       }
465       else if (caller instanceof AnnotationColourChooser)
466       {
467         if (originalLabel.equals("Min Colour"))
468         {
469           ((AnnotationColourChooser) caller)
470                   .minColour_actionPerformed(getColor());
471         }
472         else
473         {
474           ((AnnotationColourChooser) caller)
475                   .maxColour_actionPerformed(getColor());
476         }
477       }
478       else if (caller instanceof FeatureRenderer)
479       {
480         ((FeatureRenderer) caller).colourPanel
481                 .updateColor(new FeatureColour(new Colour(getColor())));
482       }
483       else if (caller instanceof FeatureColourChooser)
484       {
485         if (originalLabel.indexOf("inimum") > -1)
486         {
487           ((FeatureColourChooser) caller)
488                   .minColour_actionPerformed(getColor());
489         }
490         else
491         {
492           ((FeatureColourChooser) caller)
493                   .maxColour_actionPerformed(getColor());
494         }
495       }
496
497       return;
498     }
499
500     Color[] newColours = new Color[24];
501     for (int i = 0; i < 24; i++)
502     {
503       Button button = (Button) buttonPanel.getComponent(i);
504       newColours[i] = button.getBackground();
505     }
506
507     UserColourScheme ucs = new UserColourScheme(newColours);
508     if (ap != null)
509     {
510       ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
511     }
512
513     if (ap != null)
514     {
515       if (seqGroup != null)
516       {
517         seqGroup.cs = ucs;
518       }
519       else
520       {
521         ap.av.setGlobalColourScheme(ucs);
522       }
523       ap.seqPanel.seqCanvas.img = null;
524       ap.paintAlignment(true);
525     }
526     else if (jmol != null)
527     {
528       jmol.setJalviewColourScheme(ucs);
529     }
530     else if (pdbcanvas != null)
531     {
532       pdbcanvas.setColours(ucs);
533     }
534   }
535
536   protected void cancelButton_actionPerformed()
537   {
538     if (caller != null)
539     {
540       if (caller instanceof FeatureSettings)
541       {
542         ((FeatureSettings) caller).setUserColour(originalLabel,
543                 originalColour);
544       }
545       else if (caller instanceof AnnotationColourChooser)
546       {
547         if (originalLabel.equals("Min Colour"))
548         {
549           ((AnnotationColourChooser) caller)
550                   .minColour_actionPerformed(ColorUtils
551                           .getColor(originalColour.getColour()));
552         }
553         else
554         {
555           ((AnnotationColourChooser) caller)
556                   .maxColour_actionPerformed(ColorUtils
557                           .getColor(originalColour.getColour()));
558         }
559       }
560       else if (caller instanceof FeatureRenderer)
561       {
562         ((FeatureRenderer) caller).colourPanel.updateColor(originalColour);
563
564       }
565
566       else if (caller instanceof FeatureColourChooser)
567       {
568         if (originalLabel.indexOf("inimum") > -1)
569         {
570           ((FeatureColourChooser) caller)
571                   .minColour_actionPerformed(ColorUtils
572                           .getColor(originalColour.getColour()));
573         }
574         else
575         {
576           ((FeatureColourChooser) caller)
577                   .maxColour_actionPerformed(ColorUtils
578                           .getColor(originalColour.getColour()));
579         }
580       }
581       if (dialog != null)
582       {
583         dialog.setVisible(false);
584       }
585
586       frame.setVisible(false);
587       return;
588     }
589
590     Color[] newColours = new Color[24];
591     for (int i = 0; i < 24; i++)
592     {
593       newColours[i] = oldColours.elementAt(i);
594       buttonPanel.getComponent(i).setBackground(newColours[i]);
595     }
596
597     UserColourScheme ucs = new UserColourScheme(newColours);
598
599     if (ap != null)
600     {
601       if (seqGroup != null)
602       {
603         seqGroup.cs = ucs;
604       }
605       else
606       {
607         ap.av.setGlobalColourScheme(ucs);
608       }
609       ap.paintAlignment(true);
610     }
611     else if (jmol != null)
612     {
613       jmol.setJalviewColourScheme(ucs);
614     }
615     else if (pdbcanvas != null)
616     {
617       pdbcanvas.pdb.setColours(ucs);
618     }
619
620     frame.setVisible(false);
621   }
622
623   protected Panel buttonPanel = new Panel();
624
625   protected GridLayout gridLayout = new GridLayout();
626
627   Panel okcancelPanel = new Panel();
628
629   protected Button okButton = new Button();
630
631   protected Button applyButton = new Button();
632
633   protected Button cancelButton = new Button();
634
635   protected Scrollbar rScroller = new Scrollbar();
636
637   Label label1 = new Label();
638
639   protected TextField rText = new TextField();
640
641   Label label4 = new Label();
642
643   protected Scrollbar gScroller = new Scrollbar();
644
645   protected TextField gText = new TextField();
646
647   Label label5 = new Label();
648
649   protected Scrollbar bScroller = new Scrollbar();
650
651   protected TextField bText = new TextField();
652
653   protected Panel target = new Panel();
654
655   private void jbInit() throws Exception
656   {
657     this.setLayout(null);
658     buttonPanel.setLayout(gridLayout);
659     gridLayout.setColumns(6);
660     gridLayout.setRows(4);
661     okButton.setFont(new java.awt.Font("Verdana", 0, 11));
662     okButton.setLabel(MessageManager.getString("action.ok"));
663     okButton.addActionListener(this);
664     applyButton.setFont(new java.awt.Font("Verdana", 0, 11));
665     applyButton.setLabel(MessageManager.getString("action.apply"));
666     applyButton.addActionListener(this);
667     cancelButton.setFont(new java.awt.Font("Verdana", 0, 11));
668     cancelButton.setLabel(MessageManager.getString("action.cancel"));
669     cancelButton.addActionListener(this);
670     this.setBackground(new Color(212, 208, 223));
671     okcancelPanel.setBounds(new Rectangle(0, 265, 400, 35));
672     buttonPanel.setBounds(new Rectangle(0, 123, 400, 142));
673     rScroller.setMaximum(256);
674     rScroller.setMinimum(0);
675     rScroller.setOrientation(0);
676     rScroller.setUnitIncrement(1);
677     rScroller.setVisibleAmount(1);
678     rScroller.setBounds(new Rectangle(36, 27, 119, 19));
679     rScroller.addAdjustmentListener(this);
680     label1.setAlignment(Label.RIGHT);
681     label1.setText("R");
682     label1.setBounds(new Rectangle(19, 30, 16, 15));
683     rText.setFont(new java.awt.Font("Dialog", Font.PLAIN, 10));
684     rText.setText("0        ");
685     rText.setBounds(new Rectangle(156, 27, 53, 19));
686     rText.addActionListener(this);
687     rText.addFocusListener(this);
688     label4.setAlignment(Label.RIGHT);
689     label4.setText("G");
690     label4.setBounds(new Rectangle(15, 56, 20, 15));
691     gScroller.setMaximum(256);
692     gScroller.setMinimum(0);
693     gScroller.setOrientation(0);
694     gScroller.setUnitIncrement(1);
695     gScroller.setVisibleAmount(1);
696     gScroller.setBounds(new Rectangle(35, 52, 120, 20));
697     gScroller.addAdjustmentListener(this);
698     gText.setFont(new java.awt.Font("Dialog", Font.PLAIN, 10));
699     gText.setText("0        ");
700     gText.setBounds(new Rectangle(156, 52, 53, 20));
701     gText.addActionListener(this);
702     gText.addFocusListener(this);
703     label5.setAlignment(Label.RIGHT);
704     label5.setText("B");
705     label5.setBounds(new Rectangle(14, 82, 20, 15));
706     bScroller.setMaximum(256);
707     bScroller.setMinimum(0);
708     bScroller.setOrientation(0);
709     bScroller.setUnitIncrement(1);
710     bScroller.setVisibleAmount(1);
711     bScroller.setBounds(new Rectangle(35, 78, 120, 20));
712     bScroller.addAdjustmentListener(this);
713     bText.setFont(new java.awt.Font("Dialog", Font.PLAIN, 10));
714     bText.setText("0        ");
715     bText.setBounds(new Rectangle(157, 78, 52, 20));
716     bText.addActionListener(this);
717     bText.addFocusListener(this);
718     target.setBackground(Color.black);
719     target.setBounds(new Rectangle(229, 26, 134, 79));
720     this.add(okcancelPanel, null);
721     okcancelPanel.add(okButton, null);
722     okcancelPanel.add(applyButton, null);
723     okcancelPanel.add(cancelButton, null);
724     this.add(rText);
725     this.add(gText);
726     this.add(bText);
727     this.add(buttonPanel, null);
728     this.add(target, null);
729     this.add(gScroller);
730     this.add(rScroller);
731     this.add(bScroller);
732     this.add(label5);
733     this.add(label4);
734     this.add(label1);
735   }
736
737   @Override
738   public void focusGained(FocusEvent e)
739   {
740     // noop
741   }
742
743   /**
744    * This method applies any change to an RGB value if the user tabs out of the
745    * field instead of pressing Enter
746    */
747   @Override
748   public void focusLost(FocusEvent e)
749   {
750     Component c = e.getComponent();
751     if (c == rText)
752     {
753       rText_actionPerformed();
754     }
755     else
756     {
757       if (c == gText)
758       {
759         gText_actionPerformed();
760       }
761       else
762       {
763         if (c == bText)
764         {
765           bText_actionPerformed();
766         }
767       }
768     }
769   }
770
771 }