import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.lang.reflect.Array;
import java.awt.event.*;
import javax.swing.*;

class JpgWin extends JFrame implements ImageObserver, MouseListener, KeyListener 
{
   private int myTimer=17;
   private Image myImage;
   private Image mySrcImage;
   private Rectangle myRect;
   private Rectangle myPaintRect;
   private int myLength;
   private int myTime;
   private int myItem=0;
   private boolean myIsSource;
   private boolean myIsValid;
   private File myDir;

   private JPopupMenu myPopupMenu = new JPopupMenu();
   private JMenuItem myNextMenuItem = new JMenuItem("Next");
   private JMenuItem myZoomOutMenuItem = new JMenuItem("Zoom Out (Right Click)");
   private JMenuItem myOpenMenuItem = new JMenuItem("Open");

    public static void main(String[] args) {
      JpgWin t=new JpgWin(new File(".\\"));
   }

   public JpgWin(File inFile) {
//    String dir="c:\\java\\dev\\jpg";
      setSize(600,600);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      addMouseListener(this);
      addKeyListener(this);
      show();

      myNextMenuItem.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            myTime=myTimer*5;
         }
      });
      myPopupMenu.add(myZoomOutMenuItem);
      
      myZoomOutMenuItem.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            zoomOut();
         }
      });
      myPopupMenu.add(myNextMenuItem);

      myOpenMenuItem.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            openFile();
         }
      });
      myPopupMenu.add(myOpenMenuItem);
