//
// $Source: /nfs/elm/d3/home/cur/djb1/java/javat/RCS/ImageButtonCh.java,v $
//
// $Id: ImageButtonCh.java,v 1.2 1997/06/23 17:30:17 djb1 Exp $
//
// Button with Object_Channel interface class
//
// (C) Copyright 1997 Dave Beckett <D.J.Beckett@ukc.ac.uk>
// University of Kent at Canterbury
//

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

import Object_Channel;

import AWTProtocol;


public class ImageButtonCh extends Panel implements Runnable, ImageArrival
{
  private Object_Channel toButtonCh, fromButtonCh, event_Object_Channel;
  private boolean clicked=false;
  private Thread my_thread;
  private ImageButtonEventHandler image_button_event_handler;
  private ImageObserver comp;
  private Label l;
  
  // Handle incremental loading of images via MediaTracker
  private Image[] images;
  private boolean allImagesLoaded=false;
  private int imagesLoadedCount=0;
  private int nFrames;
  private int currentFrame=0;
  private int displayedFrame=0;
  
  private int width=0;
  private int height=0;
  
  // Constructor
  public ImageButtonCh(Object_Channel toButtonCh, Object_Channel fromButtonCh, Object_Channel event_Object_Channel, Image[] images, Component comp, int width, int height)
  {
    this.toButtonCh=toButtonCh;
    this.fromButtonCh=fromButtonCh;
    this.event_Object_Channel=event_Object_Channel;
    this.images=images;
    this.width=width;
    this.height=height;
    this.comp=comp;
    
    nFrames=images.length;
    imagesLoadedCount=0;
    
    new ImageTracker(images, comp, this);
    
    l=new Label("", Label.CENTER);
    add(l);
		     
    image_button_event_handler = new ImageButtonEventHandler(event_Object_Channel, this);
    
    setBackground(Color.white);

    my_thread=new Thread(this, "ImageButtonCh");
    
    // Start my thread (configuration handler)
    my_thread.start();
  }
  
  
  // Painting
  public void paint (Graphics g) 
  {
    if (allImagesLoaded) {
      // Get size of this component
      int width=size().width;
      int height=size().width;
      
      displayedFrame=currentFrame;
      Image image=images[displayedFrame];
      
      // Find size of this image
      int image_width=image.getWidth(comp);
      int image_height=image.getHeight(comp);
      
      // Calculate offset to center it in this Panel
      int x_offset=(width-image_width)/2;
      int y_offset=(height-image_height)/2;
      
      // Draw it
      g.drawImage(image, x_offset, y_offset, this);
    }
  }
  
  
  public void update (Graphics g) 
  {
    if (!allImagesLoaded) {
     // Get size of this component
      int width=size().width;
      int height=size().width;
      g.clearRect(0, 0, width, height);
    } else {
      paint(g);
    }
  }
  
  
  
  // AWT Event handling
  public boolean handleEvent(Event e)
  {
    if (e.id == Event.MOUSE_DOWN) {
      //System.err.println("ImageButtonCh.action: Got click");
      setClicked();
      return false;
    } else {
      return super.handleEvent(e);
    }
  }
  
  
  
  public synchronized boolean testAndResetClicked() 
  {
    boolean result=clicked;
    clicked=false;
    return result;
  }
  
  public synchronized void resetClicked() 
  {
    clicked=false;
  }

  public synchronized void setClicked() 
  {
    clicked=true;
  }
  
  public void run() 
  {
    //System.err.println("ImageButtonCh.run: Thread active ");
    for(;;) {
      try 
	{
	  AWTProtocol message=(AWTProtocol) toButtonCh.read(); // BLOCKs
	  //System.err.print("ImageButtonCh.run: Got message ");
	  switch (message.get_type()) {
	    case AWTProtocol.PREV_FRAME:
	      //System.err.println("PREV_FRAME");
	      currentFrame=(currentFrame-1+nFrames) % nFrames;
	      repaint();
	      break;
	    case AWTProtocol.NEXT_FRAME:
	      //System.err.println("NEXT_FRAME");
	      currentFrame=(currentFrame-1+nFrames) % nFrames;
	      repaint();
	      break;
	    case AWTProtocol.SET_FRAME:
	      //System.err.println("SET_FRAME");
	      int i=((Integer)message.get_arg()).intValue();
	      currentFrame=i % nFrames;
	      repaint();
	      break;
	    case AWTProtocol.GET_FRAME:
	      System.err.println("ImageButtonCh.run: Received unsupported message GET_FRAME");
	      break;
	    default:
	      System.err.println("ImageButtonCh.run: Received unknown / unsupported message "+message.get_type());
	  }
	  my_thread.sleep(100);
	}
      catch (InterruptedException e)
	{
	  //System.err.println ("ImageButtonCh.run: Thread ending");
	  break;
	}
    } // for (;;)
  }
  
  
  // fromImageArrival interface
  public void imageLoaded(int id) 
  {
    imagesLoadedCount++;
    l.setText("Loaded " + imagesLoadedCount + "/" +nFrames);
    l.invalidate();
    validate();
  }
  
  public void allImagesLoaded() 
  {
    allImagesLoaded=true;

    // Remove label from this container
    remove(l);
    l=null;
    
    // Draw 1st image
    repaint();
  }
  
  public Dimension minimumSize() 
  {
    return new Dimension(width, height);
  }
  
} // class ImageButtonCh




class ImageButtonEventHandler implements Runnable 
{
  private Thread my_thread;
  private Object_Channel event_Object_Channel;
  private ImageButtonCh imagebuttonch;
  private AWTProtocol message=null;
  
  public ImageButtonEventHandler (Object_Channel event_Object_Channel, ImageButtonCh imagebuttonch) 
  {
    my_thread=new Thread(this, "ImageButtonEventHandler");
    this.event_Object_Channel=event_Object_Channel;
    this.imagebuttonch=imagebuttonch;
    
    // Start my thread (configuration handler)
    my_thread.start();
  }
  
  public void run () 
  {
    //System.err.println("ImageButtonEventHandler.run: Thread active ");
    for(;;) {
      try 
	{
	  if (message==null) {
	    if (imagebuttonch.testAndResetClicked()) {
	      message=new AWTProtocol(AWTProtocol.MOUSE_DOWN, null);
	    }
	  }
	  		  
	  if (message != null) {
	    //System.err.println("ImageButtonEventHandler.run - Sending message");
	    event_Object_Channel.write(message);
	    message=null;
	  }
	  my_thread.sleep(100);
	}
      catch (InterruptedException e)
	{
	  //System.err.println ("ImageButtonEventHandler.run: Thread ending");
	  break;
	}
    } // for (;;)
  }


}
