/*
 * @(#) MovieUI.java 1.0 2000/7/18
 * Copyright (c) 1997 Lawrence Rodrigues
 */

package com.vistech.imageviewer;
import java.io.*;
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import java.lang.reflect.*;
import com.vistech.events.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

 /** MovieUI Class
   * @version 1.0  18 July 2000
   * @author Lawrence Rodrigues
   **/
public class MovieUI extends JPanel implements ListSelectListener{
   protected  int cineValue = 60;
   protected  JTextField frameValueField;
   protected String curImageStr;
   protected int[] cineIndices;
   protected String cineImageSet[];
   protected String fileList[];
   protected String curDir;
   protected File curPath;
   private Vector lslisteners = new Vector();
   private ListSelectEvent lsevent = null;
   transient Thread cineThread;

   protected  int cineRate = 60;
   protected  boolean cineOn = false;
   protected  int curIndex =0;
   protected  JList imlist;
   private int delay = 10;
   private JPanel listpan;
   private JPanel cinepan;
   private JButton  startButton, stopButton;
   private JRadioButton loadsel, loadall;
   protected JSlider frameSlider;
   protected CineController movie;

   public MovieUI(CineController cine){
      movie = cine;
      init();
   }
   protected void init(){
      createGUI();
      setCineRate(cineRate);
   }

   public void setCineRate(int rate){
      if(rate==0) return;
      firePropertyChange("cineRate",
                           new Integer(cineRate),
                           new Integer(rate));

      cineRate = rate;
      frameValueField.setText(Integer.toString(cineRate));
      movie.setCineRate(cineRate);
   }

   public int getCineRate(){ return cineRate; }

   public void setCineOn(boolean onOrOff){
      firePropertyChange("cineOn",
                            new Boolean(cineOn),
                            new Boolean(onOrOff));
      cineOn = onOrOff;
      movie.setCineOn(onOrOff);
   }

   public boolean getCineOn(){return cineOn;}

   public void startCine(){ setCineOn(true);}
   public void stopCine(){setCineOn(false);}

   public void setCineIndices(int[] indices){
      cineIndices = indices;
      setCineImageSet(indices);
   }

   public void setCineImageSet(int[] indices){
      if(indices == null) return;
      int len = indices.length;
      cineImageSet = new String[len];
      for(int i=0;i <len;i++){
          cineImageSet[i] = fileList[indices[i]];
      }
   }

   public void setFileList(String[] list){
      fileList = list;
      imlist.validate();
      imlist.repaint();
   }

   public String[] getFileList(){ return fileList;}

   public void setCurDir(String dir){ curDir = dir;}

   public String getCurDir(){ return curDir;}

   public void setCurPath(File path){ curPath = path; }

   public File getCurPath(){ return curPath; }

   public void setCineImageSet(String[] imagelist){
      cineImageSet = imagelist;
   }
   public void setCineImageSet(Image[] imgset){
      if(imgset == null) return;
      movie.setCineImageSet(imgset);
   }

   public String[] getCineImageSet(){ return cineImageSet; }

   public void load(ListSelectEvent ls) {
      fileList =  ls.getFileList();
      imlist.validate();
      imlist.repaint();
   }

   private void createGUI(){
      cinepan = createCinePanel();
      cinepan.setBackground(getBackground());
      cinepan.setForeground(getForeground());
      add(cinepan);
   }

