JAL-2416 allow space in score matrix name
[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 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   @Override
161   public void smoothFont_actionPerformed(ActionEvent e)
162   {
163     ap.av.antiAlias = smoothFont.isSelected();
164     ap.getAnnotationPanel().image = null;
165     ap.paintAlignment(true);
166   }
167
168   /**
169    * DOCUMENT ME!
170    * 
171    * @param e
172    *          DOCUMENT ME!
173    */
174   @Override
175   protected void ok_actionPerformed(ActionEvent e)
176   {
177     try
178     {
179       frame.setClosed(true);
180     } catch (Exception ex)
181     {
182     }
183
184     if (ap != null)
185     {
186       if (ap.getOverviewPanel() != null)
187       {
188         ap.getOverviewPanel().updateOverviewImage();
189       }
190     }
191   }
192
193   /**
194    * DOCUMENT ME!
195    * 
196    * @param e
197    *          DOCUMENT ME!
198    */
199   @Override
200   protected void cancel_actionPerformed(ActionEvent e)
201   {
202     if (ap != null)
203     {
204       ap.av.setFont(oldFont, true);
205       ap.av.setScaleProteinAsCdna(oldProteinScale);
206       ap.paintAlignment(true);
207       if (scaleAsCdna.isEnabled())
208       {
209         ap.av.setScaleProteinAsCdna(oldProteinScale);
210         ap.av.getCodingComplement().setScaleProteinAsCdna(oldProteinScale);
211       }
212     }
213     else if (tp != null)
214     {
215       tp.setTreeFont(oldFont);
216     }
217     fontName.setSelectedItem(oldFont.getName());
218     fontSize.setSelectedItem(oldFont.getSize());
219     fontStyle.setSelectedIndex(oldFont.getStyle());
220
221     try
222     {
223       frame.setClosed(true);
224     } catch (Exception ex)
225     {
226     }
227   }
228
229   /**
230    * DOCUMENT ME!
231    */
232   void changeFont()
233   {
234     if (lastSelected == null)
235     {
236       // initialise with original font
237       lastSelected = oldFont;
238       FontMetrics fm = getGraphics().getFontMetrics(oldFont);
239       double mw = fm.getStringBounds("M", getGraphics()).getWidth();
240       double iw = fm.getStringBounds("I", getGraphics()).getWidth();
241       lastSelMono = (mw == iw); // == on double - flaky?
242     }
243
244     Font newFont = new Font(fontName.getSelectedItem().toString(),
245             fontStyle.getSelectedIndex(),
246             (Integer) fontSize.getSelectedItem());
247     FontMetrics fm = getGraphics().getFontMetrics(newFont);
248     double mw = fm.getStringBounds("M", getGraphics()).getWidth();
249     final Rectangle2D iBounds = fm.getStringBounds("I", getGraphics());
250     double iw = iBounds.getWidth();
251     if (mw < 1 || iw < 1)
252     {
253       String message = iBounds.getHeight() < 1 ? MessageManager
254               .getString("label.font_doesnt_have_letters_defined")
255               : MessageManager.getString("label.font_too_small");
256       JvOptionPane.showInternalMessageDialog(this, message,
257               MessageManager.getString("label.invalid_font"),
258               JvOptionPane.WARNING_MESSAGE);
259       /*
260        * Restore the changed value - note this will reinvoke this method via the
261        * ActionListener, but now validation should pass
262        */
263       if (lastSelected.getSize() != (Integer) fontSize.getSelectedItem()) // autoboxing
264       {
265         fontSize.setSelectedItem(lastSelected.getSize());
266       }
267       if (!lastSelected.getName().equals(
268               fontName.getSelectedItem().toString()))
269       {
270         fontName.setSelectedItem(lastSelected.getName());
271       }
272       if (lastSelected.getStyle() != fontStyle.getSelectedIndex())
273       {
274         fontStyle.setSelectedIndex(lastSelected.getStyle());
275       }
276       if (lastSelMono != monospaced.isSelected())
277       {
278         monospaced.setSelected(lastSelMono);
279       }
280       return;
281     }
282     if (tp != null)
283     {
284       tp.setTreeFont(newFont);
285     }
286     else if (ap != null)
287     {
288       ap.av.setFont(newFont, true);
289       ap.fontChanged();
290     }
291
292     monospaced.setSelected(mw == iw);
293
294     /*
295      * Remember latest valid selection, so it can be restored if followed by an
296      * invalid one
297      */
298     lastSelected = newFont;
299   }
300
301   /**
302    * DOCUMENT ME!
303    * 
304    * @param e
305    *          DOCUMENT ME!
306    */
307   @Override
308   protected void fontName_actionPerformed(ActionEvent e)
309   {
310     if (init)
311     {
312       return;
313     }
314
315     changeFont();
316   }
317
318   /**
319    * DOCUMENT ME!
320    * 
321    * @param e
322    *          DOCUMENT ME!
323    */
324   @Override
325   protected void fontSize_actionPerformed(ActionEvent e)
326   {
327     if (init)
328     {
329       return;
330     }
331
332     changeFont();
333   }
334
335   /**
336    * DOCUMENT ME!
337    * 
338    * @param e
339    *          DOCUMENT ME!
340    */
341   @Override
342   protected void fontStyle_actionPerformed(ActionEvent e)
343   {
344     if (init)
345     {
346       return;
347     }
348
349     changeFont();
350   }
351
352   /**
353    * Make selected settings the defaults by storing them (via Cache class) in
354    * the .jalview_properties file (the file is only written when Jalview exits)
355    * 
356    * @param e
357    */
358   @Override
359   public void defaultButton_actionPerformed(ActionEvent e)
360   {
361     Cache.setProperty("FONT_NAME", fontName.getSelectedItem().toString());
362     Cache.setProperty("FONT_STYLE", fontStyle.getSelectedIndex() + "");
363     Cache.setProperty("FONT_SIZE", fontSize.getSelectedItem().toString());
364     Cache.setProperty("ANTI_ALIAS",
365             Boolean.toString(smoothFont.isSelected()));
366     Cache.setProperty(Preferences.SCALE_PROTEIN_TO_CDNA,
367             Boolean.toString(scaleAsCdna.isSelected()));
368   }
369
370   /**
371    * Turn on/off scaling of protein characters to 3 times the width of cDNA
372    * characters
373    */
374   @Override
375   protected void scaleAsCdna_actionPerformed(ActionEvent e)
376   {
377     ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
378     ap.av.getCodingComplement().setScaleProteinAsCdna(
379             scaleAsCdna.isSelected());
380     final SplitFrame splitFrame = (SplitFrame) ap.alignFrame
381             .getSplitViewContainer();
382     splitFrame.adjustLayout();
383     splitFrame.repaint();
384     // ap.paintAlignment(true);
385     // TODO would like to repaint
386   }
387 }