JAL-1925 update source version in license
[jalview.git] / src / jalview / appletgui / FontChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
3  * Copyright (C) 2015 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.ViewStyleI;
24 import jalview.util.MessageManager;
25
26 import java.awt.BorderLayout;
27 import java.awt.Button;
28 import java.awt.Checkbox;
29 import java.awt.Choice;
30 import java.awt.Color;
31 import java.awt.FlowLayout;
32 import java.awt.Font;
33 import java.awt.FontMetrics;
34 import java.awt.Frame;
35 import java.awt.Label;
36 import java.awt.Panel;
37 import java.awt.Toolkit;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.ItemEvent;
41 import java.awt.event.ItemListener;
42
43 /**
44  * This dialog allows the user to try different font settings and related
45  * options. Changes are immediately visible on the alignment or tree. The user
46  * can dismiss the dialog by confirming changes with 'OK', or reverting to
47  * previous settings with 'Cancel'.
48  */
49 @SuppressWarnings("serial")
50 public class FontChooser extends Panel implements ItemListener
51 {
52   private static final Font VERDANA_11PT = new Font("Verdana", 0, 11);
53
54   private Choice fontSize = new Choice();
55
56   private Choice fontStyle = new Choice();
57
58   private Choice fontName = new Choice();
59
60   private Checkbox scaleAsCdna = new Checkbox();
61
62   private Button ok = new Button();
63
64   private Button cancel = new Button();
65
66   private AlignmentPanel ap;
67
68   private TreePanel tp;
69
70   private Font oldFont;
71
72   private int oldCharWidth = 0;
73
74   private boolean oldScaleProtein = false;
75
76   private Font lastSelected = null;
77
78   private int lastSelStyle = 0;
79
80   private int lastSelSize = 0;
81
82   private boolean init = true;
83
84   private Frame frame;
85
86   /**
87    * Constructor for a TreePanel font chooser
88    * 
89    * @param tp
90    */
91   public FontChooser(TreePanel tp)
92   {
93     try
94     {
95       jbInit();
96     } catch (Exception e)
97     {
98       e.printStackTrace();
99     }
100
101     this.tp = tp;
102     oldFont = tp.getTreeFont();
103     init();
104   }
105
106   /**
107    * Constructor for an AlignmentPanel font chooser
108    * 
109    * @param ap
110    */
111   public FontChooser(AlignmentPanel ap)
112   {
113     this.ap = ap;
114     oldFont = ap.av.getFont();
115     oldCharWidth = ap.av.getViewStyle().getCharWidth();
116     oldScaleProtein = ap.av.getViewStyle().isScaleProteinAsCdna();
117
118     try
119     {
120       jbInit();
121     } catch (Exception e)
122     {
123       e.printStackTrace();
124     }
125     init();
126   }
127
128   /**
129    * Populate choice lists and open this dialog
130    */
131   void init()
132   {
133     String fonts[] = Toolkit.getDefaultToolkit().getFontList();
134     for (int i = 0; i < fonts.length; i++)
135     {
136       fontName.addItem(fonts[i]);
137     }
138
139     for (int i = 1; i < 31; i++)
140     {
141       fontSize.addItem(i + "");
142     }
143
144     fontStyle.addItem("plain");
145     fontStyle.addItem("bold");
146     fontStyle.addItem("italic");
147
148     fontName.select(oldFont.getName());
149     fontSize.select(oldFont.getSize() + "");
150     fontStyle.select(oldFont.getStyle());
151
152     this.frame = new Frame();
153     frame.add(this);
154     jalview.bin.JalviewLite.addFrame(frame,
155             MessageManager.getString("action.change_font"), 440, 115);
156
157     init = false;
158   }
159
160   /**
161    * Actions on change of font name, size or style.
162    */
163   public void itemStateChanged(ItemEvent evt)
164   {
165     final Object source = evt.getSource();
166     if (source == fontName)
167     {
168       fontName_actionPerformed();
169     }
170     else if (source == fontSize)
171     {
172       fontSize_actionPerformed();
173     }
174     else if (source == fontStyle)
175     {
176       fontStyle_actionPerformed();
177     }
178     else if (source == scaleAsCdna)
179     {
180       scaleAsCdna_actionPerformed();
181     }
182   }
183
184   /**
185    * Close this dialog on OK to confirm any changes. Also updates the overview
186    * window if displayed.
187    */
188   protected void ok_actionPerformed()
189   {
190     frame.setVisible(false);
191     if (ap != null)
192     {
193       if (ap.getOverviewPanel() != null)
194       {
195         ap.getOverviewPanel().updateOverviewImage();
196       }
197     }
198   }
199
200   /**
201    * Close this dialog on Cancel, reverting to previous font settings.
202    */
203   protected void cancel_actionPerformed()
204   {
205     if (ap != null)
206     {
207       ap.av.setScaleProteinAsCdna(oldScaleProtein);
208       if (ap.av.getCodingComplement() != null)
209       {
210         ap.av.getCodingComplement().setScaleProteinAsCdna(oldScaleProtein);
211         ap.alignFrame.getSplitFrame().repaint();
212       }
213
214       ap.av.setFont(oldFont);
215       ViewStyleI style = ap.av.getViewStyle();
216       if (style.getCharWidth() != oldCharWidth)
217       {
218         style.setCharWidth(oldCharWidth);
219         ap.av.setViewStyle(style);
220       }
221       ap.paintAlignment(true);
222     }
223     else if (tp != null)
224     {
225       tp.setTreeFont(oldFont);
226       tp.treeCanvas.repaint();
227     }
228
229     fontName.select(oldFont.getName());
230     fontSize.select(oldFont.getSize() + "");
231     fontStyle.select(oldFont.getStyle());
232
233     frame.setVisible(false);
234   }
235
236   /**
237    * DOCUMENT ME!
238    */
239   void changeFont()
240   {
241     if (lastSelected == null)
242     {
243       // initialise with original font
244       lastSelected = oldFont;
245       lastSelSize = oldFont.getSize();
246       lastSelStyle = oldFont.getStyle();
247     }
248
249     Font newFont = new Font(fontName.getSelectedItem().toString(),
250             fontStyle.getSelectedIndex(), Integer.parseInt(fontSize
251                     .getSelectedItem().toString()));
252     FontMetrics fm = getGraphics().getFontMetrics(newFont);
253     double mw = fm.getStringBounds("M", getGraphics()).getWidth(), iw = fm
254             .getStringBounds("I", getGraphics()).getWidth();
255     if (mw < 1 || iw < 1)
256     {
257       // TODO: JAL-1100
258       fontName.select(lastSelected.getName());
259       fontStyle.select(lastSelStyle);
260       fontSize.select("" + lastSelSize);
261       JVDialog d = new JVDialog(this.frame,
262               MessageManager.getString("label.invalid_font"), true, 350,
263               200);
264       Panel mp = new Panel();
265       d.cancel.setVisible(false);
266       mp.setLayout(new FlowLayout());
267       mp.add(new Label(
268               "Font doesn't have letters defined\nso cannot be used\nwith alignment data."));
269       d.setMainPanel(mp);
270       d.setVisible(true);
271       return;
272     }
273     if (tp != null)
274     {
275       tp.setTreeFont(newFont);
276     }
277     else if (ap != null)
278     {
279       ap.av.setFont(newFont);
280       ap.fontChanged();
281     }
282     // remember last selected
283     lastSelected = newFont;
284   }
285
286   protected void fontName_actionPerformed()
287   {
288     if (init)
289     {
290       return;
291     }
292     changeFont();
293   }
294
295   protected void fontSize_actionPerformed()
296   {
297     if (init)
298     {
299       return;
300     }
301     changeFont();
302   }
303
304   protected void fontStyle_actionPerformed()
305   {
306     if (init)
307     {
308       return;
309     }
310     changeFont();
311   }
312
313   /**
314    * Construct this panel's contents
315    * 
316    * @throws Exception
317    */
318   private void jbInit() throws Exception
319   {
320     this.setLayout(new BorderLayout());
321     this.setBackground(Color.white);
322
323     Label fontLabel = new Label(MessageManager.getString("label.font"));
324     fontLabel.setFont(VERDANA_11PT);
325     fontLabel.setAlignment(Label.RIGHT);
326     fontSize.setFont(VERDANA_11PT);
327     fontSize.addItemListener(this);
328     fontStyle.setFont(VERDANA_11PT);
329     fontStyle.addItemListener(this);
330
331     Label sizeLabel = new Label(MessageManager.getString("label.size"));
332     sizeLabel.setAlignment(Label.RIGHT);
333     sizeLabel.setFont(VERDANA_11PT);
334
335     Label styleLabel = new Label(MessageManager.getString("label.style"));
336     styleLabel.setAlignment(Label.RIGHT);
337     styleLabel.setFont(VERDANA_11PT);
338
339     fontName.setFont(VERDANA_11PT);
340     fontName.addItemListener(this);
341
342     scaleAsCdna.setLabel(MessageManager.getString("label.scale_as_cdna"));
343     scaleAsCdna.setFont(VERDANA_11PT);
344     scaleAsCdna.addItemListener(this);
345     scaleAsCdna.setState(ap.av.isScaleProteinAsCdna());
346
347     ok.setFont(VERDANA_11PT);
348     ok.setLabel(MessageManager.getString("action.ok"));
349     ok.addActionListener(new ActionListener()
350     {
351       @Override
352       public void actionPerformed(ActionEvent e)
353       {
354         ok_actionPerformed();
355       }
356     });
357     cancel.setFont(VERDANA_11PT);
358     cancel.setLabel(MessageManager.getString("action.cancel"));
359     cancel.addActionListener(new ActionListener()
360     {
361       @Override
362       public void actionPerformed(ActionEvent e)
363       {
364         cancel_actionPerformed();
365       }
366     });
367
368     Panel fontPanel = new Panel();
369     fontPanel.setLayout(new BorderLayout());
370     Panel stylePanel = new Panel();
371     stylePanel.setLayout(new BorderLayout());
372     Panel sizePanel = new Panel();
373     sizePanel.setLayout(new BorderLayout());
374     Panel scalePanel = new Panel();
375     scalePanel.setLayout(new BorderLayout());
376     Panel okCancelPanel = new Panel();
377     Panel optionsPanel = new Panel();
378
379     fontPanel.setBackground(Color.white);
380     stylePanel.setBackground(Color.white);
381     sizePanel.setBackground(Color.white);
382     okCancelPanel.setBackground(Color.white);
383     optionsPanel.setBackground(Color.white);
384
385     fontPanel.add(fontLabel, BorderLayout.WEST);
386     fontPanel.add(fontName, BorderLayout.CENTER);
387     stylePanel.add(styleLabel, BorderLayout.WEST);
388     stylePanel.add(fontStyle, BorderLayout.CENTER);
389     sizePanel.add(sizeLabel, BorderLayout.WEST);
390     sizePanel.add(fontSize, BorderLayout.CENTER);
391     scalePanel.add(scaleAsCdna, BorderLayout.CENTER);
392     okCancelPanel.add(ok, null);
393     okCancelPanel.add(cancel, null);
394
395     optionsPanel.add(fontPanel, null);
396     optionsPanel.add(sizePanel, null);
397     optionsPanel.add(stylePanel, null);
398
399     /*
400      * Only show 'scale protein as cDNA' in a SplitFrame
401      */
402     this.add(optionsPanel, BorderLayout.NORTH);
403     if (ap.alignFrame.getSplitFrame() != null)
404     {
405       this.add(scalePanel, BorderLayout.CENTER);
406     }
407     this.add(okCancelPanel, BorderLayout.SOUTH);
408   }
409
410   /**
411    * Turn on/off scaling of protein characters to 3 times the width of cDNA
412    * characters
413    */
414   protected void scaleAsCdna_actionPerformed()
415   {
416     ap.av.setScaleProteinAsCdna(scaleAsCdna.getState());
417     ap.av.getCodingComplement().setScaleProteinAsCdna(
418             scaleAsCdna.getState());
419     ap.alignFrame.getSplitFrame().adjustLayout();
420     ap.paintAlignment(true);
421     ap.alignFrame.getSplitFrame().repaint();
422   }
423
424 }