JAL-3032 BorderLayout renders panel correctly in JalviewJS
[jalview.git] / src / jalview / gui / TextColourChooser.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.gui;
22
23 import jalview.datamodel.SequenceGroup;
24 import jalview.gui.JalviewColourChooser.ColourChooserListener;
25 import jalview.util.MessageManager;
26
27 import java.awt.BorderLayout;
28 import java.awt.Color;
29 import java.awt.Dimension;
30 import java.awt.event.MouseAdapter;
31 import java.awt.event.MouseEvent;
32 import java.util.HashMap;
33 import java.util.Map;
34
35 import javax.swing.BorderFactory;
36 import javax.swing.JLabel;
37 import javax.swing.JPanel;
38 import javax.swing.JSlider;
39 import javax.swing.event.ChangeEvent;
40 import javax.swing.event.ChangeListener;
41
42 public class TextColourChooser
43 {
44   AlignmentPanel ap;
45
46   SequenceGroup sg;
47
48   Color original1, original2;
49
50   int originalThreshold;
51
52   Map<SequenceGroup, Color> groupColour1;
53
54   Map<SequenceGroup, Color> groupColour2;
55
56   Map<SequenceGroup, Integer> groupThreshold;
57
58   /**
59    * Show a dialogue which allows the user to select two text colours and adjust
60    * a slider for the cross-over point
61    * 
62    * @param alignPanel
63    *          the AlignmentPanel context
64    * @param sequenceGroup
65    *          the SequenceGroup context (only for group pop-menu option)
66    */
67   public void chooseColour(AlignmentPanel alignPanel,
68           SequenceGroup sequenceGroup)
69   {
70     this.ap = alignPanel;
71     this.sg = sequenceGroup;
72
73     saveInitialSettings();
74
75     final JSlider slider = new JSlider(0, 750, originalThreshold);
76     final JPanel col1 = new JPanel();
77     col1.setPreferredSize(new Dimension(40, 20));
78     col1.setBorder(BorderFactory.createEtchedBorder());
79     col1.setToolTipText(MessageManager.getString("label.dark_colour"));
80     col1.setBackground(original1);
81     final JPanel col2 = new JPanel();
82     col2.setPreferredSize(new Dimension(40, 20));
83     col2.setBorder(BorderFactory.createEtchedBorder());
84     col2.setToolTipText(MessageManager.getString("label.light_colour"));
85     col2.setBackground(original2);
86     final JPanel bigpanel = new JPanel(new BorderLayout());
87     JPanel panel = new JPanel(new BorderLayout());
88     bigpanel.add(panel, BorderLayout.CENTER);
89     bigpanel.add(
90             new JLabel("<html>"
91                     + MessageManager.getString(
92                             "label.select_dark_light_set_threshold")
93                     + "</html>"),
94             BorderLayout.NORTH);
95     panel.add(col1, BorderLayout.WEST);
96     panel.add(slider, BorderLayout.CENTER);
97     panel.add(col2, BorderLayout.EAST);
98
99     col1.addMouseListener(new MouseAdapter()
100     {
101       @Override
102       public void mousePressed(MouseEvent e)
103       {
104         String ttl = MessageManager.getString("label.select_colour_for_text");
105         ColourChooserListener listener = new ColourChooserListener()
106         {
107           @Override
108           public void colourSelected(Color c)
109           {
110             colour1Changed(c);
111             col1.setBackground(c);
112           }
113         };
114         JalviewColourChooser.showColourChooser(bigpanel, ttl,
115                 col1.getBackground(), listener);
116       }
117     });
118
119     col2.addMouseListener(new MouseAdapter()
120     {
121       @Override
122       public void mousePressed(MouseEvent e)
123       {
124         String ttl = MessageManager.getString("label.select_colour_for_text");
125         ColourChooserListener listener = new ColourChooserListener()
126         {
127           @Override
128           public void colourSelected(Color c)
129           {
130             colour2Changed(c);
131             col2.setBackground(c);
132           }
133         };
134         JalviewColourChooser.showColourChooser(bigpanel, ttl,
135                 col2.getBackground(), listener);
136       }
137     });
138
139     slider.addChangeListener(new ChangeListener()
140     {
141       @Override
142       public void stateChanged(ChangeEvent evt)
143       {
144         thresholdChanged(slider.getValue());
145       }
146     });
147
148     int reply = JvOptionPane.showInternalOptionDialog(alignPanel, bigpanel,
149             MessageManager.getString(
150                     "label.adjunst_foreground_text_colour_threshold"),
151             JvOptionPane.OK_CANCEL_OPTION, JvOptionPane.QUESTION_MESSAGE,
152             null, null, null);
153
154     if (reply == JvOptionPane.CANCEL_OPTION)
155     {
156       restoreInitialSettings();
157     }
158   }
159
160   /**
161    * Restore initial settings on Cancel
162    */
163   protected void restoreInitialSettings()
164   {
165     if (sg == null)
166     {
167       ap.av.setTextColour(original1);
168       ap.av.setTextColour2(original2);
169       ap.av.setThresholdTextColour(originalThreshold);
170     }
171     else
172     {
173       sg.textColour = original1;
174       sg.textColour2 = original2;
175       sg.thresholdTextColour = originalThreshold;
176     }
177
178     /*
179      * if 'Apply To All Groups' was in force, there will be 
180      * group-specific settings to restore as well
181      */
182     for (SequenceGroup group : this.groupColour1.keySet())
183     {
184       group.textColour = groupColour1.get(group);
185       group.textColour2 = groupColour2.get(group);
186       group.thresholdTextColour = groupThreshold.get(group);
187     }
188   }
189
190   /**
191    * Save settings on entry, for restore on Cancel
192    */
193   protected void saveInitialSettings()
194   {
195     groupColour1 = new HashMap<>();
196     groupColour2 = new HashMap<>();
197     groupThreshold = new HashMap<>();
198
199     if (sg == null)
200     {
201       /*
202        * alignment scope
203        */
204       original1 = ap.av.getTextColour();
205       original2 = ap.av.getTextColour2();
206       originalThreshold = ap.av.getThresholdTextColour();
207       if (ap.av.getColourAppliesToAllGroups()
208               && ap.av.getAlignment().getGroups() != null)
209       {
210         /*
211          * if applying changes to all groups, need to be able to 
212          * restore group settings as well
213          */
214         for (SequenceGroup group : ap.av.getAlignment().getGroups())
215         {
216           groupColour1.put(group, group.textColour);
217           groupColour2.put(group, group.textColour2);
218           groupThreshold.put(group, group.thresholdTextColour);
219         }
220       }
221     }
222     else
223     {
224       /*
225        * Sequence group scope
226        */
227       original1 = sg.textColour;
228       original2 = sg.textColour2;
229       originalThreshold = sg.thresholdTextColour;
230     }
231   }
232
233   void colour1Changed(Color col)
234   {
235     if (sg == null)
236     {
237       ap.av.setTextColour(col);
238       if (ap.av.getColourAppliesToAllGroups())
239       {
240         setGroupTextColour();
241       }
242     }
243     else
244     {
245       sg.textColour = col;
246     }
247
248     ap.paintAlignment(false, false);
249   }
250
251   void colour2Changed(Color col)
252   {
253     if (sg == null)
254     {
255       ap.av.setTextColour2(col);
256       if (ap.av.getColourAppliesToAllGroups())
257       {
258         setGroupTextColour();
259       }
260     }
261     else
262     {
263       sg.textColour2 = col;
264     }
265
266     ap.paintAlignment(false, false);
267   }
268
269   void thresholdChanged(int value)
270   {
271     if (sg == null)
272     {
273       ap.av.setThresholdTextColour(value);
274       if (ap.av.getColourAppliesToAllGroups())
275       {
276         setGroupTextColour();
277       }
278     }
279     else
280     {
281       sg.thresholdTextColour = value;
282     }
283
284     ap.paintAlignment(false, false);
285   }
286
287   void setGroupTextColour()
288   {
289     if (ap.av.getAlignment().getGroups() == null)
290     {
291       return;
292     }
293
294     for (SequenceGroup group : ap.av.getAlignment().getGroups())
295     {
296       group.textColour = ap.av.getTextColour();
297       group.textColour2 = ap.av.getTextColour2();
298       group.thresholdTextColour = ap.av.getThresholdTextColour();
299     }
300   }
301
302 }