/*
 * MogensenPlanetDisplay.java  1.0  98/06/03  Carl Burke
 *
 * Provides a simple interface to Torben AE. Mogensen's planet generator.
 *
 * Copyright (c) 1998 Carl Burke.
 */

import java.awt.*;
import java.awt.image.*;
import java.applet.*;

class MogensenPlanetPanel extends Panel implements ImageObserver
{
    private Dimension panelDimensions;
    private ImageProjection ip;
    private Image img;
    private Button working;
    private boolean creatingImage;
    public MogensenPlanetPanel(Button w)
    {
	super();
	panelDimensions = new Dimension(400, 400);
	working = w;
	creatingImage = false;
    }
    public Dimension getMinimumSize()
    {
	return new Dimension(panelDimensions);
    }
    public Dimension getMaximumSize()
    {
	return new Dimension(panelDimensions);
    }
    public Dimension getPreferredSize()
    {
	return new Dimension(panelDimensions);
    }
    public Dimension minimumSize()
    {
	return new Dimension(panelDimensions);
    }
    public Dimension preferredSize()
    {
	return new Dimension(panelDimensions);
    }
    public void setImageProjection(ImageProjection IP)
    {
	ip = IP;
	recalculateProjection();
    }
    public void recalculateProjection()
    {
	img = null;
	ip.forcePixelRecalc();
	repaint();
    }
    public void paint(Graphics g)
    {
	g.setColor(Color.white);
	if (ip==null)
	{
	    Color c = g.getColor();
	    g.setColor(Color.black);
	    g.fillRect(0, 0, panelDimensions.width, panelDimensions.height);
	    g.setColor(c);
	}
	else
	{
	    if (img==null)
	    {
		creatingImage = true;
		working.setBackground(Color.red);
		working.setForeground(Color.black);
		working.setLabel("working");
		working.repaint();
		img = createImage(ip);
	    }
	    g.drawImage(img, 0, 0, Color.black, this);
	}
    }
    public boolean imageUpdate(
	Image img,
	int infoflags,
	int x, int y,
	int width, int height)
    {
	int doneflags = ImageObserver.ALLBITS |
			ImageObserver.ERROR |
			ImageObserver.ABORT; 
	if (creatingImage && ((infoflags & doneflags) != 0))
	{
	    creatingImage = false;
	    working.setBackground(Color.black);
	    working.setForeground(Color.black);
	    working.setLabel(null);
	    working.repaint();
	}
	return super.imageUpdate(img, infoflags, x, y, width, height);
    }
}

public class MogensenPlanetDisplay extends Applet
{
    private Choice projection;
    private String selectedProjection;
    private Button working;
    private Button redraw;
    private MogensenPlanetPanel mainPanel;
    private MogensenSolidNoiseGenerator msng;
    private ImageProjection ip;

    private double latitude;
    private double longitude;
    private TextField latField;
    private TextField longField;
    private Label latLabel;
    private Label longLabel;

    private double latgrid;
    private double longrid;
    private TextField latGridField;
    private TextField lonGridField;
    private Label latGridLabel;
    private Label lonGridLabel;

    private double magnification;
    private TextField magField;
    private Label magLabel;

    private double seed;
    private TextField seedField;
    private Label seedLabel;

    private Checkbox changeColorsWithLatitude;

