/*

	Block area class (Java 1.1.6)
	(c)1999 Andrew Partington / Kung-Fu Coders 
 
	Info:  This class represents a higher level control system for 
			the canvas inside the tile window, allowing blocks to be
			selected

*/


import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;

public class BlockSelector extends Frame implements ActionListener, ItemListener
{


/*
	Some useful constants
 */ 
 
	public static final int TILE8x8 =  3;				//position/8   (pos >> 3)
	public static final int TILE16x16 = 4;				//position/16  (pos >> 4)
	public static final int TILE32x32 = 5;				//position/32  (pos >> 5)

 
	Panel mainPanel,infoPanel;
	BlockCanvas blockCanvas;
	TextField coords,blockInfo;

	Toolkit toolkit;									//Java AWT toolkit
	Image blockImage;									//Image containing the map blocks
	int imageData[];									//Array containing actual pixel data

	int blockSizeX,blockSizeY;							//Tile size (e.g. 8*8, 16*16 etc...)
	int currentBlockSize;
	int currentBlockID;
	
	int mouseX,mouseY;
	int blockStartX,blockStartY;
	
	int[][] blockID;									//The sequential block ID for each block
														//  (GsBG format)
	Dialog d1;

	Label l1=new Label("Loading image, please wait...");

	int blocksX,blocksY;
/*================================================================*
 *	Class constructor method
 *----------------------------------------------------------------*
	Info:	The BlockArea class holds information and provides 
			access to the source pixel data representing the map
			blocks.  It also provides a user interface for selecting
			the blocks.
 
 *================================================================*/ 
	 
	public BlockSelector()
	{
		super("Tile window");
		toolkit=getToolkit();									//Get the current windows toolkit		
		addWindowListener(new BlockSelector.WindowEventHandler());		
		
		mainPanel=new Panel();
		mainPanel.setLayout(new BorderLayout()); 
	
		d1=new Dialog(this,"Information");
		d1.add(l1);
		d1.pack();
		
		/*
			Set up information panel  (for coords and current block)
		*/
		
		infoPanel=new Panel();
		infoPanel.setLayout(new GridLayout(1,2));
		
		coords=new TextField(5);		//careful!  has effect on window sizing
		coords.setEditable(false);
			
		blockInfo=new TextField(5);
		blockInfo.setEditable(false);
		
		infoPanel.add(coords);
		infoPanel.add(blockInfo);

		blockCanvas=new BlockCanvas();
		blockCanvas.addMouseListener(new MouseHandler());
		blockCanvas.addMouseMotionListener(new MouseMotionHandler());
	
	 	this.add(blockCanvas,"Center");
		this.add(infoPanel,"South");
			 
		blockSizeX=blockSizeY=16;
		currentBlockSize=TILE16x16;
	//	blockCanvas.setBlockSize(TILE16x16);
		imageData=new int[(1<<currentBlockSize)*(1<<currentBlockSize)];
	
		blockImage=null;			
	
		openBlockGFX("default.gif");

		
		setBlockID();						// Assign each block a sequential ID number
	
	}
	
	
	
	/*===========================================*
		Set the size of the tile selector to allow 
		various sized tiles.
	
	 *===========================================*/
	
	public void setBlockSize(int size)
	{
	
		switch(size)
		{
			case(TILE8x8):
				blockSizeX=blockSizeY=8;
				currentBlockSize=TILE8x8;
				blockCanvas.setBlockSize(TILE8x8);
				imageData=new int[(1<<currentBlockSize)*(1<<currentBlockSize)];
				break;
			
			
			case(TILE16x16):
				blockSizeX=blockSizeY=16;
				currentBlockSize=TILE16x16;
				blockCanvas.setBlockSize(TILE16x16);
				imageData=new int[(1<<currentBlockSize)*(1<<currentBlockSize)];
				break;
			
			case(TILE32x32):
				blockSizeX=blockSizeY=32;
				currentBlockSize=TILE32x32;
				blockCanvas.setBlockSize(TILE32x32);
				imageData=new int[(1<<currentBlockSize)*(1<<currentBlockSize)];
				break;
				
			default:
				break;
					
		}
	
		setBlockID();
	}
	
/*===============================================*
 *
 *		Open the tile graphics
 *		
 *===============================================*/
	
	public synchronized void openBlockGFX(String path)
	{
		blockImage=toolkit.getImage((String)path);
		blockCanvas.loadImage(blockImage);
		
		while(prepareImage(blockImage,this)==false)
		{
			d1.show();
		}
		
		d1.dispose();
		
		setBlockID();

	//	blocksX=blockImage.getWidth(this)>>currentBlockSize;
	//	blocksY=blockImage.getHeight(this)>>currentBlockSize;

		this.setSize(blockImage.getWidth(this),blockImage.getHeight(this));
		blockCanvas.setSize(blockImage.getWidth(this),blockImage.getHeight(this));

		this.pack();
		this.show();		
		this.repaint();
	}
	


	public int getBlockID()
	{
		return(currentBlockID);
	}



/*===================================================================*
 *																	 *
 *	Routine:  Assign sequential number to blocks in the tile window. *
 *				Crap way of doing it, could do (y*tile data width)+x *
 *				but sod it, it works!								 *
 *																	 *
 *===================================================================*/

