/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public Liense as published by        *
 * the Free Software Foundation, either version 2 of the License, or (at      * 
 * your option) any later version.                                            *
 *                                                                            *
 * The ITX package is distributed in the hope that it will be useful, but     *
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          * 
 *                                                                            *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.                                                   *
 *                                                                            * 
 * Contact information:                                                       *
 * Donna Bergmark                                                             *
 * 484 Rhodes Hall                                                            *
 * Cornell University                                                         *
 * Ithaca, NY 14853-3801                                                      *
 * bergmark@cs.cornell.edu                                                    *
 ******************************************************************************/
package shared;

import com.ms.com.*;
import msppt8.*;

/**
 * A <code>PowerPointControl</code> is a class used to control the playback
 * of a PowerPoint slide show.  It uses COM automation (through the use of
 * JActiveX) to control PowerPoint.
 * 
 * @author Jason Howes
 * @version 1.0, 11/4/1998
 * @see cnrg.apps.spot.shared.PowerPointException
 */
public class PowerPointControl extends Object
{
	/**
	 *  Is there a presentation open?
	 */
	private boolean mPresentationOpen;

	/**
	 *  Various PowerPoint COM objects
	 */
	private _Application _mPPTApp;
	private Presentations mPresentationOpener;
	private _Presentation _mPresentation;
	private Slides mSlides;
	private SlideShowSettings mSettings;
	private SlideShowWindow mWindow;
	private SlideShowView mView;

	/**
	 *  Slide show ranges and current slide
	 */
	private int mStartingSlide;
	private int mEndingSlide;
	private int mCurrentSlide;

	/**
	 * Class constructor.
	 */
	public PowerPointControl()
	{			   
		mPresentationOpen = false;
		mStartingSlide = 0;
		mEndingSlide = 0;
		mCurrentSlide = 0;		
	}

