Module10- QTZoo/Source/AnimalPane.java

import java.awt.Dimension;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Hashtable;
 
import quicktime.app.QTFactory;
import quicktime.app.anim.Compositor;
import quicktime.app.anim.TwoDSprite;
import quicktime.app.anim.SWController;
import quicktime.app.event.QTActionEvent;  
import quicktime.app.event.QTActionListener;
import quicktime.app.event.QTMouseTargetController; 
import quicktime.app.image.GraphicsImporterDrawer; 
import quicktime.app.image.ImagePresenter; 
import quicktime.app.image.ImageDataSequence;
import quicktime.app.image.ImageUtil;
import quicktime.app.ui.ReleaseButton;
import quicktime.app.ui.ButtonActivator;
import quicktime.app.players.MoviePresenter;
import quicktime.app.players.QTPlayer;
 
import quicktime.app.actions.GenericResponder;
import quicktime.app.actions.MouseResponder;
 
import quicktime.io.QTFile;
import quicktime.io.OpenMovieFile;
 
import quicktime.qd.QDRect;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDColor; 
import quicktime.qd.QDConstants; 
 
import quicktime.std.StdQTConstants;
import quicktime.std.movies.Movie; 
import quicktime.std.image.Matrix;
import quicktime.std.image.GraphicsMode;
 
import quicktime.QTSession;
import quicktime.QTException; 
 
/**
 * QTZoo Module 8 - Using QuickTime Transitions
 *
 * @author Levi Brown
 * @author Michael Hopkins
 * @author Apple Computer, Inc.
 * @version 8.0 4/10/2000
 * Copyright:   © Copyright 1999 Apple Computer, Inc. All rights reserved.
 *  
 * Disclaimer:  IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
 *              ("Apple") in consideration of your agreement to the following terms, and your
 *              use, installation, modification or redistribution of this Apple software
 *              constitutes acceptance of these terms.  If you do not agree with these terms,
 *              please do not use, install, modify or redistribute this Apple software.
 *
 *              In consideration of your agreement to abide by the following terms, and subject
 *              to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
 *              copyrights in this original Apple software (the "Apple Software"), to use,
 *              reproduce, modify and redistribute the Apple Software, with or without
 *              modifications, in source and/or binary forms; provided that if you redistribute
 *              the Apple Software in its entirety and without modifications, you must retain
 *              this notice and the following text and disclaimers in all such redistributions of
 *              the Apple Software.  Neither the name, trademarks, service marks or logos of
 *              Apple Computer, Inc. may be used to endorse or promote products derived from the
 *              Apple Software without specific prior written permission from Apple.  Except as
 *              expressly stated in this notice, no other rights or licenses, express or implied,
 *              are granted by Apple herein, including but not limited to any patent rights that
 *              may be infringed by your derivative works or by other works in which the Apple
 *              Software may be incorporated.
 *
 *              The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
 *              WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 *              WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *              PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 *              COMBINATION WITH YOUR PRODUCTS.
 *
 *              IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 *              CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *              GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *              ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
 *              OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
 *              (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
 *              ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */
public class AnimalPane extends ZooPane
{
    /**
     *  Public default constructor
     *  Creates the map button, and sets up the listeners
     */
    public AnimalPane()
    {
        QDRect size = new QDRect(MainFrame.WIDTH, MainFrame.HEIGHT);
        try
        {
            loadSound("data/zebra/Zebra.au");
 
            QDGraphics gw = new QDGraphics (size);
            compositor = new Compositor (gw, QDColor.white, 30, 1);
            
            displayImage( "data/zebra/ZebraBackground.jpg", 6, 5, 110 );        
                        
            addText( "data/zebra/Zebra.txt", 5, 15, 65, 415, 220 );
            
            addMovie( "data/zebra/Zebra.mov", 2, 425, 65 );
            
            ctr = new QTMouseTargetController( false );
            ctr.addQTMouseListener( new PaneMouseListener( QDColor.lightGray, QDColor.white, QDColor.darkGray));
            compositor.addController( ctr );            
                
            TwoDSprite currentSprite;
            areas = new Hashtable(1);
            currentSprite = CreateRollover( "data/MapButton.jpg", 5, 12, 406 );
            areas.put(currentSprite, "map");    
            
            compositor.getTimer().setRate(0);   
        }
        catch ( QTException qte )
        {
            qte.printStackTrace();
        }
    }   
    