   private JPanel createCinePanel() {
      int startValue = 60;
      int minCycles = 10;
      int maxCycles = 360;

      listpan = new JPanel();
      listpan.setBackground(getBackground());
      listpan.setForeground(getForeground());
      ListModel  imageListModel = new AbstractListModel(){
         public int getSize(){
            if(fileList == null) return 0;
            else return fileList.length;
         }
         public Object getElementAt(int index){
            if(fileList == null) return null;
            if((index <0) || (index>fileList.length)) return null;
            return fileList[index];
         }
      };
      imlist = new JList(imageListModel);
      MouseListener mouseListener = new MouseAdapter() {
         public void mouseClicked(MouseEvent e) {
            int[] ind = imlist.getSelectedIndices();
            movie.setCineIndices(ind);
         }
      };

      imlist.addMouseListener(mouseListener);
      imlist.setBackground(Color.white);
      imlist.setForeground(Color.black);
      imlist.setFixedCellWidth(150);
      imlist.setFixedCellHeight(15);
      JScrollPane scp= new JScrollPane(imlist);

      imlist.setSelectedIndex(0);
      JLabel ldlab = new JLabel("Select Images");
      ButtonGroup bg = new ButtonGroup();
      loadall = new JRadioButton("All");
      loadall.setSelected(true);

      loadsel = new JRadioButton("Selected");
      GridBagLayout    gb = new GridBagLayout() ;
      GridBagConstraints c = new GridBagConstraints();
      listpan.setLayout(gb);
      c.insets = new Insets(0,1, 0,10);
      c.gridwidth = GridBagConstraints.REMAINDER;
      c.insets = new Insets(0,10, 2,5);
      gb.setConstraints(scp, c);
      listpan.add(scp);
      gb.setConstraints(ldlab, c);
      listpan.add(ldlab);
      c.weighty = 1.0; c.weightx = 1.0;
      c.gridwidth = 1;
      gb.setConstraints(loadall, c);
      listpan.add(loadall);
      gb.setConstraints(loadsel, c);
      listpan.add(loadsel);

      JPanel pan = new JPanel();

      gb = new GridBagLayout() ;
      c = new GridBagConstraints();
      pan.setLayout(gb);
      c.fill = GridBagConstraints.BOTH;
      c.gridheight = 3;
      gb.setConstraints(listpan, c);
      pan.add(listpan);
      c.fill = GridBagConstraints.HORIZONTAL;
      c.gridheight = 1; c.weighty = 1.0; c.weightx = 1.0;

      c.insets = new Insets(0,1,0,10);

      c.gridwidth = 1; c.weightx = 1.0;
      JLabel frameLabel= new JLabel("Frames/min", SwingConstants.LEFT);
      gb.setConstraints(frameLabel, c);
      pan.add(frameLabel);
      c.gridwidth = GridBagConstraints.REMAINDER;
      frameValueField  = new  JTextField(Integer.toString(cineValue),3);
      frameValueField.setBackground(Color.gray);
      gb.setConstraints(frameValueField, c);
      pan.add(frameValueField);
      int minValue =1;
      int maxValue = 360;
      int startVlaue = 10;
      frameSlider = new JSlider(minValue,maxValue,startValue);
      frameSlider.setMajorTickSpacing(60);
      frameSlider.setMinorTickSpacing(20);
      frameSlider.setExtent(10);
      frameSlider.setPaintTicks(true);
      frameSlider.setPaintLabels(true);
      gb.setConstraints(frameSlider, c);
      pan.add(frameSlider);

      c.gridwidth = GridBagConstraints.REMAINDER;
      c.weightx = 1.0;

      JPanel reportBtns= new JPanel();
      reportBtns.setLayout(new GridLayout(1,2));
      startButton = new JButton("Start");
      stopButton = new JButton("Stop");

      reportBtns.add(startButton);
      reportBtns.add(stopButton);
      c.fill = GridBagConstraints.NONE;
      gb.setConstraints(reportBtns, c);
      pan.add(reportBtns);
      addEventHandlers();
      pan.setBorder(BorderFactory.createTitledBorder("Movie Mode"));
      return pan;
   }

   private void addEventHandlers(){
      frameSlider.addChangeListener(
         new ChangeListener() {
             public void stateChanged(ChangeEvent e){
                cineValue = ((JSlider)(e.getSource())).getValue();
                setCineRate(cineValue);
                frameValueField.setText(Integer.toString(cineValue));
             }
         }
      );

      loadall.addActionListener(
          new ActionListener(){
              public void actionPerformed(ActionEvent e){
                 if(fileList == null) return;
                 cineIndices = new int[fileList.length];
                 for (int i=0; i< fileList.length;i++) cineIndices[i] =i;
                 movie.setCineIndices(cineIndices);
                 fireListSelEvent();
              }
          }
      );

      loadsel.addActionListener(
          new ActionListener(){
              public void actionPerformed(ActionEvent e){
                 cineIndices = imlist.getSelectedIndices();
                 movie.setCineIndices(cineIndices);
                 fireListSelEvent();
              }
            }
      );

      startButton.addActionListener(
            new ActionListener(){
              public void actionPerformed(ActionEvent e){
                 startCine();
              }

            }
      );
      stopButton.addActionListener(
           new ActionListener(){
              public void actionPerformed(ActionEvent e){
                 stopCine();
              }
            }
      );
   }

    public void addListSelectListener(ListSelectListener l){
       if(lslisteners == null) lslisteners = new Vector();
          lslisteners.addElement(l);
    }

    public void removeListSelectListener(ListSelectListener l){
       if(lslisteners != null) lslisteners.removeElement(l);
    }

    public void fireListSelEvent(){
       if(lslisteners.isEmpty()) return;
         //Check whether an image list is received
       if(curPath == null){
          if(curDir != null) curPath = new File(curDir);
          else return;
       }
       ListSelectEvent cinelse = new ListSelectEvent(this,
                                                     "Load Images",
                                                     curPath,
                                                     cineImageSet);
       for(Enumeration e= lslisteners.elements(); e.hasMoreElements(); ){
          ((ListSelectListener)(e.nextElement())).load(cinelse);
       }
    }

    public void loadFileList(ListSelectEvent e){
       if(e == null) return;
       setFileList(e.getFileList());
       setCurPath(e.getPath());
       setCurDir(e.getPath().getAbsolutePath());
    }

   //------------------Serialization Methods ---------------------------
      /**
        * Writes the Object to the output stream.
        */
    private void writeObject(ObjectOutputStream out)throws IOException{
          //Save all the non transient, non-static fields
          out.defaultWriteObject();
    }
      /**
        * After restoring the Object, restores the event handling registration.
        */
     private void readObject(ObjectInputStream in)
                     throws IOException, ClassNotFoundException{
          //Read all the default fields
          in.defaultReadObject();
          //Register again for event handling
          addEventHandlers();
    }
}


