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