/*
int w = 100;
               int h = 100;
               int[] pix = new int[w * h];
               int index = 0;
               for (int y = 0; y < h; y++) {
                   int red = (y * 255) / (h - 1);
                   for (int x = 0; x < w; x++) {
                         int blue = (x * 255) / (w - 1);
                         pix[index++] = (255 << 24) | (red << 16) | blue;
                   }
               }
    image = createImage(new MemoryImageSource(w, h, pix, 0, w));
*/
      if(!inFile.isDirectory())
         myDir=inFile.getParentFile();
      else
         myDir=inFile;
      
      int length;
      int dot;
      String type;
      String name;
      File[] files;
      boolean found;
      myItem=0;

      while(true) {
         files=myDir.listFiles();
         myLength=files.length;
         found=false;

         for(;myItem<myLength; myItem++) {
            name=files[myItem].getName();
            dot=name.indexOf('.');

            if(dot>-1)
               type=name.substring(dot, name.length());
            else
               type="";

System.out.println("name: "+name+"  type: "+type);
            if(type.toLowerCase().equals(".jpg")) {
               found=true;
               setTitle(name);
               Image image=Toolkit.getDefaultToolkit().getImage(files[myItem].getPath());
               setImage(image);

               for(myTime=0; myTime<myTimer*5; myTime++) {
                  try {
                     Thread.sleep(200);
                  }
                  catch (Exception e) {
                     System.out.println(e);
                  }
               }  // for
            }  // if jpg
         }          
         
         if(!found) {
            if(!openFile())
               System.exit(1);
            else
               myItem++;
         }
         else
            myItem=0;
      }  // while
   }

   public void paint(Graphics inGraphics) {
      if(myIsValid) {
         Rectangle r=getBounds();
         Insets insets=getInsets();
         r.width=r.width-insets.left-insets.right;
         r.height=r.height-insets.bottom-insets.top;
//         int x=myImage.getWidth(this);
//         int y=myImage.getHeight(this);
         int x=myRect.width;
         int y=myRect.height;

         if(x==0 || y==0) 
            return;
         
         int nX=(r.height*x)/y;
         int nY=(r.width*y)/x;
         inGraphics.setColor(Color.BLACK);

         if (nX>r.width) {
            nX=r.width;
            inGraphics.fillRect(insets.left, insets.top, nX, (r.height-nY)/2);
            inGraphics.fillRect(insets.left, insets.top+(r.height+nY)/2, nX, 
                    (r.height-nY)/2);
         }
         else {
            nY=r.height;
            inGraphics.fillRect(insets.left, insets.top, (r.width-nX)/2, nY);
            inGraphics.fillRect(insets.left+(r.width+nX)/2, insets.top,
                    (r.width-nX)/2, nY);
         }
         
         myPaintRect=new Rectangle((r.width-nX)/2, (r.height-nY)/2, nX, nY);
         inGraphics.drawImage(myImage, insets.left+myPaintRect.x,
            insets.top+myPaintRect.y, myPaintRect.width, myPaintRect.height,
            this);

         myPopupMenu.repaint();
      }
   }

  public boolean imageUpdate(Image theimg, int infoflags,
                                   int x, int y, int w, int h) {
 //   if ((infoflags & (ERROR)) != 0) {
 //     errored = true;
 //   }
    if ((infoflags & (WIDTH | HEIGHT))!=0 && myIsSource) {
        myRect=new Rectangle(0, 0, theimg.getWidth(this),
             theimg.getHeight(this));
    }
    
    boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
    
    if(done) {
      myIsValid=true;
      repaint();
    }
    return !done; //If done, no further updates required.
  }

   public void setImage(Image inImage) {
      if(myImage!=null)
         myImage.flush();
 
      myImage=inImage;
      myIsSource=true;
      mySrcImage=myImage;
      int status=checkImage(myImage, this);
      myIsValid=((status & (ERROR | FRAMEBITS | ALLBITS)) != 0);

      if(myIsValid) {
         myRect=new Rectangle(0, 0, myImage.getWidth(this),
            myImage.getHeight(this));
         repaint();
      }
      else
         prepareImage(myImage,this);

      System.runFinalization();
   }

   public void mouseClicked(MouseEvent inEvent) {
      int status=checkImage(myImage, this);
      
      if(myIsValid && (status & (WIDTH | HEIGHT)) != 0) {
         int button=inEvent.getModifiers();
         
         if((button&inEvent.BUTTON1_MASK)>0)
            zoomIn(inEvent.getPoint());
         else if((button&inEvent.BUTTON2_MASK)>0) {
            Point point=inEvent.getPoint();
            myPopupMenu.show(this, point.x, point.y);
         }
         else if((button&inEvent.BUTTON3_MASK)>0) {
            zoomOut();
         }
      }
   }

  public void mousePressed(MouseEvent e) {
//    System.out.println("Pressed");
  }

  public void mouseReleased(MouseEvent e) {
//    System.out.println("Released");
  }

  public void mouseEntered(MouseEvent e) {
//    System.out.println("Entered");
  }

  public void mouseExited(MouseEvent e) {
//    System.out.println("Exited");
  }

   public void keyPressed(KeyEvent e) {
//    System.out.println("Exited");
  }

   public void keyReleased(KeyEvent e) {
//    System.out.println("Exited");
  }

   public void keyTyped(KeyEvent inEvent) {
      char key=inEvent.getKeyChar();

      if(key==' ')
         myTime=myTimer*5;  //go to next picture
      else {
         Rectangle rect=getBounds();
         //Point point=inEvent.getPoint();
         myPopupMenu.show(this, rect.width/2, rect.height/2);
         System.out.println("bounds:"+myPopupMenu.getBounds()+":"+rect);
//         myPopupMenu.show(inEvent.getComponent(),point.x,point.y);
//         System.out.println(((int)key)+":"+key);
      }
   }

 public void zoomIn(Point inPoint) {
      myIsSource=false;
      myTime=0;  // reset timer
      Rectangle iRect=getBounds();  // get screen size
      Insets insets=getInsets();
      iRect.width=iRect.width-insets.left-insets.right;
      iRect.height=iRect.height-insets.top-insets.bottom;

      int oWidth=mySrcImage.getWidth(this);
      int oHeight=mySrcImage.getHeight(this);
      int zoom=2;

      // translate mouse point to source image point
      int mX=(inPoint.x-myPaintRect.x)*myRect.width/myPaintRect.width+myRect.x;
      int mY=(inPoint.y-myPaintRect.y)*myRect.height/myPaintRect.height+myRect.y;

      // attempt to fill the screen
      int nWidth=myRect.height*iRect.width/(zoom*iRect.height);
      int nHeight=myRect.width*iRect.height/(zoom*iRect.width);
      
      if(nWidth>myRect.width/zoom)
        nHeight=myRect.height/zoom;
      else
        nWidth=myRect.width/zoom;
      
      if(nWidth<1)
         nWidth=1;
      else if(nWidth>oWidth)
         nWidth=oWidth;
      
      if(nHeight<1)
         nHeight=1;
      else if(nHeight>oHeight)
         nHeight=oHeight;

      int nX=mX-nWidth/2;
      int nY=mY-nHeight/2;

      if(nX<0)
         nX=0;
      else if(nX>oWidth-nWidth)
         nX=oWidth-nWidth;

      if(nY<0)
         nY=0;
      else if(nY>oHeight-nHeight)
         nY=oHeight-nHeight;

      ImageFilter f=new CropImageFilter(nX, nY, nWidth, nHeight);
      ImageProducer ip=new FilteredImageSource(mySrcImage.getSource(), f);
      myImage=createImage(ip);

      myRect=new Rectangle(nX, nY, nWidth, nHeight);
      repaint();
  }

   public boolean openFile() {
      JFileChooser chooser = new JFileChooser(myDir);
      chooser.setFileSelectionMode(chooser.FILES_AND_DIRECTORIES);
      //ExampleFileFilter filter = new ExampleFileFilter();
      //filter.addExtension("jpg");
      //filter.addExtension("gif");
      //filter.setDescription("JPG & GIF Images");
      //chooser.setFileFilter(filter);      
      int returnVal = chooser.showOpenDialog(this);
      
      if(returnVal != JFileChooser.APPROVE_OPTION) 
         return false;
      
      File file=chooser.getSelectedFile();

      if(!file.isDirectory()) {
         String name=file.getName();
         int dot=name.indexOf('.');
         myDir=file.getParentFile();

         if(dot>-1 && name.substring(dot, name.length()).toLowerCase()
            .equals(".jpg"))
         {
            File[] files=myDir.listFiles();
            int length=files.length;
   
            for(int i=0; i<length; i++) {
               if(files[i].getName().equals(name)) {
                  myItem=i-1;
                  myLength=length;
System.out.println("item:"+myItem);
                  myTime=myTimer*5;
                  return true;
               }
            }
         }
         
      }
      else
         myDir=file;
      
      myItem=1000000;
      myTime=myTimer*5;
      return true;
 }

  public void zoomOut() {
      myIsSource=false;
      myTime=0;
      Rectangle iRect=getBounds();
      Insets insets=getInsets();
      iRect.width=iRect.width-insets.left-insets.right;
      iRect.height=iRect.height-insets.top-insets.bottom;
      int zoom=2;

      // attempt to fill the screen
      int nWidth=myRect.height*iRect.width*zoom/iRect.height;
      int nHeight=myRect.width*iRect.height*zoom/iRect.width;
      int oWidth=mySrcImage.getWidth(this);
      int oHeight=mySrcImage.getHeight(this);
      
      if(nWidth>myRect.width*zoom)
        nHeight=myRect.height*zoom;
      else
        nWidth=myRect.width*zoom;
      
      if(nWidth>oWidth)
        nWidth=oWidth;
      if(nHeight>oHeight)
        nHeight=oHeight;

      int nX=myRect.x-(nWidth-myRect.width)/2;
      int nY=myRect.y-(nHeight-myRect.height)/2;

      if(nX<0)
        nX=0;
      else if(nX>oWidth-nWidth)
        nX=oWidth-nWidth;

      if(nY<0)
        nY=0;
      else if(nY>oHeight-nHeight)
        nY=oHeight-nHeight;

      ImageFilter f=new CropImageFilter(nX, nY, nWidth, nHeight);
      ImageProducer ip=new FilteredImageSource(mySrcImage.getSource(), f);
      myImage=createImage(ip);

      myRect=new Rectangle(nX,nY,nWidth,nHeight);
      repaint();
  }
}  //end of class

