/*
* [FontShower.java]
*
* Summary: FontShower: displays Swing fonts.
*
* Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.5 2004-05-18 initial released Fahd Shariff
* TODO: add more entities, Greek, hex, JColorChooser
* figure out why anti-alias sometimes fails.
* 1.6 2004-05-18 Roedy, add about box, make work as application too. change defaults.
* add more pangrams.
* 1.7 2004-05-18 Use JSpinner for font size.
* 1.8 2005-07-20 add more sample chars, allow anti-alias.
* 1.9 2005-08-11 prompt whether selecting text or background color.
* Separate out FontSamples class to make it common
* to FontShower and FontShowerAwt.
* Sort out why anti-alias was not working. Remove Baht char.
* 2.0 2005-09-01 add Japanese Hiragana and Katagana char.
* 2.1 2006-03-05
* 2.2 2007-02-09 more Chinese sample chars
* 2.3 2007-05-03 more reserved colour scheme.
* 2.4 2008-04-01 display title and build number.
* 2.5 2008-05-26 add arrows to sample chars
* 2.6 2008-08-18 summary list of all fonts you can copy paste.
* 2.7 2008-11-20 add Esperanto accented letters
* 2.8 2009-01-23 add Kanji digits to font samples.
* 2.9 2009-09-30 add true font heights to allfonts display
*/
package com.mindprod.fontshower;
import com.mindprod.common18.Build;
import com.mindprod.common18.CMPAboutJBox;
import com.mindprod.common18.Common18;
import com.mindprod.common18.FontFactory;
import com.mindprod.common18.HybridJ;
import com.mindprod.common18.JEButton;
import com.mindprod.common18.Misc;
import com.mindprod.common18.ST;
import com.mindprod.common18.VersionCheck;
import com.mindprod.fontshowerawt.FontSamples;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Vector;
import static java.lang.System.*;
/**
* FontShower: displays Swing fonts.
*
*
* An Applet that lets you choose the font family, size, style
* text color, background color and displays a message in the selected
* font. Requires Swing. Text for sample comes from
* com.mindprod.fontshowerawt.FontSamples.
* Use either as Applet with
* <applet code="com.mindprod.fontshower.FontShower.class"
* archive="fontshower.jar"
* width="655"
* height="370"
* vspace="10"
* hspace="10"
* alt="Sorry, you need Java to run FontShower">
* Sorry, you need Java to run FontShower
* </applet>
*
* or as an application with:
* java -ea -jar fontshower.jar
*
*
*
* @author Roedy Green, Canadian Mind Products
* @version 2.9 2009-09-30 add true font heights to all fonts display
* @noinspection FieldCanBeLocal
* @since 2005
*/
public final class FontShower extends JApplet
{
/**
* height of Applet box in pixels. Does not include surrounding frame.
*/
private static final int APPLET_HEIGHT = 660;
/**
* Width of Applet box in pixels., wide enough for a very long font name.
*/
private static final int APPLET_WIDTH = 720;
/**
* starting font size
*/
private static final int defaultSize = 18;
private static final int FIRST_COPYRIGHT_YEAR = 2005;
/**
* how the all fonts option is displayed
*/
private static final String allFontsWording = "\u00aball fonts summary\u00bb";
/**
* starting font
*/
private static final String defaultFontFamily = "Dialog";
/**
* undisplayed copyright notice
*
* @noinspection UnusedDeclaration
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
private static final String RELEASE_DATE = "2009-09-30";
/**
* title for about box
*/
private static final String TITLE_STRING = "Swing Font Shower";
/**
* program version for about box
*/
private static final String VERSION_STRING = "2.9";
/**
* background colour, light violet
*/
private static final Color BACKGROUND_FOR_BODY = new Color( 0xfce8ff );
/**
* light green to match mindprod.com background.
*/
private static final Color BACKGROUND_FOR_DEFAULT = Build.BACKGROUND_FOR_BLENDING;
/**
* dark green foreground
*/
private static final Color FOREGROUND_FOR_DEFAULT = new Color( 0x004000 );
/**
* for titles
*/
private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c );
/**
* formats the true height of a 10 point font with one decimal place
*/
private static final DecimalFormat fontSizeFormatter = new DecimalFormat( "#0.9" );
/**
* for for titles and About buttons
*/
private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 );
/**
* for for title second line
*/
private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 );
/**
* show all fonts at once.
*/
private AntiAliasedJTextArea allDisplayArea;
/**
* where we display the font sample
*/
private AntiAliasedJTextArea displayArea;
/**
* about button
*/
private JButton about;
/**
* select background color
*/
private JButton chooseBackgroundColor;
/**
* select foreground color
*/
private JButton chooseForegroundColor;
/**
* choice of all supported fonts
*/
private JComboBox fontChoices;
/**
* Applet Title
*/
private JLabel title;
/**
* title, second line
*/
private JLabel title2;
/**
* scrolls list of all fonts
*/
private JScrollPane allScroller;
/**
* scrolls the font sample
*/
private JScrollPane scroller;
/**
* font size selection
*/
private JSpinner sizeSpinner;
/**
* toggle anti-alias state
*/
private JToggleButton toggleAntiAlias;
/**
* toggle bold state
*/
private JToggleButton toggleBold;
/**
* toggle italic state
*/
private JToggleButton toggleItalic;
/**
* helper for sizeSpinner
*/
private SpinnerNumberModel sizeSpinnerModel;
/**
* get actual height of font
*
* @param FontName name of font
*
* @return true height of a 10 point font in pixels.
*/
private static float getTrueFontHeight( String FontName )
{
final Font f = new Font( FontName, Font.PLAIN, 10 );
final BufferedImage dummybi = new BufferedImage( 200
/* dummy */,
200
/* dummy */,
BufferedImage.TYPE_4BYTE_ABGR_PRE );
final Graphics2D dummyg2d = dummybi.createGraphics();
final FontRenderContext fr = dummyg2d.getFontRenderContext();
final LineMetrics lm = f.getLineMetrics( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnoprstuvwxyz01234567809()[]{}",
fr );
return lm.getDescent() + lm.getAscent();
}
/**
* allocate the components
*/
private void buildComponents()
{
title = new JLabel( TITLE_STRING + " " + VERSION_STRING );
title.setFont( FONT_FOR_TITLE );
title.setForeground( FOREGROUND_FOR_TITLE );
title2 = new JLabel(
"released:" +
RELEASE_DATE +
" build:" +
Build.BUILD_NUMBER
);
title2.setFont( FONT_FOR_TITLE2 );
title2.setForeground( FOREGROUND_FOR_TITLE );
buildFontChoices();
fontChoices.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
final String newFontFamily = ( String ) fontChoices.getSelectedItem();
if ( newFontFamily.equals( allFontsWording ) )
{
if ( !allScroller.isVisible() )
{
scroller.setVisible( false );
allScroller.setVisible( true );
validate();
}
}
else
{
if ( !scroller.isVisible() )
{
allScroller.setVisible( false );
scroller.setVisible( true );
validate();
}
// display a single font
final Font oldFont = displayArea.getFont();
// don't use FontFactory. We want the official font.
displayArea.setFont( new Font( newFontFamily, oldFont.getStyle(), oldFont.getSize() ) );
}
}
} );
// font sizes
sizeSpinner = new JSpinner();
Dimension d = new Dimension( 40, 25 );
sizeSpinner.setMinimumSize( d );
sizeSpinner.setPreferredSize( d );
sizeSpinner.setMaximumSize( d );
sizeSpinnerModel = new SpinnerNumberModel( /* init value */ 18,
/* min*/ 8,
/* max */ 300,
/* step */ 1 );
sizeSpinner.setModel( sizeSpinnerModel );
sizeSpinner.addChangeListener( new ChangeListener()
{
/**
* Invoked when the sizeSpinner changes
* @param e a ChangeEvent object
*/
public void stateChanged( ChangeEvent e )
{
float fontSize = sizeSpinnerModel.getNumber().floatValue();
displayArea.setFont( displayArea.getFont().deriveFont( fontSize ) );
allDisplayArea.setFont( allDisplayArea.getFont().deriveFont( fontSize ) );
}
} );
// bold button
toggleBold = new JToggleButton( "Bold", false );
toggleBold.setMnemonic( KeyEvent.VK_B );
toggleBold.setToolTipText( "Bold" );
ActionListener styleChangeListener = new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
changeStyle();
}
};
toggleBold.addActionListener( styleChangeListener );
// italic
toggleItalic = new JToggleButton( "Italics", false );
toggleItalic.setMnemonic( KeyEvent.VK_I );
toggleItalic.setToolTipText( "Italic" );
toggleItalic.addActionListener( styleChangeListener );
// anti-alias
toggleAntiAlias = new JToggleButton( "Anti-alias", false );
toggleAntiAlias.setMnemonic( KeyEvent.VK_A );
toggleAntiAlias.setToolTipText( "Anti-alias font smoothing" );
toggleAntiAlias.addActionListener( styleChangeListener );
// background
chooseBackgroundColor = new JEButton( "Background Colour", false );
chooseBackgroundColor.setMnemonic( KeyEvent.VK_C );
chooseBackgroundColor.setToolTipText( "Change Background Colour" );
chooseBackgroundColor.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
final Color newBackground = getColorChoice( false );
displayArea.setBackground( newBackground );
allDisplayArea.setBackground( newBackground );
}
} );
// foreground
chooseForegroundColor = new JEButton( "Text Colour", false );
chooseForegroundColor.setMnemonic( KeyEvent.VK_T );
chooseForegroundColor.setToolTipText( "Change Text Colour" );
chooseForegroundColor.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
Color newForeground = getColorChoice( true );
displayArea.setForeground( newForeground );
allDisplayArea.setForeground( newForeground );
}
} );
// about
about = new JEButton( "About" );
about.setToolTipText( "About " + TITLE_STRING + " " + VERSION_STRING );
about.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
// open aboutbox frame
new CMPAboutJBox( Misc.getParentFrame( FontShower.this ),
TITLE_STRING,
VERSION_STRING,
"Shows you what fonts are available in Swing and what they",
"look like, in various styles, sizes and colours.",
"freeware",
RELEASE_DATE,
FIRST_COPYRIGHT_YEAR,
"Fahd Shariff, Roedy Green",
"FONTSHOWER",
"1.8" );
}
} );
displayArea = new AntiAliasedJTextArea( FontSamples.getFontSampleText() );
// build some text to display to show all fonts at once.
displayArea.setEditable( false );
displayArea.setBackground( BACKGROUND_FOR_DEFAULT );
displayArea.setForeground( FOREGROUND_FOR_DEFAULT );
// don't use FontFactory. We want the official font.
displayArea.setFont( new Font( defaultFontFamily, Font.PLAIN, defaultSize ) );
displayArea.setAntiAlias( false );
// make the text sit back a bit from the edges.
displayArea.setMargin( new Insets( 3, 3, 3, 3 ) );
scroller = new JScrollPane( displayArea );// VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED)
// displaying a sample of each font means the page takes about 6 seconds to render -- too slow to react
// to the buttons, so we just show the name.
final GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
final String[] fontNames = ge.getAvailableFontFamilyNames();
StringBuilder sb = new StringBuilder( fontNames.length * 25 + 100 );
sb.append( "Fonts Available to Java under " );
sb.append( System.getProperty( "os.name", "unknown OS" ) );
sb.append( "\n" );
sb.append( ST.rightPad( "Font Name", 30, false ) );
sb.append( "True height of a 10 point font" );
sb.append( "\n" );
for ( String f : fontNames )
{
sb.append( ST.rightPad( f, 30, false ) );
sb.append( ST.leftPad( fontSizeFormatter.format( getTrueFontHeight( f ) ), 4, false ) );
sb.append( "\n" );
}
final String allFontsList = sb.toString();
// echo list of all fonts to console for easy copy/paste
out.println( allFontsList );
// put list of all fonts to component for rapid showing.
allDisplayArea = new AntiAliasedJTextArea( sb.toString() );
allDisplayArea.setEditable( false );
allDisplayArea.setBackground( BACKGROUND_FOR_DEFAULT );
allDisplayArea.setForeground( FOREGROUND_FOR_DEFAULT );
// don't use FontFactory. We want the official font.
allDisplayArea.setFont( new Font( "Monospaced", Font.PLAIN, defaultSize ) );
allDisplayArea.setAntiAlias( true );
// make the text sit back a bit from the edges.
allDisplayArea.setMargin( new Insets( 3, 3, 3, 3 ) );
allScroller = new JScrollPane( allDisplayArea );// VERTICAL_SCROLLBAR_AS_NEEDED,
// HORIZONTAL_SCROLLBAR_AS_NEEDED)
allScroller.setVisible( false );
}
/**
* set up fontChoices Widget with lislt of all possible fonts, but not listeners.
*/
private void buildFontChoices()
{
// font names
final GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
final String[] fontNames = ge.getAvailableFontFamilyNames();
// use Vector instead of ArrayList because JComboBox wants a vector
final Vector v = new Vector<>( fontNames.length + 1 );
v.add( allFontsWording );
v.addAll( Arrays.asList( fontNames ) );
fontChoices = new JComboBox<>( v );
fontChoices.setMaximumSize( fontChoices.getPreferredSize() );
fontChoices.setEditable( true );
fontChoices.setSelectedItem( defaultFontFamily );
}
/**
* Changes the style (Bold, Italic ) of the selected text by checking the style buttons
*/
private void changeStyle()
{
int style = Font.PLAIN;
if ( toggleBold.isSelected() )
{
style |= Font.BOLD;
}
if ( toggleItalic.isSelected() )
{
style |= Font.ITALIC;
}
displayArea.setFont( displayArea.getFont().deriveFont( style ) );
displayArea.setAntiAlias( toggleAntiAlias.isSelected() );
allDisplayArea.setFont( allDisplayArea.getFont().deriveFont( style ) );
allDisplayArea.setAntiAlias( toggleAntiAlias.isSelected() );
// changing font invalidates textarea.
}
/**
* Displays a color chooser and returns the selected color.
*
* @param foreground true if want to change the foreground color, false to change the background color.
*
* @return the selected Color
*/
private Color getColorChoice( boolean foreground )
{
return JColorChooser.showDialog( this,
"Choose "
+ ( foreground
? "Text"
: "Background" )
+ " Color",
foreground
? displayArea.getForeground()
: displayArea.getBackground()
);
}
/**
* layout all the components in a GridBag
*
* @param contentPane where to place the components
*/
private void layoutComponents( Container contentPane )
{
// --0---0----1----2-----3-------4----------5---------6----
// 0 title -----------------title2---------------- about
// 1 font size bold italics antialias background textcolor-
// 2 -----------scroller-------------------------------------
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( title,
new GridBagConstraints( 0,
0,
4,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 10, 10, 5, 10 ),
0,
0 )
);
contentPane.add( title2,
new GridBagConstraints( 4,
0,
2,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 10, 10, 5, 10 ),
0,
0 )
);
contentPane.add( about,
new GridBagConstraints( 6,
0,
1,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 10, 10, 5, 10 ),
0,
0 )
);
contentPane.add( fontChoices,
new GridBagConstraints( 0,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 10, 5, 5 ),
0,
0 )
);
contentPane.add( sizeSpinner,
new GridBagConstraints( 1,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 5 ),
5,
0 )
);
contentPane.add( toggleBold,
new GridBagConstraints( 2,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 5 ),
0,
0 )
);
contentPane.add( toggleItalic,
new GridBagConstraints( 3,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 5 ),
0,
0 )
);
contentPane.add( toggleAntiAlias,
new GridBagConstraints( 4,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 5 ),
0,
0 )
);
contentPane.add( chooseBackgroundColor,
new GridBagConstraints( 5,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 5 ),
0,
0 )
);
contentPane.add( chooseForegroundColor,
new GridBagConstraints( 6,
1,
1,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 0, 5, 10 ),
0,
0 )
);
contentPane.add( scroller, /* sample chars */
new GridBagConstraints( 0,
2,
7,
1,
100.0,
100.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 10, 10, 10 ),
0,
0 )
);
contentPane.add( allScroller, /* names of all fonts */
new GridBagConstraints( 0,
2,
7,
1,
100.0,
100.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 0, 10, 10, 10 ),
0,
0 )
);
}
/**
* Allow this Applet to run as as application as well.
*
* @param args command line arguments ignored.
*/
public static void main( String args[] )
{
HybridJ.fireup( new FontShower(),
TITLE_STRING + " " + VERSION_STRING,
APPLET_WIDTH,
APPLET_HEIGHT );
} // end main
/**
* Called by the browser or Applet viewer to inform
* this Applet that it is being reclaimed and that it should destroy
* any resources that it has allocated.
*/
public void destroy()
{
about = null;
allDisplayArea = null;
allScroller = null;
chooseBackgroundColor = null;
chooseForegroundColor = null;
displayArea = null;
fontChoices = null;
scroller = null;
sizeSpinner = null;
sizeSpinnerModel = null;
title = null;
title2 = null;
toggleAntiAlias = null;
toggleBold = null;
toggleItalic = null;
}
/**
* Called by the browser or Applet viewer to inform
* this Applet that it has been loaded into the system.
*/
@Override
public void init()
{
// need 1.3 for Swing
if ( !VersionCheck.isJavaVersionOK( 1, 7, 0, this.getContentPane() ) )
{
// effectively abort
return;
}
Common18.setLaf();
Container contentPane = this.getContentPane();
contentPane.setLayout( new GridBagLayout() );
contentPane.setBackground( BACKGROUND_FOR_BODY );
buildComponents();
layoutComponents( contentPane );
this.validate();
this.setVisible( true );
}
}