/* @(#) ImageManip2D.java 1.1 99/11/18
 * Copyright (c) 1999 Lawrence Rodrigues
 */
package app;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.print.*;
import java.text.*;
import java.beans.*;
import com.vistech.imageloader.*;
import com.vistech.events.*;
import com.vistech.util.*;
import com.vistech.imageviewer.*;

/** An image viewer application that can load, display, print, and
  * manipulate images. The basic manipulation operations supported are:
  * pan, zoom, rotate, shear, and flip.
  * @version 1.0  18 Nov 1999
  * @author Lawrence Rodrigues
  **/
public class ImageManip2D extends ImageViewer2D
                                     implements PropertyChangeListener{
    protected JTextArea vmMessageBar;
    protected JTextArea pzMessageBar;
    protected JTextArea mnpMessageBar;
    protected JFrame ilFrame;
    protected PanZoom panZoom;
    protected GeomManip manip;
    protected JFrame  lensFrame;
    protected JFrame manipFrame;
    protected LensPanel lensPanel;

    public static void  main(String[] args){ ImageManip2D iv = new ImageManip2D();}

    public ImageManip2D() { init(); }
    public void init(){
       panZoom = new PanZoom((ImageManipulator)viewerPane);
       this.updateMessageBar();
       viewerPane.addPropertyChangeListener(this);
       repaint();
    }

    protected void createGUI(){
       createImageLoader();
       ViewerMenuBar viewerMenuBar = new ViewerMenuBar();
       setJMenuBar((JMenuBar)viewerMenuBar);
       Dimension ssize= Toolkit.getDefaultToolkit().getScreenSize();

       this.setLocation((ssize.width/4),
                         (ssize.height/4));
       this.setSize((int)(ssize.width*3/4.0), (int)(ssize.height*3/4.0));

       viewerPane = new ImageCanvas2D();
       manip =  new GeomManip((ImageManipulator)viewerPane);

       vmMessageBar = new JTextArea();
       pzMessageBar = new JTextArea();
       mnpMessageBar = new JTextArea();
       vmMessageBar.setBorder(BorderFactory.createTitledBorder("View Modes"));
       vmMessageBar.setBackground(Color.black);
       vmMessageBar.setForeground(Color.green);
       pzMessageBar.setBackground(Color.black);
       pzMessageBar.setForeground(Color.green);
       pzMessageBar.setBorder(BorderFactory.createTitledBorder("Pan Zoom"));
       mnpMessageBar.setBackground(Color.black);
       mnpMessageBar.setForeground(Color.green);
       mnpMessageBar.setBorder(BorderFactory.createTitledBorder("Rotate Shear"));
       JPanel mbpan = new JPanel();
       mbpan.setLayout(new GridLayout(1,3));
       mbpan.add(vmMessageBar);
       mbpan.add(pzMessageBar);
       mbpan.add(mnpMessageBar);

       GridBagLayout gb = new GridBagLayout() ;
       GridBagConstraints c = new GridBagConstraints();
       this.getContentPane().setLayout(gb);
       c.fill = GridBagConstraints.BOTH;
       c.weighty = 1.0; c.weightx = 1.0;
       c.gridheight =1;c.gridwidth = 1;
       c.gridwidth = GridBagConstraints.REMAINDER;
       gb.setConstraints(viewerPane, c);
       this.getContentPane().add(viewerPane);
       c.fill = GridBagConstraints.BOTH;
       c.weighty = 0.03; c.weightx = 1.0;
       gb.setConstraints(mbpan, c);
       this.getContentPane().add(mbpan);
       this.setPrinterObj(viewerPane);
       this.show();
       this.repaint();
   }

   public void propertyChange(PropertyChangeEvent p){
      updateMessageBar();
   }

   public void updateMessageBar(){
       if((vmMessageBar == null)||(viewerPane == null)) return;
        vmMessageBar.setBackground(Color.black);
        vmMessageBar.setText("Display Mode : "+
                            getDisplayModeString(viewerPane.getDisplayMode())+"\n"+
                           "Flip Mode : " +
                            getFlipModeString(viewerPane.getFlipMode()));
        vmMessageBar.repaint();
        StringBuffer result = new StringBuffer();
        java.text.NumberFormat decformat = new java.text.DecimalFormat(new String("##0.##"));
        result = decformat.format(panZoom.getZoomFactor(),
                                  result,
                                  new FieldPosition(NumberFormat.FRACTION_FIELD));

        pzMessageBar.setText(" Pan " + ((panZoom.getPanOn())? "on": "off")+ "  "+
                             " Zoom "+ ((panZoom.getZoomOut())? "out": "in") + "\n"+
                             " Zoom Factor = " +result.toString());

        pzMessageBar.repaint();
        int angle = (int)(((ImageManipulator)viewerPane).getRotationAngle() * 180/Math.PI);
        StringBuffer shx = new StringBuffer();
        StringBuffer shy = new StringBuffer();
        decformat.format(((ImageManipulator)viewerPane).getShearFactor(),
                                  shx,
                                  new FieldPosition(NumberFormat.FRACTION_FIELD));
        decformat.format(((ImageManipulator)viewerPane).getShearFactor(),
                                  shy,
                                  new FieldPosition(NumberFormat.FRACTION_FIELD));

        mnpMessageBar.setText("Rotation angle: "+ angle + "\n" +
                              "ShearX         : " + shx.toString()+ "  "+
                              "ShearY         : " + shy.toString()+ "\n");
        mnpMessageBar.repaint();
    }

    public class ViewerMenuBar extends com.vistech.util.ApplicationFrame.AppMenuBar {
       public ViewerMenuBar(){
          createImageSelectionMenu();
          createViewModeMenu();
          createManipMenu();
          createHelpMenu();
       }

       public JMenu createImageSelectionMenu(){
          JMenu selMenu = new JMenu("Load");
          JMenuItem ls = new JMenuItem("List/Select");
          ls.addActionListener(
              new ActionListener() {
                public void actionPerformed(ActionEvent e){
                   showImageLoader();
                }
              }
           );
           selMenu.add(ls);
           add(selMenu);
           return selMenu;
       }

       public JMenu createManipMenu(){
          JMenu manipMenu = new JMenu("Manipulate");
          JMenu flip = createFlipMenu();
          JMenuItem rot = new JMenuItem("Rotate/Shear");
          JMenuItem ls = new JMenuItem("Lens");
          ls.addActionListener(
              new ActionListener() {
                public void actionPerformed(ActionEvent e){
                   if(lensFrame != null) { lensFrame.dispose();}
                      lensFrame = new JFrame();
                      lensFrame.addWindowListener(
                         new WindowAdapter(){
                            public void windowClosing(WindowEvent w){
                               panZoom.setPanZoomOn(true);
                               lensPanel.setLensOn(false);
                            }
                         }
                      );
                      lensPanel = new LensPanel((ImageManipulator)viewerPane);
                      lensFrame.getContentPane().add(lensPanel);
                      lensFrame.pack();
                   //}
                   viewerPane.paintImage();
                   panZoom.setPanZoomOn(false);
                   lensFrame.show();
                   lensPanel.setLensOn(true);
                 }
              }
          );
          rot.addActionListener(
              new ActionListener() {
                public void actionPerformed(ActionEvent e){
                   if(manipFrame == null) {
                      manipFrame = new JFrame();
                      ManipUI manipui = new ManipUI(manip);
                      manipFrame.getContentPane().add(manipui);
                      manipFrame.pack();
                   }
                   manipFrame.show();
                }
              }
           );
           manipMenu.add(flip);
           manipMenu.add(rot);
           manipMenu.add(ls);
           add(manipMenu);
           return manipMenu;
       }
       public JMenu createViewModeMenu(){
          JMenu viewModeMenu = new JMenu("View");
          JMenu dispMode = new JMenu("Display Mode");
          JMenu flipMode = new JMenu("Flip Mode");
          viewModeMenu.add(dispMode);
          viewModeMenu.add(flipMode);
          JMenuItem orig = new JMenuItem("Original Size");
          JMenuItem tofit = new JMenuItem("To Fit");
          JMenuItem scaled= new JMenuItem("Scaled");
          orig.addActionListener(new DisplayModeAdapter(DisplayMode.ORIG_SIZE));
          tofit.addActionListener(new DisplayModeAdapter(DisplayMode.TO_FIT));
          scaled.addActionListener(new DisplayModeAdapter(DisplayMode.SCALED));

          dispMode.add(orig);
          dispMode.add(tofit);
          dispMode.add(scaled);

          JMenuItem normal = new JMenuItem("Normal");
          JMenuItem leftright = new JMenuItem("Left to Right");
          JMenuItem topbottom = new JMenuItem("Top to Bottom");
          JMenuItem topbotlefrig = new JMenuItem("Top to Bottom and left to right");

          flipMode.add(normal);
          flipMode.add(leftright);
          flipMode.add(topbottom);
          flipMode.add(topbotlefrig);
          normal.addActionListener(new FlipModeAdapter(FlipMode.NORMAL));
          leftright.addActionListener(new FlipModeAdapter(FlipMode.LEFT_RIGHT));
          topbottom.addActionListener(new FlipModeAdapter(FlipMode.TOP_BOTTOM));
          topbotlefrig.addActionListener(new FlipModeAdapter(FlipMode.TOP_BOTTOM_LEFT_RIGHT));

          JCheckBoxMenuItem invertOn = new JCheckBoxMenuItem("Invert image");
          invertOn.addChangeListener(
              new ChangeListener() {
                 public void stateChanged(ChangeEvent e){
                    JCheckBoxMenuItem jce = (JCheckBoxMenuItem)e.getSource();
                    if(viewerPane != null) viewerPane.setInvert(jce.getState());
                 }
              }
          );
          viewModeMenu.add(invertOn);
          add(viewModeMenu);
          return viewModeMenu;
       }

       public JMenu createFlipMenu() {
          JMenu flipMode = new JMenu("Flip");
          JMenuItem normal = new JMenuItem("Normal");
          JMenuItem leftright = new JMenuItem("Left to Right");
          JMenuItem topbottom = new JMenuItem("Top to Bottom");
          JMenuItem topbotlefrig = new JMenuItem("Top to Bottom and left to right");

          flipMode.add(leftright);
          flipMode.add(topbottom);
          flipMode.add(topbotlefrig);
          leftright.addActionListener(new FlipAdapter(FlipMode.LEFT_RIGHT));
          topbottom.addActionListener(new FlipAdapter(FlipMode.TOP_BOTTOM));
          topbotlefrig.addActionListener(new FlipAdapter(FlipMode.TOP_BOTTOM_LEFT_RIGHT));
          return flipMode;
      }
    class FlipAdapter implements ActionListener{
       int flipmode;
       public FlipAdapter(int mode){ flipmode = mode;}
       public void actionPerformed(ActionEvent e){manip.flip(flipmode);}
    }
  }
}