	/**
	 * Sets the size of the PowerPoint slide presentation window.
	 * 
	 * @param w the horizontal size (in pixels).
	 * @param h the vertical size (in pixels).
	 * @exception <code>PowerPointControlException</code> on error.
	 */	
	public void setSize(int w, int h) throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return;
		}
		
		// Set the size
		try
		{
			mWindow.setWidth(w);
			mWindow.setHeight(h);
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}
	}

	/**
	 * Sets the location of the PowerPoint slide presentation window.
	 * 
	 * @param x the horizontal screen location.
	 * @param y the vertical screen location.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public void setLocation(float x, float y) throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return;
		}

		// Set the location
		try
		{
			mWindow.setLeft(x);
			mWindow.setTop(y);
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}
	}

	/**
	 * Updates the presentation to show the first slide.
	 * 
	 * @return <code>true</code> if the current slide changed, <code>false</code> otherwise.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public boolean firstSlide() throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return false;
		}

		if (mCurrentSlide == mStartingSlide)
		{
			return false;
		}

		// Go to the first slide
		try
		{
			mView.First();
			mCurrentSlide = mStartingSlide;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		return true;
	}

	/**
	 * Updates the presentation to show the previous slide.
	 * 
	 * @return <code>true</code> if the current slide changed, <code>false</code> otherwise.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public boolean previousSlide() throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return false;
		}

		if (mCurrentSlide == mStartingSlide)
		{
			return false;
		}

		// Go to the previous slide
		try
		{
			mView.Previous();
			mCurrentSlide--;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		return true;
	}

	/**
	 * Updates the presentation to show the next slide.
	 * 
	 * @return <code>true</code> if the current slide changed, <code>false</code> otherwise.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public boolean nextSlide() throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return false;
		}

		if (mCurrentSlide == mEndingSlide)
		{
			return false;
		}

		// Go to the next slide
		try
		{
			mView.Next();
			mCurrentSlide++;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		return true;
	}

	/**
	 * Updates the presentation to show the last slide.
	 * 
	 * @return <code>true</code> if the current slide changed, <code>false</code> otherwise.
	 * @exception <code>PowerPointControlException</code> on error.
	 */	
	public boolean lastSlide() throws PowerPointControlException
	{
		if (!mPresentationOpen)
		{
			return false;
		}

		if (mCurrentSlide == mEndingSlide)
		{
			return false;
		}

		// Go to the last slide
		try
		{
			mView.Last();
			mCurrentSlide = mEndingSlide;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		return true;
	}

	/**
	 * Returns the current slide index.
	 * 
	 * @return the current slide index.
	 */		
	public int getCurrentSlide()
	{
		return mCurrentSlide;
	}
	
	/**
	 * Returns the first slide index.
	 * 
	 * @return the first slide index.
	 */		
	public int getFirstSlide()
	{
		return mStartingSlide;
	}
	
	/**
	 * Returns the last slide index.
	 * 
	 * @return the last slide index.
	 */		
	public int getLastSlide()
	{
		return mEndingSlide;
	}	

	/**
	 * Updates the presentation to show the slide with the specified index.
	 * 
	 * @param index the index of the desired slide.
	 * @return <code>true</code> if the current slide changed, <code>false</code> otherwise.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public boolean gotoSlide(int index) throws PowerPointControlException
	{
		if ((index < mStartingSlide) || (index > mEndingSlide))
		{
			return false;
		}

		if (mCurrentSlide == index)
		{
			return false;
		}

		// Go to the specified slide
		try
		{
			mView.GotoSlide(index + 1, 0);
			mCurrentSlide = index;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		return true;
	}

	/**
	 * Starts a PowerPoint slide show presentation.
	 * 
	 * @param presentationFilename filename of the presentation.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public void startPresentation(String presentationFilename) throws PowerPointControlException
	{		
		if (mPresentationOpen)
		{
			return;
		}

		try
		{
			// Open PowerPoint
			_mPPTApp = (_Application)new Application();
			mPresentationOpener = _mPPTApp.getPresentations();
			_mPPTApp.setWindowState(2);

			// Open the PowerPoint presentation
			_mPresentation = (_Presentation)mPresentationOpener.Open(presentationFilename, 1, 1, 0);

			// Set the presentation settings
			mSettings = _mPresentation.getSlideShowSettings();
			mWindow = mSettings.Run();
			mView = mWindow.getView();

			// Set the slide ranges and current slide
			mSlides = _mPresentation.getSlides();
			mStartingSlide = 0;
			mEndingSlide = mSlides.getCount() - 1;
			mCurrentSlide = mStartingSlide;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		// Success...
		mPresentationOpen = true;
	}
	
	/**
	 * Starts a PowerPoint slide show presentation.
	 * 
	 * @param presentationFilename filename of the presentation.
	 * @param w the horizontal size of the presentation window (in pixels).
	 * @param h the vertical size of the presentation window (in pixels).
	 * @param x the horizontal screen position of the presentation window.
	 * @param y the vertical screen position of the presentation window.
	 * @exception <code>PowerPointControlException</code> on error.
	 */		
	public void startPresentation(String presentationFilename,
								  int w,
								  int h,
								  float x,
								  float y) throws PowerPointControlException
	{		
		if (mPresentationOpen)
		{
			return;
		}

		try
		{
			// Open PowerPoint
			_mPPTApp = (_Application)new Application();
			mPresentationOpener = _mPPTApp.getPresentations();
			_mPPTApp.setWindowState(2);

			// Open the PowerPoint presentation
			_mPresentation = (_Presentation)mPresentationOpener.Open(presentationFilename, 1, 1, 0);

			// Set the presentation settings
			mSettings = _mPresentation.getSlideShowSettings();
			mWindow = mSettings.Run();
			mView = mWindow.getView();

			// Set the slide ranges and current slide
			mSlides = _mPresentation.getSlides();
			mStartingSlide = 0;
			mEndingSlide = mSlides.getCount() - 1;
			mCurrentSlide = mStartingSlide;
		}
		catch (Exception e)
		{
			throw new PowerPointControlException(e.getMessage());
		}

		// Success...
		mPresentationOpen = true;
		
		// Set the size and location
		setSize(w, h);
		setLocation(x, y);		
	}	

	/**
	 * Stops and closes the current PowerPoint slide show presentation.
	 */		
	public void stopPresentation()
	{
		if (!mPresentationOpen)
		{
			return;
		}

		try
		{
			// Exit and close the presentation
			mView.Exit();
			_mPresentation.Close();
	
			// Exit PowerPoint
			_mPPTApp.Quit();
		}
		catch (Exception e)
		{
		}
		
		// Delete objects
		mView = null;
		_mPresentation = null;
		_mPPTApp = null;
		System.gc();

		// Success...
		mPresentationOpen = false;
	}
	
	/**
	 * Releases any open resources.
	 */		
	protected void finalize() throws Throwable
	{
		super.finalize();
		stopPresentation();
	}
}
