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 */
021package csheets.ext.style.ui;
022
023import java.awt.BorderLayout;
024import java.awt.Component;
025import java.awt.Dimension;
026import java.awt.Font;
027import java.awt.GraphicsEnvironment;
028import java.awt.GridLayout;
029import java.awt.event.ActionEvent;
030import java.awt.event.ActionListener;
031
032import javax.swing.BorderFactory;
033import javax.swing.DefaultListCellRenderer;
034import javax.swing.Icon;
035import javax.swing.JCheckBox;
036import javax.swing.JComponent;
037import javax.swing.JLabel;
038import javax.swing.JList;
039import javax.swing.JOptionPane;
040import javax.swing.JPanel;
041import javax.swing.JScrollPane;
042import javax.swing.ListSelectionModel;
043import javax.swing.event.ListSelectionEvent;
044import 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")
051public 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}