/* $Id$
 *
 * Copyright (c) 1999 Xenonsoft Limited. All Rights Reserved.
 *
 * This software is protected by copyright. You are hereby notified from
 * now by reading this message. This software is also the confidential 
 * and proprietary information of Xenonsoft Limited.  ("Confidential
 * Information"). 
 *
 * This software is distributed under the Xenonsoft Public end user 
 * License ("XPeL"), where the machine-readable source code is provided 
 * under the "Open Source" model.
 * For more information, please read the file "LICENSE-XPL.txt" 
 */

// File:`GraphicsUtils.java'
//
//
// DESCRIPTION
//	Graphics Utilities
// 
// Author
//
//	Peter Pilgrim
//	Tue May 18 23:09:23 BST 1999
// 
// RCS HEADER ``Lander.java''
// 
//	$Author$
//	$Date$
//	$Source$
//	$Revision$    $State$    $Locker$
//

package xenon.gamekit;

import java.util.Vector;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.awt.*;
import java.awt.image.*;

public class GraphicsUtils {

    public static void loadImageCompletely( 
	Component component, Image image )
    {
	loadImageListCompletely( component, new Image[] { image } );
    }
    
    public static void loadImageListCompletely( 
	Component component, Image images[] )
    {
	MediaTracker tracker = new MediaTracker( component );
	for ( int j=0; j<images.length; ++j ) 
	    if ( images[j] != null )
		tracker.addImage( images[j], 0 );

	try {
	    tracker.waitForAll();
	}
	catch (InterruptedException ie) {
	    ie.printStackTrace();
	}

	for ( int j=0; j<images.length; ++j ) 
	    if ( images[j] != null )
		tracker.removeImage( images[j], 0 );
    }

    /**
     * A convenience method load an GIF/JPEG image using the method 
     * <code>java.lang.Class.getResourceAsInputStream(String)</code>.
     *
     * <p>
     * <code>java.lang.Class.getResource(String)</code>
     * does <b>not</b> work in Netscape Browsers due to Security Issues
     * see Java Programmer's FAQ for more details http://www.afu.com/
     *
     * @param refObject the reference object to load image 
     * @param imageFileName the image filename
     * 
     * 
     * @return image loaded or null if there was an error.
     */
    public static Image XXXX_getImageAsClassResource(
	Object refObject,  String imageFileName )
    {
	Image img=null;
	
	// System.out.println( "getImageAsClassResource() loading image:`"+imageFileName+"'");
	// System.out.println( "   refobject:"+refObject.getClass().getName() );
	try {
	    URL url = refObject.getClass().getResource( imageFileName );    
	    // System.out.println( "    url="+url );
	    if ( url != null ) {
		img = Toolkit.getDefaultToolkit().getImage(url);
	    }
	    else {
		InputStream is =
		    refObject.getClass().getResourceAsStream( imageFileName ); 
		// System.out.println( "    is="+is );
		if ( is != null ) {
		    byte[] buffer = new byte[is.available()]; 
		    is.read(buffer); 
		    img = Toolkit.getDefaultToolkit().createImage(buffer);            
		}
		else {
		    System.err.println( "Image:"+imageFileName+
					" not found via getResource or getResourceAsStream."); 
		    System.exit(1);
		}
	    }
	} 
	catch (java.io.IOException e) { 
	    System.err.println("Unable to read image:"+imageFileName ); 
	    e.printStackTrace(); 
	}

	return (img);
    }
    
    /**
     * A convenience method load an GIF/JPEG image using the method 
     * <code>java.lang.Class.getResourceAsInputStream(String)</code>.
     *
     * <p>
     * It may be worth surfing to
     * <a href="http://developer.netscape.com/docs/technote/java/getresource/getresource.html">
     * http://developer.netscape.com/docs/technote/java/getresource/getresource.html </a>
     *
     * <p>
     * <code>java.lang.Class.getResource(String)</code>
     * does <b>not</b> work in Netscape Browsers due to Security Issues
     * see Java Programmer's FAQ for more details http://www.afu.com/
     *
     * @param refObject the reference object to load image 
     * @param imageFileName the image filename
     * 
     * 
     * @return image loaded or null if there was an error.
     */
    public static Image getImageAsClassResource(
	Object refObject,  String imageFileName )
    {	
	InputStream is = refObject.getClass().getResourceAsStream(imageFileName);
	Toolkit tk = Toolkit.getDefaultToolkit();

	// System.out.println( "getImageAsClassResource() loading image:`"+imageFileName);
	// System.out.println( "  is:"+is+"  refobject:"+refObject.getClass().getName() );

	if ( is == null ) {
	    System.err.println("no such image filename:`"+imageFileName+
			       "' on class:"+refObject.getClass().getName() );
	    return (null);
	}
	
	Image img = null;
	ByteArrayOutputStream out = new ByteArrayOutputStream();

	try {
	    byte [] buffer = new byte[8192];
	    byte[] imageBytes = null;

	    int total_bytes=0;
	    int num_bytes;
	    while ( (num_bytes = is.read( buffer )) > 0 ) {
		out.write( buffer, 0, num_bytes );
		total_bytes += num_bytes;
	    }
	    imageBytes = out.toByteArray();
	    img = tk.createImage(imageBytes);
	    // System.out.println( "    size:"+total_bytes+" DEBUG:");
	}
	catch (IOException ioe) {
	    System.err.println( 
		"Whilst reading image name:`"+imageFileName+
		"' on class:"+refObject.getClass().getName()+
		"  I/O Exception:"+ioe.getMessage() );
	    img = null;
	}
	finally {
	    if (is == null ) {
		// try { is.close(); } catch (IOException e1) { }
	    }
	}

	return (img);
    }
    
