// DisplayFonts: Java font browser
// Copyright (C) Lemma 1 Ltd. 1997
// Author: Rob Arthan; rda@lemma-one.com

// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
// The GNU General Public License can be obtained at URL:
// http://www.lemma-one.com/scrapbook/gpl.html
// or by writing to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA.

import java.awt.*;
import GUIUtils.*;

interface DisplayChar {
	public void displayChar(char ch);
}

class DisplayFontsCanvas extends Canvas {

// font related sizes:
	private int width; // width in pixels of the containing rectangles
	private int height; // height in pixels of containing rectangles
	private int ascent; // font ascent
	private int descent; // font ascent
	private int grid_height; // width of overall display
	private int grid_width; // height of overall display
// grid parameters:
	final private int border = 2;
	final private int first_ch = 0;
	final private int last_ch = 255;
	final private int n_cols = 16;
	final private int n_rows = (last_ch - first_ch + n_cols - 1)/n_cols;
// display procedure
	DisplayChar display_char;
//
// setSizes: set up above int variables  from the font metrics
//
	protected void setSizes() {
		FontMetrics metrics = getFontMetrics(getFont());
		if(metrics == null) {
			return;
		}
		ascent = metrics.getMaxAscent();
		descent = metrics.getMaxDescent();
		int advance = metrics.getMaxAdvance();
		if(advance < 0) { // getMaxAdvance may not know the answer
			advance = metrics.stringWidth("W");
		}
		height = ascent + descent + 2 * border - 1;
		width = advance + 2*border - 1;

		grid_height = n_rows * height + 1;
		grid_width = n_cols * width + 1;
	}


//
// paint method; display grid
//
	public void paint(Graphics g) {

		for(int i = 0; i <= grid_height; i += height) {
			g.drawLine(0, i, grid_width, i);
		}

		for(int j = 0; j <= grid_width; j += width) {
			g.drawLine(j, 0, j, grid_height - 1);
		}

		for(int ch = first_ch; ch <= last_ch; ++ch) {
			int row = (ch - first_ch)/n_cols;
			int col = (ch - first_ch)%n_cols;
			char[] c = { (char) ch };
			g.drawChars(c, 0, 1,
				col*width+border, row*height+border+ascent);
		}
	}
//
// constructor function:
//
	DisplayFontsCanvas (String font, int style, int size, DisplayChar disp) {

		setFont(new Font(font, style, size));
		setBackground(Color.white);
		setForeground(Color.black);
		display_char = disp;
	}
//
// preferredSize method for layout managers
//
	public Dimension preferredSize() {
		return new Dimension(grid_width, grid_height);
	}
//
// minimumSize method for layout managers
//
	public Dimension minimumSize() {
		return new Dimension(grid_width, grid_height);
	}
//
// addNotify method: set up peer and extract sizes
//
	public void addNotify() {
		super.addNotify();
		setSizes();
	}
//
// mouseMove method: if display_char isn't null display character under cursor
//
	public boolean mouseMove(Event evt, int x, int y) {
		if(display_char != null) {
			int row = y / height;
			int col = x / width;
			int ch = (row*n_cols + col + first_ch);
			display_char.displayChar
				((char)(ch <= last_ch ? ch : last_ch));
		}
		return true;
	}
}

