001 /* JAPI - (Yet another (hopefully) useful) Java API
002 *
003 * Copyright (C) 2004-2006 Christian Hujer
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but
011 * WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018 * 02111-1307, USA.
019 */
020
021 package net.sf.japi.swing.font;
022
023 import java.awt.Component;
024 import java.awt.Font;
025 import static java.awt.Font.BOLD;
026 import static java.awt.Font.ITALIC;
027 import static java.awt.Font.PLAIN;
028 import java.awt.GraphicsEnvironment;
029 import java.awt.GridBagConstraints;
030 import java.awt.GridBagLayout;
031 import java.awt.Insets;
032 import static javax.swing.BorderFactory.createCompoundBorder;
033 import static javax.swing.BorderFactory.createEmptyBorder;
034 import static javax.swing.BorderFactory.createTitledBorder;
035 import javax.swing.JComponent;
036 import javax.swing.JLabel;
037 import javax.swing.JList;
038 import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
039 import static javax.swing.JOptionPane.OK_OPTION;
040 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
041 import static javax.swing.JOptionPane.showConfirmDialog;
042 import javax.swing.JScrollPane;
043 import javax.swing.JSpinner;
044 import static javax.swing.ListSelectionModel.SINGLE_SELECTION;
045 import javax.swing.SpinnerNumberModel;
046 import javax.swing.event.ChangeEvent;
047 import javax.swing.event.ChangeListener;
048 import javax.swing.event.ListSelectionEvent;
049 import javax.swing.event.ListSelectionListener;
050 import org.jetbrains.annotations.Nullable;
051 import net.sf.japi.swing.ActionFactory;
052 import static net.sf.japi.swing.ActionFactory.getFactory;
053
054 /** Class for letting the user choose a font.
055 * There are two possibilities to use this class:
056 * <ul>
057 * <li>You can use an instance of FontChooser as a Pane and add it to the desired Container.</li>
058 * <li>You can use this class' static methods to display a Dialog which lets the user choose a font.</li>
059 * </ul>
060 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
061 */
062 public class FontChooser extends JComponent implements ListSelectionListener, ChangeListener {
063
064 /** Action Factory. */
065 private static final ActionFactory ACTION_FACTORY = getFactory("net.sf.japi.swing.font");
066
067 /** JList for Font Family.
068 * @serial include
069 */
070 private JList familyList;
071
072 /** JList for Font Style.
073 * @serial include
074 */
075 private JList styleList;
076
077 /** JList for Font Size.
078 * @serial include
079 */
080 private JList sizeList;
081
082 /** JSpinner for Font Size.
083 * @serial include
084 */
085 private JSpinner sizeSpinner;
086
087 /** FontPreview for Font.
088 * @serial include
089 */
090 private FontPreview preview;
091
092 /** Selected Font.
093 * @serial include
094 */
095 private Font selectedFont;
096
097 /** Create a new FontChooser. */
098 public FontChooser() {
099 setBorder(createCompoundBorder(createCompoundBorder(createEmptyBorder(8, 8, 8, 8), createTitledBorder(ACTION_FACTORY.getString("desiredFont_borderTitle"))), createEmptyBorder(8, 4, 4, 4)));
100 setLayout(new GridBagLayout());
101 final GridBagConstraints gbc = new GridBagConstraints();
102 gbc.insets = new Insets(2, 2, 2, 2);
103 final JLabel familyLabel = ACTION_FACTORY.createLabel("family.label");
104 final JLabel styleLabel = ACTION_FACTORY.createLabel("style.label");
105 final JLabel sizeLabel = ACTION_FACTORY.createLabel("size.label");
106 familyList = new JList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
107 styleList = new JList(new Integer[] { PLAIN, ITALIC, BOLD, BOLD|ITALIC });
108 styleList.setCellRenderer(new FontStyleListCellRenderer());
109 sizeList = new JList(new Integer[] { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 32, 48, 64 });
110 preview = new FontPreview();
111 sizeSpinner = new JSpinner(new SpinnerNumberModel(12, 4, 100, 1));
112 gbc.weightx = 1.0;
113 gbc.fill = GridBagConstraints.BOTH;
114 add(familyLabel, gbc);
115 add(styleLabel, gbc);
116 gbc.gridwidth = GridBagConstraints.REMAINDER;
117 add(sizeLabel, gbc);
118 gbc.gridwidth = 1;
119 gbc.gridheight = 2;
120 gbc.weighty = 1.0;
121 add(new JScrollPane(familyList), gbc);
122 add(new JScrollPane(styleList), gbc);
123 gbc.gridheight = 1;
124 gbc.gridwidth = GridBagConstraints.REMAINDER;
125 gbc.weighty = 0.0;
126 add(sizeSpinner, gbc);
127 gbc.weighty = 1.0;
128 add(new JScrollPane(sizeList), gbc);
129 gbc.gridwidth = 3;
130 add(preview, gbc);
131 familyList.addListSelectionListener(this);
132 styleList.addListSelectionListener(this);
133 sizeList.addListSelectionListener(this);
134 sizeSpinner.addChangeListener(this);
135 familyList.setSelectionMode(SINGLE_SELECTION);
136 styleList.setSelectionMode(SINGLE_SELECTION);
137 sizeList.setSelectionMode(SINGLE_SELECTION);
138 }
139
140 /** Set the selected font. */
141 public void setSelectedFont(final Font selectedFont) {
142 this.selectedFont = selectedFont;
143 preview.setFont(selectedFont);
144 //lock = true;
145 sizeSpinner.setValue(selectedFont.getSize());
146 sizeList.setSelectedValue(selectedFont.getSize(), true);
147 styleList.setSelectedValue(selectedFont.getStyle(), true);
148 familyList.setSelectedValue(selectedFont.getFamily(), true);
149 //lock = false;
150 }
151
152 /** Set the selected family. */
153 private void updateFont() {
154 //if (lock) { return; }
155 final String family = familyList.getSelectedValue() == null ? selectedFont.getFamily() : (String) familyList.getSelectedValue();
156 final int style = styleList.getSelectedValue() == null ? selectedFont.getStyle() : (Integer) styleList.getSelectedValue();
157 final int size = sizeList.getSelectedValue() == null ? selectedFont.getSize() : (Integer) sizeSpinner.getValue();
158 selectedFont = new Font(family, style, size);
159 preview.setFont(selectedFont);
160 }
161
162 /** {@inheritDoc} */
163 public void valueChanged(final ListSelectionEvent e) {
164 final Object source = e.getSource();
165 if (source == familyList) {
166 // No special action except updateFont()
167 } else if (source == styleList) {
168 // No special action except updateFont()
169 } else if (source == sizeList) {
170 final Object size = sizeList.getSelectedValue();
171 if (!sizeSpinner.getValue().equals(size) && size != null) {
172 sizeSpinner.setValue(size);
173 }
174 } else {
175 assert false;
176 }
177 updateFont();
178 }
179
180 /** {@inheritDoc} */
181 public void stateChanged(final ChangeEvent e) {
182 final Object source = e.getSource();
183 if (source == sizeSpinner) {
184 final Object size = sizeSpinner.getValue();
185 if (!size.equals(sizeList.getSelectedValue())) {
186 sizeList.setSelectedValue(size, true);
187 }
188 } else {
189 assert false;
190 }
191 updateFont();
192 }
193
194 /** Show a dialog.
195 * @param parent Parent component
196 * @return seleced font or null
197 */
198 public static Font showChooseFontDialog(final Component parent) {
199 return showChooseFontDialog(parent, Font.decode(null));
200 }
201
202 /** Show a dialog.
203 * @param parent Parent compnent
204 * @param font Font to modify
205 * @return selected font or null
206 */
207 @Nullable public static Font showChooseFontDialog(final Component parent, final Font font) {
208 final FontChooser chooser = new FontChooser();
209 chooser.setSelectedFont(font);
210 if (showConfirmDialog(parent, chooser, ACTION_FACTORY.getString("chooser.title"), OK_CANCEL_OPTION, PLAIN_MESSAGE) == OK_OPTION) {
211 return chooser.selectedFont;
212 } else {
213 return null;
214 }
215 }
216
217 } // class FontChooser