    /**
     * Listener object for the Movie controller buttons
     * Called when the button is released
     */
    public class ButtonListener implements QTActionListener 
    {
        /**
         * Called when the button is released
         * @param ???
         */
        public void actionPerformed( QTActionEvent event ) 
        {
            System.out.println( "AnimalPane.actionPerformed() " );
            try
            {
                Object source = event.getSource();
                
                if (source.equals(playButton))          // Play >
                {
                    if ( md.getRate() == 0 )
                    {
                        md.setRate( 1 );
                    }
                    stopButton.setCurrentImage( stopRel );
                    stopButton.setReleasedImage( stopRel );
                    playButton.setCurrentImage( playPlaying );
                    playButton.setReleasedImage( playPlaying );
                }               
                else if (source.equals(stopButton))     // Stop []
                {
                    if ( md.getRate() == 1 )
                    {
                        md.setRate( 0 );
                    }
                    stopButton.setCurrentImage( stopDeactive );
                    stopButton.setReleasedImage( stopDeactive );
                    playButton.setCurrentImage( playRel );
                    playButton.setReleasedImage( playRel );
                }
                else if (source.equals(rewindButton))   // Rewind <<
                {
                    md.setTime(0);
                }
            }
            catch (QTException exc )
            {
                exc.printStackTrace();
            }
        }
    }
    
