// =========================================================
// Рисование вращающегося компакт-диска
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW:    http://www.glasnet.ru/~frolov
//            или
//         http://www.dials.ccas.ru/frolov
// =========================================================
import java.applet.*;
import java.awt.*;

public class CDRotation extends Applet implements Runnable
{
	// Ссылка на задачу рисования 
  // вращающегося компакт-диска
  Thread m_CDRotation = null;

  // Контекст отображения для рисования
  private Graphics m_Graphics;

  // Массив изображений компакт-диска
	private Image m_Images[];

  // Номер текущего изображения
	private int m_nCurrImage;
	
  // Ширина изображения
  private int m_nImgWidth  = 0;
 
  // Высота изображения
	private int m_nImgHeight = 0;

  // Флаг загрузки всех изображений
	private boolean m_fAllLoaded = false;

  // Общее количество изображений
	private final int NUM_IMAGES = 11;

	// -------------------------------------------------------
  // getAppletInfo
  // Метод, возвращающей строку информации об аплете
  // -------------------------------------------------------
	public String getAppletInfo()
	{
		return "Name: CDRotation\r\n" +
      "Author: Alexandr Frolov\r\n" +
      "E-mail: frolov@glas.apc.org" +
      "WWW:    http://www.glasnet.ru/~frolov" +
      "Created with Microsoft Visual J++ Version 1.0";
	}

  // -------------------------------------------------------
  // displayImage
  // Рисование текущего изображения, если все изображения
  // уже загружены
  // -------------------------------------------------------
	private void displayImage(Graphics g)
	{
    // Если не все изображения загружены,
    // ничего не делаем
    if (!m_fAllLoaded)
			return;

		// Рисуем текущее изображение в центре окна аплета
    g.drawImage(m_Images[m_nCurrImage],
		  (size().width - m_nImgWidth)   / 2,
			(size().height - m_nImgHeight) / 2, null);

    // Рисуем в вернем левом углу кадра его порядковый номер
    g.drawString((new Integer(m_nCurrImage)).toString(),
		  (size().width - m_nImgWidth)   / 2,
			((size().height - m_nImgHeight) / 2) + 10);
  }

  // -------------------------------------------------------
  // paint
  // Метод paint, выполняющий рисование в окне аплета
  // -------------------------------------------------------
	public void paint(Graphics g)
	{
    // Определяем текущие размеры окна аплета
    Dimension dimAppWndDimension = size();
    
    // Выбираем в контекст отображения белый цвет
    g.setColor(Color.white);
    
    // Закрашиваем внутреннюю область окна аплета
    g.fillRect(0, 0, 
      dimAppWndDimension.width  - 1, 
      dimAppWndDimension.height - 1);

    // Выбираем в контекст отображения черный цвет
    g.setColor(Color.black);

    // Рисуем рамку вокруг окна аплета
    g.drawRect(0, 0, 
      dimAppWndDimension.width  - 1, 
      dimAppWndDimension.height - 1);

    // Если все изображения загружены, рисуем
    // текущее изображение
    if (m_fAllLoaded)
		{
			displayImage(g);
		}
		
    // Если не загружены, рисуем сообщение
    // о загрузке
    else
			g.drawString("Подождите, идет загрузка...", 
        10, dimAppWndDimension.height / 2);
	}

  // -------------------------------------------------------
  // start
  // Метод вызывается при первом отображении окна аплета
  // -------------------------------------------------------
	public void start()
	{
		if (m_CDRotation == null)
		{
			m_CDRotation = new Thread(this);
			m_CDRotation.start();
		}
	}
	
  // -------------------------------------------------------
  // stop
  // Метод вызывается, когда окно аплета исчезает с экрана
  // -------------------------------------------------------
	public void stop()
	{
		if (m_CDRotation != null)
		{
			m_CDRotation.stop();
			m_CDRotation = null;
		}
	}

	// -------------------------------------------------------
  // run
  // Метод, который работает в рамках отдельной задачи
  // Он рисует в окне аплета изображения - кадры
  // клипа "вращающийся компакт-диск"
  // -------------------------------------------------------
	public void run()
	{
	  // Инициализируем номер текущего изображения
    m_nCurrImage = 0;
		
    // Проверяем, все ли изображения загружены.
    // Если нет, загружаем их
    if (!m_fAllLoaded)
		{
      // Перерисовываем окно аплета
      repaint();

      // Получаем контекст отображения для окна 
      m_Graphics = getGraphics();

      // Создаем массив изображений
    	m_Images   = new Image[NUM_IMAGES];

    	// Создаем объект MediaTracker для контроля
      // загружки изображений
      MediaTracker tracker = new MediaTracker(this);

      // Переменная для хранения имени файла изображения
    	String strImage;

      // Цикл загрузки изображений
    	for (int i = 0; i < NUM_IMAGES; i++)
    	{
    	  // Записываем в строку strImage имя текущего файла
        // с изображением
        strImage = "images/cdimg0" + 
          ((i < 10) ? "0" : "") + i + ".gif";

        // Инициируем получение изображения
			  m_Images[i] = getImage(getDocumentBase(), strImage);

        // Добавляем изображение в объект MediaTracker
        tracker.addImage(m_Images[i], 0);
    	}

			// Ожидаем окончание загрузки всех изображений
      try
			{
				tracker.waitForAll();

        // Если не было ошибок, устанавливаем флаг
        // окончания загрузки
				m_fAllLoaded = !tracker.isErrorAny();
			}
			catch (InterruptedException e)
			{
			}
			
      // Если при загрузке изображений произошла ошибка,
      // останавливаем задачу и рисуем сообщение об
      // ошибке
      if (!m_fAllLoaded)
			{
			  stop();
			  m_Graphics.drawString(
          "При загрузке изображений произошла ошибка",
          10, size().height / 2);
			  
        return;
			}
			
      // Сохраняем ширину и высоту первого изображения
      m_nImgWidth  = m_Images[0].getWidth(this);
		  m_nImgHeight = m_Images[0].getHeight(this);
    }	
    
    // Перерисовываем окно аплета
		repaint();

		// Запускаем цикл рисования изображений
    while (true)
		{
			try
			{
		    // Рисуем текущее изображение
        displayImage(m_Graphics);

        // Увеличиваем номер текущего изображения
				m_nCurrImage++;

        // Если достигли максимального номера,
        // начинаем с самого начала
				if(m_nCurrImage == NUM_IMAGES)
					m_nCurrImage = 0;

				// Выполняем задержку в 30 миллисекунд
        Thread.sleep(30);
      }
      
      // Если в процессе рисования возникло
      // исключение, останавливаем задачу
      catch (InterruptedException e)
			{
				stop();
			}
		}
	}
}
