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