    /**
     * Loads a graphics file from a relative path and creates an ImagePresenter object
     * @param ???
     */
    public ImagePresenter MakePresenterFromFile( String name )
    {
        try
        {
            QTFile file = new QTFile (QTFactory.findAbsolutePath (name));
            GraphicsImporterDrawer drawer = new GraphicsImporterDrawer(file);
            return ImagePresenter.fromGraphicsImporterDrawer(drawer);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (QTException e)
        {
            e.printStackTrace();
        }
        return null;    
    }
    
    /**
     * Called to do any setup after being set as the client of the QTCanvas.
     * May be used to start effects running, movies playing, etc.
     */
    public void start()
    {
        buttonController.addQTMouseListener(buttonActivator);
        try
        {
            stopButton.setCurrentImage(  stopRel );     // Stop button should not have focus
            playButton.setCurrentImage(  playPlaying );  // Play button should get focus (blue arrow)
            playButton.setReleasedImage( playPlaying );
        }
        catch( QTException e )
        {
            e.printStackTrace();
        }
        try
        {
            md.setRate(1);                              // start the player
        }
        catch( QTException e )
        {
            e.printStackTrace();
        }
        compositor.getTimer().setRate(1);               // start the compositor
    }
    
    /**
     * Called to do clean up after being removed as the client of the QTCanvas.
     * Should be used to stop effects running, movies playing, etc.
     */
    public void stop()
    {
        System.out.println( "Stop" );
        buttonController.removeQTMouseListener(buttonActivator);
        compositor.getTimer().setRate(0);
        try
        {
            md.setRate(0);
        }
        catch( QTException e )
        {
            e.printStackTrace();
        }
    }
    
    /**
     *  Plays the sound file associated with the current AnimalPane
     */
    public void playSound()
    {
        if (player == null)
            return;
 
        try
        {
            player.setTime(0);          //Start the sound at the beginning
            player.startTasking();      //Make sure the player gets time to play the sound
            player.setRate(1);          //Start playing
        }
        catch (QTException exc)
        {
            exc.printStackTrace();
        }
    }
    
    /**
     * Creates a Movie from the specified path and adds it
     * to the compositor in the hardcoded location.
     * @param moviePath the relative path to the movie file to add.
     * @param layer, the layer of the compositor to add the movie to.
     * @param x the x coordinate location.
     * @param y the y coordinate location.
     * @see #makeMovie
     */
    protected void addMovie(String moviePath, int layer, int x, int y)
    {
        try
        {
            Movie m = makeMovie (new QTFile (QTFactory.findAbsolutePath (moviePath)));
            md = new MoviePresenter (m);
            md.setLocation (x, y);
            // Add the Movie Controls
            
            playRel     = MakePresenterFromFile( "data/Play.jpg" );         // Play >
            playPress   = MakePresenterFromFile( "data/PlayPressed.jpg" );
            playPlaying = MakePresenterFromFile( "data/Playing.jpg" );
            playButton = new MovieButton( playRel, playPress, playPlaying );
            playButton.setLabel ("Play");
            playButton.setLocation( x + 68, y + 152 );
            
            stopRel      = MakePresenterFromFile( "data/Stop.jpg" );        // Stop []
            stopPress    = MakePresenterFromFile( "data/StopPressed.jpg" );
            stopDeactive = MakePresenterFromFile( "data/Stopped.jpg" );
            stopButton  = new MovieButton( stopRel, stopPress, stopDeactive );
            stopButton.setLabel ("Stop");
            stopButton.setLocation( x + 136, y + 152 );
            
            rewRel      = MakePresenterFromFile( "data/Rewind.jpg" );       // Rewind <<
            rewPress    = MakePresenterFromFile( "data/RewindPressed.jpg" );
            rewDeactive = MakePresenterFromFile( "data/Rewind.jpg" );
            rewindButton = new MovieButton( rewRel, rewPress, rewDeactive );
            rewindButton.setLabel( "Rewind" );
            rewindButton.setLocation( x, y + 152 );
            
            ButtonListener bl = new ButtonListener();                       // create a new listener for the buttons
            
            playButton.addActionListener(bl);
            stopButton.addActionListener(bl);
            rewindButton.addActionListener(bl);
            
            compositor.addMember (md, layer);                               // add the movie presenter
            compositor.addMember (playButton);                              //   and buttons to the compositor
            compositor.addMember (stopButton);
            compositor.addMember (rewindButton);
            
            buttonController = new QTMouseTargetController (false); 
            buttonController.addMember(playButton);
            buttonController.addMember(stopButton);
            buttonController.addMember(rewindButton);
        
            compositor.addController (buttonController);
            buttonActivator = new ButtonActivator();
            
            md.setRate(1);                                                  // start the movie      
        }
        catch (QTException exc)
        {
            exc.printStackTrace();
        }
        catch ( IOException exc )
        {
            exc.printStackTrace();
        }   
    }
    
    /**
     * Utility routine loads an image from a file, renders it, and adds it to the compositor
     * @param filename the name of the file to be displayed
     * @param layer the layer in the compositor where the image will be displayed
     * @param x the x coordinate of the top left corner where the image is to be displayed
     * @param y the y coordinate of the top left corner where the image is to be displayed
     */
    protected void displayImage( String filename, int layer, int x, int y )
    {
        try
        {   
            QTFile file = new QTFile (QTFactory.findAbsolutePath (filename));
            GraphicsImporterDrawer drawer = new GraphicsImporterDrawer(file);
            ImagePresenter presenter = ImagePresenter.fromGraphicsImporterDrawer(drawer);
            presenter.setLocation( x, y );
            compositor.addMember(presenter, layer );
        }
        catch (QTException exc)
        {
            exc.printStackTrace();
        }
        catch (IOException exc)
        {
            exc.printStackTrace();
        }       
    }
    
    /**
     * Reads a text file from the disk and displays it in the compositor
     * @param textPath the relative path where the text is located
     * @param layer, the layer of the compositor to add the text to.
     * @param x the x coordinate location.
     * @param y the y coordinate location.
     * @param width the width of the area to display the text.
     * @param height the height of the area to display the text.
     */
    protected void addText(String textPath, int layer, int x, int y, int width, int height)
    {
        try
        {
            TextPresenter text = new TextPresenter(textPath, new Dimension(width, height));
            
            ImagePresenter presenter = text.getPresenter();
            Matrix theMatrix = new Matrix();
            theMatrix.translate( (float) x, (float) y );
            presenter.setMatrix(theMatrix);
            compositor.addMember(presenter, layer);
        }
        catch ( QTException exc )
        {
            exc.printStackTrace();
        }
        catch ( FileNotFoundException exc )
        {
            exc.printStackTrace();
        }   
    }
    
    /**
     * Loads the specified sound file from disk and prepares it for playing
     * @param ???
     */
    protected void loadSound(String soundPath)
    {
        try
        {
            String soundLocation = QTFactory.findAbsolutePath(soundPath).getPath();
            //this call works with a file://, http://, rtsp://located movie
            player = (QTPlayer)QTFactory.makeDrawable ("file://" + soundLocation);
        }
        catch (IOException exc)
        {
            exc.printStackTrace();
        }
        catch (QTException exc)
        {
            exc.printStackTrace();
        }
    }
    
 
    /**
     * Opens the movie file and sets it up to be played.
     * @param f a QTFile representing the movie to initialize.
     * @return the movie, ready to play
     * @see #addMovie
     */
    protected Movie makeMovie (QTFile f) throws IOException, QTException
    {
        OpenMovieFile movieFile = OpenMovieFile.asRead(f);
        Movie m = Movie.fromFile (movieFile);
        m.getTimeBase().setFlags (StdQTConstants.loopTimeBase); 
        return m;   
    }
    
    /**
     *  Creates a TwoDSprite that behaves as a simple rollover button (such as the map button)
     */
    protected TwoDSprite CreateRollover( String filename, int layer, int x, int y )
    {
        TwoDSprite sprite = null;
        try
        {
            QTFile              file = new QTFile( QTFactory.findAbsolutePath( filename ));
            ImagePresenter      presenter = ImagePresenter.fromFile( file );
            ImageDataSequence   dataSeq = new ImageDataSequence (presenter.getDescription());
            
            dataSeq.addMember( presenter.getImage() );
            
            if ((QTSession.isCurrentOS(QTSession.kWin32) && QTSession.getQTMajorVersion() == 3) == false)   //doesn't work on QT3.0.2 on Win
                dataSeq = ImageUtil.makeTransparent ( dataSeq, QDColor.white );     // recompress the image using white as the transparent color
            
            Matrix theMatrix = new Matrix();
            theMatrix.translate( (float) x, (float) y );
            sprite = new TwoDSprite( dataSeq, theMatrix, true, 10 );
            
            GraphicsMode normalGM = new GraphicsMode (QDConstants.blend, QDColor.lightGray);
            sprite.setGraphicsMode (normalGM);
            compositor.addMember(sprite, layer);
            ctr.addMember( sprite );
        }
        catch ( QTException exc )
        {
            exc.printStackTrace();
        }
        catch ( IOException exc )
        {
            exc.printStackTrace();
        }
        
        return sprite;  
    }
    
    
    protected QTPlayer player;
    protected MoviePresenter md;
    
    protected ImagePresenter playRel;
    protected ImagePresenter playPress;
    protected ImagePresenter playPlaying;
    protected MovieButton playButton;
            
    protected ImagePresenter stopRel;
    protected ImagePresenter stopPress;
    protected ImagePresenter stopDeactive;
    protected MovieButton stopButton;
    
    protected ImagePresenter rewRel;
    protected ImagePresenter rewPress;
    protected ImagePresenter rewDeactive;
    protected MovieButton rewindButton;
    
    protected QTMouseTargetController buttonController;
    protected ButtonActivator buttonActivator;
}