// (by Dalubar)

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
// per le immagini
import java.io.*;
import javax.imageio.*;
import java.awt.image.*;
import javax.swing.filechooser.FileFilter;


/* PROVA LABORATORIO "TIPO" 2004 */

// il frame principale
class myFrame extends JFrame {
    //dimensioni schermo
    Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize();
    //pannello pubblico
    public myPanel mainPanel;
   // costruttore
    public myFrame() {
        setTitle("Esempio per prova Itinere 2004");
        setSize(dScreen.width/2, dScreen.height/2);
        //il pannello appare centrato
        setLocation((dScreen.width - getSize().width) / 2,
                    (dScreen.height - getSize().height) / 2);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // crea e inserisce pannello nel frame
        mainPanel = new myPanel();
        getContentPane().add(mainPanel);
        // inserisce menu nel frame
         new menuProvaItinere(this);
    }    
}

//pannello principale
class myPanel extends JPanel {
    //pannelli
    panelA pannelloA;
    panelB pannelloB;
    //costruttore
    public myPanel() {
        super();
        setLayout(new GridLayout(1,2));
        pannelloA = new panelA();
        pannelloB = new panelB();
        add(pannelloA);
        add(new JScrollPane(pannelloB));
    }
}

class panelA extends JPanel {
    // variab istanza
    private Color colore;
    private boolean vuotoPieno, isDeformato;
    //costruttore
    public panelA() {
        // colore di sfondo
        setBackground(Color.WHITE);
        // colore casuale scelto iniziale
        colore = new Color((float)Math.random(), (float)Math.random(), (float)Math.random());
        // flag per vuoto/pieno
        vuotoPieno = true;
        isDeformato = false;
        
    }
    
    // qui si disegnano le forme
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        //setta rendering x ANTI-ALIASING
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);        
        //prende centro del pannello
        Dimension center = new Dimension((getSize().width/2), getSize().height/2);
        //prelevo il minimo tra width ed height
        int min = (getSize().width <= getSize().height)? getSize().width : getSize().height;
        
        //setto colore a scelta
        g2.setPaint(colore);
                    
        //Disegna Cerchio quanto la metà del pannello
        Ellipse2D circle = new Ellipse2D.Double();
        if (isDeformato)
            circle.setFrameFromCenter(center.width, center.height,
                            center.width + min / 4,
                            center.height + min / 4);
            
        else
            circle.setFrameFromCenter(center.width, center.height,
                            center.width + getSize().width / 4,
                            center.height + getSize().height / 4);
            
        // disegna il cerchio pieno oppure vuoto
        if (!vuotoPieno) g2.fill(circle); else g2.draw(circle);
            
        // Disegna rettangoli tangenti al cerchio
        Rectangle2D rectA = new Rectangle2D.Double();
        Rectangle2D rectB = new Rectangle2D.Double();
        g2.setPaint(invertiColore(colore));
        int sizeRect = 60;
        
        rectA.setRect(  center.width - (getSize().width / 4) - sizeRect,
                        center.height - (sizeRect/2),
                        sizeRect, sizeRect);
        
        rectB.setRect(  center.width + (getSize().width / 4),
                        center.height - (sizeRect/2),
                        sizeRect, sizeRect);

        // disegna il rettangolo vuoto oppure pieno
        if (!vuotoPieno) {
            g2.fill(rectA);
            g2.fill(rectB);
        }
        else {
            g2.draw(rectA);
            g2.draw(rectB);
        }
    }
    
    public void setFullEmpty(boolean sw) {
        vuotoPieno = sw;
        repaint();
    }
    
    public void invertiDeforma() {
        isDeformato = !isDeformato;
        repaint();
    }
    
    //restituisce un colore che è complementare a quello dato come paramentro
    private Color invertiColore(Color c) {
        return (new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue()));
    }
    
}



// pannello per le immagini
class panelB extends JPanel {
    //immagine da caricare
    BufferedImage immagine;     //immagine da visualizzare
    JFileChooser fileChooser;   //finestra di dialogo per aprire i file
    JLabel label;               //label nel quale verrà disegnata l'immagine
    
    //costruttore
    public panelB() {
        setBackground(Color.ORANGE);
        //Creo il JFileChooser
        fileChooser = new JFileChooser();
        //Disabilito al visualizzazione di tutti i tipi di file
        fileChooser.setAcceptAllFileFilterUsed(false);
        //Abilito la visualizzazione dei file di tipo jpg
        fileChooser.setFileFilter(new JPGFilter());    
        // Imposto la directory iniziale
        fileChooser.setCurrentDirectory(new File("e:\\Immagini/FotoSilvio/Etna"));         
        label = new JLabel();
        add(label);
    }
        
