001    /*
002     * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>.
003     *
004     * This file is part of
005     * CleanSheets - a spreadsheet application for the Java platform.
006     *
007     * CleanSheets is free software; you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published by
009     * the Free Software Foundation; either version 2 of the License, or
010     * (at your option) any later version.
011     *
012     * CleanSheets is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with CleanSheets; if not, write to the Free Software
019     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     02111-1307      USA
020     */
021    package csheets.ext.style.ui;
022    
023    import java.awt.BorderLayout;
024    import java.awt.Component;
025    import java.awt.Dimension;
026    import java.awt.Font;
027    import java.awt.GraphicsEnvironment;
028    import java.awt.GridLayout;
029    import java.awt.event.ActionEvent;
030    import java.awt.event.ActionListener;
031    
032    import javax.swing.BorderFactory;
033    import javax.swing.DefaultListCellRenderer;
034    import javax.swing.Icon;
035    import javax.swing.JCheckBox;
036    import javax.swing.JComponent;
037    import javax.swing.JLabel;
038    import javax.swing.JList;
039    import javax.swing.JOptionPane;
040    import javax.swing.JPanel;
041    import javax.swing.JScrollPane;
042    import javax.swing.ListSelectionModel;
043    import javax.swing.event.ListSelectionEvent;
044    import javax.swing.event.ListSelectionListener;
045    
046    /**
047     * A component which allows the user to select a font.
048     * @author Einar Pehrson
049     */ 
050    @SuppressWarnings("serial")
051    public class FontChooser extends JComponent {
052    
053            /** The font sizes that can be selected */
054            private static final Integer[] SIZES = new Integer[]
055                    {4, 6, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 48, 64};   
056    
057            /** The default font size, if none is selected */
058            private static final Integer DEFAULT_SIZE = 10;
059    
060            /** The font family list */
061            private JList familyList;
062    
063            /** The font size list */
064            private JList sizeList;
065    
066            /** The checkbox that indicates whether the font is bold */
067            private JCheckBox boldBox = new JCheckBox("Bold");
068    
069            /** The checkbox that indicates whether or not the font is italic */
070            private JCheckBox italicBox = new JCheckBox("Italic");
071    
072            /** The preview label */
073            private JLabel previewLabel = new JLabel();
074    
075            /**
076             * Creates a new font selection panel.
077             */
078            public FontChooser () {
079                    this(null);
080            }
081    
082            /**
083             * Creates a new font selection panel with the given initial font selected.
084             * @param initialFont the font to select initially
085             */
086            public FontChooser(Font initialFont) {
087                    // Fetches the available font family names
088                    String[] fontFamilyNames = GraphicsEnvironment
089                            .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
090    
091                    // Creates and configures lists
092                    familyList = new JList(fontFamilyNames);
093                    familyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
094                    familyList.setVisibleRowCount(10);
095    
096                    sizeList = new JList(SIZES);
097                    sizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
098                    sizeList.setVisibleRowCount(6);
099                    ((DefaultListCellRenderer)sizeList.getCellRenderer())
100                            .setHorizontalAlignment(JLabel.RIGHT);
101    
102                    // Configures preview label
103                    previewLabel.setBorder(BorderFactory.createTitledBorder("Preview"));
104                    previewLabel.setHorizontalAlignment(JLabel.CENTER);
105                    previewLabel.setPreferredSize(
106                            new Dimension(getPreferredSize().width, 80));
107    
108                    // Creates and configures containers
109                    JPanel familyPanel = new JPanel(new BorderLayout());
110                    familyPanel.add(new JScrollPane(familyList));
111                    familyPanel.setBorder(BorderFactory.createTitledBorder("Family"));
112    
113                    JPanel sizePanel = new JPanel(new BorderLayout());
114                    sizePanel.add(new JScrollPane(sizeList));
115                    sizePanel.setBorder(BorderFactory.createTitledBorder("Size"));
116    
117                    JPanel stylePanel = new JPanel(new GridLayout(2, 1));
118                    stylePanel.add(boldBox);
119                    stylePanel.add(italicBox);
120                    stylePanel.setBorder(BorderFactory.createTitledBorder("Style"));
121    
122                    JPanel propPanel = new JPanel(new BorderLayout());
123                    propPanel.add(sizePanel, BorderLayout.CENTER);
124                    propPanel.add(stylePanel, BorderLayout.SOUTH);
125    
126                    // Registers listener
127                    PreviewLabelUpdater updater = new PreviewLabelUpdater();
128                    familyList.addListSelectionListener(updater);
129                    sizeList.addListSelectionListener(updater);
130                    boldBox.addActionListener(updater);
131                    italicBox.addActionListener(updater);
132    
133                    // Configures layout and adds components
134                    setLayout(new BorderLayout(5, 5));
135                    add(familyPanel, BorderLayout.CENTER);
136                    add(propPanel, BorderLayout.EAST);
137                    add(previewLabel, BorderLayout.SOUTH);
138    
139                    // Sets the initial font
140                    if (initialFont != null)
141                            setSelectedFont(initialFont);
142                    else
143                            setSelectedFont(new Font(fontFamilyNames[0], Font.PLAIN, 12));
144            }
145    
146            /**
147             * Lets the user select a font from a chooser in a standard dialog.
148             * @param parent the parent component of the dialog
149             * @param title the title of the dialog
150             * @param initialFont the font to select initially
151             * @return the selected font or, if the user did not press OK, null
152             */
153            public static Font showDialog(Component parent, String title,
154                            Font initialFont) {
155                    FontChooser chooser = new FontChooser(initialFont);
156                    int returnValue = JOptionPane.showConfirmDialog(
157                            parent,
158                            chooser,
159                            title,
160                            JOptionPane.OK_CANCEL_OPTION,
161                            JOptionPane.PLAIN_MESSAGE,
162                            (Icon)null);
163                    if (returnValue == JOptionPane.OK_OPTION)
164                            return chooser.getSelectedFont();
165                    else
166                            return null;
167            }
168    
169            /**
170             * Returns the currently selected font in the dialog.
171             * @return the currently selected font
172             */
173            public Font getSelectedFont() {
174                    return new Font(
175                            (String)familyList.getSelectedValue(),
176                            (boldBox.isSelected() ? Font.BOLD : Font.PLAIN)
177                                    | (italicBox.isSelected() ? Font.ITALIC : Font.PLAIN),
178                            sizeList.isSelectionEmpty() ? DEFAULT_SIZE
179                                    : (Integer)sizeList.getSelectedValue()
180                    );
181            }
182    
183            /**
184             * Sets the currently selected font in the dialog.
185             * @param font the font to select
186             */
187            public void setSelectedFont(Font font) {
188                    familyList.setSelectedValue(font.getFamily(), true);
189                    sizeList.setSelectedValue(font.getSize(), true);
190                    boldBox.setSelected(font.isBold());
191                    italicBox.setSelected(font.isItalic());
192            }
193    
194            /**
195             * A controller that updates the preview label.
196             */
197            private class PreviewLabelUpdater implements ListSelectionListener, ActionListener {
198    
199                    /**
200                     * Creates a new preview label updater.
201                     */
202                    public PreviewLabelUpdater() {}
203    
204                    /**
205                     * Updates the preview label.
206                     * @param e the event that was fired
207                     */
208                    public void actionPerformed(ActionEvent e) {
209                            previewLabel.setFont(getSelectedFont());
210                    }
211    
212                    /**
213                     * Updates the preview label.
214                     * @param e the event that was fired
215                     */
216                    public void valueChanged(ListSelectionEvent e) {
217                            if (!e.getValueIsAdjusting()) {
218                                    Font font = getSelectedFont();
219                                    previewLabel.setFont(font);
220                                    previewLabel.setText(font.getName());
221                            }
222                    }
223            }
224    }