Mega Code Archive

 
Categories / Java / Swing Components
 

JFont Chooser

// revised from greef ui import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.HeadlessException; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.Serializable; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; /**  * <code>JFontChooser</code> provides a pane of controls designed to allow  * a user to manipulate and select a font.  *  * This class provides three levels of API:  * <ol>  * <li>A static convenience method which shows a modal font-chooser  * dialog and returns the font selected by the user.  * <li>A static convenience method for creating a font-chooser dialog  * where <code>ActionListeners</code> can be specified to be invoked when  * the user presses one of the dialog buttons.  * <li>The ability to create instances of <code>JFontChooser</code> panes  * directly (within any container). <code>PropertyChange</code> listeners  * can be added to detect when the current "font" property changes.  * </ol>  * <p>  *  * @author Adrian BER  */ public class JFontChooser extends JComponent {     /** The list of possible font sizes. */     private static final Integer[] SIZES =             {8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72};     /** The list of possible fonts. */     private static final String[] FONTS = GraphicsEnvironment.getLocalGraphicsEnvironment()             .getAvailableFontFamilyNames();     private FontSelectionModel selectionModel;     private JList fontList;     private JList sizeList;     private JCheckBox boldCheckBox;     private JCheckBox italicCheckBox;     private JLabel previewLabel;     /** The preview text, if null the font name will be the preview text. */     private String previewText;     /** Listener used to update the font of the selection model. */     private SelectionUpdater selectionUpdater = new SelectionUpdater();     /** Listener used to update the font in the components. This should be registered      * with the selection model. */     private LabelUpdater labelUpdater = new LabelUpdater();     /** True if the components are being updated and no event should be generated. */     private boolean updatingComponents = false;     /** Listener class used to update the font in the components. This should be registered       * with the selection model. */     private class LabelUpdater implements ChangeListener {         public void stateChanged(ChangeEvent e) {             updateComponents();         }     }     /** Listener class used to update the font of the preview label. */     private class SelectionUpdater implements ChangeListener, ListSelectionListener {         public void stateChanged(ChangeEvent e) {             if (!updatingComponents) {                 setFont(buildFont());             }         }         public void valueChanged(ListSelectionEvent e) {             if (!updatingComponents) {                 setFont(buildFont());             }         }     }     /**      * Shows a modal font-chooser dialog and blocks until the      * dialog is hidden.  If the user presses the "OK" button, then      * this method hides/disposes the dialog and returns the selected color.      * If the user presses the "Cancel" button or closes the dialog without      * pressing "OK", then this method hides/disposes the dialog and returns      * <code>null</code>.      *      * @param component    the parent <code>Component</code> for the dialog      * @param title        the String containing the dialog's title      * @return the selected font or <code>null</code> if the user opted out      * @exception HeadlessException if GraphicsEnvironment.isHeadless()      * returns true.      * @see java.awt.GraphicsEnvironment#isHeadless      */     public Font showDialog(Component component, String title) {         FontTracker ok = new FontTracker(this);         JDialog dialog = createDialog(component, title, true, ok, null);         dialog.addWindowListener(new FontChooserDialog.Closer());         dialog.addComponentListener(new FontChooserDialog.DisposeOnClose());         dialog.setVisible(true); // blocks until user brings dialog down...         return ok.getFont();     }     /**      * Creates and returns a new dialog containing the specified      * <code>ColorChooser</code> pane along with "OK", "Cancel", and "Reset"      * buttons. If the "OK" or "Cancel" buttons are pressed, the dialog is      * automatically hidden (but not disposed).  If the "Reset"      * button is pressed, the color-chooser's color will be reset to the      * font which was set the last time <code>show</code> was invoked on the      * dialog and the dialog will remain showing.      *      * @param c              the parent component for the dialog      * @param title          the title for the dialog      * @param modal          a boolean. When true, the remainder of the program      *                       is inactive until the dialog is closed.      * @param okListener     the ActionListener invoked when "OK" is pressed      * @param cancelListener the ActionListener invoked when "Cancel" is pressed      * @return a new dialog containing the font-chooser pane      * @exception HeadlessException if GraphicsEnvironment.isHeadless()      * returns true.      * @see java.awt.GraphicsEnvironment#isHeadless      */     public JDialog createDialog(Component c, String title, boolean modal,         ActionListener okListener, ActionListener cancelListener) {         return new FontChooserDialog(c, title, modal, this,                 okListener, cancelListener);     }     /**      * Creates a color chooser pane with an initial font which is the same font      * as the default font for labels.      */     public JFontChooser() {         this(new DefaultFontSelectionModel());     }     /**      * Creates a font chooser pane with the specified initial font.      *      * @param initialFont the initial font set in the chooser      */     public JFontChooser(Font initialFont) {         this(new DefaultFontSelectionModel(initialFont));     }     /**      * Creates a font chooser pane with the specified      * <code>FontSelectionModel</code>.      *      * @param model the font selection model used by this component      */     public JFontChooser(FontSelectionModel model) {         selectionModel = model;         init(model.getSelectedFont());         selectionModel.addChangeListener(labelUpdater);     }     private void init(Font font) {         setLayout(new GridBagLayout());         Insets ins = new Insets(2, 2, 2, 2);         fontList = new JList(FONTS);         fontList.setVisibleRowCount(10);         fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);         add(new JScrollPane(fontList), new GridBagConstraints(0, 0, 1, 1, 2, 2,                 GridBagConstraints.CENTER, GridBagConstraints.BOTH,                 ins, 0, 0));         sizeList = new JList(SIZES);         ((JLabel)sizeList.getCellRenderer()).setHorizontalAlignment(JLabel.RIGHT);         sizeList.setVisibleRowCount(10);         sizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);         add(new JScrollPane(sizeList), new GridBagConstraints(1, 0, 1, 1, 1, 2,                 GridBagConstraints.CENTER, GridBagConstraints.BOTH,                 ins, 0, 0));         boldCheckBox = new JCheckBox("Bold");         add(boldCheckBox, new GridBagConstraints(0, 1, 2, 1, 1, 0,                 GridBagConstraints.WEST, GridBagConstraints.NONE,                 ins, 0, 0));         italicCheckBox = new JCheckBox("Italic");         add(italicCheckBox, new GridBagConstraints(0, 2, 2, 1, 1, 0,                 GridBagConstraints.WEST, GridBagConstraints.NONE,                 ins, 0, 0));         previewLabel = new JLabel("");         previewLabel.setHorizontalAlignment(JLabel.CENTER);         previewLabel.setVerticalAlignment(JLabel.CENTER);         add(new JScrollPane(previewLabel), new GridBagConstraints(0, 3, 2, 1, 1, 1,                 GridBagConstraints.CENTER, GridBagConstraints.BOTH,                 ins, 0, 0));         setFont(font == null ? previewLabel.getFont() : font);         fontList.addListSelectionListener(selectionUpdater);         sizeList.addListSelectionListener(selectionUpdater);         boldCheckBox.addChangeListener(selectionUpdater);         italicCheckBox.addChangeListener(selectionUpdater);     }     private Font buildFont() { //        Font labelFont = previewLabel.getFont();         String fontName = (String)fontList.getSelectedValue();         if (fontName == null) {             return null; //            fontName = labelFont.getName();         }         Integer sizeInt = (Integer)sizeList.getSelectedValue();         if (sizeInt == null) { //            size = labelFont.getSize();             return null;         }         // create the font //        // first create the font attributes //        HashMap map = new HashMap(); //        map.put(TextAttribute.BACKGROUND, Color.white); //        map.put(TextAttribute.FAMILY, fontName); //        map.put(TextAttribute.FOREGROUND, Color.black); //        map.put(TextAttribute.SIZE , new Float(size)); //        map.put(TextAttribute.UNDERLINE, italicCheckBox.isSelected() ? TextAttribute.UNDERLINE_LOW_ONE_PIXEL : TextAttribute.UNDERLINE_LOW_TWO_PIXEL); //        map.put(TextAttribute.STRIKETHROUGH, italicCheckBox.isSelected() ? TextAttribute.STRIKETHROUGH_ON : Boolean.FALSE); //        map.put(TextAttribute.WEIGHT, boldCheckBox.isSelected() ? TextAttribute.WEIGHT_BOLD : TextAttribute.WEIGHT_REGULAR); //        map.put(TextAttribute.POSTURE, //                italicCheckBox.isSelected() ? TextAttribute.POSTURE_OBLIQUE : TextAttribute.POSTURE_REGULAR); // //        return new Font(map);         return new Font(fontName,                 (italicCheckBox.isSelected() ? Font.ITALIC : Font.PLAIN)                 | (boldCheckBox.isSelected() ? Font.BOLD : Font.PLAIN),                 sizeInt);     }     /** Updates the font in the preview component according to the selected values. */     private void updateComponents() {         updatingComponents = true;         Font font = getFont();         fontList.setSelectedValue(font.getName(), true);         sizeList.setSelectedValue(font.getSize(), true);         boldCheckBox.setSelected(font.isBold());         italicCheckBox.setSelected(font.isItalic());         if (previewText == null) {             previewLabel.setText(font.getName());         }         // set the font and fire a property change         Font oldValue = previewLabel.getFont();         previewLabel.setFont(font);         firePropertyChange("font", oldValue, font);         updatingComponents = false;     }     /**      * Returns the data model that handles font selections.      *      * @return a FontSelectionModel object      */     public FontSelectionModel getSelectionModel() {         return selectionModel;     }     /**      * Set the model containing the selected font.      *      * @param newModel   the new FontSelectionModel object      */     public void setSelectionModel(FontSelectionModel newModel ) {         FontSelectionModel oldModel = selectionModel;         selectionModel = newModel;         oldModel.removeChangeListener(labelUpdater);         newModel.addChangeListener(labelUpdater);         firePropertyChange("selectionModel", oldModel, newModel);     }     /**      * Gets the current font value from the font chooser.      *      * @return the current font value of the font chooser      */     public Font getFont() {         return selectionModel.getSelectedFont();     }     /**      * Sets the current font of the font chooser to the specified font.      * The <code>ColorSelectionModel</code> will fire a <code>ChangeEvent</code>      * @param font the font to be set in the font chooser      * @see JComponent#addPropertyChangeListener      */     public void setFont(Font font) {         selectionModel.setSelectedFont(font);     }     /** Returns the preview text displayed in the preview component.      * @return the preview text, if null the font name will be displayed      */     public String getPreviewText() {         return previewText;     }     /** Sets the preview text displayed in the preview component.      * @param previewText the preview text, if null the font name will be displayed      */     public void setPreviewText(String previewText) {         this.previewText = previewText;         previewLabel.setText("");         updateComponents();     } } /*  * Class which builds a font chooser dialog consisting of  * a JFontChooser with "Ok", "Cancel", and "Reset" buttons.  *  * Note: This needs to be fixed to deal with localization!  */ class FontChooserDialog extends JDialog {     private Font initialFont;     private JFontChooser chooserPane;     public FontChooserDialog(Component c, String title, boolean modal,               JFontChooser chooserPane,               ActionListener okListener, ActionListener cancelListener) {         super(JOptionPane.getFrameForComponent(c), title, modal);         //setResizable(false);         String okString = UIManager.getString("ColorChooser.okText");         String cancelString = UIManager.getString("ColorChooser.cancelText");         String resetString = UIManager.getString("ColorChooser.resetText");         /*          * Create Lower button panel          */         JPanel buttonPane = new JPanel();         buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));         JButton okButton = new JButton(okString);         getRootPane().setDefaultButton(okButton);         okButton.setActionCommand("OK");         if (okListener != null) {             okButton.addActionListener(okListener);         }         okButton.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 setVisible(false);             }         });         buttonPane.add(okButton);         JButton cancelButton = new JButton(cancelString);         // The following few lines are used to register esc to close the dialog         Action cancelKeyAction = new AbstractAction() {             public void actionPerformed(ActionEvent e) {                 // todo make it in 1.3 //                ActionListener[] listeners //                        = ((AbstractButton) e.getSource()).getActionListeners(); //                for (int i = 0; i < listeners.length; i++) { //                    listeners[i].actionPerformed(e); //                }             }         };         KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char) KeyEvent.VK_ESCAPE);         InputMap inputMap = cancelButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);         ActionMap actionMap = cancelButton.getActionMap();         if (inputMap != null && actionMap != null) {             inputMap.put(cancelKeyStroke, "cancel");             actionMap.put("cancel", cancelKeyAction);         }         // end esc handling         cancelButton.setActionCommand("cancel");         if (cancelListener != null) {             cancelButton.addActionListener(cancelListener);         }         cancelButton.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 setVisible(false);             }         });         buttonPane.add(cancelButton);         JButton resetButton = new JButton(resetString);         resetButton.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 reset();             }         });         int mnemonic = UIManager.getInt("ColorChooser.resetMnemonic");         if (mnemonic != -1) {             resetButton.setMnemonic(mnemonic);         }         buttonPane.add(resetButton);         // initialiase the content pane         this.chooserPane = chooserPane;         Container contentPane = getContentPane();         contentPane.setLayout(new BorderLayout());         contentPane.add(chooserPane, BorderLayout.CENTER);         contentPane.add(buttonPane, BorderLayout.SOUTH);         pack();         setLocationRelativeTo(c);     }     public void setVisible(boolean visible) {         if (visible)             initialFont = chooserPane.getFont();         super.setVisible(visible);     }     public void reset() {         chooserPane.setFont(initialFont);     }     static class Closer extends WindowAdapter implements Serializable {         public void windowClosing(WindowEvent e) {             Window w = e.getWindow();             w.setVisible(false);         }     }     static class DisposeOnClose extends ComponentAdapter implements Serializable {         public void componentHidden(ComponentEvent e) {             Window w = (Window) e.getComponent();             w.dispose();         }     } } class FontTracker implements ActionListener, Serializable {     JFontChooser chooser;     Font color;     public FontTracker(JFontChooser c) {         chooser = c;     }     public void actionPerformed(ActionEvent e) {         color = chooser.getFont();     }     public Font getFont() {         return color;     } } /**  * A generic implementation of <code>{@link FontSelectionModel}</code>.  *  * @author Adrian BER  */ class DefaultFontSelectionModel implements FontSelectionModel {     /** The default selected font. */     private static final Font DEFAULT_INITIAL_FONT = new Font("Dialog", Font.PLAIN, 12);          /** The selected font. */     private Font selectedFont;     /** The change listeners notified by a change in this model. */     private EventListenerList listeners = new EventListenerList();     /**      * Creates a <code>DefaultFontSelectionModel</code> with the      * current font set to <code>Dialog, 12</code>.  This is      * the default constructor.      */     public DefaultFontSelectionModel() {         this(DEFAULT_INITIAL_FONT);     }     /**      * Creates a <code>DefaultFontSelectionModel</code> with the      * current font set to <code>font</code>, which should be      * non-<code>null</code>.  Note that setting the font to      * <code>null</code> is undefined and may have unpredictable      * results.      *      * @param selectedFont the new <code>Font</code>      */     public DefaultFontSelectionModel(Font selectedFont) {         if (selectedFont == null) {             selectedFont = DEFAULT_INITIAL_FONT;         }         this.selectedFont = selectedFont;     }     public Font getSelectedFont() {         return selectedFont;     }     public void setSelectedFont(Font selectedFont) {         if (selectedFont != null) {             this.selectedFont = selectedFont;             fireChangeListeners();         }     }     public void addChangeListener(ChangeListener listener) {         listeners.add(ChangeListener.class, listener);     }     public void removeChangeListener(ChangeListener listener) {         listeners.remove(ChangeListener.class, listener);     }     /** Fires the listeners registered with this model. */     protected void fireChangeListeners() {         ChangeEvent ev = new ChangeEvent(this);         Object[] l = listeners.getListeners(ChangeListener.class);         for (Object listener : l) {             ((ChangeListener) listener).stateChanged(ev);         }     } } /**  * A model that supports selecting a <code>Font</code>.  *  * @author Adrian BER  *  * @see java.awt.Font  */ interface FontSelectionModel {     /**      * Returns the selected <code>Font</code> which should be      * non-<code>null</code>.      *      * @return  the selected <code>Font</code>      * @see     #setSelectedFont      */     Font getSelectedFont();     /**      * Sets the selected font to <code>font</code>.      * Note that setting the font to <code>null</code>      * is undefined and may have unpredictable results.      * This method fires a state changed event if it sets the      * current font to a new non-<code>null</code> font.      *      * @param font the new <code>Font</code>      * @see   #getSelectedFont      * @see   #addChangeListener      */     void setSelectedFont(Font font);     /**      * Adds <code>listener</code> as a listener to changes in the model.      * @param listener the <code>ChangeListener</code> to be added      */     void addChangeListener(ChangeListener listener);     /**      * Removes <code>listener</code> as a listener to changes in the model.      * @param listener the <code>ChangeListener</code> to be removed      */     void removeChangeListener(ChangeListener listener); } ////////////////////////////// package com.greef.ui.font; import com.greef.ui.UIUtilities; import javax.swing.*; import javax.swing.event.ChangeListener; import javax.swing.event.ChangeEvent; import javax.swing.event.DocumentListener; import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; /**  * @author Adrian BER (beradrian@yahoo.com)  */ public class JFontChooserDemo extends JPanel {     private static final Insets INSETS = new Insets(5, 5, 5, 5);     private JFontChooser fontChooser;     private JCheckBox defaultPreviewCheckBox;     private JTextField previewTextField;     private JLabel previewLabel;     private JTextArea codeTextArea;     public JFontChooserDemo() {         init();     }     private void init() {         setLayout(new GridBagLayout());         defaultPreviewCheckBox = new JCheckBox("Use font name as the preview text");         defaultPreviewCheckBox.addChangeListener(new ChangeListener() {             public void stateChanged(ChangeEvent e) {                 boolean selected = defaultPreviewCheckBox.isSelected();                 fontChooser.setPreviewText(selected ? null : previewTextField.getText());                 previewLabel.setEnabled(!selected);                 previewTextField.setEnabled(!selected);                 updateCode();             }         });         add(defaultPreviewCheckBox, new GridBagConstraints(0, 0, 2, 1, 0, 0, GridBagConstraints.WEST,                 GridBagConstraints.NONE, INSETS, 0, 0));         previewLabel = new JLabel("Preview text:");         add(previewLabel, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.EAST,                 GridBagConstraints.NONE, INSETS, 0, 0));         previewTextField = new JTextField();         previewTextField.getDocument().addDocumentListener(new DocumentListener() {             private void changePreviewText() {                 fontChooser.setPreviewText(previewTextField.getText());                 updateCode();             }             public void insertUpdate(DocumentEvent e) {                 changePreviewText();             }             public void removeUpdate(DocumentEvent e) {                 changePreviewText();             }             public void changedUpdate(DocumentEvent e) {                 changePreviewText();             }         });         add(previewTextField, new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.WEST,                 GridBagConstraints.HORIZONTAL, INSETS, 0, 0));         JButton testButton = new JButton("Test");         testButton.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 Font font = fontChooser.showDialog(JFontChooserDemo.this, "Choose a font");                 JOptionPane.showMessageDialog(JFontChooserDemo.this, font == null ? "You canceled the dialog."                         : "You have selected " + font.getName() + ", " + font.getSize()                         + (font.isBold() ? ", Bold" : "") + (font.isItalic() ? ", Italic" : ""));             }         });         add(testButton, new GridBagConstraints(0, 2, 2, 1, 1, 0, GridBagConstraints.NORTHEAST,                 GridBagConstraints.NONE, INSETS, 0, 0));         codeTextArea = new JTextArea(5, 30);         codeTextArea.setOpaque(false);         codeTextArea.setEditable(false);         codeTextArea.setBorder(BorderFactory.createTitledBorder("Code"));         add(codeTextArea, new GridBagConstraints(0, 3, 2, 1, 1, 1, GridBagConstraints.CENTER,                 GridBagConstraints.BOTH, INSETS, 0, 0));         setFontChooser(new JFontChooser());     }     private void setFontChooser(JFontChooser fontChooser) {         this.fontChooser = fontChooser;         String previewText = fontChooser.getPreviewText();         defaultPreviewCheckBox.setSelected(previewText == null);         previewTextField.setText(previewText);         updateCode();     }     private void updateCode() {         codeTextArea.setText("JFontChooser fontChooser = new JFontChooser();\n"                 + (defaultPreviewCheckBox.isSelected() ? "" : "fontChooser.setPreviewText(\""                     + previewTextField.getText() + "\");\n")                 + "Font font = fontChooser.showDialog(invokerComponent, \"Choose a font\");\n"                 + "System.out.println(font == null ? \"You have canceled the dialog.\" : \"You have selected \" + font);");     }     public void updateUI() {         super.updateUI();         if (fontChooser != null)             SwingUtilities.updateComponentTreeUI(fontChooser);     } }