    public void openFile() {
        //Imposto il titolo della finestra
        fileChooser.setDialogTitle("Apri file");
        //Visualizzo la finestra di dialogo
        int risposta=fileChooser.showOpenDialog(this);
        //Se ho premuto il tasto apri...
        if (risposta==fileChooser.APPROVE_OPTION)  {  
          //Recupero il file selezionato
          File f = fileChooser.getSelectedFile();
          try {
                BufferedImage buff = ImageIO.read(f);
                //recupero le dimensioni dell'immagine
                int w=buff.getWidth();
                int h=buff.getHeight();
                //Creo un'immagine nuova delle stesse dimensioni
                immagine = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
                /* Disegno l'immagine caricata sulla nuova immagine.
                  Operazione che garantisce un immagine di tipo TYPE_INT_ARGB */
                Graphics2D g2 = immagine.createGraphics();
                g2.drawImage(buff, 0, 0, null);
                //rilascio contesto grafico
                g2.dispose();       
                //aggiorno icona
                label.setIcon(new ImageIcon(immagine));
                //ridisegno
                repaint();
              
          }
          catch (Exception ex) {}
        }        
    }
    
    public void filterImage() {
        if (immagine == null)
            JOptionPane.showMessageDialog(null,"E' nencessario prima aprire una immagine");
        else {
            // codice x filtro... Derivata X
            filterDerivataX();
        }
    }
    
    private void filterDerivataX() {
        //Creo la matrice del kernel
        float[] data = new float[] {
          -1F, 0F, 1F,
          -1F, 0F, 1F,
          -1F, 0F, 1F        
        };        
        //Creo una nuova immagine buffer
        BufferedImage buff = new BufferedImage(immagine.getWidth(), immagine.getHeight(),
                                 BufferedImage.TYPE_INT_RGB);
        //creo il kernel
        Kernel k = new Kernel(3, 3, data);
        //Creo il filtro convolutivo
        ConvolveOp op = new ConvolveOp(k);
        //Eseguo il filtro
        op.filter(immagine, buff);
        //Ricopio il risultato sull'immagine originale
        Graphics2D g2 = immagine.createGraphics();
        g2.drawImage(buff, 0, 0, null);
        //Rilascio le risorse
        g2.dispose();
        //Ridisegno la label aggiornata
        label.setIcon(new ImageIcon(immagine));
        label.validate();
    }    
}



// il menu del frame principale
class menuProvaItinere implements ActionListener {
    //variabile di istanza
    private myFrame frame;
    // le scelte di menu
    JMenuItem menu1_1, menu1_2, menu1_3, menu2_1, menu2_2;
    //costruttore
    public menuProvaItinere(myFrame f) {
        //creazione barra menù
        JMenuBar menuBar = new JMenuBar();
        f.setJMenuBar(menuBar);
        //menu1
        JMenu menu1 = new JMenu("Menu 1");
        menu1_1 = menu1.add("Deforma");
        menu1_2 = menu1.add("Pieno");
        menu1_3 = menu1.add("Vuoto");
        //menu2
        JMenu menu2 = new JMenu("Menu 2");
        menu2_1 = menu2.add("Carica Immagine");
        menu2_2 = menu2.add("Elabora Immagine");
        //inserimento menu nella barra del menu
        menuBar.add(menu1);
        menuBar.add(menu2);
        // ascoltatore degli eventi: questa stessa classe
        menu1_1.addActionListener(this);
        menu1_2.addActionListener(this);
        menu1_3.addActionListener(this);
        menu2_1.addActionListener(this);
        menu2_2.addActionListener(this);
        
        // passo il frame al fine di controllare i pannelli dagli eventi del menù.
        frame = f;
        
    }
    
    public void actionPerformed(ActionEvent e) {
        //eventi per il pannelloA
        if (e.getSource().equals(menu1_1) ) frame.mainPanel.pannelloA.invertiDeforma();
        if (e.getSource().equals(menu1_2) ) frame.mainPanel.pannelloA.setFullEmpty(false);
        if (e.getSource().equals(menu1_3) ) frame.mainPanel.pannelloA.setFullEmpty(true);
        
        //eventi per il pannelloB
        if (e.getSource().equals(menu2_1) )  frame.mainPanel.pannelloB.openFile();
        if (e.getSource().equals(menu2_2) )  frame.mainPanel.pannelloB.filterImage();
    }

}

// Filtro per le immagini JPG
class JPGFilter extends FileFilter {
  // file da accettare: jpg o jpeg (oppure sono cartelle)
  public boolean accept(File f) {
    String str = f.getName().toLowerCase();
    return str.endsWith(".jpg")||str.endsWith(".jpeg")||f.isDirectory();
  }
  
  // descrizione del filtro
  public String getDescription() {
    return "Immagine JPG";
  }
}

// Filtro per le immagini GIF
class GIFFilter extends FileFilter {
  // file da accettare: jpg o jpeg (oppure sono cartelle)
  public boolean accept(File f) {
    String str = f.getName().toLowerCase();
    return str.endsWith(".gif")||f.isDirectory();
  }
  
  // descrizione del filtro
  public String getDescription() {
    return "Immagine GIF";
  }
}

// Filtro per le immagini PNG
class PNGFilter extends FileFilter {
  // file da accettare: jpg o jpeg (oppure sono cartelle)
  public boolean accept(File f) {
    String str = f.getName().toLowerCase();
    return str.endsWith(".png")||f.isDirectory();
  }
  
  // descrizione del filtro
  public String getDescription() {
    return "Immagine PNG";
  }
}


// classe principale
public class provaItinere {
public static void main(String[] args) {
     JFrame f = new myFrame();
     f.show();
  }
}