merge
[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 java.awt.Font;
24 import java.awt.FontMetrics;
25 import java.awt.event.ActionEvent;
26 import java.awt.geom.Rectangle2D;
27
28 import javax.swing.JInternalFrame;
29 import javax.swing.JLayeredPane;
30 import javax.swing.JOptionPane;
31
32 import jalview.bin.Cache;
33 import jalview.jbgui.GFontChooser;
34 import jalview.util.MessageManager;
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
253               .showInternalMessageDialog(
254                       this,
255               MessageManager.getString(messageKey),
256                       MessageManager.getString("label.invalid_font"), JOptionPane.WARNING_MESSAGE);
257       /*
258        * Restore the changed value - note this will reinvoke this method via the
259        * ActionListener, but now validation should pass
260        */
261       if (lastSelected.getSize() != (Integer) fontSize.getSelectedItem()) // autoboxing
262       {
263         fontSize.setSelectedItem(lastSelected.getSize());
264       }
265       if (!lastSelected.getName().equals(
266               fontName.getSelectedItem().toString()))
267       {
268         fontName.setSelectedItem(lastSelected.getName());
269       }
270       if (lastSelected.getStyle() != fontStyle.getSelectedIndex())
271       {
272         fontStyle.setSelectedIndex(lastSelected.getStyle());
273       }
274       if (lastSelMono != monospaced.isSelected())
275       {
276         monospaced.setSelected(lastSelMono);
277       }
278       return;
279     }
280     if (tp != null)
281     {
282       tp.setTreeFont(newFont);
283     }
284     else if (ap != null)
285     {
286       ap.av.setFont(newFont, true);
287       ap.fontChanged();
288     }
289
290     monospaced.setSelected(mw == iw);
291
292     /*
293      * Remember latest valid selection, so it can be restored if followed by an
294      * invalid one
295      */
296     lastSelected = newFont;
297   }
298
299   /**
300    * DOCUMENT ME!
301    * 
302    * @param e
303    *          DOCUMENT ME!
304    */
305   protected void fontName_actionPerformed(ActionEvent e)
306   {
307     if (init)
308     {
309       return;
310     }
311
312     changeFont();
313   }
314
315   /**
316    * DOCUMENT ME!
317    * 
318    * @param e
319    *          DOCUMENT ME!
320    */
321   protected void fontSize_actionPerformed(ActionEvent e)
322   {
323     if (init)
324     {
325       return;
326     }
327
328     changeFont();
329   }
330
331   /**
332    * DOCUMENT ME!
333    * 
334    * @param e
335    *          DOCUMENT ME!
336    */
337   protected void fontStyle_actionPerformed(ActionEvent e)
338   {
339     if (init)
340     {
341       return;
342     }
343
344     changeFont();
345   }
346
347   /**
348    * Make selected settings the defaults by storing them (via Cache class) in
349    * the .jalview_properties file (the file is only written when Jalview exits)
350    * 
351    * @param e
352    */
353   public void defaultButton_actionPerformed(ActionEvent e)
354   {
355     Cache.setProperty("FONT_NAME", fontName.getSelectedItem().toString());
356     Cache.setProperty("FONT_STYLE", fontStyle.getSelectedIndex() + "");
357     Cache.setProperty("FONT_SIZE", fontSize.getSelectedItem().toString());
358     Cache.setProperty("ANTI_ALIAS",
359             Boolean.toString(smoothFont.isSelected()));
360     Cache.setProperty(Preferences.SCALE_PROTEIN_TO_CDNA,
361             Boolean.toString(scaleAsCdna.isSelected()));
362   }
363
364   /**
365    * Turn on/off scaling of protein characters to 3 times the width of cDNA
366    * characters
367    */
368   @Override
369   protected void scaleAsCdna_actionPerformed(ActionEvent e)
370   {
371     ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
372     ap.av.getCodingComplement().setScaleProteinAsCdna(
373             scaleAsCdna.isSelected());
374     final SplitFrame splitFrame = (SplitFrame) ap.alignFrame
375             .getSplitViewContainer();
376     splitFrame.adjustLayout();
377     splitFrame.repaint();
378     // ap.paintAlignment(true);
379     // TODO would like to repaint
380   }
381 }