001/* Copyright 2004-2005,2007-2008 Masahiko SAWAI All Rights Reserved.
002 *
003 * Permission is hereby granted, free of charge, to any person obtaining
004 * a copy of this software and associated documentation files (the "Software"),
005 * to deal in the Software without restriction, including without limitation
006 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
007 * and/or sell copies of the Software, and to permit persons to whom
008 * the Software is furnished to do so, subject to the following conditions:
009 *
010 * The above copyright notice and this permission notice shall be included
011 * in all copies or substantial portions of the Software.
012 *
013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
014 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
015 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
016 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
017 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
018 * OUT OF OR IN CONNECTION WITH THE SOFTWARE
019 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
020 */
021
022package org.nuxeo.shell.swing.widgets;
023
024import java.awt.BorderLayout;
025import java.awt.Component;
026import java.awt.Dimension;
027import java.awt.Font;
028import java.awt.Frame;
029import java.awt.GraphicsEnvironment;
030import java.awt.GridLayout;
031import java.awt.event.ActionEvent;
032import java.awt.event.FocusAdapter;
033import java.awt.event.FocusEvent;
034import java.awt.event.KeyAdapter;
035import java.awt.event.KeyEvent;
036import java.awt.event.WindowAdapter;
037import java.awt.event.WindowEvent;
038import java.util.MissingResourceException;
039import java.util.ResourceBundle;
040
041import javax.swing.AbstractAction;
042import javax.swing.Action;
043import javax.swing.ActionMap;
044import javax.swing.BorderFactory;
045import javax.swing.BoxLayout;
046import javax.swing.InputMap;
047import javax.swing.JButton;
048import javax.swing.JComponent;
049import javax.swing.JDialog;
050import javax.swing.JLabel;
051import javax.swing.JList;
052import javax.swing.JPanel;
053import javax.swing.JScrollPane;
054import javax.swing.JTextField;
055import javax.swing.KeyStroke;
056import javax.swing.ListSelectionModel;
057import javax.swing.SwingUtilities;
058import javax.swing.border.Border;
059import javax.swing.event.DocumentEvent;
060import javax.swing.event.DocumentListener;
061import javax.swing.event.ListSelectionEvent;
062import javax.swing.event.ListSelectionListener;
063import javax.swing.text.BadLocationException;
064import javax.swing.text.Document;
065import javax.swing.text.JTextComponent;
066import javax.swing.text.Position;
067
068/**
069 * The <code>JFontChooser</code> class is a swing component for font selection. This class has <code>JFileChooser</code>
070 * like APIs. The following code pops up a font chooser dialog.
071 *
072 * <pre>
073 *   JFontChooser fontChooser = new JFontChooser();
074 *   int result = fontChooser.showDialog(parent);
075 *   if (result == JFontChooser.OK_OPTION)
076 *   {
077 *       Font font = fontChooser.getSelectedFont();
078 *       System.out.println("Selected Font : " + font);
079 * }
080 *
081 * <pre>
082 **/
083@SuppressWarnings("serial")
084public class JFontChooser extends JComponent {
085    // class variables
086    /**
087     * Return value from <code>showDialog()</code>.
088     *
089     * @see #showDialog
090     **/
091    public static final int OK_OPTION = 0;
092
093    /**
094     * Return value from <code>showDialog()</code>.
095     *
096     * @see #showDialog
097     **/
098    public static final int CANCEL_OPTION = 1;
099
100    /**
101     * Return value from <code>showDialog()</code>.
102     *
103     * @see #showDialog
104     **/
105    public static final int ERROR_OPTION = -1;
106
107    private static final Font DEFAULT_SELECTED_FONT = new Font("Serif", Font.PLAIN, 12);
108
109    private static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 10);
110
111    private static final int[] FONT_STYLE_CODES = { Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC };
112
113    private static final String[] DEFAULT_FONT_SIZE_STRINGS = { "8", "9", "10", "11", "12", "14", "16", "18", "20",
114            "22", "24", "26", "28", "36", "48", "72", };
115
116    // instance variables
117    protected int dialogResultValue = ERROR_OPTION;
118
119    private ResourceBundle messageCatalog = ResourceBundle.getBundle(JFontChooser.class.getName() + "Messages",
120            getLocale());
121
122    protected String _(String key) {
123        String value = key;
124        try {
125            value = messageCatalog.getString(key);
126        } catch (MissingResourceException e) {
127        }
128        return value;
129    }
130
131    private String[] fontStyleNames = null;
132
133    private String[] fontFamilyNames = null;
134
135    private String[] fontSizeStrings = null;
136
137    private JTextField fontFamilyTextField = null;
138
139    private JTextField fontStyleTextField = null;
140
141    private JTextField fontSizeTextField = null;
142
143    private JList fontNameList = null;
144
145    private JList fontStyleList = null;
146
147    private JList fontSizeList = null;
148
149    private JPanel fontNamePanel = null;
150
151    private JPanel fontStylePanel = null;
152
153    private JPanel fontSizePanel = null;
154
155    private JPanel samplePanel = null;
156
157    private JTextField sampleText = null;
158
159    /**
160     * Constructs a <code>JFontChooser</code> object.
161     **/
162    public JFontChooser() {
163        this(DEFAULT_FONT_SIZE_STRINGS);
164    }
165
166    /**
167     * Constructs a <code>JFontChooser</code> object using the given font size array.
168     *
169     * @param fontSizeStrings the array of font size string.
170     **/
171    public JFontChooser(String[] fontSizeStrings) {
172        if (fontSizeStrings == null) {
173            fontSizeStrings = DEFAULT_FONT_SIZE_STRINGS;
174        }
175        this.fontSizeStrings = fontSizeStrings;
176
177        JPanel selectPanel = new JPanel();
178        selectPanel.setLayout(new BoxLayout(selectPanel, BoxLayout.X_AXIS));
179        selectPanel.add(getFontFamilyPanel());
180        selectPanel.add(getFontStylePanel());
181        selectPanel.add(getFontSizePanel());
182
183        JPanel contentsPanel = new JPanel();
184        contentsPanel.setLayout(new GridLayout(2, 1));
185        contentsPanel.add(selectPanel, BorderLayout.NORTH);
186        contentsPanel.add(getSamplePanel(), BorderLayout.CENTER);
187
188        this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
189        this.add(contentsPanel);
190        this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
191        this.setSelectedFont(DEFAULT_SELECTED_FONT);
192    }
193
194    public JTextField getFontFamilyTextField() {
195        if (fontFamilyTextField == null) {
196            fontFamilyTextField = new JTextField();
197            fontFamilyTextField.addFocusListener(new TextFieldFocusHandlerForTextSelection(fontFamilyTextField));
198            fontFamilyTextField.addKeyListener(new TextFieldKeyHandlerForListSelectionUpDown(getFontFamilyList()));
199            fontFamilyTextField.getDocument().addDocumentListener(
200                    new ListSearchTextFieldDocumentHandler(getFontFamilyList()));
201            fontFamilyTextField.setFont(DEFAULT_FONT);
202
203        }
204        return fontFamilyTextField;
205    }
206
207    public JTextField getFontStyleTextField() {
208        if (fontStyleTextField == null) {
209            fontStyleTextField = new JTextField();
210            fontStyleTextField.addFocusListener(new TextFieldFocusHandlerForTextSelection(fontStyleTextField));
211            fontStyleTextField.addKeyListener(new TextFieldKeyHandlerForListSelectionUpDown(getFontStyleList()));
212            fontStyleTextField.getDocument().addDocumentListener(
213                    new ListSearchTextFieldDocumentHandler(getFontStyleList()));
214            fontStyleTextField.setFont(DEFAULT_FONT);
215        }
216        return fontStyleTextField;
217    }
218
219    public JTextField getFontSizeTextField() {
220        if (fontSizeTextField == null) {
221            fontSizeTextField = new JTextField();
222            fontSizeTextField.addFocusListener(new TextFieldFocusHandlerForTextSelection(fontSizeTextField));
223            fontSizeTextField.addKeyListener(new TextFieldKeyHandlerForListSelectionUpDown(getFontSizeList()));
224            fontSizeTextField.getDocument().addDocumentListener(
225                    new ListSearchTextFieldDocumentHandler(getFontSizeList()));
226            fontSizeTextField.setFont(DEFAULT_FONT);
227        }
228        return fontSizeTextField;
229    }
230
231    public JList getFontFamilyList() {
232        if (fontNameList == null) {
233            fontNameList = new JList(getFontFamilies());
234            fontNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
235            fontNameList.addListSelectionListener(new ListSelectionHandler(getFontFamilyTextField()));
236            fontNameList.setSelectedIndex(0);
237            fontNameList.setFont(DEFAULT_FONT);
238            fontNameList.setFocusable(false);
239        }
240        return fontNameList;
241    }
242
243    public JList getFontStyleList() {
244        if (fontStyleList == null) {
245            fontStyleList = new JList(getFontStyleNames());
246            fontStyleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
247            fontStyleList.addListSelectionListener(new ListSelectionHandler(getFontStyleTextField()));
248            fontStyleList.setSelectedIndex(0);
249            fontStyleList.setFont(DEFAULT_FONT);
250            fontStyleList.setFocusable(false);
251        }
252        return fontStyleList;
253    }
254
255    public JList getFontSizeList() {
256        if (fontSizeList == null) {
257            fontSizeList = new JList(this.fontSizeStrings);
258            fontSizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
259            fontSizeList.addListSelectionListener(new ListSelectionHandler(getFontSizeTextField()));
260            fontSizeList.setSelectedIndex(0);
261            fontSizeList.setFont(DEFAULT_FONT);
262            fontSizeList.setFocusable(false);
263        }
264        return fontSizeList;
265    }
266
267    /**
268     * Get the family name of the selected font.
269     *
270     * @return the font family of the selected font.
271     * @see #setSelectedFontFamily
272     **/
273    public String getSelectedFontFamily() {
274        String fontName = (String) getFontFamilyList().getSelectedValue();
275        return fontName;
276    }
277
278    /**
279     * Get the style of the selected font.
280     *
281     * @return the style of the selected font. <code>Font.PLAIN</code>, <code>Font.BOLD</code>, <code>Font.ITALIC</code>
282     *         , <code>Font.BOLD|Font.ITALIC</code>
283     * @see java.awt.Font#PLAIN
284     * @see java.awt.Font#BOLD
285     * @see java.awt.Font#ITALIC
286     * @see #setSelectedFontStyle
287     **/
288    public int getSelectedFontStyle() {
289        int index = getFontStyleList().getSelectedIndex();
290        return FONT_STYLE_CODES[index];
291    }
292
293    /**
294     * Get the size of the selected font.
295     *
296     * @return the size of the selected font
297     * @see #setSelectedFontSize
298     **/
299    public int getSelectedFontSize() {
300        int fontSize = 1;
301        String fontSizeString = getFontSizeTextField().getText();
302        while (true) {
303            try {
304                fontSize = Integer.parseInt(fontSizeString);
305                break;
306            } catch (NumberFormatException e) {
307                fontSizeString = (String) getFontSizeList().getSelectedValue();
308                getFontSizeTextField().setText(fontSizeString);
309            }
310        }
311
312        return fontSize;
313    }
314
315    /**
316     * Get the selected font.
317     *
318     * @return the selected font
319     * @see #setSelectedFont
320     * @see java.awt.Font
321     **/
322    public Font getSelectedFont() {
323        Font font = new Font(getSelectedFontFamily(), getSelectedFontStyle(), getSelectedFontSize());
324        return font;
325    }
326
327    /**
328     * Set the family name of the selected font.
329     *
330     * @param name the family name of the selected font.
331     * @see getSelectedFontFamily
332     */
333    public void setSelectedFontFamily(String name) {
334        String[] names = getFontFamilies();
335        for (int i = 0; i < names.length; i++) {
336            if (names[i].toLowerCase().equals(name.toLowerCase())) {
337                getFontFamilyList().setSelectedIndex(i);
338                break;
339            }
340        }
341        updateSampleFont();
342    }
343
344    /**
345     * Set the style of the selected font.
346     *
347     * @param style the size of the selected font. <code>Font.PLAIN</code>, <code>Font.BOLD</code>,
348     *            <code>Font.ITALIC</code>, or <code>Font.BOLD|Font.ITALIC</code>.
349     * @see java.awt.Font#PLAIN
350     * @see java.awt.Font#BOLD
351     * @see java.awt.Font#ITALIC
352     * @see #getSelectedFontStyle
353     **/
354    public void setSelectedFontStyle(int style) {
355        for (int i = 0; i < FONT_STYLE_CODES.length; i++) {
356            if (FONT_STYLE_CODES[i] == style) {
357                getFontStyleList().setSelectedIndex(i);
358                break;
359            }
360        }
361        updateSampleFont();
362    }
363
364    /**
365     * Set the size of the selected font.
366     *
367     * @param size the size of the selected font
368     * @see #getSelectedFontSize
369     **/
370    public void setSelectedFontSize(int size) {
371        String sizeString = String.valueOf(size);
372        for (int i = 0; i < this.fontSizeStrings.length; i++) {
373            if (this.fontSizeStrings[i].equals(sizeString)) {
374                getFontSizeList().setSelectedIndex(i);
375                break;
376            }
377        }
378        getFontSizeTextField().setText(sizeString);
379        updateSampleFont();
380    }
381
382    /**
383     * Set the selected font.
384     *
385     * @param font the selected font
386     * @see #getSelectedFont
387     * @see java.awt.Font
388     **/
389    public void setSelectedFont(Font font) {
390        setSelectedFontFamily(font.getFamily());
391        setSelectedFontStyle(font.getStyle());
392        setSelectedFontSize(font.getSize());
393    }
394
395    public String getVersionString() {
396        return _("Version");
397    }
398
399    /**
400     * Show font selection dialog.
401     *
402     * @param parent Dialog's Parent component.
403     * @return OK_OPTION, CANCEL_OPTION or ERROR_OPTION
404     * @see #OK_OPTION
405     * @see #CANCEL_OPTION
406     * @see #ERROR_OPTION
407     **/
408    public int showDialog(Component parent) {
409        dialogResultValue = ERROR_OPTION;
410        JDialog dialog = createDialog(parent);
411        dialog.addWindowListener(new WindowAdapter() {
412            @Override
413            public void windowClosing(WindowEvent e) {
414                dialogResultValue = CANCEL_OPTION;
415            }
416        });
417
418        dialog.setVisible(true);
419        dialog.dispose();
420        dialog = null;
421
422        return dialogResultValue;
423    }
424
425    protected class ListSelectionHandler implements ListSelectionListener {
426        private JTextComponent textComponent;
427
428        ListSelectionHandler(JTextComponent textComponent) {
429            this.textComponent = textComponent;
430        }
431
432        public void valueChanged(ListSelectionEvent e) {
433            if (e.getValueIsAdjusting() == false) {
434                JList list = (JList) e.getSource();
435                String selectedValue = (String) list.getSelectedValue();
436
437                String oldValue = textComponent.getText();
438                textComponent.setText(selectedValue);
439                if (!oldValue.equalsIgnoreCase(selectedValue)) {
440                    textComponent.selectAll();
441                    textComponent.requestFocus();
442                }
443
444                updateSampleFont();
445            }
446        }
447    }
448
449    protected class TextFieldFocusHandlerForTextSelection extends FocusAdapter {
450        private JTextComponent textComponent;
451
452        public TextFieldFocusHandlerForTextSelection(JTextComponent textComponent) {
453            this.textComponent = textComponent;
454        }
455
456        @Override
457        public void focusGained(FocusEvent e) {
458            textComponent.selectAll();
459        }
460
461        @Override
462        public void focusLost(FocusEvent e) {
463            textComponent.select(0, 0);
464            updateSampleFont();
465        }
466    }
467
468    protected class TextFieldKeyHandlerForListSelectionUpDown extends KeyAdapter {
469        private JList targetList;
470
471        public TextFieldKeyHandlerForListSelectionUpDown(JList list) {
472            this.targetList = list;
473        }
474
475        @Override
476        public void keyPressed(KeyEvent e) {
477            int i = targetList.getSelectedIndex();
478            switch (e.getKeyCode()) {
479            case KeyEvent.VK_UP:
480                i = targetList.getSelectedIndex() - 1;
481                if (i < 0) {
482                    i = 0;
483                }
484                targetList.setSelectedIndex(i);
485                break;
486            case KeyEvent.VK_DOWN:
487                int listSize = targetList.getModel().getSize();
488                i = targetList.getSelectedIndex() + 1;
489                if (i >= listSize) {
490                    i = listSize - 1;
491                }
492                targetList.setSelectedIndex(i);
493                break;
494            default:
495                break;
496            }
497        }
498    }
499
500    protected class ListSearchTextFieldDocumentHandler implements DocumentListener {
501        JList targetList;
502
503        public ListSearchTextFieldDocumentHandler(JList targetList) {
504            this.targetList = targetList;
505        }
506
507        public void insertUpdate(DocumentEvent e) {
508            update(e);
509        }
510
511        public void removeUpdate(DocumentEvent e) {
512            update(e);
513        }
514
515        public void changedUpdate(DocumentEvent e) {
516            update(e);
517        }
518
519        private void update(DocumentEvent event) {
520            String newValue = "";
521            try {
522                Document doc = event.getDocument();
523                newValue = doc.getText(0, doc.getLength());
524            } catch (BadLocationException e) {
525                e.printStackTrace();
526            }
527
528            if (newValue.length() > 0) {
529                int index = targetList.getNextMatch(newValue, 0, Position.Bias.Forward);
530                if (index < 0) {
531                    index = 0;
532                }
533                targetList.ensureIndexIsVisible(index);
534
535                String matchedName = targetList.getModel().getElementAt(index).toString();
536                if (newValue.equalsIgnoreCase(matchedName)) {
537                    if (index != targetList.getSelectedIndex()) {
538                        SwingUtilities.invokeLater(new ListSelector(index));
539                    }
540                }
541            }
542        }
543
544        public class ListSelector implements Runnable {
545            private int index;
546
547            public ListSelector(int index) {
548                this.index = index;
549            }
550
551            public void run() {
552                targetList.setSelectedIndex(this.index);
553            }
554        }
555    }
556
557    protected class DialogOKAction extends AbstractAction {
558        protected static final String ACTION_NAME = "OK";
559
560        private JDialog dialog;
561
562        protected DialogOKAction(JDialog dialog) {
563            this.dialog = dialog;
564            putValue(Action.DEFAULT, ACTION_NAME);
565            putValue(Action.ACTION_COMMAND_KEY, ACTION_NAME);
566            putValue(Action.NAME, _(ACTION_NAME));
567        }
568
569        public void actionPerformed(ActionEvent e) {
570            dialogResultValue = OK_OPTION;
571            dialog.setVisible(false);
572        }
573    }
574
575    protected class DialogCancelAction extends AbstractAction {
576        protected static final String ACTION_NAME = "Cancel";
577
578        private JDialog dialog;
579
580        protected DialogCancelAction(JDialog dialog) {
581            this.dialog = dialog;
582            putValue(Action.DEFAULT, ACTION_NAME);
583            putValue(Action.ACTION_COMMAND_KEY, ACTION_NAME);
584            putValue(Action.NAME, _(ACTION_NAME));
585        }
586
587        public void actionPerformed(ActionEvent e) {
588            dialogResultValue = CANCEL_OPTION;
589            dialog.setVisible(false);
590        }
591    }
592
593    protected JDialog createDialog(Component parent) {
594        Frame frame = parent instanceof Frame ? (Frame) parent : (Frame) SwingUtilities.getAncestorOfClass(Frame.class,
595                parent);
596        JDialog dialog = new JDialog(frame, _("SelectFont"), true);
597
598        Action okAction = new DialogOKAction(dialog);
599        Action cancelAction = new DialogCancelAction(dialog);
600
601        JButton okButton = new JButton(okAction);
602        okButton.setFont(DEFAULT_FONT);
603        JButton cancelButton = new JButton(cancelAction);
604        cancelButton.setFont(DEFAULT_FONT);
605
606        JPanel buttonsPanel = new JPanel();
607        buttonsPanel.setLayout(new GridLayout(2, 1));
608        buttonsPanel.add(okButton);
609        buttonsPanel.add(cancelButton);
610        buttonsPanel.setBorder(BorderFactory.createEmptyBorder(25, 0, 10, 10));
611
612        ActionMap actionMap = buttonsPanel.getActionMap();
613        actionMap.put(cancelAction.getValue(Action.DEFAULT), cancelAction);
614        actionMap.put(okAction.getValue(Action.DEFAULT), okAction);
615        InputMap inputMap = buttonsPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
616        inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), cancelAction.getValue(Action.DEFAULT));
617        inputMap.put(KeyStroke.getKeyStroke("ENTER"), okAction.getValue(Action.DEFAULT));
618
619        JPanel dialogEastPanel = new JPanel();
620        dialogEastPanel.setLayout(new BorderLayout());
621        dialogEastPanel.add(buttonsPanel, BorderLayout.NORTH);
622
623        dialog.getContentPane().add(this, BorderLayout.CENTER);
624        dialog.getContentPane().add(dialogEastPanel, BorderLayout.EAST);
625        dialog.pack();
626        dialog.setLocationRelativeTo(frame);
627        return dialog;
628    }
629
630    protected void updateSampleFont() {
631        Font font = getSelectedFont();
632        getSampleTextField().setFont(font);
633    }
634
635    protected JPanel getFontFamilyPanel() {
636        if (fontNamePanel == null) {
637            fontNamePanel = new JPanel();
638            fontNamePanel.setLayout(new BorderLayout());
639            fontNamePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
640            fontNamePanel.setPreferredSize(new Dimension(180, 130));
641
642            JScrollPane scrollPane = new JScrollPane(getFontFamilyList());
643            scrollPane.getVerticalScrollBar().setFocusable(false);
644            scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
645
646            JPanel p = new JPanel();
647            p.setLayout(new BorderLayout());
648            p.add(getFontFamilyTextField(), BorderLayout.NORTH);
649            p.add(scrollPane, BorderLayout.CENTER);
650
651            JLabel label = new JLabel(_("FontName"));
652            label.setHorizontalAlignment(JLabel.LEFT);
653            label.setHorizontalTextPosition(JLabel.LEFT);
654            label.setLabelFor(getFontFamilyTextField());
655            label.setDisplayedMnemonic('F');
656
657            fontNamePanel.add(label, BorderLayout.NORTH);
658            fontNamePanel.add(p, BorderLayout.CENTER);
659
660        }
661        return fontNamePanel;
662    }
663
664    protected JPanel getFontStylePanel() {
665        if (fontStylePanel == null) {
666            fontStylePanel = new JPanel();
667            fontStylePanel.setLayout(new BorderLayout());
668            fontStylePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
669            fontStylePanel.setPreferredSize(new Dimension(140, 130));
670
671            JScrollPane scrollPane = new JScrollPane(getFontStyleList());
672            scrollPane.getVerticalScrollBar().setFocusable(false);
673            scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
674
675            JPanel p = new JPanel();
676            p.setLayout(new BorderLayout());
677            p.add(getFontStyleTextField(), BorderLayout.NORTH);
678            p.add(scrollPane, BorderLayout.CENTER);
679
680            JLabel label = new JLabel(_("FontStyle"));
681            label.setHorizontalAlignment(JLabel.LEFT);
682            label.setHorizontalTextPosition(JLabel.LEFT);
683            label.setLabelFor(getFontStyleTextField());
684            label.setDisplayedMnemonic('Y');
685
686            fontStylePanel.add(label, BorderLayout.NORTH);
687            fontStylePanel.add(p, BorderLayout.CENTER);
688        }
689        return fontStylePanel;
690    }
691
692    protected JPanel getFontSizePanel() {
693        if (fontSizePanel == null) {
694            fontSizePanel = new JPanel();
695            fontSizePanel.setLayout(new BorderLayout());
696            fontSizePanel.setPreferredSize(new Dimension(70, 130));
697            fontSizePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
698
699            JScrollPane scrollPane = new JScrollPane(getFontSizeList());
700            scrollPane.getVerticalScrollBar().setFocusable(false);
701            scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
702
703            JPanel p = new JPanel();
704            p.setLayout(new BorderLayout());
705            p.add(getFontSizeTextField(), BorderLayout.NORTH);
706            p.add(scrollPane, BorderLayout.CENTER);
707
708            JLabel label = new JLabel(_("FontSize"));
709            label.setHorizontalAlignment(JLabel.LEFT);
710            label.setHorizontalTextPosition(JLabel.LEFT);
711            label.setLabelFor(getFontSizeTextField());
712            label.setDisplayedMnemonic('S');
713
714            fontSizePanel.add(label, BorderLayout.NORTH);
715            fontSizePanel.add(p, BorderLayout.CENTER);
716        }
717        return fontSizePanel;
718    }
719
720    protected JPanel getSamplePanel() {
721        if (samplePanel == null) {
722            Border titledBorder = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), _("Sample"));
723            Border empty = BorderFactory.createEmptyBorder(5, 10, 10, 10);
724            Border border = BorderFactory.createCompoundBorder(titledBorder, empty);
725
726            samplePanel = new JPanel();
727            samplePanel.setLayout(new BorderLayout());
728            samplePanel.setBorder(border);
729
730            samplePanel.add(getSampleTextField(), BorderLayout.CENTER);
731        }
732        return samplePanel;
733    }
734
735    protected JTextField getSampleTextField() {
736        if (sampleText == null) {
737            Border lowered = BorderFactory.createLoweredBevelBorder();
738
739            sampleText = new JTextField(_("SampleString"));
740            sampleText.setBorder(lowered);
741            sampleText.setPreferredSize(new Dimension(300, 100));
742        }
743        return sampleText;
744    }
745
746    protected String[] getFontFamilies() {
747        if (fontFamilyNames == null) {
748            GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
749            fontFamilyNames = env.getAvailableFontFamilyNames();
750        }
751        return fontFamilyNames;
752    }
753
754    protected String[] getFontStyleNames() {
755        if (fontStyleNames == null) {
756            int i = 0;
757            fontStyleNames = new String[4];
758            fontStyleNames[i++] = _("Plain");
759            fontStyleNames[i++] = _("Bold");
760            fontStyleNames[i++] = _("Italic");
761            fontStyleNames[i++] = _("BoldItalic");
762        }
763        return fontStyleNames;
764    }
765}