78b4ff55aa184e6039958f4c303aa9b0da9de4d9
[jalview.git] / src / jalview / gui / FontChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b1)
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.gui;
22
23 import jalview.bin.Cache;
24 import jalview.jbgui.GFontChooser;
25 import jalview.util.MessageManager;
26
27 import java.awt.Font;
28 import java.awt.FontMetrics;
29 import java.awt.event.ActionEvent;
30 import java.awt.geom.Rectangle2D;
31
32 import javax.swing.JInternalFrame;
33 import javax.swing.JLayeredPane;
34 import javax.swing.JOptionPane;
35
36 /**
37  * DOCUMENT ME!
38  * 
39  * @author $author$
40  * @version $Revision$
41  */
42 public class FontChooser extends GFontChooser
43 {
44   AlignmentPanel ap;
45
46   TreePanel tp;
47
48   /*
49    * The font on opening the dialog (to be restored on Cancel)
50    */
51   Font oldFont;
52
53   boolean oldProteinScale;
54
55   boolean init = true;
56
57   JInternalFrame frame;
58
59   /*
60    * The last font settings selected in the dialog
61    */
62   private Font lastSelected = null;
63
64   private boolean lastSelMono = false;
65
66   /**
67    * Creates a new FontChooser object.
68    * 
69    * @param ap
70    *          DOCUMENT ME!
71    */
72   public FontChooser(TreePanel tp)
73   {
74     this.tp = tp;
75     ap = tp.treeCanvas.ap;
76     oldFont = tp.getTreeFont();
77     defaultButton.setVisible(false);
78     smoothFont.setEnabled(false);
79     init();
80   }
81
82   /**
83    * Creates a new FontChooser object.
84    * 
85    * @param ap
86    *          DOCUMENT ME!
87    */
88   public FontChooser(AlignmentPanel ap)
89   {
90     oldFont = ap.av.getFont();
91     oldProteinScale = ap.av.isScaleProteinAsCdna();
92
93     this.ap = ap;
94     init();
95   }
96
97   void init()
98   {
99     frame = new JInternalFrame();
100     frame.setContentPane(this);
101
102     smoothFont.setSelected(ap.av.antiAlias);
103
104     /*
105      * Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
106      * stored in the ViewStyle of both dna and protein Viewport
107      */
108     scaleAsCdna.setEnabled(false);
109     if (ap.av.getCodingComplement() != null)
110     {
111       scaleAsCdna.setEnabled(true);
112       scaleAsCdna.setVisible(true);
113       scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
114     }
115
116     if (tp != null)
117     {
118       Desktop.addInternalFrame(frame,
119               MessageManager.getString("action.change_font_tree_panel"),
120               400, 200, false);
121     }
122     else
123     {
124       Desktop.addInternalFrame(frame,
125               MessageManager.getString("action.change_font"), 380, 200,
126               false);
127     }
128
129     frame.setLayer(JLayeredPane.PALETTE_LAYER);
130
131     String[] fonts = java.awt.GraphicsEnvironment
132             .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
133
134     for (int i = 0; i < fonts.length; i++)
135     {
136       fontName.addItem(fonts[i]);
137     }
138
139     for (int i = 1; i < 51; i++)
140     {
141       fontSize.addItem(i);
142     }
143
144     fontStyle.addItem("plain");
145     fontStyle.addItem("bold");
146     fontStyle.addItem("italic");
147
148     fontName.setSelectedItem(oldFont.getName());
149     fontSize.setSelectedItem(oldFont.getSize());
150     fontStyle.setSelectedIndex(oldFont.getStyle());
151
152     FontMetrics fm = getGraphics().getFontMetrics(oldFont);
153     monospaced.setSelected(fm.getStringBounds("M", getGraphics())
154             .getWidth() == fm.getStringBounds("|", getGraphics())
155             .getWidth());
156
157     init = false;
158   }
159
160   public void smoothFont_actionPerformed(ActionEvent e)
161   {
162     ap.av.antiAlias = smoothFont.isSelected();
163     ap.getAnnotationPanel().image = null;
164     ap.paintAlignment(true);
165   }
166
167   /**
168    * DOCUMENT ME!
169    * 
170    * @param e
171    *          DOCUMENT ME!
172    */
173   protected void ok_actionPerformed(ActionEvent e)
174   {
175     try
176     {
177       frame.setClosed(true);
178     } catch (Exception ex)
179     {
180     }
181
182     if (ap != null)
183     {
184       if (ap.getOverviewPanel() != null)
185       {
186         ap.getOverviewPanel().updateOverviewImage();
187       }
188     }
189   }
190
191   /**
192    * DOCUMENT ME!
193    * 
194    * @param e
195    *          DOCUMENT ME!
196    */
197   protected void cancel_actionPerformed(ActionEvent e)
198   {
199     if (ap != null)
200     {
201       ap.av.setFont(oldFont, true);
202       ap.av.setScaleProteinAsCdna(oldProteinScale);
203       ap.paintAlignment(true);
204       if (scaleAsCdna.isEnabled())
205       {
206         ap.av.setScaleProteinAsCdna(oldProteinScale);
207         ap.av.getCodingComplement().setScaleProteinAsCdna(oldProteinScale);
208       }
209     }
210     else if (tp != null)
211     {
212       tp.setTreeFont(oldFont);
213     }
214     fontName.setSelectedItem(oldFont.getName());
215     fontSize.setSelectedItem(oldFont.getSize());
216     fontStyle.setSelectedIndex(oldFont.getStyle());
217
218     try
219     {
220       frame.setClosed(true);
221     } catch (Exception ex)
222     {
223     }
224   }
225
226   /**
227    * DOCUMENT ME!
228    */
229   void changeFont()
230   {
231     if (lastSelected == null)
232     {
233       // initialise with original font
234       lastSelected = oldFont;
235       FontMetrics fm = getGraphics().getFontMetrics(oldFont);
236       double mw = fm.getStringBounds("M", getGraphics()).getWidth();
237       double iw = fm.getStringBounds("I", getGraphics()).getWidth();
238       lastSelMono = (mw == iw); // == on double - flaky?
239     }
240
241     Font newFont = new Font(fontName.getSelectedItem().toString(),
242             fontStyle.getSelectedIndex(),
243             (Integer) fontSize.getSelectedItem());
244     FontMetrics fm = getGraphics().getFontMetrics(newFont);
245     double mw = fm.getStringBounds("M", getGraphics()).getWidth();
246     final Rectangle2D iBounds = fm.getStringBounds("I", getGraphics());
247     double iw = iBounds.getWidth();
248     if (mw < 1 || iw < 1)
249     {
250       final String messageKey = iBounds.getHeight() < 1 ? "label.font_doesnt_have_letters_defined"
251               : "label.font_too_small";
252       JOptionPane.showInternalMessageDialog(this,
253               MessageManager.getString(messageKey),
254               MessageManager.getString("label.invalid_font"),
255               JOptionPane.WARNING_MESSAGE);
256       /*
257        * Restore the changed value - note this will reinvoke this method via the
258        * ActionListener, but now validation should pass
259        */
260       if (lastSelected.getSize() != (Integer) fontSize.getSelectedItem()) // autoboxing
261       {
262         fontSize.setSelectedItem(lastSelected.getSize());
263       }
264       if (!lastSelected.getName().equals(
265               fontName.getSelectedItem().toString()))
266       {
267         fontName.setSelectedItem(lastSelected.getName());
268       }
269       if (lastSelected.getStyle() != fontStyle.getSelectedIndex())
270       {
271         fontStyle.setSelectedIndex(lastSelected.getStyle());
272       }
273       if (lastSelMono != monospaced.isSelected())
274       {
275         monospaced.setSelected(lastSelMono);
276       }
277       return;
278     }
279     if (tp != null)
280     {
281       tp.setTreeFont(newFont);
282     }
283     else if (ap != null)
284     {
285       ap.av.setFont(newFont, true);
286       ap.fontChanged();
287     }
288
289     monospaced.setSelected(mw == iw);
290
291     /*
292      * Remember latest valid selection, so it can be restored if followed by an
293      * invalid one
294      */
295     lastSelected = newFont;
296   }
297
298   /**
299    * DOCUMENT ME!
300    * 
301    * @param e
302    *          DOCUMENT ME!
303    */
304   protected void fontName_actionPerformed(ActionEvent e)
305   {
306     if (init)
307     {
308       return;
309     }
310
311     changeFont();
312   }
313
314   /**
315    * DOCUMENT ME!
316    * 
317    * @param e
318    *          DOCUMENT ME!
319    */
320   protected void fontSize_actionPerformed(ActionEvent e)
321   {
322     if (init)
323     {
324       return;
325     }
326
327     changeFont();
328   }
329
330   /**
331    * DOCUMENT ME!
332    * 
333    * @param e
334    *          DOCUMENT ME!
335    */
336   protected void fontStyle_actionPerformed(ActionEvent e)
337   {
338     if (init)
339     {
340       return;
341     }
342
343     changeFont();
344   }
345
346   /**
347    * Make selected settings the defaults by storing them (via Cache class) in
348    * the .jalview_properties file (the file is only written when Jalview exits)
349    * 
350    * @param e
351    */
352   public void defaultButton_actionPerformed(ActionEvent e)
353   {
354     Cache.setProperty("FONT_NAME", fontName.getSelectedItem().toString());
355     Cache.setProperty("FONT_STYLE", fontStyle.getSelectedIndex() + "");
356     Cache.setProperty("FONT_SIZE", fontSize.getSelectedItem().toString());
357     Cache.setProperty("ANTI_ALIAS",
358             Boolean.toString(smoothFont.isSelected()));
359     Cache.setProperty(Preferences.SCALE_PROTEIN_TO_CDNA,
360             Boolean.toString(scaleAsCdna.isSelected()));
361   }
362
363   /**
364    * Turn on/off scaling of protein characters to 3 times the width of cDNA
365    * characters
366    */
367   @Override
368   protected void scaleAsCdna_actionPerformed(ActionEvent e)
369   {
370     ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
371     ap.av.getCodingComplement().setScaleProteinAsCdna(
372             scaleAsCdna.isSelected());
373     final SplitFrame splitFrame = (SplitFrame) ap.alignFrame
374             .getSplitViewContainer();
375     splitFrame.adjustLayout();
376     splitFrame.repaint();
377     // ap.paintAlignment(true);
378     // TODO would like to repaint
379   }
380 }