    private void setImageProjection()
    {
	if (selectedProjection.equals("Azimuth"))
	    ip = new AzimuthImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Conical"))
	{
	    if (latitude==0.0)
		ip = new MercatorImageProjection(400, 400, msng);
	    else
		ip = new ConicalImageProjection(400, 400, msng);
	}
	else if (selectedProjection.equals("Gnomonic"))
	    ip = new GnomonicImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Mercator"))
	    ip = new MercatorImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Mollweide"))
	    ip = new MollweideImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Orthographic"))
	    ip = new OrthographicImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Peter"))
	    ip = new PeterImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Sinusoid"))
	    ip = new SinusoidImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Square"))
	    ip = new SquareImageProjection(400, 400, msng);
	else if (selectedProjection.equals("Stereo"))
	    ip = new StereoImageProjection(400, 400, msng);
	ip.setCenterOfProjection(longitude, latitude);
	ip.setGridSpacing(longrid, latgrid);
	ip.setMagnification(magnification);
	mainPanel.setImageProjection(ip);
    }
    private void extractTextFieldValues()
    {
	double dblval;
	// check text fields for changed values
	String latText = latField.getText();
	String longText = longField.getText();
	String latGridText = latGridField.getText();
	String lonGridText = lonGridField.getText();
	String magText = magField.getText();
	String seedText = seedField.getText();
	try {
	    dblval = Double.valueOf(latText).doubleValue();
	    if (dblval <= 90.0 && dblval >= -90.0)
	    {
		dblval *= ImageProjection.DEG2RAD;
		if (latitude != dblval)
		    ip.setCenterOfProjection(longitude, latitude=dblval);
	    }
	} catch (NumberFormatException nfe) {
	    latField.setText(String.valueOf(latitude));
	}
	try {
	    dblval = Double.valueOf(longText).doubleValue();
	    if (dblval <= 360.0 && dblval >= -360.0)
	    {
		dblval *= ImageProjection.DEG2RAD;
		if (longitude != dblval)
		    ip.setCenterOfProjection(longitude=dblval, latitude);
	    }
	} catch (NumberFormatException nfe) {
	    longField.setText(String.valueOf(longitude));
	}
	try {
	    dblval = Double.valueOf(latGridText).doubleValue();
	    if (dblval <= 90.0 && dblval >= 0.0)
	    {
		if (latgrid != dblval)
		    ip.setGridSpacing(longrid, latgrid=dblval);
	    }
	} catch (NumberFormatException nfe) {
	    latGridField.setText(String.valueOf(latgrid));
	}
	try {
	    dblval = Double.valueOf(lonGridText).doubleValue();
	    if (dblval <= 360.0 && dblval >= 0.0)
	    {
		if (longrid != dblval)
		    ip.setGridSpacing(longrid=dblval, latgrid);
	    }
	} catch (NumberFormatException nfe) {
	    lonGridField.setText(String.valueOf(longrid));
	}
	try {
	    dblval = Double.valueOf(magText).doubleValue();
	    if (dblval > 1.0)
	    {
		if (magnification != dblval)
		    ip.setMagnification(magnification=dblval);
	    }
	} catch (NumberFormatException nfe) {
	    magField.setText(String.valueOf(magnification));
	}
	try {
	    dblval = Double.valueOf(seedText).doubleValue();
	    if (seed != dblval)
		msng.setSeed(seed=dblval);
	} catch (NumberFormatException nfe) {
	    seedField.setText(String.valueOf(seed));
	}
    }
    private void setGadgetColors()
    {
	// set background color

	working.setBackground(Color.black);
	projection.setBackground(Color.black);
	latLabel.setBackground(Color.black);
	longLabel.setBackground(Color.black);
	latField.setBackground(Color.black);
	longField.setBackground(Color.black);
	latGridLabel.setBackground(Color.black);
	lonGridLabel.setBackground(Color.black);
	latGridField.setBackground(Color.black);
	lonGridField.setBackground(Color.black);
	changeColorsWithLatitude.setBackground(Color.black);
	magLabel.setBackground(Color.black);
	seedLabel.setBackground(Color.black);
	magField.setBackground(Color.black);
	seedField.setBackground(Color.black);
	redraw.setBackground(Color.black);
	setBackground(Color.black);

	// set foreground color

	working.setForeground(Color.black);
	projection.setForeground(Color.white);
	latLabel.setForeground(Color.white);
	longLabel.setForeground(Color.white);
	latField.setForeground(Color.white);
	longField.setForeground(Color.white);
	latGridLabel.setForeground(Color.white);
	lonGridLabel.setForeground(Color.white);
	latGridField.setForeground(Color.white);
	lonGridField.setForeground(Color.white);
	changeColorsWithLatitude.setForeground(Color.white);
	magLabel.setForeground(Color.white);
	seedLabel.setForeground(Color.white);
	magField.setForeground(Color.white);
	seedField.setForeground(Color.white);
	redraw.setForeground(Color.white);
	setForeground(Color.white);
    }
    public void init()
    {
	latitude = 0.0;
	longitude = 0.0;
	latgrid = 0.0;
	longrid = 0.0;
	magnification = 1.0;
	seed = 0.123;
	setLayout(new FlowLayout());
	working = new Button("Working");
	add(working);
	projection=new Choice();
	projection.addItem("Azimuth");
	projection.addItem("Conical");
	projection.addItem("Gnomonic");
	projection.addItem("Mercator");
	projection.addItem("Mollweide");
	projection.addItem("Orthographic");
	projection.addItem("Peter");
	projection.addItem("Sinusoid");
	projection.addItem("Square");
	projection.addItem("Stereo");
	projection.select("Mercator");
	selectedProjection = null;
	add(projection);
	add(latLabel = new Label("Lat:"));
	add(latField = new TextField("0.0"));
	add(longLabel = new Label("Long:"));
	add(longField = new TextField("0.0"));
	add(latGridLabel = new Label("LatGrid:"));
	add(latGridField = new TextField("0.0"));
	add(lonGridLabel = new Label("LonGrid:"));
	add(lonGridField = new TextField("0.0"));
	add(changeColorsWithLatitude = new Checkbox("Icy poles", null, false));
	add(magLabel = new Label("Mag:"));
	add(magField = new TextField("1.0"));
	add(seedLabel = new Label("Seed:"));
	add(seedField = new TextField("0.123"));
	add(redraw = new Button("Redraw"));
	mainPanel = new MogensenPlanetPanel(working);
	msng = new MogensenSolidNoiseGenerator();
	msng.setSeed(0.123);
	add(mainPanel);
	setGadgetColors();
    }

