Implemented ProgressBar for PaSiMap
[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.geom.Rectangle2D;
26
27 import javax.swing.JInternalFrame;
28 import javax.swing.JLayeredPane;
29
30 import jalview.bin.Cache;
31 import jalview.jbgui.GFontChooser;
32 import jalview.util.MessageManager;
33
34 /**
35  * DOCUMENT ME!
36  * 
37  * @author $author$
38  * @version $Revision$
39  */
40 public class FontChooser extends GFontChooser
41 {
42   AlignmentPanel ap;
43
44   TreePanel tp;
45
46   CutAndPasteTransfer cap;
47
48   /*
49    * The font on opening the dialog (to be restored on Cancel)
50    */
51   Font oldFont;
52
53   /*
54    * The font on opening the dialog (to be restored on Cancel)
55    * on the other half of a split frame (if applicable)
56    */
57   Font oldComplementFont;
58
59   /*
60    * the state of 'scale protein as cDNA' on opening the dialog
61    */
62   boolean oldProteinScale;
63
64   /*
65    * the state of 'same font for protein and cDNA' on opening the dialog
66    */
67   boolean oldMirrorFont;
68
69   boolean init = true;
70
71   JInternalFrame frame;
72
73   /*
74    * The last font settings selected in the dialog
75    */
76   private Font lastSelected = null;
77
78   private boolean lastSelMono = false;
79
80   private boolean oldSmoothFont;
81
82   private boolean oldComplementSmooth;
83
84   /**
85    * Creates a new FontChooser for a tree panel
86    * 
87    * @param treePanel
88    */
89   public FontChooser(TreePanel treePanel)
90   {
91     this.tp = treePanel;
92     ap = treePanel.getTreeCanvas().getAssociatedPanel();
93     oldFont = treePanel.getTreeFont();
94     defaultButton.setVisible(false);
95     smoothFont.setEnabled(false);
96     init();
97   }
98
99   /**
100    * Creates a new FontChooser for an alignment panel
101    * 
102    * @param alignPanel
103    */
104   public FontChooser(AlignmentPanel alignPanel)
105   {
106     oldFont = alignPanel.av.getFont();
107     oldProteinScale = alignPanel.av.isScaleProteinAsCdna();
108     oldMirrorFont = alignPanel.av.isProteinFontAsCdna();
109     oldSmoothFont = alignPanel.av.antiAlias;
110     this.ap = alignPanel;
111     init();
112   }
113
114   /**
115    * Creates a new FontChooser for a CutAndPasteTransfer
116    * @param cap
117   */
118   public FontChooser(CutAndPasteTransfer cap)
119   {
120     oldFont = new Font("Monospaced", Font.PLAIN, 12);
121     this.cap = cap;
122     init();
123   }
124
125   void init()
126   {
127     frame = new JInternalFrame();
128     frame.setFrameIcon(null);
129     frame.setContentPane(this);
130
131     if (!isCapFont())
132     {
133       smoothFont.setSelected(ap.av.antiAlias);
134   
135       /*
136        * Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
137        * stored in the ViewStyle of both dna and protein Viewport. Also enable
138        * checkbox for copy font changes to other half of split frame.
139        */
140       boolean inSplitFrame = ap.av.getCodingComplement() != null;
141       if (inSplitFrame)
142       {
143         oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
144                 .getFont();
145         oldComplementSmooth = ((AlignViewport) ap.av
146                 .getCodingComplement()).antiAlias;
147         scaleAsCdna.setVisible(true);
148         scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
149         fontAsCdna.setVisible(true);
150         fontAsCdna.setSelected(ap.av.isProteinFontAsCdna());
151       }
152     }
153
154     if (isTreeFont())
155     {
156       Desktop.addInternalFrame(frame,
157               MessageManager.getString("action.change_font_tree_panel"),
158               400, 200, false);
159     }
160     else
161     {
162       Desktop.addInternalFrame(frame,
163               MessageManager.getString("action.change_font"), 380, 220,
164               false);
165     }
166
167     frame.setLayer(JLayeredPane.PALETTE_LAYER);
168
169     String[] fonts = java.awt.GraphicsEnvironment
170             .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
171
172     for (int i = 0; i < fonts.length; i++)
173     {
174       fontName.addItem(fonts[i]);
175     }
176
177     for (int i = 1; i < 51; i++)
178     {
179       fontSize.addItem(i);
180     }
181
182     fontStyle.addItem("plain");
183     fontStyle.addItem("bold");
184     fontStyle.addItem("italic");
185
186     fontName.setSelectedItem(oldFont.getName());
187     fontSize.setSelectedItem(oldFont.getSize());
188     fontStyle.setSelectedIndex(oldFont.getStyle());
189
190     FontMetrics fm = getGraphics().getFontMetrics(oldFont);
191     monospaced.setSelected(
192             fm.getStringBounds("M", getGraphics()).getWidth() == fm
193                     .getStringBounds("|", getGraphics()).getWidth());
194
195     init = false;
196   }
197
198   @Override
199   protected void smoothFont_actionPerformed()
200   {
201     ap.av.antiAlias = smoothFont.isSelected();
202     ap.getAnnotationPanel().image = null;
203     ap.paintAlignment(true, false);
204     if (ap.av.getCodingComplement() != null && ap.av.isProteinFontAsCdna())
205     {
206       ((AlignViewport) ap.av
207               .getCodingComplement()).antiAlias = ap.av.antiAlias;
208       SplitFrame sv = (SplitFrame) ap.alignFrame.getSplitViewContainer();
209       sv.adjustLayout();
210       sv.repaint();
211     }
212
213   }
214
215   /**
216    * DOCUMENT ME!
217    * 
218    * @param e
219    *          DOCUMENT ME!
220    */
221   @Override
222   protected void ok_actionPerformed()
223   {
224     try
225     {
226       frame.setClosed(true);
227     } catch (Exception ex)
228     {
229     }
230
231     if (ap != null)
232     {
233       if (ap.getOverviewPanel() != null)
234       {
235         ap.getOverviewPanel().updateOverviewImage();
236       }
237     }
238   }
239
240   /**
241    * DOCUMENT ME!
242    * 
243    * @param e
244    *          DOCUMENT ME!
245    */
246   @Override
247   protected void cancel_actionPerformed()
248   {
249     if (isTreeFont())
250     {
251       tp.setTreeFont(oldFont);
252     }
253     else if (ap != null)
254     {
255       ap.av.setFont(oldFont, true);
256       ap.av.setScaleProteinAsCdna(oldProteinScale);
257       ap.av.setProteinFontAsCdna(oldMirrorFont);
258       ap.av.antiAlias = oldSmoothFont;
259       ap.fontChanged();
260
261       if (scaleAsCdna.isVisible() && scaleAsCdna.isEnabled())
262       {
263         ap.av.getCodingComplement().setScaleProteinAsCdna(oldProteinScale);
264         ap.av.getCodingComplement().setProteinFontAsCdna(oldMirrorFont);
265         ((AlignViewport) ap.av
266                 .getCodingComplement()).antiAlias = oldComplementSmooth;
267         ap.av.getCodingComplement().setFont(oldComplementFont, true);
268         SplitFrame splitFrame = (SplitFrame) ap.alignFrame
269                 .getSplitViewContainer();
270         splitFrame.adjustLayout();
271         splitFrame.repaint();
272       }
273     }
274
275     try
276     {
277       frame.setClosed(true);
278     } catch (Exception ex)
279     {
280     }
281   }
282
283   private boolean isTreeFont()
284   {
285     return tp != null;
286   }
287
288   private boolean isCapFont()
289   {
290     return cap != null;
291   }
292   /**
293    * DOCUMENT ME!
294    */
295   void changeFont()
296   {
297     if (lastSelected == null)
298     {
299       // initialise with original font
300       lastSelected = oldFont;
301       FontMetrics fm = getGraphics().getFontMetrics(oldFont);
302       double mw = fm.getStringBounds("M", getGraphics()).getWidth();
303       double iw = fm.getStringBounds("I", getGraphics()).getWidth();
304       lastSelMono = (mw == iw); // == on double - flaky?
305     }
306
307     Font newFont = new Font(fontName.getSelectedItem().toString(),
308             fontStyle.getSelectedIndex(),
309             (Integer) fontSize.getSelectedItem());
310     FontMetrics fm = getGraphics().getFontMetrics(newFont);
311     double mw = fm.getStringBounds("M", getGraphics()).getWidth();
312     final Rectangle2D iBounds = fm.getStringBounds("I", getGraphics());
313     double iw = iBounds.getWidth();
314     if (mw < 1 || iw < 1)
315     {
316       String message = iBounds.getHeight() < 1
317               ? MessageManager
318                       .getString("label.font_doesnt_have_letters_defined")
319               : MessageManager.getString("label.font_too_small");
320       JvOptionPane.showInternalMessageDialog(this, message,
321               MessageManager.getString("label.invalid_font"),
322               JvOptionPane.WARNING_MESSAGE);
323       /*
324        * Restore the changed value - note this will reinvoke this method via the
325        * ActionListener, but now validation should pass
326        */
327       if (lastSelected.getSize() != (Integer) fontSize.getSelectedItem()) // autoboxing
328       {
329         fontSize.setSelectedItem(lastSelected.getSize());
330       }
331       if (!lastSelected.getName()
332               .equals(fontName.getSelectedItem().toString()))
333       {
334         fontName.setSelectedItem(lastSelected.getName());
335       }
336       if (lastSelected.getStyle() != fontStyle.getSelectedIndex())
337       {
338         fontStyle.setSelectedIndex(lastSelected.getStyle());
339       }
340       if (lastSelMono != monospaced.isSelected())
341       {
342         monospaced.setSelected(lastSelMono);
343       }
344       return;
345     }
346     if (isTreeFont())
347     {
348       tp.setTreeFont(newFont);
349     }
350     else if (ap != null)
351     {
352       ap.av.setFont(newFont, true);
353       ap.fontChanged();
354
355       /*
356        * adjust other half of split frame if present, whether or not same font or
357        * scale to cDNA is selected, because a font change may affect character
358        * width, and this is kept the same in both panels
359        */
360       if (fontAsCdna.isVisible())
361       {
362         if (fontAsCdna.isSelected())
363         {
364           ap.av.getCodingComplement().setFont(newFont, true);
365         }
366
367         SplitFrame splitFrame = (SplitFrame) ap.alignFrame
368                 .getSplitViewContainer();
369         splitFrame.adjustLayout();
370         splitFrame.repaint();
371       }
372     }
373     else if (isCapFont())
374     {
375       cap.setFont(newFont);
376     }
377
378     monospaced.setSelected(mw == iw);
379
380     /*
381      * Remember latest valid selection, so it can be restored if followed by an
382      * invalid one
383      */
384     lastSelected = newFont;
385   }
386
387   /**
388    * Updates on change of selected font name
389    */
390   @Override
391   protected void fontName_actionPerformed()
392   {
393     if (init)
394     {
395       return;
396     }
397
398     changeFont();
399   }
400
401   /**
402    * Updates on change of selected font size
403    */
404   @Override
405   protected void fontSize_actionPerformed()
406   {
407     if (init)
408     {
409       return;
410     }
411
412     changeFont();
413   }
414
415   /**
416    * Updates on change of selected font style
417    */
418   @Override
419   protected void fontStyle_actionPerformed()
420   {
421     if (init)
422     {
423       return;
424     }
425
426     changeFont();
427   }
428
429   /**
430    * Make selected settings the defaults by storing them (via Cache class) in
431    * the .jalview_properties file (the file is only written when Jalview exits)
432    */
433   @Override
434   public void defaultButton_actionPerformed()
435   {
436     Cache.setProperty("FONT_NAME", fontName.getSelectedItem().toString());
437     Cache.setProperty("FONT_STYLE", fontStyle.getSelectedIndex() + "");
438     Cache.setProperty("FONT_SIZE", fontSize.getSelectedItem().toString());
439     Cache.setProperty("ANTI_ALIAS",
440             Boolean.toString(smoothFont.isSelected()));
441     Cache.setProperty(Preferences.SCALE_PROTEIN_TO_CDNA,
442             Boolean.toString(scaleAsCdna.isSelected()));
443   }
444
445   /**
446    * Turn on/off scaling of protein characters to 3 times the width of cDNA
447    * characters
448    */
449   @Override
450   protected void scaleAsCdna_actionPerformed()
451   {
452     ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
453     ap.av.getCodingComplement()
454             .setScaleProteinAsCdna(scaleAsCdna.isSelected());
455     final SplitFrame splitFrame = (SplitFrame) ap.alignFrame
456             .getSplitViewContainer();
457     splitFrame.adjustLayout();
458     splitFrame.repaint();
459   }
460
461   /**
462    * Turn on/off mirroring of font across split frame. If turning on, also
463    * copies the current font across the split frame. If turning off, restores
464    * the other half of the split frame to its initial font.
465    */
466   @Override
467   protected void mirrorFonts_actionPerformed()
468   {
469     boolean selected = fontAsCdna.isSelected();
470     ap.av.setProteinFontAsCdna(selected);
471     ap.av.getCodingComplement().setProteinFontAsCdna(selected);
472
473     /*
474      * reset other half of split frame if turning option off
475      */
476     if (!selected)
477     {
478       ap.av.getCodingComplement().setFont(oldComplementFont, true);
479     }
480
481     changeFont();
482   }
483 }