    public static void drawWallpaper( 
	Component component, Graphics g, Image image )
    {
	Dimension compsize = component.getSize();
	GraphicsUtils.loadImageCompletely( component, image);
	
	int width  = image.getWidth( component );
	int height = image.getHeight( component );
	
	for (int y=0; y<compsize.height; y+=width ) 
	    for (int x=0; x<compsize.width; x+=width ) 
		g.drawImage( image, x, y, component );
    }
    
    public static void drawCenteredString( Graphics g, String s, int ypos )
    {
	Rectangle clip = g.getClipBounds();
	FontMetrics fm = g.getFontMetrics();
	int lineWidth = fm.stringWidth(s);
	int xpos = ( clip.width - lineWidth ) / 2;
	g.drawString( s, xpos, ypos );
	// DEBUG: System.out.println( "    "+xpos+","+ypos+"  `"+s+"'" );
    }
    
    public static int drawCenteredStringList( Graphics g, String s[] )
    {
	Rectangle clip = g.getClipBounds();
	FontMetrics fm = g.getFontMetrics();
	int lineHeight = fm.getAscent() + fm.getDescent() + 3;
	int ypos_start = ( clip.height - (s.length * lineHeight) ) / 2;

	return drawCenteredStringList( g, s, ypos_start );
    }
    
    public static int drawCenteredStringList( Graphics g, String s[], int ypos_start )
    {
	FontMetrics fm = g.getFontMetrics();
	int lineHeight = fm.getAscent() + fm.getDescent() + 3;
	int ypos = ypos_start;
	
	for (int j=0; j<s.length; ++j) {
	    if ( s[j] != null )
		GraphicsUtils.drawCenteredString( g, s[j], ypos );
	    ypos += lineHeight;
	}
	
	return (ypos);
    }

    /**
     * @param comp the component
     * @param g the graphics context
     * @param img the image
     * @param s the string
     * @param x the x coordinate
     * @param y the x coordinate
     * @param xmargin the x coordinate margin
     */
    public static int drawImageAndString( 
	ImageObserver observer, Graphics g, Image img, String s, 
	int xpos, int ypos, int xmargin )
    {
	Rectangle clip = g.getClipBounds();
	FontMetrics fm = g.getFontMetrics();
	int lineHeight = fm.getAscent() + fm.getDescent();
	// int width = img.getWidth( observer ) + 5;
	lineHeight = Math.max( lineHeight, img.getHeight( observer ) + 3 );
	g.drawImage( img, xpos, ypos - fm.getAscent(), observer );
	g.drawString( s, xpos+xmargin, ypos );
	// DEBUG: System.out.println( "    "+xpos+","+ypos+"  `"+s+"'" );

	return (ypos+lineHeight+3);
    }

    /** get the ancestor <b>Frame<b> of the <p>Component</p> 
     * otherwise return null if no such ancestor can be found.
     */
    public static Frame getFrameOfComponent( Component comp )
    {
	Frame frame = null;
	
	while ( comp != null && !( comp instanceof Frame ) )
	    comp = (Component)comp.getParent();
	if ( comp != null && comp instanceof Frame )
	    frame = (Frame)comp;
	else
	    frame = null;

	return (frame);
    }
    
    /** get the ancestor <b>Dialog<b> of the <p>Component</p> 
     * otherwise return null if no such ancestor can be found.
     */
    public static Dialog getDialogOfComponent( Component comp )
    {
	Dialog dialog = null;
	
	while ( comp != null && !( comp instanceof Dialog ) )
	    comp = (Component)comp.getParent();
	if ( comp != null && comp instanceof Dialog )
	    dialog = (Dialog)comp;
	else
	    dialog = null;

	return (dialog);
    }

    /** get the ancestor <b>Window<b> of a Component
     * otherwise return null if no such ancestor can be found.
     */
    public static Window getWindowOfComponent( Component comp )
    {
	Window window = null;
	
	while ( comp != null && !( comp instanceof Window ) )
	    comp = (Component)comp.getParent();
	if ( comp != null && comp instanceof Window )
	    window = (Window)comp;
	else
	    window = null;

	return (window);
    }
}

// fini