    public void paint(Graphics g)
    {
	if (selectedProjection == null)
	{
	    selectedProjection = projection.getSelectedItem();
	    setImageProjection();
	}
	super.paint(g);
    }

    public boolean action(Event evt, Object obj)
    {
	double dblval;
	if (evt.target instanceof Button)
	{
	    Button btn = (Button)(evt.target);
	    if (btn.getLabel().equals("Redraw"))
	    {
		extractTextFieldValues();
		mainPanel.recalculateProjection();
	    }
	    return true;
	}
	else if (evt.target instanceof TextField)
	{
	    if (evt.target == latField)
	    {
		String latText = latField.getText();
		try {
		    dblval = Double.valueOf(latText).doubleValue();
		    if (dblval <= 90.0 && dblval >= -90.0)
		    {
			dblval *= ImageProjection.DEG2RAD;
			if (latitude != dblval)
			    ip.setCenterOfProjection(longitude, latitude=dblval);
		    }
		} catch (NumberFormatException nfe) {
		    latField.setText(String.valueOf(latitude));
		}
	    }
	    else if (evt.target == longField)
	    {
		String longText = longField.getText();
		try {
		    dblval = Double.valueOf(longText).doubleValue();
		    if (dblval <= 360.0 && dblval >= -360.0)
		    {
			dblval *= ImageProjection.DEG2RAD;
			if (longitude != dblval)
			    ip.setCenterOfProjection(longitude=dblval, latitude);
		    }
		} catch (NumberFormatException nfe) {
		    longField.setText(String.valueOf(longitude));
		}
	    }
	    else if (evt.target == latGridField)
	    {
		String latGridText = latGridField.getText();
		try {
		    dblval = Double.valueOf(latGridText).doubleValue();
		    if (dblval <= 90.0 && dblval >= 0.0)
		    {
			if (latgrid != dblval)
			    ip.setGridSpacing(longrid, latgrid=dblval);
		    }
		} catch (NumberFormatException nfe) {
		    latGridField.setText(String.valueOf(latgrid));
		}
	    }
	    else if (evt.target == lonGridField)
	    {
		String lonGridText = lonGridField.getText();
		try {
		    dblval = Double.valueOf(lonGridText).doubleValue();
		    if (dblval <= 360.0 && dblval >= 0.0)
		    {
			if (longrid != dblval)
			    ip.setGridSpacing(longrid=dblval, latgrid);
		    }
		} catch (NumberFormatException nfe) {
		    lonGridField.setText(String.valueOf(longrid));
		}
	    }
	    else if (evt.target == magField)
	    {
		String magText = magField.getText();
		try {
		    dblval = Double.valueOf(magText).doubleValue();
		    if (dblval > 1.0)
		    {
			if (magnification != dblval)
			    ip.setMagnification(magnification=dblval);
		    }
		} catch (NumberFormatException nfe) {
		    magField.setText(String.valueOf(magnification));
		}
	    }
	    else if (evt.target == seedField)
	    {
		String seedText = seedField.getText();
		try {
		    dblval = Double.valueOf(seedText).doubleValue();
		    if (seed != dblval)
			msng.setSeed(seed=dblval);
		} catch (NumberFormatException nfe) {
		    seedField.setText(String.valueOf(seed));
		}
	    }
	    else
	    {
		System.out.println("data from unknown TextField");
	    }
	    return true;
	}
	else if (evt.target instanceof Checkbox)
	{
	    msng.latic = changeColorsWithLatitude.getState();
	    return true;
	}
	else if (evt.target instanceof Choice)
	{
	    selectedProjection = new String((String)(evt.arg));
	    extractTextFieldValues();
	    setImageProjection();
	    return true;
	}
	return false;
    }
}