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