/*
 *  BasicButton.java
 *  Cookbook
 *
 *  Copyright (c) 2001-2009 Flagstone Software Ltd. All rights reserved.
 *
 *  This code is distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 *  EXPRESS OR IMPLIED, AND Flagstone HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING
 *  WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 *  PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 */

import com.flagstone.transform.*;
import com.flagstone.transform.util.*;

import java.awt.Font;
import java.util.*;

/*
 * This example shows how to create a button using the FSDefineButton class which 
 * wil display a web page in a browser when clicked.
 *
 * To run this example, type the following on a command line:
 *
 *     java -cp cookbook.jar BasicButton string file-out
 *
 * where
 *
 *     string, the label that will be displayed on the button - enclose in quotes 
 *     if the label contains spaces.
 *
 *     file-out is the path where the file will be written. If no output file 
 *     is specified then a file named after the example will be written to the 
 *     current directory.

 */
public class BasicButton
{
	public static void main(String[] args)
	{
        try
        {
        	String label = args[0];
        	String out = args.length == 1 ? "BasicButton.swf" : args[1];
        	BasicButton example = new BasicButton();         
            FSMovie movie = new FSMovie();            
            example.createMovie(movie, label);
            movie.encodeToFile(out);
        }
        catch (Exception e)
        {
        	e.printStackTrace();
        }
	}
    
	void createMovie(FSMovie movie, String buttonLabel)
	{
		Font font = new Font("Arial", Font.PLAIN, 12);
		FSTextConstructor textGenerator = new FSTextConstructor(movie.newIdentifier(), font);
		FSShapeConstructor path = new FSShapeConstructor();

		int layer = 1;       // initial layer in the display list
		int fontSize = 280;  // 280 twips == 14 point, 1 point == 20 twips

		/*
		 * Define margins added to define the width of the button relative to 
		 * the size of the label and the screen width relative to the width of 
		 * the button.
		 */
		int buttonMargin = 200; // The margin between the label and the edge of the button.
		int screenMargin = 400; // The margin between the edge of the button and the screen.

		/*
		 * Define colours used to fill the buttons in each of its states.
		 */
		FSColor lineColor = FSColorTable.black();
		FSColor shadowColor = FSColorTable.gray();
		FSColor upColor = FSColorTable.red();
		FSColor overColor = FSColorTable.orange();

		/*
		 * Define coordinate transform applied to the basic button shape 
		 * to perform a simple animation giving the impression the button
		 * was physically clicked.
		 */
		FSCoordTransform recess = new FSCoordTransform(60, 60);

		FSDefineText2 label = textGenerator.defineText(movie.newIdentifier(), 
			buttonLabel, fontSize, lineColor);

		// define a 10 pixel margin around the text.
    
		int buttonWidth = label.getBounds().getWidth() + buttonMargin;
		int buttonHeight = -label.getBounds().getMinY() + buttonMargin;

		int lineWidth = 20;
		int cornerRadius = 100;

		/*
		 * The button will cast as shadow when it in the up state. Recessing the 
		 * button by changing the location of the shapes when the button is 
		 * clicked allows a very simple animation to be performed. More complex 
		 * animations can be created by using movie clips.
		 */
		int xShadow = 60;
		int yShadow = 60;
		
		path.add(new FSSolidLine(lineWidth, shadowColor));
		path.add(new FSSolidFill(shadowColor));
		path.rect(0, 0, buttonWidth, buttonHeight, cornerRadius);
		
		FSDefineShape2 shadow = path.defineShape(movie.newIdentifier());
			
		path.set(0, new FSSolidLine(lineWidth, lineColor));
		path.set(0, new FSSolidFill(upColor));
		path.rect(0, 0, buttonWidth, buttonHeight, cornerRadius);
		
		FSDefineShape2 upShape = path.defineShape(movie.newIdentifier());

		path.set(0, new FSSolidLine(lineWidth, lineColor));
		path.set(0, new FSSolidFill(overColor));
		path.rect(0, 0, buttonWidth, buttonHeight, cornerRadius);
		
		FSDefineShape2 overShape = path.defineShape(movie.newIdentifier());

		/*
		 * Used to hold the width and height of the bounding rectangle that
		 * encloses the button labels.
		 */
		int xOffset = -label.getBounds().getWidth()/2;
		int yOffset = (buttonHeight - label.getBounds().getHeight())/2;

		/*
		 * Add the button records that define the button's appearance
		 */
		ArrayList records = new ArrayList();
    
		records.add(new FSButton(FSButton.Active, upShape.getIdentifier(), layer++));

		records.add(new FSButton(FSButton.Up, shadow.getIdentifier(), layer++, recess));
		records.add(new FSButton(FSButton.Up, upShape.getIdentifier(), layer++));
		records.add(new FSButton(FSButton.Up, label.getIdentifier(), layer++, 
			new FSCoordTransform(xOffset, yOffset)));

		records.add(new FSButton(FSButton.Over, shadow.getIdentifier(), layer++, recess));
		records.add(new FSButton(FSButton.Over, overShape.getIdentifier(), layer++));
		records.add(new FSButton(FSButton.Over, label.getIdentifier(), layer++, 
			new FSCoordTransform(xOffset, yOffset)));

		records.add(new FSButton(FSButton.Down, overShape.getIdentifier(), layer++, recess));
		records.add(new FSButton(FSButton.Down, label.getIdentifier(), layer++, 
			new FSCoordTransform(xOffset + xShadow, yOffset + yShadow)));

		/*
		 * FSDefineButton executes a single set of actions when it is clicked. More 
		 * complex behaviour can be implemented using FSDefineButton2 which allows 
		 * diffent sets of actions to executed in response to a wide range of events.
		 */
		ArrayList actions = new ArrayList();
		actions.add(new FSGetUrl("http://www.flagstonesoftware.com", ""));
    
		FSDefineButton button = new FSDefineButton(movie.newIdentifier(), records, actions);

		/***************************************************
		 *     Put all the objects together in a movie
		 ***************************************************/

		int screenWidth = buttonWidth + 2*screenMargin;
		int screenHeight = buttonHeight + 2*screenMargin;
        
		movie.setFrameSize(new FSBounds(0, 0, screenWidth, screenHeight));
		movie.setFrameRate(1.0f);
		movie.add(new FSSetBackgroundColor(FSColorTable.lightblue()));

		// Add the font definition for the text labels
		movie.add(textGenerator.defineFont());

		// Add the shapes used to define the button
		movie.add(shadow);
		movie.add(upShape);
		movie.add(overShape);

		// Add the button 
		movie.add(label);
		movie.add(button);

		movie.add(new FSPlaceObject2(button.getIdentifier(), layer++, 
			screenWidth/2 , screenHeight/2));

		movie.add(new FSShowFrame());
	}
}