Swing Components Java

// 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;
/**
 * JFontChooser provides a pane of controls designed to allow
 * a user to manipulate and select a font.
 *
 * This class provides three levels of API:
 * 

     * 
  1. A static convenience method which shows a modal font-chooser
     * dialog and returns the font selected by the user.
     * 
  2. A static convenience method for creating a font-chooser dialog
     * where ActionListeners can be specified to be invoked when
     * the user presses one of the dialog buttons.
     * 
  3. The ability to create instances of JFontChooser panes
     * directly (within any container). PropertyChange listeners
     * can be added to detect when the current "font" property changes.
     * 

 * 


 *
 * @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
     * null.
     *
     * @param component    the parent Component for the dialog
     * @param title        the String containing the dialog's title
     * @return the selected font or null 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
     * ColorChooser 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 show 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
     * FontSelectionModel.
     *
     * @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 ColorSelectionModel will fire a ChangeEvent
     * @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 {@link FontSelectionModel}.
 *
 * @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 DefaultFontSelectionModel with the
     * current font set to Dialog, 12.  This is
     * the default constructor.
     */
    public DefaultFontSelectionModel() {
        this(DEFAULT_INITIAL_FONT);
    }
    /**
     * Creates a DefaultFontSelectionModel with the
     * current font set to font, which should be
     * non-null.  Note that setting the font to
     * null is undefined and may have unpredictable
     * results.
     *
     * @param selectedFont the new Font
     */
    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 Font.
 *
 * @author Adrian BER
 *
 * @see java.awt.Font
 */
interface FontSelectionModel {
    /**
     * Returns the selected Font which should be
     * non-null.
     *
     * @return  the selected Font
     * @see     #setSelectedFont
     */
    Font getSelectedFont();
    /**
     * Sets the selected font to font.
     * Note that setting the font to null
     * is undefined and may have unpredictable results.
     * This method fires a state changed event if it sets the
     * current font to a new non-null font.
     *
     * @param font the new Font
     * @see   #getSelectedFont
     * @see   #addChangeListener
     */
    void setSelectedFont(Font font);
    /**
     * Adds listener as a listener to changes in the model.
     * @param listener the ChangeListener to be added
     */
    void addChangeListener(ChangeListener listener);
    /**
     * Removes listener as a listener to changes in the model.
     * @param listener the ChangeListener 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);
    }
}