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