/**
* FontChooser - Swing dialog for choosing font, size and styles.
*
* Copyright 2006 Oleg Kobchenko, http://olegykj.sourceforge.net
*
* Licensed under the GNU LGPL License, Version 2.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/copyleft/lesser.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Revision history
* 09/05/06 Oleg Kobchenko - original release
*
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.StringTokenizer;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
/**
* FontChooser
provides a pane of controls and a dialog
* designed to allow a user to manipulate and select font, size and styles.
*
* @author Oleg Kobchenko, http://olegykj.sourceforge.net
*/
public class FontChooser extends JPanel
implements ListSelectionListener, ItemListener, ActionListener, HierarchyListener {
AttributeSet initialAttrs = null;
AttributeSet currentAttrs = null;
AttributeSet resultAttrs = null;
int MIN_SIZE = 4;
int MAX_SIZE = 72;
JButton okButton;
JList familyList;
JList sizeList;
JCheckBox boldStyle;
JCheckBox italicStyle;
JCheckBox underlineStyle;
JCheckBox strikeStyle;
JTextPane previewText;
boolean isAdjusted = true;
String familyArray[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
String fontChooserString = "Font Chooser";
String okString = "OK";
String cancelString = "Cancel";
String resetString = "Reset";
String familyString = "Family";
String sizeString = "Size";
String styleString = "Style";
String previewString = "Preview";
String boldString = "Bold";
String italicString = "Italic";
String underlineString = "Underline";
String strikeString = "Strike";
static final String previewSample = "AaBbCc GgJjYy\r\n012345 iiiwww";
static final String spaceString = " ";
static final String quoteString = "\"";
public static final String BOLD = "bold";
public static final String ITALIC = "italic";
public static final String UNDERLINE = "underline";
/**
* Creates a font chooser pane with specified style attributes
*/
public FontChooser(AttributeSet initialAttrs) {
MutableAttributeSet attrs = initialAttrs == null
? new SimpleAttributeSet() : new SimpleAttributeSet(initialAttrs);
if (Arrays.binarySearch(familyArray, StyleConstants.getFontFamily(attrs)) < 0)
attrs.removeAttribute(StyleConstants.FontFamily);
int size = StyleConstants.getFontSize(attrs);
if (size < MIN_SIZE || size > MAX_SIZE)
attrs.removeAttribute(StyleConstants.FontSize);
this.initialAttrs = attrs;
buildUI();
setAttributes(null);
}
protected void buildUI() {
this.addHierarchyListener(this);
this.setBorder(BorderFactory.createEmptyBorder(8, 10, 6, 10));
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
JPanel fontPanel = new JPanel();
fontPanel.setLayout(new BoxLayout(fontPanel, BoxLayout.LINE_AXIS));
// Font Family
JPanel familyPanel = new JPanel();
familyPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEmptyBorder(), familyString));
familyPanel.setLayout(new BoxLayout(familyPanel, BoxLayout.PAGE_AXIS));
familyList = new JList(familyArray);
JScrollPane familyScroller = new JScrollPane(familyList);
familyScroller.getVerticalScrollBar().setFocusable(false);
familyScroller.getHorizontalScrollBar().setFocusable(false);
familyPanel.add(familyScroller);
fontPanel.add(familyPanel);
// Font Size
JPanel sizePanel = new JPanel();
sizePanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEmptyBorder(), sizeString));
sizePanel.setLayout(new BoxLayout(sizePanel, BoxLayout.PAGE_AXIS));
String sizeArray[] = new String[MAX_SIZE-MIN_SIZE+1];
for (int i = MIN_SIZE; i <= MAX_SIZE; i++)
sizeArray[i-MIN_SIZE] = String.valueOf(i);
sizeList = new JList(sizeArray);
JScrollPane sizeScroller = new JScrollPane(sizeList);
sizeScroller.getVerticalScrollBar().setFocusable(false);
sizeScroller.getHorizontalScrollBar().setFocusable(false);
sizePanel.add(sizeScroller);
fontPanel.add(sizePanel);
// Font Style
JPanel stylePanel = new JPanel();
stylePanel.setBorder(BorderFactory.createTitledBorder(styleString));
stylePanel.setLayout(new BoxLayout(stylePanel, BoxLayout.PAGE_AXIS));
stylePanel.setMaximumSize(new Dimension(100, Integer.MAX_VALUE));
boldStyle = new JCheckBox(boldString);
stylePanel.add(boldStyle);
italicStyle = new JCheckBox(italicString);
stylePanel.add(italicStyle);
underlineStyle = new JCheckBox(underlineString);
underlineStyle.setVisible(initialAttrs.isDefined(StyleConstants.Underline));
stylePanel.add(underlineStyle);
strikeStyle = new JCheckBox(strikeString);
strikeStyle.setVisible(initialAttrs.isDefined(StyleConstants.StrikeThrough));
stylePanel.add(strikeStyle);
fontPanel.add(stylePanel);
this.add(fontPanel);
// end Font Panel
this.add(Box.createRigidArea(new Dimension(0, 5)));
// Preview
previewText = new JTextPane();
previewText.setText(previewSample);
previewText.setEditable(false);
previewText.setFocusable(false);
previewText.setBackground(getBackground());
JScrollPane previewPane = new JScrollPane(previewText,
JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
previewPane.setBackground(getBackground());
previewPane.setBorder(BorderFactory.createTitledBorder(previewString));
previewPane.setPreferredSize(new Dimension(Integer.MAX_VALUE, 100));
this.add(previewPane);
this.add(Box.createRigidArea(new Dimension(0, 8)));
// Buttons
JPanel buttonPanel = new JPanel();
okButton = new JButton(okString);
okButton.setPreferredSize(new Dimension(80, okButton.getMinimumSize().height));
okButton.addActionListener(this);
buttonPanel.add(okButton);
JButton cancelButton = new JButton(cancelString);
cancelButton.setPreferredSize(new Dimension(80, cancelButton.getMinimumSize().height));
cancelButton.addActionListener(this);
buttonPanel.add(cancelButton);
buttonPanel.add(Box.createRigidArea(new Dimension(20, 0)));
JButton resetButton = new JButton(resetString);
resetButton.setPreferredSize(new Dimension(80, resetButton.getMinimumSize().height));
resetButton.addActionListener(this);
buttonPanel.add(resetButton);
this.add(buttonPanel);
}
////////////////////////////////////////////////////////////////////////////////
// Events
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
SwingUtilities.getRootPane(this).setDefaultButton(okButton);
}
}
public void valueChanged(ListSelectionEvent e) {
updateText();
}
public void itemStateChanged(ItemEvent e) {
updateText();
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand() == resetString) {
setAttributes(null);
return;
}
if (e.getActionCommand() == okString) {
resultAttrs = currentAttrs;
}
SwingUtilities.getRoot(this).setVisible(false);
}
////////////////////////////////////////////////////////////////////////////////
// Operations
void updateText() {
MutableAttributeSet attrs = previewText.getInputAttributes();
StyleConstants.setFontFamily(attrs, familyList.getSelectedValue().toString());
int size = Integer.parseInt(sizeList.getSelectedValue().toString());
StyleConstants.setFontSize(attrs, size);
StyleConstants.setBold(attrs, boldStyle.isSelected());
StyleConstants.setItalic(attrs, italicStyle.isSelected());
StyleConstants.setUnderline(attrs, underlineStyle.isSelected());
StyleConstants.setStrikeThrough(attrs, strikeStyle.isSelected());
currentAttrs = new SimpleAttributeSet(attrs);
if (isAdjusted) {
StyleConstants.setFontSize(attrs, adjustSize(size));
}
StyledDocument doc = previewText.getStyledDocument();
doc.setCharacterAttributes(0, doc.getLength()+1, attrs, false);
MutableAttributeSet para = new SimpleAttributeSet(previewText.getParagraphAttributes());
StyleConstants.setAlignment(para, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, doc.getLength()+1, para, false);
}
////////////////////////////////////////////////////////////////////////////////
// Public API
/**
* Shows a modal dialog on top of specified parentFrame
with
* optional title
and initial attributes.
*
* @param parentFrame
* the parent window or null
* @param title
* specified dialog title or null
* @param initialAttrs
* the initial font and style attributes as defined with
* StyleConstants
or null
.
* Presence (either true or false) of Underline
* and StrikeThrough
attributes enables
* corresponding optional checkboxes.
*
* @return the selected attributes or null
if the user
* canceled
*
* @see javax.swing.text.StyleConstants
*/
public static AttributeSet showDialog(Frame parentFrame, String title, AttributeSet initialAttrs) {
JDialog chooserFrame = createDialog(parentFrame, title, initialAttrs);
chooserFrame.setVisible(true);
return ((FontChooser)chooserFrame.getContentPane().getComponent(0)).getAttributes();
}
public static JDialog createDialog(Frame parentFrame, String title, AttributeSet initialAttrs) {
FontChooser chooserPanel = new FontChooser(initialAttrs);
if (title == null)
title = chooserPanel.fontChooserString;
JDialog chooserFrame = new JDialog(parentFrame, title, true);
chooserFrame.getContentPane().add(chooserPanel);
chooserFrame.setSize(420, 380);
chooserFrame.setLocationRelativeTo(parentFrame);
return chooserFrame;
}
public void setAdjusted(boolean flag) {
isAdjusted = flag;
}
public static int adjustSize(int size) {
return Math.round(size * 4.0f / 3.0f);
}
public void setAttributes(AttributeSet attributes) {
familyList.removeListSelectionListener(this);
sizeList.removeListSelectionListener(this);
boldStyle.removeItemListener(this);
italicStyle.removeItemListener(this);
underlineStyle.removeItemListener(this);
strikeStyle.removeItemListener(this);
if (attributes != null)
initialAttrs = attributes;
currentAttrs = initialAttrs;
familyList.setSelectedValue(StyleConstants.getFontFamily(currentAttrs), true);
sizeList.setSelectedValue(String.valueOf(StyleConstants.getFontSize(currentAttrs)), true);
boldStyle.setSelected(StyleConstants.isBold(currentAttrs));
italicStyle.setSelected(StyleConstants.isItalic(currentAttrs));
underlineStyle.setSelected(StyleConstants.isUnderline(currentAttrs));
strikeStyle.setSelected(StyleConstants.isStrikeThrough(currentAttrs));
updateText();
familyList.addListSelectionListener(this);
sizeList.addListSelectionListener(this);
boldStyle.addItemListener(this);
italicStyle.addItemListener(this);
underlineStyle.addItemListener(this);
strikeStyle.addItemListener(this);
}
public AttributeSet getAttributes() {
return resultAttrs;
}
public static MutableAttributeSet attributesFromString(String str) {
MutableAttributeSet attrs = new SimpleAttributeSet();
if (str == null)
return attrs;
str = str.trim();
if (str.length() == 0)
return attrs;
if (str.charAt(0) == '"') {
int i = str.indexOf('"', 1);
if (i == -1)
return attrs;
StyleConstants.setFontFamily(attrs, str.substring(1, i));
str = str.substring(i+1);
} else {
int i = str.indexOf(' ', 1);
if (i == -1) i = str.length();
StyleConstants.setFontFamily(attrs, str.substring(0, i));
str = str.substring(i);
}
StringTokenizer st = new StringTokenizer(str, " ");
if (st.hasMoreTokens()) {
try {
StyleConstants.setFontSize(attrs, Integer.parseInt(st.nextToken()));
} catch (Exception ex) { return attrs; }
}
StyleConstants.setUnderline(attrs, false);
while (st.hasMoreTokens()) {
String tok = st.nextToken();
if (tok.equals(BOLD)) {
StyleConstants.setBold(attrs, true);
} else if (tok.equals(ITALIC)) {
StyleConstants.setItalic(attrs, true);
} else if (tok.equals(UNDERLINE)) {
StyleConstants.setUnderline(attrs, true);
}
}
return attrs;
}
public static String stringFromAttributes(AttributeSet attrs) {
if (attrs == null)
return "";
StringBuffer str = new StringBuffer();
str.append(quoteString);
str.append(StyleConstants.getFontFamily(attrs));
str.append(quoteString).append(spaceString);
str.append(StyleConstants.getFontSize(attrs));
if (StyleConstants.isBold(attrs))
str.append(spaceString).append(BOLD);
if (StyleConstants.isItalic(attrs))
str.append(spaceString).append(ITALIC);
if (StyleConstants.isUnderline(attrs))
str.append(spaceString).append(UNDERLINE);
return str.toString();
}
////////////////////////////////////////////////////////////////////////////////
// Example
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) { }
JFrame f = new JFrame("Font Chooser Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JTextField selectedAttrs = new JTextField("...");
panel.add(selectedAttrs, BorderLayout.NORTH);
JTextArea textArea = new JTextArea(FontChooser.previewSample);
textArea.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
panel.add(new JScrollPane(textArea), BorderLayout.CENTER);
f.getContentPane().add(panel);
f.setSize(560, 460);
f.setLocationRelativeTo(null);
f.setVisible(true);
MutableAttributeSet initAttrs = FontChooser.attributesFromString("Arial 12 bold");
// enable optional styles
StyleConstants.setStrikeThrough(initAttrs, StyleConstants.isStrikeThrough(initAttrs));
AttributeSet attrs = FontChooser.showDialog(f, null, initAttrs);
if (attrs != null) {
textArea.setFont(new Font(StyleConstants.getFontFamily(attrs),
(StyleConstants.isBold(attrs) ? Font.BOLD : 0) |
(StyleConstants.isItalic(attrs) ? Font.ITALIC : 0),
FontChooser.adjustSize(StyleConstants.getFontSize(attrs)) )); // adjusted size
}
String result = FontChooser.stringFromAttributes(attrs);
selectedAttrs.setText(result);
//f.dispose();
}
}