class DisplayFontsFrame extends Frame implements DisplayChar {
//
// label to display the code of the character under the mouse
//
	Label char_code_label;
//
// the allowed font styles
//
	public final static String[] styles = {
		"Plain",
		"Italic",
		"Bold",
		"Bold Italic"
	};
//
// turn a style number from class java.awt.Font into a string
//
	public final static String decode_style(int style) {
		switch(style) {
		case Font.PLAIN: return styles[0];
		case Font.ITALIC: return styles[1];
		case Font.BOLD: return styles[2];
		default: return styles[3];
		}
	}
//
// turn a string into a style number
//
	public final static int encode_style(String style) {
		return
		style == styles[0] ? Font.PLAIN  :
		style == styles[1] ? Font.ITALIC:
		style == styles[2] ? Font.BOLD   :
		                     Font.BOLD + Font.ITALIC;
	}
//
// method to display a character code in the label
//
	public void displayChar(char ch) {
		if(char_code_label != null) {
			String msg = "Character code = 0x" +
					Integer.toString(ch, 16);
			char_code_label.setText(msg);
		}
	}
//
// Construct the window title:
//
	private String make_title(String font, int style, int size) {
		return font + " at " + size + "pt., " + decode_style(style);
	}
//
// constructor: build a frame and populate it with a font display canvas
// and the label for the character code display
//
	DisplayFontsFrame (String font, int style, int size) {
		super();
		setTitle(make_title(font, style, size));

		GridBagLayout layout = new GridBagLayout();

		setLayout(layout);

		DisplayFontsCanvas c = new DisplayFontsCanvas
						(font, style, size, this);

		GridBagConstraints c_con = new GridBagConstraints();

		c_con.gridx = 0; c_con.gridy = 0;

		layout.setConstraints(c, c_con);

		add(c);

		char_code_label = new Label("Character code = 0x00    ", Label.LEFT);
		GridBagConstraints ccl_con = new GridBagConstraints();

		ccl_con.gridx = 0; c_con.gridy = 1;

		layout.setConstraints(char_code_label, ccl_con);

		add(char_code_label);

		pack();
		show();
	}

	public boolean handleEvent(Event evt) {
		switch (evt.id) {
		case Event.WINDOW_DESTROY:
			dispose();
			break;
		default: ;
		}
		return true;
	}
}

class DisplayFontsControlPanel extends Panel {

	private String[] fonts = {
		"Courier",
		"Default",
		"Dialog",
		"DialogInput",
		"Helvetica",
		"TimesRoman",
		"ZapfDingbats"
	};

	private Choice font_choice;

	private Choice style_choice;

	private NatField size_field;

	private Button display_button;


	private GridBagConstraints
		 place(GridBagLayout gbl, Component comp,
			int x, int y, int width, int anchor) {
		
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = x;
		gbc.gridy = y;
		gbc.gridwidth = width;
		gbc.anchor = anchor;
		gbc.fill = GridBagConstraints.BOTH;
		gbl.setConstraints(comp, gbc);
		return gbc;
	}
		
	DisplayFontsControlPanel() {

		GridBagLayout gbl = new GridBagLayout();
		setLayout(gbl);

		Label font_label = new Label("Font:", Label.LEFT);
		add(font_label);

		font_choice = new Choice();
		for(int i = 0; i < fonts.length; ++i) {
			font_choice.addItem(fonts[i]);
		}
		add(font_choice);

		Label style_label = new Label("Style:", Label.LEFT);
		add(style_label);

		style_choice = new Choice();
		for(int i = 0; i < DisplayFontsFrame.styles.length; ++i) {
			style_choice.addItem(DisplayFontsFrame.styles[i]);
		}
		add(style_choice);

		Label size_label = new Label("Size:", Label.LEFT);
		add(size_label);

		size_field = new NatField(12, 3);
		add(size_field);

		display_button = new Button("Display");
		add(display_button);

		place(gbl, font_label,     0, 0, 1, GridBagConstraints.WEST);
		place(gbl, font_choice,    1, 0, 1, GridBagConstraints.EAST);
		place(gbl, style_label,    0, 1, 1, GridBagConstraints.WEST);
		place(gbl, style_choice,   1, 1, 1, GridBagConstraints.EAST);
		place(gbl, size_label,     0, 2, 1, GridBagConstraints.WEST);
		place(gbl, size_field,     1, 2, 1, GridBagConstraints.EAST);
		place(gbl, display_button, 0, 3, 2, GridBagConstraints.WEST);

		show();
	}

	public boolean handleEvent(Event evt) {
		if(evt.target == display_button
		&& evt.id == Event.ACTION_EVENT) {
			String font = font_choice.getSelectedItem();
			int style = DisplayFontsFrame.encode_style(
				style_choice.getSelectedItem());
			int size = size_field.getNat();
			new DisplayFontsFrame(font, style, size);
			return true;
		}
		return false;
	}
}

public class DisplayFonts extends java.applet.Applet {
	public void init () {
		DisplayFontsControlPanel pan = new DisplayFontsControlPanel();
		add(pan);
		resize(pan.size());
	}
}