	private void setBlockID()
	{
		int imgX,imgY;						//width and height of the block image
		int b_id=0;
							
		imgX=blockImage.getWidth(this)>>currentBlockSize;
		imgY=blockImage.getHeight(this)>>currentBlockSize;

		blocksX=imgX;
		blocksY=imgY;
							
		blockID=new int[imgX][imgY];
							
		for(int j=0;j<imgY;j++)
		{
			for (int i=0;i<imgX;i++)
			{
				blockID[i][j]=b_id;			//assign sequential ID number to things.
				b_id++;
			}
		}
	}


/*===========================================================*
 *  Locate a block with a given block ID, and get an image	 *
 *-----------------------------------------------------------*
 *															 *
 *	In:  id	- The ID number of the block to look for		 *
 *															 *
 *	returns:  null if not found/blank block, or else		 *
 *			  an Image containing the graphics we want		 *
 *															 *
 *===========================================================*/


	public Image locateBlock(int id)
	{
		int x,y;
		Image img;
				
		if(id==0xffff)
		{
			img=null;							//If its a blank block, then sod it and 
			return(img);						//  return before doing a lookup
		}
		
		for(y=0;y<blocksY;y++)
		{
			for(x=0;x<blocksX;x++)
			{
				if(blockID[x][y]==id)			//If found, set the current block ID, and create
				{								//  an Image of the block to be returned
					currentBlockID=id;
					
					imageData=(int[])blockCanvas.getTile(x<<currentBlockSize,y<<currentBlockSize);
					img=createImage(new MemoryImageSource((1<<currentBlockSize),(1<<currentBlockSize),
						ColorModel.getRGBdefault(),imageData,0,(1<<currentBlockSize)));		
		
					while(prepareImage(img,this)==false)  { /* spin lock until image is ready */ }		
					return(img);
				}
			}
		}
		
	//	System.out.println("could not locate block "+id);
		img=null;
		return(img);
	}


/*==============================================================*
 * Item and action event handlers								* 
 *==============================================================*/
	
	
	public void update(Graphics g)
	{	
			blockCanvas.getGraphics().drawImage(blockImage,0,0,this);
			blockCanvas.getGraphics().setColor(Color.red);
		    blockCanvas.getGraphics().drawRect((1<<currentBlockSize)*blockStartX,(1<<currentBlockSize)*blockStartY,(1<<currentBlockSize),(1<<currentBlockSize));				
	}
	
	public void actionPerformed(ActionEvent e)
	{
		// if ((e.getSource()==fileExit))		
	}

		
	public void itemStateChanged(ItemEvent e)
	{
		
	}
/*
	Window event handler
*/

	class WindowEventHandler extends WindowAdapter 
	{
		public void windowClosing(WindowEvent e)
		{
		//	dispose();
		//	System.exit(0);
		}
		
		public void windowActivated(WindowEvent e)
		{
			repaint();
		}
		
		public void windowOpened(WindowEvent e)
		{
			repaint();
		}
		
		public void windowDeiconified(WindowEvent e)
		{
		//	repaint();
		}
		
	}


/*=============================================*
 * mouse buton handler
 *=============================================*/

	 
	class MouseHandler extends MouseAdapter
	{
	
		public void mouseEntered(MouseEvent e)
		{
			setCursor(new Cursor(CROSSHAIR_CURSOR));
		}
	
		public void mouseExited(MouseEvent e)
		{
			setCursor(new Cursor(DEFAULT_CURSOR));
		}


//		public void mousePressed(MouseEvent e)
//		{
//			
//		}

		
	/**
	 *		When mouse is released, the ID number of the 
	 *		appropriate block is set.  When blocks are
	 *		being drawn, the calling routine must get the
	 *		current block ID first.
	 *		
	 **/
		
		public void mouseReleased(MouseEvent e)
		{
			try
			{
		
				blockStartX=e.getX()>>currentBlockSize;				//get X and Y positions to the
				blockStartY=e.getY()>>currentBlockSize;				//  nearest block position
		
				currentBlockID=blockID[(e.getX()>>currentBlockSize)][(e.getY()>>currentBlockSize)];
		
				blockInfo.setText(blockStartX+" "+blockStartY+" (ID: "+currentBlockID+")");
				repaint();									
			}								
			
		/**
		 *	catch out of bounds array accesses when clicking on
		 *	areas which do not have graphics in them - stops Java
		 *	throwing an ugly exception message
		 **/
			
			catch(ArrayIndexOutOfBoundsException ex)
			{
				//	System.out.println("Nothing to click out here");
			}
		}
	}

	
/*============================================*
	Mouse movement handler
 *============================================*/

	 class MouseMotionHandler extends MouseMotionAdapter
	 {
	 	
	 
	 	public void mouseMoved(MouseEvent e)
		{
			mouseX=e.getX();
			mouseY=e.getY();
			coords.setText("X: "+mouseX+"   Y: "+mouseY);		
		}
		
		
		public void mouseDragged(MouseEvent e)
		{
			mouseX=e.getX();
			mouseY=e.getY();	
			coords.setText("X: "+mouseX+"   Y: "+mouseY);		
		}
	
	}
	

}






